目标检测之选择性搜索算法实现(符动图演示)

定义

选择性搜索是在对象检测中使用的区域提议算法。它的设计速度很快,召回率很高。它基于基于颜色,纹理,大小和形状兼容性的相似区域的分层分组计算。

操作步骤

  1. 首先使用 Felzenszwalb 和 Huttenlocher 基于图像的分割方法
  2. 对分割的图像进行超像素的合并,合并彼此相似的相邻区域 ,合并的规则包括颜色相似度、纹理相似度、尺寸相似度、形状相似性等

自下而上的方法创建了从较小细分到较大细分的区域建议 ,如下图所示

image

合并规则

  • 颜色相似度

计算图像每个通道的 25 个 bins 的颜色直方图,并将所有通道的直方图连接起来,得到 25×3 = 75 维的颜色描述符(归一化)。

image

其中
image

代表两块区域,
image
代表第 i 块区域直方图中第 k 个 bins 的颜色描述符,以上公式表示
image
两块区域的 n=75 维颜色描述符完全一致的话(就是两块区域的 75 维直方图一对一完全相同)那么说明这两块区域的颜色完全相同,可以进行合并
  • 纹理相似度

通过为每个通道在 8 个方向上提取高斯导数来计算纹理特征。对于每个方向和每个颜色通道,都将计算 10 bin 直方图,从而生成 10x8x3 = 240 维特征描述符。

image

以上的公式与颜色相似度的计算公式指代的意义差不多,都是计算每块区域的纹理特征,再比较不同区域的纹理相似度

  • 尺寸相似度

大小相似性鼓励较小的区域尽早合并。它可以确保在图像的所有部分形成所有尺度的区域建议。如果不考虑这种相似性度量,则单个区域将使所有较小的相邻区域一一吞并,因此仅在该位置会生成多个尺度的区域建议。大小相似度定义为

image

上面的公式表示,两个区域越小,其相似度越大,越接近 1。 size(im) 计算的是图片的像素个数

  • 形状相容性
image

形状兼容性可衡量两个区域相互配合的程度,如果匹配则进行合并,如果它们接触都没有,则不合并

  • 最终相似度

最终相似度就是在上面四个相似度的基础上添加一个权重来计算最终相似度,公式如下:

image

代码实现

先上效果:

image

在 OpenCV 中,提供了一个选择性搜索的接口供我们使用,这个模块是在 OpenCV 扩展模块包opencv-contrib-python 里面

首先需要进行安装 pip install opencv-contrib-python

所有代码都进行了注释,这里就不在赘述

#!/usr/bin/env python
'''
安装依赖
!pip install opencv-python
!pip install opencv-contrib-python


Usage:
    ./ssearch.py input_image (f|q)
    f=fast, q=quality
Use "l" to display less rects, 'm' to display more rects, "q" to quit.
'''
 
import sys
import cv2
if __name__ == '__main__':
    # If image path and f/q is not passed as command
    # line arguments, quit and display help message
    
    # speed-up using multithreads
    cv2.setUseOptimized(True);
    cv2.setNumThreads(4)  # 设置线程数
 
    # read image
    path = "F:/jupyter/Dive-into-DL-PyTorch/docs/img/cat1.jpg"
    im = cv2.imread(path)
    
    # resize image 重置大小
    newHeight = 2000
    newWidth = int(im.shape[1]*200/im.shape[0])
#     im = cv2.resize(im, (newWidth, newHeight))    
 
    # create Selective Search Segmentation Object using default parameters
    # 使用默认参数创建一个选择性搜索的分割对象
    ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
 
    # set input image on which we will run segmentation    
    ss.setBaseImage(im)
    
    
    model = "f"   # 快速模式 f 还是 高召回率模式 q
    # 三种模式,参考
    # https://docs.opencv.org/3.4/d6/d6d/classcv_1_1ximgproc_1_1segmentation_1_1SelectiveSearchSegmentation.html
    
    # Switch to fast but low recall Selective Search method
    # 快速模式,但是意味着低召回率
    if (model == 'f'):
        ss.switchToSelectiveSearchFast()
 
    # Switch to high recall but slow Selective Search method
    # 高召回率模式,但是速度较慢
    elif (model == 'q'):
        ss.switchToSelectiveSearchQuality()
    elif (model == "ToString"):
        ss.switchToSingleStrategy()
    # if argument is neither f nor q print help message
    else:
        print("plase set model!")
 
    # run selective search segmentation on input image
    # 运行选择性搜索算法,返回他们的可能边框
    rects = ss.process()
    print('Total Number of Region Proposals: {}'.format(len(rects)))
     
    # number of region proposals to show
    numShowRects = 10
    # increment to increase/decrease total number of reason proposals to be shown
    increment = 20
 
    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.imwrite("Output.jpg", imOut)

        # record key press 
        k = cv2.waitKey(0) & 0xFF
        # m is pressed  m  键增加要显示的矩形框数
        if k == 109:
            # increase total number of rectangles to show by increment
            numShowRects += increment
            
        # l is pressed  l 键减少要显示的矩形框数
        elif k == 108 and numShowRects > increment:
            # decrease total number of rectangles to show by increment
            numShowRects -= increment
            
        # q is pressed  q 键退出
        elif k == 113:
            break
            
    # close image show window
    cv2.destroyAllWindows() 

参考:

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

推荐阅读更多精彩内容