D2L: Object Detection
Object Detection
Concept and Principle
目标检测任务与图像分类不同,目标检测要在图片中识别出多个不同的目标并表明每个目标的位置
边缘框
- 边缘框表示了目标的位置,有两种坐标表示法
- (左上x,左上y,右下x,右下y)
- (左上x,左上y,边框宽,边框高)
- 边缘框表示了目标的位置,有两种坐标表示法
锚框
- 锚框在目标检测算法中很常用,许多目标检测算法都用到了这项技术
- 锚框是对边缘框的一个猜测:
- 提出多个被称为锚框的区域
- 预测每个锚框中是否含有目标物体
- 如果有,则继续预测从这个锚框到真实边缘框的偏移
- 使用交并比(IoU)来计算两个框的相似度(预测框和标签框)
- 赋予锚框标号
- 在训练时,每个锚框都是一个训练样本,每次读取一张图片都要进行一次赋予锚框标号的操作
- 将每个锚框要么标注为背景,要么标注为与真实边缘框相关
- 可能生成大量锚框导致负样本过多
- 锚框可固定生成,或根据图片生成,甚至随机
- 假设一个图片有4个标签边缘框,生成了9个锚框,一种赋予标号的算法如下图
- 在预测时,使用非极大值抑制(NMS)输出
目标检测常用算法
Faster R-CNN
图片进入一个CNN后分成两条路线,一条路线进入RPN(负责生成锚框),另一条路线经过RoI pooling(将不同大小的锚框提取为同一大小)后连接至全连接层,最后做出分类以及边缘框预测。Faster R-CNN相对其他算法来说还是很慢,但精度很高,适合刷榜。SSD(单发多框检测)
SSD由一个基础的网络来抽取特征,然后多个卷积层块来减半高宽。每段都会生成锚框,底部段拟合小物体,顶部段拟合大物体。每个锚框都会预测类别和边缘框YOLO
SSD中锚框有大量重叠,YOLO将图片均匀分成SxS个锚框,每个锚框预测B个边缘框。
Implementation
边缘框实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69import torch
from PIL import Image
from matplotlib import pyplot as plt
img=Image.open("./1.jpg")
plt.imshow(img)
plt.show()
fig=plt.imshow(img)
def box_corner_to_center(boxes):
"""(左上,右下)转换到(中间,宽度,高度)
Args:
boxs : 一组边缘框
"""
x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]
cx = (x1 + x2) / 2
cy = (y1 + y2) / 2
w = x2 - x1
h = y2 - y1
# 将新坐标堆叠起来变为二维Tensor,注意与cat不同
boxes = torch.stack((cx, cy, w, h))
# 返回转置
return boxes.T
def box_center_to_corner(boxes):
"""(中间,宽度,高度)转换到(左上,右下)
Args:
boxs : 一组边缘框
"""
cx, cy, w, h = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]
x1 = cx - 0.5 * w
y1 = cy - 0.5 * h
x2 = cx + 0.5 * w
y2 = cy + 0.5 * h
boxes = torch.stack((x1, y1, x2, y2))
return boxes.T
x=torch.tensor([[0., 0., 2., 2.]])
x=box_corner_to_center(x)
print(x)
x=box_center_to_corner(x)
print(x)
box1=torch.tensor([360,170,650,650])
box2=torch.tensor([120,210,350,290])
def show_bboxes(fig,bboxes,color):
"""显示带边缘框的图片
"""
for b,c in zip(bboxes,color):
fig.axes.add_patch(_bbox_to_rect(b, c))
plt.show()
def _bbox_to_rect(bbox, color):
return plt.Rectangle(xy=(bbox[0], bbox[1]), width=bbox[2] - bbox[0],
height=bbox[3] - bbox[1], fill=False,
edgecolor=color, linewidth=2)
show_bboxes(fig,[box1,box2],['red','green'])
Comment