OpenCV直方图反向投影

原理:

对输入HSV图像某通道计算它的直方图,通过反向投影,把像素区间出现频率高的像素加亮也就是像素值提高,频率低的拉低。

API:

把一张图象某个通道拷贝到另一张图片上特定通道

CV_EXPORTS void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts,
                            const int* fromTo, size_t npairs);

src:原图像

nsrcs:输入图像数量

dst:输出

ndsts:输出图像数量

fromto:一个数组指针,像这样://HSV图像

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

channel表示从src的0通道也就是H,到dst的0通道(H)

npairs:channel中的序号对数(两个算1对)

2直方图反向投影

CV_EXPORTS void calcBackProject( const Mat* images, int nimages,
                                 const int* channels, InputArray hist,
                                 OutputArray backProject, const float** ranges,
                                 double scale = 1, bool uniform = true );

images     输入图像
nimages   源图像的数目
channels  用于计算反向投影的通道列表。通道数必须和直方图的通道相匹配。
hist           输入calcHist计算得到的直方图。
backProject  直方图反向投影输出
ranges         直方图bins的边界范围H就是{0,180},S是{0,255}
scale           输出反射投影的缩放因子//默认1

注意:这里!!

    const float my_range[]={0,180};
    const float *rangs=my_range;

    cout<<"my_range"<<my_range<<endl;
    cout<<"rangs"<<rangs<<endl;

    cout<<"&my_range"<<&my_range<<endl;
    cout<<"&rangs"<<&rangs<<endl;

    calcHist(&hue,1,0,Mat(),h_hist,1,&temp,&rangs,true,false);

我们知道my_range等于ranges,那么是否就说明我们可以把calclHist里面的&rangs改成&my_range??

额,结果是不能,会报错的,我发现网上有关于这个问题的说明,你也可以打印他们地址看一下。

可以看得出,make=11时候,一格方格表示也就是256/11=23.27,也就是说0~23区间内的全部加亮,因为他们占的比例最大//原图就很多空白

完整代码

#include <iostream>
#include <opencv.hpp>
#include <math.h>
using namespace cv;
using namespace std;
Mat dst;
Mat hsv,hue;
char ch[]="Window";
int bins=25;
void magic(int ,void *);
int main()
{
    Mat src=imread("E:\\opencv\\templt.jpg");
    namedWindow(ch,WINDOW_AUTOSIZE);
    cvtColor(src,hsv,CV_BGR2HSV);
    imshow("input",src);
    int channel[]={0,0};
    hue.create(hsv.size(),hsv.depth());
    mixChannels(&hsv,1,&hue,1,channel,1);


    createTrackbar("make",ch,&bins,180,magic);
    magic(0,0);

    waitKey(0);
    return 0;
}
void magic(int ,void *)
{
    Mat h_hist;

    int temp=MAX(1,bins);//
    const float my_range[]={0,180};
    const float *rangs=my_range;

    cout<<"my_range"<<my_range<<endl;
    cout<<"rangs"<<rangs<<endl;

    cout<<"&my_range"<<&my_range<<endl;
    cout<<"&rangs"<<&rangs<<endl;

    calcHist(&hue,1,0,Mat(),h_hist,1,&temp,&rangs,true,false);
    normalize(h_hist,h_hist,0,255,NORM_MINMAX);

    Mat backproj;
    calcBackProject(&hue,1,0,h_hist,backproj,&rangs,1,true);

    imshow(ch,backproj);



    int h=400;
    int w=400;
    int grap=w/temp;
    Mat histimage=Mat::zeros(w,h,CV_8UC3);
    for(int i=0;i<bins;i++)
    {
        rectangle(histimage,Point(i*grap,h),Point((i+1)*grap,h-cvRound(h_hist.at<float>(i)*h/255)),
                  Scalar(0,255,0),1,LINE_AA);//把在0~255区间内的除以255,再与400相乘,归一化到高度400的空间里面
    }
    imshow("histogram",histimage);
}

猜你喜欢

转载自blog.csdn.net/shuiyihang0981/article/details/82973257