• 反向投影(BackProjection)


    如果一幅图像的区域中显示的是一种结构纹理或者一个独特的物体,那么这个区域的直方图可以看作一个概率函数,他给的是某个像素属于该纹理或物体的概率。

    所谓反向投影就是首先计算某一特征的直方图模型,然后使用模型去寻找测试图像中存在的该特征。

    利用Hue直方图解释反向投影原理:

    1、获取测试图像中每个像素的hue数据 hi,j,并找到 hi,j 在hue直方图中的bin的位置。

    2、查询hue直方图中对应bin的数值。

    3、将该数值存储在新的图像中(BackProjection),也可以先归一化hue直方图数值到0-255范围,这样可以直接显示BackProjection图像(单通道图像)。

    4、通过对测试图像每个像素采取以上步骤,可以得到最终的BackProjection图像。

    代码如下:

    backprojection.h

    #ifndef BACKPROJECTION_H
    #define BACKPROJECTION_H
    
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <iostream>
    
    //全局函数/////////////////////////////////
    void hist_and_backprojection(int, void* );
    
    
    #endif // BACKPROJECTION_H

    backprojection.cpp

    #include "backprojection.h"
    
    extern cv::Mat src, hsv, hue;
    extern int bins;
    
    void hist_and_backprojection(int, void* )
    {
        cv::MatND hist;
        //直方图bin的数目大小
        int histSize = cv::max(bins, 2);
        float hue_range[] = {0, 180};
        const float *ranges = { hue_range };
    
        //计算直方图并归一化
        cv::calcHist(&hue,
                     1,              //图像数量
                     0,              //通道数
                     cv::Mat(),      //不使用掩膜
                     hist,
                     1,              //直方图维度
                     &histSize,      //每一维直方图bin的数目
                     &ranges,        //每一维直方图的范围
                     true,
                     false
                     );
        //将直方图bin的数值归一化到0-255,可方便直接显示反向投影图
        cv::normalize(hist, hist, 0, 255, cv::NORM_MINMAX, -1, cv::Mat());
    
        //计算反向投影
        cv::MatND backproj;
        cv::calcBackProject(&hue,
                            1,               //源图像的数目
                            0,               //用于计算反向投影值的通道列表
                            hist,            //输入直方图
                            backproj,        //单通道反向投影图像
                            &ranges,         //每一维直方图bin的范围
                            1,
                            true);
    
        //显示反向投影图
        cv::namedWindow("BackProjection");
        cv::imshow("BackProjection", backproj);
    
        //显示直方图
        int w = 400, h = 400;
        int bin_w = cvRound((double)w / histSize);
        cv::Mat histImg = cv::Mat::zeros( w, h, CV_8UC3 );
    
        for(int i = 0; i < bins; i++)
        {
            cv::rectangle(histImg,
                          cv::Point(i*bin_w, h),
                          cv::Point((i+1)*bin_w, h - cvRound(hist.at<float>(i) * h / 255.0) ),
                          cv::Scalar(0, 0, 255),
                          -1);
        }
        cv::namedWindow("Histogram");
        cv::imshow("Histogram", histImg);
    }

    main.cpp

    #include <QtCore/QCoreApplication>
    #include "backprojection.h"
    
    //全局变量/////////////////////////////////
    cv::Mat src, hsv, hue;
    int bins = 25;
    
    int main(int argc, char *argv[])
    {
    //    QCoreApplication a(argc, argv);
    //    return a.exec();
    
        src = cv::imread("../image/HandIndoorColor.jpg", 1);
    
        //转换到HSV
        cv::cvtColor(src, hsv, cv::COLOR_RGB2HSV);
    
        cv::namedWindow("hsvImg");
        cv::imshow("hsvImg", hsv);
    
        //分离Hue通道(即色相通道)
        hue.create(hsv.size(), hsv.depth());
        int ch[] = {0, 0};
        cv::mixChannels(&hsv, 1, &hue, 1, ch, 1);
    
        //创建Trackbar来输入bin的数目
        const char *window_image = "Source image";
        cv::namedWindow(window_image, cv::WINDOW_AUTOSIZE);
        cv::createTrackbar("* Hue bins: ",window_image, &bins, 180,
                           hist_and_backprojection                   //回调函数
                           );
        hist_and_backprojection(0, 0);
    
        cv::imshow(window_image, src);
    
        //等待用户反应
        cv::waitKey(0);
        return 0;
    }

    运行结果图:

    滑动条用于调节直方图bin的数目。

    HSV颜色空间图像:

    调节不同bin的数目对应的Hue直方图:

    调节不同bin的数目对应的反向投影(BackProjection)图像:

    当你心中只有一个目标时,全世界都会给你让路!Read more! Write more! Practise more! 新浪微博:liu_军
  • 相关阅读:
    手把手带你玩转 DialogFragment
    紧张的去京东面试7,没想到可以成功拿下offer
    这个有点强,MySQL常用优化指南及大表优化思路(值得收藏)
    Java程序员两年经验斩获头条 Offer,技术杠杠的
    为什么大家都说 SELECT * 效率低
    Java程序员想要靠外包刷题,结果却大跌眼镜,心态都崩了
    一次请求在SpringMVC核心执行流程
    工作三年经验,一年内我靠这份javaBAT进阶面试题从13K到大厂25K
    用了这么久的数据库连接池,你知道原理吗?
    poj 3295 Tautology(栈)
  • 原文地址:https://www.cnblogs.com/liu-jun/p/3482211.html
Copyright © 2020-2023  润新知