目标检测

CV03_06:选择性搜索算法

2020-03-19  本文已影响0人  杨强AT南京

  是选基于图的图像分割后,就可以使用选择性搜索算法找到目标的候选区域。本主题介绍了选择性搜索算法的原理,主要是基于OpenCV实现框架来说明,起核心是四个常规的相似度计算:颜色相似度、尺度相似度、交叠相似度、纹理相似度。可以根据特色的规则建立其他相似度:比如人脸可以选在高宽差别不大的区域等。
  有了候选区域,就可以使用卷积神经网络做特征抽取,抽取的特征没有使用神经网络的分类器,标准算法中都是使用号称史上最好的分类器SVM来训练分类(请参考我们对OpenCV与Sklearn中SVM的解释)。
  在老版本的OpenCV(3.4以前)采用的是级联分类,新版本提供了基于SS算法的分类目标检测训练。可以参考OpenCV的app提供的工具。


选择性搜索(Selective Search)

OpenCV的Selective Search模块使用

搜索的使用

  1. 基于质量的搜索
import cv2

# 准备一张图像
img = cv2.imread("gpu.jpeg")

# 创建SelectiveSearch对象
ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()

# 添加图像到处理列表
ss.setBaseImage(img)

# 初始化算法参数
ss.switchToSelectiveSearchQuality()
# int   base_k = 150,
# int   inc_k = 150,
# float sigma = 0.8f 

# ss.switchToSelectiveSearchFast()
# ss.switchToSingleStrategy()
# 所选择性搜索
rects = ss.process()

print(type(rects), rects.shape)
<class 'numpy.ndarray'> (51469, 4)
  1. 基于速度的搜索
import cv2

# 准备一张图像
img = cv2.imread("gpu.jpeg")

# 创建SelectiveSearch对象
ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()

# 添加图像到处理列表
ss.setBaseImage(img)

# 初始化算法参数
# ss.switchToSelectiveSearchQuality()
# int   base_k = 150,
# int   inc_k = 150,
# float sigma = 0.8f 

ss.switchToSelectiveSearchFast()
# ss.switchToSingleStrategy()
# 所选择性搜索
rects = ss.process()

print(type(rects), rects.shape)
<class 'numpy.ndarray'> (12569, 4)
  1. 单策略搜索
import cv2

# 准备一张图像
img = cv2.imread("gpu.jpeg")

# 创建SelectiveSearch对象
ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()

# 添加图像到处理列表
ss.setBaseImage(img)

# 初始化算法参数
# ss.switchToSelectiveSearchQuality()
# int   base_k = 150,
# int   inc_k = 150,
# float sigma = 0.8f 

# ss.switchToSelectiveSearchFast()
ss.switchToSingleStrategy()
# 所选择性搜索
rects = ss.process()

print(type(rects), rects.shape)
<class 'numpy.ndarray'> (2750, 4)

基于颜色、交叠、尺度、纹理的搜索策略

SelectiveSearchSegmentationStrategyColor
import cv2
# 基于颜色策略的搜索
ssc = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyColor()
# 基于填充的策略
ssf = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyFill()


img = cv2.imread("gpu.jpeg")
ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
ss.clearStrategies()
ss.addStrategy(ssc)      ## 不用设置,下面几个方法意境是比较成熟的策略方案了,看源代码了解
ss.addStrategy(ssf)
ss.addImage(img)
ss.setBaseImage(img)
# ss.switchToSingleStrategy()
ss.switchToSelectiveSearchFast()
rects = ss.process()

print(type(rects), rects.shape)
<class 'numpy.ndarray'> (12569, 4)

OpenCV实现说明

策略类


    class SelectiveSearchSegmentationStrategyColorImpl CV_FINAL : public SelectiveSearchSegmentationStrategyColor {
        public:
            SelectiveSearchSegmentationStrategyColorImpl() {
                name_ = "SelectiveSearchSegmentationStrategyColor";
                last_image_id = -1;
            }

            virtual void setImage(InputArray img, InputArray regions, InputArray sizes, int image_id = -1) CV_OVERRIDE;
            virtual float get(int r1, int r2) CV_OVERRIDE;
            virtual void merge(int r1, int r2) CV_OVERRIDE;

        private:
            String name_;

            Mat histograms; // [Region X Histogram]
            Mat sizes;
            int histogram_size;

            int last_image_id; // If the image_id is not equal to -1 and the same as the previous call for setImage, computations are used again
            Mat last_histograms;
    };

