Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added exercises/__pycache__/conv.cpython-39.pyc
Binary file not shown.
Binary file not shown.
Binary file added exercises/__pycache__/iou.cpython-39.pyc
Binary file not shown.
Binary file added exercises/__pycache__/leaky_relu.cpython-39.pyc
Binary file not shown.
Binary file added exercises/__pycache__/maxpool.cpython-39.pyc
Binary file not shown.
Binary file added exercises/__pycache__/nms.cpython-39.pyc
Binary file not shown.
Binary file added exercises/__pycache__/smooth_l1.cpython-39.pyc
Binary file not shown.
23 changes: 22 additions & 1 deletion exercises/contour_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,25 @@ def contour_detection(image_path):
# 7. 使用 cv2.drawContours() 在副本上绘制轮廓。
# 8. 返回绘制后的图像和轮廓列表。
# 9. 使用 try...except 处理异常。
pass
try:
img=cv2.imread(image_path)
if img is None:
return None,None

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, binary=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours=cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

if len(contours)==2:
contours=contours[0]
elif len(contours)==3:
contours=contours[1]
else:
raise ValueError("error")
if not isinstance(contours,list):
contours=list(contours)
img_with_contours=img.copy()
cv2.drawContours(img_with_contours,contours,-1,(0,255,0),2)
return img_with_contours, contours
except Exception as e:
return None, None
41 changes: 40 additions & 1 deletion exercises/conv.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,43 @@ def conv2d(x, kernel):
# 5. 提取输入 x 中与当前卷积核对应的区域 (patch)。
# 6. 计算 patch 和 kernel 的元素乘积之和 (np.sum(patch * kernel))。
# 7. 将结果存入输出数组 out[i, j]。
pass
# 获取输入和卷积核的形状
H,W=x.shape
kH,kW=kernel.shape
# print('H,W:',H,' ',W)
# print('kH,kW:',kH,' ',kW)
out_H=H-kH+1
out_W=W-kW+1
out = np.zeros((out_H,out_W))
for i in range(out_H):
for j in range(out_W):
patch=x[i:i+kH,j:j+kW]
out[i,j]=np.sum(patch*kernel)
return out

if __name__=='__main__':
img1 = np.zeros((5,5))
kernel1 = np.random.rand(3,3)
result1 = conv2d(img1, kernel1)

img2 = np.eye(5)
kernel2 = np.array([[1,0,0],
[0,1,0],
[0,0,1]])
result2 = conv2d(img2, kernel2)
expected2 = np.array([[3.,0.,0.],
[0.,3.,0.],
[0.,0.,3.]])

img3 = np.arange(25).reshape(5,5)
kernel3 = np.ones((3,3))
result3 = conv2d(img3, kernel3)
expected3 = np.array([
[ 54, 63, 72],
[ 99, 108, 117],
[144, 153, 162]
])

print(result1)
print(result2)
print(result3)
9 changes: 8 additions & 1 deletion exercises/cross_entropy.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,11 @@ def cross_entropy_loss(y_true, y_pred):
# 4. 计算交叉熵损失:L = - sum(y_true * log(y_pred))。
# 在 NumPy 中是 -np.sum(y_true * np.log(y_pred))。
# 5. 计算所有样本的平均损失:L / N。
pass
N = y_pred.shape[0]
C = y_pred.shape[1]
if y_true.ndim==1 or (y_true.ndim==2 and y_true.shape[1]==1):
y_true=np.eye(C)[y_true.reshape(-1)]
eps=1e-12
y_pred=np.clip(y_pred,eps,1.0-eps)
loss=-np.sum(y_true*np.log(y_pred))/N
return loss
12 changes: 11 additions & 1 deletion exercises/image_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@ def image_processing_pipeline(image_path):
# 4. 使用 cv2.GaussianBlur() 进行高斯滤波。
# 5. 使用 cv2.Canny() 进行边缘检测。
# 6. 使用 try...except 包裹代码以处理可能的异常。
pass
try:
img=cv2.imread(image_path)
if img is None:
return None
gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

