选择性搜索算法 (Selective Search)

引言

计算机视觉领域有几个基本的任务:

  • object recognition:物体识别,即在给定的图片中辨认出其中的物体种类,例如猫,飞机,行人等。这里的输入是整个图片,输出是类别标签以及相应的概率(自信度)。
  • image classification = object recognition
from [https://github.com/apache/incubator-mxnet/tree/master/example/image-classification]
  • object detection: 物体检测,不仅要识别图片中的物体,还要定位 (localization),即用 bounding box 将物体圈出来。如果图片中有多个物体,则每个物体都要有对应的 bounding box 和识别出的类型标签。
from https://medium.com/synapse-blog/tech-deep-dive-object-detection-ensembles-as-graph-cliques-a7f7d33b5477

object detection 的基础是 object recognition,只不过要先将图片进行分割,对每个分割之后的子图区域 region (也称为 patch) 进行 object recognition.

由于事先并不知道物体在图片的哪个位置,为了避免漏检,我们应该对图片中尽量多的 region 进行搜索。理论上来说,可以有无穷多个 region。这里就需要一种 region proposal 的算法,以比较高效的方式提出图片划分 region 的方式,从而加速整个 object detection 的过程并且提高准确率。

本文将要介绍的 selective search 算法,是比较经典的,也是 R-CNN 中使用的 region proposal 算法。

参考文献:

  1. original paper by Uijlings et al
  2. https://www.learnopencv.com/selective-search-for-object-detection-cpp-python/

基本思想

为了避免蛮力搜索,selective search 算法首先需要一个基于像素的图像分割。这里用的是 Felzenszwalb and Huttenlocher 算法 (因为是当时速度最快的算法,而且是公开的),得到一个 oversegmented 的图像分割。例如:

oversegmented.png

这里之所以用 oversegmented 图像,是为了得到尽可能细分的区域,再以此为基础逐步合并,形成更大的区域。

image segmentation 可以用作 region proposal 的基础,每个分割的区域都可以看作一个潜在的 region,但是一个 object 往往包含了多个分割的区域,例如盛有咖啡的杯子,咖啡和杯子应该作为一个整体来看待。因此,还要根据某种相似性原则进行分割区域的合并,得到更大范围的 region。

Selective search 算法考虑了 4 种相似性度量,取值都在 [0,1] 之间,越大越相似。

  • 颜色相似性 s_{colour}(r_i, r_j)
  • 纹理相似性 s_{texture}(r_i, r_j)
  • size 相似性 s_{size}(r_i, r_j),促使小的区域之间优先合并
  • shape 相似性 s_{fill}(r_i, r_j),合并只能在紧邻的两个区域间进行,远离的两个区域不能合并

最终的相似性度量是上述四个度量的组合:
s(r_i, r_j) = a_1\times s_{colour}(r_i, r_j) + a_2\times s_{texture}(r_i, r_j) + a_3 \times s_{size}(r_i, r_j) + a_4 \times s_{fill}(r_i, r_j)
其中 a_k 取 0 或 1.

总结起来,selective search 的算法步骤非常简单:

  1. 基于 oversegmented 得到细分的区域,作为初始的 region 集合。
  2. 计算 region 两两之间的相似性,合并具有最大相似性的两个 region,得到新的更大的 region,加入 region 集合中。
  3. 重复 step 2,直到整幅图只剩一个 region。至此,得到的 region 集合就是算法的输出。
hierarchical-segmentation-1.jpg

实例程序

环境配置:

  • opencv >= 3.3,本机用的 4.1.0 版本
  • 安装 opencv-contrib-python package
    pip install opencv-contrib-python --user
    
  • 测试用的图片如下:


    from https://people.com/pets/dog-breeds-diversity-verses-cats-breeds-explainer/

具体程序:

import sys
import cv2
 
# 读取照片,这里要根据具体情况设置路径
im = cv2.imread("./pic/cats-dogs.jpg")

# 重置图片大小,高设置为 400,保持高、宽比例
newHeight = 400
newWidth = int(im.shape[1]*400/im.shape[0])
im = cv2.resize(im, (newWidth, newHeight))    

# 创建 Selective Search Segmentation 对象
ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()

# 添加待处理的图片
ss.setBaseImage(im)

# 可以选择快速但是低 recall 的方式 
# 这里的 recall 指的是选择出来的 region 是否包含了所有应该包含的区域。recall 越高越好
#ss.switchToSelectiveSearchFast()

# 也可以选择慢速但是高 recall 的方式
ss.switchToSelectiveSearchQuality()


# 进行 region 划分,输出得到的 region 数目
rects = ss.process()
print('Total Number of Region Proposals: {}'.format(len(rects)))

# 设定要显示的 region 数目
numShowRects = 100

# 可以通过按键逐步增加或者减少显示的 region 数目
increment = 50

while True:
    # 不要在原图上画 bounding box,而是复制一个新图
    imOut = im.copy()

    # 遍历 regions
    for i, rect in enumerate(rects):
        # 通过 bounding box 显示出指定数量的 region
        if (i < numShowRects):
            x, y, w, h = rect  # bounding box 左上角坐标 x,y, 以及 box 的宽和高
            cv2.rectangle(imOut, (x, y), (x+w, y+h), (0, 255, 0), 1) # 绿色 box,线宽为 1
        else:
            break

    # 显示图片+bbox
    cv2.imshow("Output", imOut)

    # 接收按键输入
    k = cv2.waitKey(0) & 0xFF

    # “m” 键 is pressed
    if k == 109:
        # 增加显示的 bbox 数目
        numShowRects += increment
    # “l” 键 is pressed
    elif k == 108 and numShowRects > increment:
        # 减少显示的 bbox 数目
        numShowRects -= increment
    # “q” 键 is pressed
    elif k == 113:  
        break
# close image show window
cv2.destroyAllWindows()

最后效果如下:


regions.png

显示的 100 个 region 已经包含了我们感兴趣的待检测区域,说明了 selective search 算法的高效。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355