选择性搜索(selective search)

该文翻译整理自:selective search for object detection(c++ / python)


一、目标检测 VS 目标识别

目标识别(objec recognition)是指明一幅输入图像中包含那类目标。其输入为一幅图像,输出是该图像中的目标属于哪个类别(class probability)。而目标检测(object detection)除了要告诉输入图像中包含了哪类目前外,还要框出该目标的具体位置(bounding boxes)。

在目标检测时,为了定位到目标的具体位置,通常会把图像分成许多子块(sub-regions / patches),然后把子块作为输入,送到目标识别的模型中。分子块的最直接方法叫滑动窗口法(sliding window approach)。滑动窗口的方法就是按照子块的大小在整幅图像上穷举所有子图像块。这种方法产生的数据量想想都头大。和滑动窗口法相对的是另外一类基于区域(region proposal)的方法。selective search就是其中之一!

二、selective search算法流程

选择性搜索(selective search)

step0:生成区域集R,具体参见论文《Efficient Graph-Based Image Segmentation》

step1:计算区域集R里每个相邻区域的相似度S={s1,s2,…} 
step2:找出相似度最高的两个区域,将其合并为新集,添加进R 
step3:从S中移除所有与step2中有关的子集 
step4:计算新集与所有子集的相似度 
step5:跳至step2,直至S为空


三、相似度计算

论文考虑了颜色、纹理、尺寸和空间交叠这4个参数。

3.1、颜色相似度(color similarity)
将色彩空间转为HSV,每个通道下以bins=25计算直方图,这样每个区域的颜色直方图有25*3=75个区间。 对直方图除以区域尺寸做归一化后使用下式计算相似度:

选择性搜索(selective search)

3.2、纹理相似度(texture similarity)

论文采用方差为1的高斯分布在8个方向做梯度统计,然后将统计结果(尺寸与区域大小一致)以bins=10计算直方图。直方图区间数为8*3*10=240(使用RGB色彩空间)。

选择性搜索(selective search)

其中,选择性搜索(selective search)是直方图中第选择性搜索(selective search)个bin的值。

3.3、尺寸相似度(size similarity)

选择性搜索(selective search)

保证合并操作的尺度较为均匀,避免一个大区域陆续“吃掉”其他小区域。

例:设有区域a-b-c-d-e-f-g-h。较好的合并方式是:ab-cd-ef-gh -> abcd-efgh -> abcdefgh。 不好的合并方法是:ab-c-d-e-f-g-h ->abcd-e-f-g-h ->abcdef-gh -> abcdefgh。

3.4、交叠相似度(shape compatibility measure)

选择性搜索(selective search)

选择性搜索(selective search)

3.5、最终的相似度

选择性搜索(selective search)


四、OpenCV 3.3 实现了selective search

在OpenCV的contrib模块中实现了selective search算法。类定义为:

[cpp] view plain copy
  1. cv::ximgproc::segmentation::SelectiveSearchSegmentation  


举例:

[cpp] view plain copy
  1. #include "opencv2/ximgproc/segmentation.hpp"  
  2. #include "opencv2/highgui.hpp"  
  3. #include "opencv2/core.hpp"  
  4. #include "opencv2/imgproc.hpp"  
  5. #include <iostream>  
  6. #include <ctime>  
  7.    
  8. using namespace cv;  
  9. using namespace cv::ximgproc::segmentation;  
  10.    
  11. static void help() {  
  12.     std::cout << std::endl <<  
  13.     "Usage:" << std::endl <<  
  14.     "./ssearch input_image (f|q)" << std::endl <<  
  15.     "f=fast, q=quality" << std::endl <<  
  16.     "Use l to display less rects, m to display more rects, q to quit" << std::endl;  
  17. }  
  18.    
  19.    
  20. int main(int argc, char** argv) {  
  21.     // If image path and f/q is not passed as command  
  22.     // line arguments, quit and display help message  
  23.     if (argc < 3) {  
  24.         help();  
  25.         return -1;  
  26.     }  
  27.    
  28.     // speed-up using multithreads  
  29.     // void cv::setUseOptimized(bool onoff), Enables or disables the optimized code.  
  30.     setUseOptimized(true);  
  31.     setNumThreads(4);  
  32.    
  33.     // read image  
  34.     Mat im = imread(argv[1]);  
  35.     // resize image  
  36.     int newHeight = 200;  
  37.     int newWidth = im.cols*newHeight/im.rows;  
  38.     resize(im, im, Size(newWidth, newHeight));  
  39.    
  40.     // create Selective Search Segmentation Object using default parameters  
  41.     Ptr<SelectiveSearchSegmentation> ss = createSelectiveSearchSegmentation();  
  42.     // set input image on which we will run segmentation  
  43.     ss->setBaseImage(im);  
  44.    
  45.     // Switch to fast but low recall Selective Search method  
  46.     if (argv[2][0] == 'f') {  
  47.         ss->switchToSelectiveSearchFast();  
  48.     }  
  49.     // Switch to high recall but slow Selective Search method  
  50.     else if (argv[2][0] == 'q') {  
  51.         ss->switchToSelectiveSearchQuality();  
  52.     }   
  53.     // if argument is neither f nor q print help message  
  54.     else {  
  55.         help();  
  56.         return -2;  
  57.     }  
  58.    
  59.     // run selective search segmentation on input image  
  60.     std::vector<Rect> rects;  
  61.     ss->process(rects);  
  62.     std::cout << "Total Number of Region Proposals: " << rects.size() << std::endl;  
  63.    
  64.     // number of region proposals to show  
  65.     int numShowRects = 100;  
  66.     // increment to increase/decrease total number of reason proposals to be shown  
  67.     int increment = 50;  
  68.    
  69.     while(1) {  
  70.         // create a copy of original image  
  71.         Mat imOut = im.clone();  
  72.    
  73.         // itereate over all the region proposals  
  74.         for(int i = 0; i < rects.size(); i++) {  
  75.             if (i < numShowRects) {  
  76.                 rectangle(imOut, rects[i], Scalar(0, 255, 0));  
  77.             }  
  78.             else {  
  79.                 break;  
  80.             }  
  81.         }  
  82.    
  83.         // show output  
  84.         imshow("Output", imOut);  
  85.    
  86.         // record key press  
  87.         int k = waitKey();  
  88.    
  89.         // m is pressed  
  90.         if (k == 109) {  
  91.             // increase total number of rectangles to show by increment  
  92.             numShowRects += increment;  
  93.         }  
  94.         // l is pressed  
  95.         else if (k == 108 && numShowRects > increment) {  
  96.             // decrease total number of rectangles to show by increment  
  97.             numShowRects -= increment;  
  98.         }  
  99.         // q is pressed  
  100.         else if (k == 113) {  
  101.             break;  
  102.         }  
  103.     }  
  104.     return 0;  
  105. }  
上边代码git地址:https://code.****.net/guoyunfei20/selective_search_opencv_demo.git(运行需要安装OpenCV3.0以上 + contrib)