OpenCV均值平移查找目标

OpenCV均值平移查找目标,直方图反向投影的结果是一个概率分布图,表示一个指定图像片段出现在特定位置的概率。如果我们已经知道图像中某个物体的大致位置,就可以用概率分布图找到物体的准确位置。窗口中概率最大的位置就是物体最可能出现的位置。因此,我们可以从一个初始位置开始,在周围反复移动以提高局部匹配概率,也许就能找到物体的准确位置。这个实现方法称为均值平移算法。

如何实现

假设我们已经识别出一个感兴趣的物体(例如狒狒的脸),如下图所示:
OpenCV均值平移查找目标

这次采用HSV色彩空间的色调通道来描述物体。这意味着需要把图像转换成HSV色彩空间并提取色调通道,然后计算指定ROI的一维色调直方图。参见以下代码:

        // 读取参考图像
        cv::Mat image= cv::imread("baboon01.jpg");
        // 狒狒脸部的ROI
        cv::Rect rect(110, 45, 35, 45);
        cv::Mat imageROI= image(rect);
        // 得到狒狒脸部的直方图
        int minSat=65;
        ColorHistogram hc;
        cv::Mat colorhist= hc.getHueHistogram(imageROI, minSat);

我们在ColorHistogram类中增加了一个简便的方法来获得色调直方图,代码如下所示:

        // 计算一维色调直方图
        // BGR的原图转换成HSV
        // 忽略低饱和度的像素
        cv::Mat getHueHistogram(const cv::Mat &image, int minSaturation=0) {

            cv::Mat hist;

            // 转换成HSV色彩空间
            cv::Mat hsv;
            cv::cvtColor(image, hsv, CV_BGR2HSV);

            // 掩码(可能用到,也可能用不到)
            cv::Mat mask;
            // 根据需要创建掩码
            if (minSaturation>0) {

              // 将3 个通道分割进3 幅图像
              std::vector<cv::Mat> v;
              cv::split(hsv, v);

              // 屏蔽低饱和度的像素
              cv::threshold(v[1], mask, minSaturation,
                            255, cv::THRESH_BINARY);
            }

            // 准备一维色调直方图的参数
            hranges[0]= 0.0;     // 范围为0~180
            hranges[1]= 180.0;
            channels[0]= 0;      // 色调通道

            // 计算直方图
            cv::calcHist(&hsv, 1,   // 只有一幅图像的直方图
                          channels, // 用到的通道
                          mask,      // 二值掩码
                          hist,      // 生成的直方图
                          1,          // 这是一维直方图
                          histSize, // 箱子数量
                          ranges     // 像素值范围
            );

            return hist;
          }

然后把得到的直方图传给ContentFinder类的实例,代码如下所示:

ContentFinder finder;
finder.setHistogram(colorhist);

现在打开第二幅图像,我们想在它上面定位狒狒的脸部。首先,需要把这幅图像转换成HSV色彩空间,然后对第一幅图像的直方图做反向投影,参见下面的代码:

        image= cv::imread("baboon3.jpg");
        // 转换成HSV色彩空间
        cv::cvtColor(image, hsv, CV_BGR2HSV);
        // 得到色调直方图的反向投影
        int ch[1]={0};
        finder.setThreshold(-1.0f); // 不做阈值化
        cv::Mat result= finder.find(hsv,0.0f,180.0f, ch);

rect对象是一个初始矩形区域(即初始图像中狒狒脸部的位置),现在OpenCV的cv::meanShift算法将会把它修改成狒狒脸部的新位置,代码如下所示:

        // 窗口初始位置
        cv::Rect rect(110,260,35,40);

        // 用均值偏移法搜索物体
        cv::TermCriteria criteria(
                    cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS,
                    10, // 最多迭代10 次
                    1); // 或者重心移动距离小于1 个像素
        cv::meanShift(result, rect, criteria);

脸部的初始位置(红色框)和新位置(绿色框)显示如下。
OpenCV均值平移查找目标

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!