switchToSingleStrategy函数实现


    void SelectiveSearchSegmentationImpl::switchToSingleStrategy(int k, float sigma) {
        clearImages();
        clearGraphSegmentations();
        clearStrategies();

        Mat hsv;
        cvtColor(base_image, hsv, COLOR_BGR2HSV);
        addImage(hsv);

        Ptr<GraphSegmentation> gs = createGraphSegmentation();
        gs->setK((float)k);
        gs->setSigma(sigma);
        addGraphSegmentation(gs);

        Ptr<SelectiveSearchSegmentationStrategyColor> color = createSelectiveSearchSegmentationStrategyColor();
        Ptr<SelectiveSearchSegmentationStrategyFill> fill = createSelectiveSearchSegmentationStrategyFill();
        Ptr<SelectiveSearchSegmentationStrategyTexture> texture = createSelectiveSearchSegmentationStrategyTexture();
        Ptr<SelectiveSearchSegmentationStrategySize> size = createSelectiveSearchSegmentationStrategySize();

        Ptr<SelectiveSearchSegmentationStrategyMultiple> m = createSelectiveSearchSegmentationStrategyMultiple(color, fill, texture, size);

        addStrategy(m);

    }

process的实现


void SelectiveSearchSegmentationImpl::process(std::vector<Rect>& rects) {

    std::vector<Region> all_regions;

    int image_id = 0;

    for(std::vector<Mat>::iterator image = images.begin(); image != images.end(); ++image) {
        for(std::vector<Ptr<GraphSegmentation> >::iterator gs = segmentations.begin(); gs != segmentations.end(); ++gs) {

            Mat img_regions;
            Mat_<char> is_neighbour;
            Mat_<int> sizes;

            // Compute initial segmentation
            (*gs)->processImage(*image, img_regions);

            // Get number of regions
            double min, max;
            minMaxLoc(img_regions, &min, &max);
            int nb_segs = (int)max + 1;

            // Compute bouding rects and neighbours
            std::vector<Rect> bounding_rects;
            bounding_rects.resize(nb_segs);

            std::vector<std::vector<cv::Point> > points;

            points.resize(nb_segs);

            is_neighbour = Mat::zeros(nb_segs, nb_segs, CV_8UC1);
            sizes = Mat::zeros(nb_segs, 1, CV_32SC1);

            const int* previous_p = NULL;

            for (int i = 0; i < (int)img_regions.rows; i++) {
                const int* p = img_regions.ptr<int>(i);

                for (int j = 0; j < (int)img_regions.cols; j++) {

                    points[p[j]].push_back(cv::Point(j, i));
                    sizes.at<int>(p[j], 0) = sizes.at<int>(p[j], 0) + 1;

                    if (i > 0 && j > 0) {

                        is_neighbour.at<char>(p[j], p[j - 1]) = 1;
                        is_neighbour.at<char>(p[j], previous_p[j]) = 1;
                        is_neighbour.at<char>(p[j], previous_p[j - 1]) = 1;

                        is_neighbour.at<char>(p[j - 1], p[j]) = 1;
                        is_neighbour.at<char>(previous_p[j], p[j]) = 1;
                        is_neighbour.at<char>(previous_p[j - 1], p[j]) = 1;
                    }
                }
                previous_p = p;
            }

            for(int seg = 0; seg < nb_segs; seg++) {
                bounding_rects[seg] = cv::boundingRect(points[seg]);
            }

            for(std::vector<Ptr<SelectiveSearchSegmentationStrategy> >::iterator strategy = strategies.begin(); strategy != strategies.end(); ++strategy) {
                std::vector<Region> regions;
                hierarchicalGrouping(*image, *strategy, img_regions, is_neighbour, sizes, nb_segs, bounding_rects, regions, image_id);

                for(std::vector<Region>::iterator region = regions.begin(); region != regions.end(); ++region) {
                    all_regions.push_back(*region);
                }
            }

            image_id++;
        }
    }

    std::sort(all_regions.begin(), all_regions.end());

    std::map<Rect, char, rectComparator> processed_rect;

    rects.clear();

    // Remove duplicate in rect list
    for(std::vector<Region>::iterator region = all_regions.begin(); region != all_regions.end(); ++region) {
        if (processed_rect.find((*region).bounding_box) == processed_rect.end()) {
            processed_rect[(*region).bounding_box] = true;
            rects.push_back((*region).bounding_box);
        }
    }

}

SelectiveSearch算法的相似度计算公式

颜色相似度

纹理相似度

尺寸相似度

交叠相似度

最终相似度


附录


上一篇 下一篇

猜你喜欢

热点阅读