3.1 视觉任务简介
计算机视觉的任务包括(如图1所示):
- 图像分类:判断图像是什么类别。结果是class。
- 目标检测:判断目标是什么,以及框出目标。结果是bounding box和class。
- 语义分割:判断像素的类别。结果是pixel对应的class。
- 实例分割:判断像素的实体。结果是pixel对应的instance。
语义分割和实例分割的区别,可以参考重叠的两只羊这个例子。
3.2 目标检测
图2 目标检测示例图像目标检测的结果:
- target class
- Bounding Box(x, y, width, height)
3.2.1 R-CNN
R-CNN包括三个部分:
- 候选区域生成(Region Proposal):生成物体类别无关的Region proposal的模块。这里没有任何神经网络,它使用图像处理的技术产生可能包含物体的候选区域。
- 特征提取:一个CNN来提取固定大小的特征。这个CNN只是用来提取特征。
- 识别器和Bounding Box回归:每个类别都有一个线性的SVM分类器来判断候选区域是否属于这个类别。
- Region Proposal
R-CNN的Region Proposal算法是selective search算法,其算法复杂度依然很高。
图5 基于图的图像分割结果
由图4和图5对比,selective search算法复杂度依然很高。
由图5,经过聚类算法得到图6。
然后由过度分割的图片根据以下算法得到Region Proposal。算法步骤如下:
- 所有细粒度的分隔都加到候选区域里(当然分割不是矩形区域我们需要把它变成矩形区域);
- 在候选区域里根据相似度把最相似的区域合并,然后加到候选区域里;
- 回到1不断的重复这个过程。
文章到这里,居然给了个opencv实现selective search算法的源码,经过了3秒钟的思考,我决定将它们粘贴过来分析下。(注意:这个算法是在contrib包里,所有需要使用命令pip install opencv-contrib-python来安装。)
import sys
import cv2
print(cv2.__version__)
if __name__ == '__main__':
# 使用多线程加速
cv2.setUseOptimized(True);
cv2.setNumThreads(4);
# 读取图片
im = cv2.imread(sys.argv[1])
# resize图片
newHeight = 200
newWidth = int(im.shape[1] * 200 / im.shape[0])
im = cv2.resize(im, (newWidth, newHeight))
# 这行代码创建一个Selective Search Segmentation对象,使用默认的参数。
ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
# 设置应用算法的图片
ss.setBaseImage(im)
# fast模式,速度快,但是召回率低
if (sys.argv[2] == 'f'):
ss.switchToSelectiveSearchFast()
# 高召回率但是速度慢
elif (sys.argv[2] == 'q'):
ss.switchToSelectiveSearchQuality()
else:
print(__doc__)
sys.exit(1)
# 实际运行算法
rects = ss.process()
print('Total Number of Region Proposals: {}'.format(len(rects)))
# 只显示100个区域
numShowRects = 100
# increment to increase/decrease total number
# of reason proposals to be shown
increment = 50
while True:
# create a copy of original image
imOut = im.copy()
# itereate over all the region proposals
for i, rect in enumerate(rects):
# draw rectangle for region proposal till numShowRects
if (i < numShowRects):
x, y, w, h = rect
cv2.rectangle(imOut, (x, y), (x + w, y + h), (0, 255, 0),
1, cv2.LINE_AA)
else:
break
# show output
cv2.imshow("Output", imOut)
cv2.destroyAllWindows()
- 特征提取
特征提取采用的AlexNet,这个网络性能和速度不如SqueezeNet、MobileNet、ShuffleNet和MNasNet等等。但是那个年代已经是石破天惊了。
需要注意的问题是需要将不同大小的Region变为统一大小的输入图像,这也是R-CNN的缺点,这个缺点在Faster R-CNN中被改进了。
- 识别器和Bounding Box回归
- 使用non-maximum suppression来去掉重复的区域。
- 使用SVM来判断region中的目标分类。
这里解释下Non-Maximum Suppression(NMS)算法:
- 找到某一类的SVM分类得分最高的区域;
- 然后再看该类得分第二高的区域,计算该区域和前述区域的交并比(IoU);
- 如果大于一个阈值,则认为这两个区域是同一个区域;如果小于一个阈值,则认为是一个该类的新目标。
这里要注意的是,如果是两类的IoU大于一个阈值,这还是两个区域。
IoU的计算如下:
- 训练
- 用AlexNet的预训练模型和参数,用Proposal区域和标注区域做fine-tuning;
- SVM分类器的训练,fine-tuning数据采用阈值为0.3来获取。(这个阈值是根据交叉验证的方法得到的)
- Bounding Box回归
Bounding Box回归微调最后的(x, y, width, height)的结果,使得结果更好。不过该方法会被后面的方法改进,因此书中没有对Bounding Box的细节进行详细描述。
这里只讲一点,就是真正用于回归的不是(x, y, width, height),而是这四个变量的伸缩值,细节看论文附录吧!
网友评论