反向投影(Back Projection)

こ雲淡風輕ζ 提交于 2019-11-27 00:26:16

官网教程

原理

  • 反向投影表示的是一种(给定的一幅图的直方图)和(需要匹配的图的像素)匹配程度。
  • 举例:如果已知一副图像的直方图,图中有特征区域, 根据此直方图能在其他图像中检测到相似的特征区域

步骤:

  1. 先对特征图片计算它的直方图(可能是多维)
  2. 遍历匹配图像,找到每一个像素点对应特征图的直方图中的bin
  3. 将此bin中的值保存到新图像(最后的back projection)



代码

官网代码

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;


Mat hue;
int bins=25;

void Hist_and_Backprj(int,void*);

int main(void)
{
    Mat src = imread("../res/hand.jpg");
    if(src.empty())
    {
	cout << "can't load the image" << endl;
    }

    Mat hsv;
    cvtColor(src,hsv,cv::COLOR_BGR2HSV);

    hue.create(src.size(),src.depth());
    int ch[] = {0,0};
    cv::mixChannels(&hsv,1,&hue,1,ch,1);


    const char* window_image = "sourc image";
    namedWindow(window_image);
    createTrackbar("Hue bins:", window_image,&bins,180,Hist_and_Backprj);

	
    imshow(window_image,src);
    waitKey();

    return 0;
};

void Hist_and_Backprj(int,void*)
{
    int histSize = MAX(bins,2);
    float hue_range[] = {0,180};
    const float* ranges = {hue_range};

    Mat hist;
    calcHist(&hue,1,0,Mat(),hist,1,&histSize,&ranges,true,false); //对于hue计算它的直方图
    normalize(hist,hist,0,255,NORM_MINMAX,-1,Mat()); //规范化到0-255之间,因为Back Projection需要bin里面的值形成一幅图

    Mat backproj;
    cv::calcBackProject(&hue,1,0,hist,backproj,&ranges,1,true);//计算back projection
    imshow("BackProj",backproj);


//画直方图
    int w=400,h=400;
    int bin_w = cvRound((double)w/histSize);
    Mat histImg = Mat::zeros(h,w,CV_8UC3);
    
    for(int i=0; i<bins; i++)
    {
	cv::rectangle(histImg, Point(i*bin_w,h), Point( (i+1)*bin_w, h-cvRound(hist.at<float>(i)*h/255.0)), Scalar(0,0,255),FILLED);
    }
    imshow("Histogram",histImg);

}

结果:

在这里插入图片描述




OpenCV API

  1. 复制输入图像的一个通道到输出图像的一个通道
    void cv::mixChannels
    (
    const Mat * src,     // 输入图像的数组,每个图像都必须相同size和depth
    size_t nsrcs,    //输入图像的个数
    Mat * dst,       //输出图像数组,所有图像必须是已经被分配好大小、深度,和src[0]的size和depth一样
    size_t ndsts,    //输出图像的个数
    const int * fromTo,    // channel 配对的 编号 ,见下面解释
    size_t npairs     //复制的对数(1,0)意味着一对,从输入图像1channel 到输出图像的0channel
    )

下面代码是将BGRA的一副图像,转化成 3通道的RGB图和单通道的alpha图

第一行:创建bgra图像
第二行:先将输出的图像分配好
第三行:创建输出图像数组,作为参数传递
第四行:就是上面函数的fromTo参数,通道的编号是连续的,比如输出图像RGB通道编号为0,1,2;alpha图编号为3,



  1. 计算一个直方图的反向投影
    void cv::calcBackProject
    (
    const Mat * images,     //输入图像数组,有相同的szie、depth。可以有不同的channels
    int nimages,        //输入图像的个数
    const int * channels,    // 输入图像channels的数组,{[0,1],[2,3,4]}意味着两张图,图片一有2通道,图片二有3个通道
    InputArray hist,       //输入的直方图
    OutputArray backProject,    //输出的反向投影的数组,每个元素都是单通道,size和depth和image[0]一样
    const float ** ranges,    // 直方图每个维度bin的rang(参考上一个例程
    double scale = 1,    // 每个像素输出的反向投影值的scale
    bool uniform = true     // range是否是均匀分布
    )
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!