1. 程式人生 > >OpenCV直方圖反向投影

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);
}