blurred=cv2.GaussianBlur(gray,(5,5),1.5)
edges=cv2.Canny(blurred,50,150)
return edges
except Exception as e:
return None
11 changes: 10 additions & 1 deletion exercises/iou.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,13 @@ def calculate_iou(box1, box2):
# 6. 计算并集面积 union_area = box1_area + box2_area - intersection_area。
# 7. 计算 IoU = intersection_area / union_area。
# 注意处理 union_area 为 0 的情况 (除零错误)。
pass
x_left = max(box1[0], box2[0])
y_top = max(box1[1], box2[1])
x_right = min(box1[2], box2[2])
y_bottom = min(box1[3], box2[3])
intersection_area = max(0, x_right - x_left) * max(0, y_bottom - y_top)
box1_area=(box1[2]-box1[0])*(box1[3]-box1[1])
box2_area=(box2[2]-box2[0])*(box2[3]-box2[1])
union_area = box1_area + box2_area - intersection_area
IoU = 0 if union_area==0 else intersection_area / union_area
return IoU
2 changes: 1 addition & 1 deletion exercises/leaky_relu.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ def leaky_relu(x, alpha=0.01):
# 1. 可以使用 np.maximum() 函数。
# 2. 计算 alpha * x。
# 3. 计算 max(alpha * x, x)。
pass
return np.maximum(alpha * x, x)
15 changes: 14 additions & 1 deletion exercises/maxpool.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,17 @@ def maxpool(x, kernel_size, stride):
# 5. 提取当前池化窗口 window = x[h_start:h_start+kernel_size, w_start:w_start+kernel_size]。
# 6. 找到窗口中的最大值 np.max(window)。
# 7. 将最大值存入输出数组 out[i, j]。
pass
H,W=x.shape

out_H=(H-kernel_size)//stride+1
out_W=(W-kernel_size)//stride+1

out=np.zeros((out_H,out_W))
for i in range(out_H):
for j in range(out_W):
h_start=i*stride
w_start=j*stride

window=x[h_start:h_start+kernel_size,w_start:w_start+kernel_size]
out[i,j]=np.max(window)
return out
39 changes: 37 additions & 2 deletions exercises/nms.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,16 @@ def calculate_iou(box1, box2):
# 请在此处编写代码
# (与 iou.py 中的练习相同,可以复用代码或导入)
# 提示:计算交集面积和并集面积,然后相除。
pass
x_left = max(box1[0], box2[0])
y_top = max(box1[1], box2[1])
x_right = min(box1[2], box2[2])
y_bottom = min(box1[3], box2[3])
intersection_area = max(0, x_right - x_left) * max(0, y_bottom - y_top)
box1_area=(box1[2]-box1[0])*(box1[3]-box1[1])
box2_area=(box2[2]-box2[0])*(box2[3]-box2[1])
union_area = box1_area + box2_area - intersection_area
IoU = 0 if union_area==0 else intersection_area / union_area
return IoU

def nms(boxes, scores, iou_threshold):
"""
Expand Down Expand Up @@ -52,4 +61,30 @@ def nms(boxes, scores, iou_threshold):
# c. 找到 IoU 小于等于 iou_threshold 的索引 inds。
# d. 更新 order,只保留那些 IoU <= threshold 的框的索引 (order = order[inds + 1])。
# 7. 返回 keep 列表。
pass
if len(boxes)<=0:
return boxes
areas=[]
for box1 in boxes:
areas.append((box1[2]-box1[0])*(box1[3]-box1[1]))
boxes=np.array(boxes)
scores=np.array(scores)
order = np.argsort(scores)[::-1].tolist()
# print(order)
i=order.pop(0)
keep=[i]
for v in range(len(order)):
# print(calculate_iou(boxes[i],boxes[order[v]]))
if calculate_iou(boxes[i],boxes[order[v]])<=iou_threshold:
keep.append(order[v])
return keep

if __name__=='__main__':
boxes2 = [
[10, 10, 60, 60], # 得分最高
[15, 15, 65, 65], # 与第一个框IoU≈0.53
[50, 50, 100, 100], # 与第一个框IoU≈0.11
[150, 150, 200, 200] # 完全独立
]
scores2 = [0.9, 0.85, 0.8, 0.75]
result2 = nms(boxes2, scores2, 0.5)
print(result2)
6 changes: 5 additions & 1 deletion exercises/smooth_l1.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ def smooth_l1(x, sigma=1.0):
# 3. 对满足条件的元素应用第一个公式 (0.5 * (sigma * x)**2)。
# 4. 对不满足条件的元素应用第二个公式 (|x| - 0.5 / sigma2)。
# 5. 可以使用 np.where() 来根据条件选择应用哪个公式。
pass
sigma2=sigma**2
t=1.0/sigma2
ax=np.abs(x)
loss=np.where(ax<t, 0.5*(sigma*x)**2, ax-0.5/sigma2)
return loss