selective search 算法

该博客详细介绍了Selective Search算法在目标检测中的应用,它首先通过图分割生成区域提案,然后计算区域间的相似度并进行合并。算法涉及颜色、纹理、尺寸和矩形相似度的计算,并通过并查集实现高效的数据结构操作。最终,筛选出合适大小且非扭曲的候选框作为目标检测的输入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

早期的RCNN目标检测算法中使用selective search算法来产生region proposals.
该算法的大致流程如下:
1、利用图分割算法将图像分成不同的区域,并为这些区域产生相应的包围框
2、计算包围框之间的相似度,相似度可以分为四个部分(颜色相似度、纹理相似度和大小,相交约束),合并相近的包围框
3、排除过大、过小、长宽比过大、过小的包围框即可

参考代码:https://github.com/tttanikawa/selective-search-cpp

#pragma once

#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <cmath>
#include <iostream>
#include <iterator>
#include <map>
#include <memory>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/ml.hpp>
#include <opencv2/objdetect.hpp>
#include <random>
#include <unordered_map>
#include <vector>

namespace std
{
   
    template <>
    class hash<std::pair<int, int>>
    {
   
    public:
        std::size_t operator()(const std::pair<int, int> &x) const
        {
   
            return hash<int>()(x.first) ^ hash<int>()(x.second);
        }
    };
} // namespace std

namespace ss
{
   

    inline double square(double a)
    {
   
        return a * a;
    }

    inline double diff(const cv::Mat &img, int x1, int y1, int x2, int y2)
    {
   
        return sqrt(square(img.at<cv::Vec3f>(y1, x1)[0] - img.at<cv::Vec3f>(y2, x2)[0]) +
                    square(img.at<cv::Vec3f>(y1, x1)[1] - img.at<cv::Vec3f>(y2, x2)[1]) +
                    square(img.at<cv::Vec3f>(y1, x1)[2] - img.at<cv::Vec3f>(y2, x2)[2]));
    }

    struct UniverseElement
    {
   
        int rank;
        int p;
        int size;

        UniverseElement() : rank(0), size(1), p(0) {
   }
        UniverseElement(int rank, int size, int p) : rank(rank), size(size), p(p) {
   }

        bool operator==(const UniverseElement &other) const
        {
   
            return rank == other.rank && p == other.p && size == other.size;
        }
    };

    class Universe
    {
   
    private:
        std::vector<UniverseElement> elements;
        int num;

    public:
        Universe(int num) : num(num)
        {
   
            elements.reserve(num);

            for (int i = 0; i < num; i++)
            {
   
                elements.emplace_back(0, 1, i);
            }
        }

        ~Universe() {
   }

        int findFast(int x)
        {
   
            return elements[x].p;
        }

        int find(int x)
        {
   
            int y = x;
            while (y != elements[y].p)
            {
   
                y = elements[y].p;
            }
            elements[x].p = y;

            return y;
        }

        void join(int x, int y)
        {
   
            if (elements[x].rank > elements[y].rank)
            {
   
                elements[y].p = x;
                elements[x].size += elements[y].size;
            }
            else
            {
   
                elements[x].p = y;
                elements[y].size += elements[x].size;
                if (elements[x].rank == elements[y].rank)
                {
   
                    elements[y].rank++;
                }
            }
            num--;
        }

        int size(int x) const {
    return elements[x].size; }
        int numSets() const {
    return num; }
    };

    struct edge
    {
   
        int a;
        int b;
        double w;
    };

    bool operator<(const edge &a, const edge &b)
    {
   
        return a.w < b.w;
    }

    inline double calThreshold(int size, double scale)
    {
   
        return scale / size;
    }

    std::shared_ptr<Universe> segmentGraph(int numVertices, int numEdges, std::vector<edge> &edges, double scale)
    {
   
        std::sort(edges.begin(), edges.end());
        auto universe = std::make_shared<Universe>(numVertices);
        std::vector<double> threshold(numVertices, scale);

        for (auto &pedge : edges)
        {
   
            int a = universe->find(pedge.a);
            int b = universe->find(pedge.b);
            if (a != b)
            {
   
                if ((pedge.w <= threshold[a]) && (pedge.w <= threshold[b]))
                {
   
                    universe->join(a, b);
                    a = universe->find(a);
                    threshold[a] = pedge.w + calThreshold(universe->size(a), scale);
                }
            }
        }

        return universe;
    }

    // image segmentation using "Efficient Graph-Based Image Segmentation" // 类似并查集
    std::sha
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值