OpenCV直方圖反向投影
阿新 • • 發佈:2018-11-05
原理:
對輸入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
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);
}