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