反向投影用于在输入图像中查找与特定图像最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。
1、计算反向投影的函数
void calcBackProject(const Mat *image,int nimages,const int *channels,InputArray Hist,OutputArray backProject,const float **ranges,double scale =1,bool uniform =true)
参数一:输入数组或者数组集,必须是相同深度的,通道可以任意
参数二:输入图片数或数组的个数
参数三:通道索引
参数四:输入的直方图
参数五:目标反向投影阵列
参数六:每一个维度数组的每一维边界阵列,每一维数组的取值范围
参数七:输出的反向投影可选缩放因子
参数八:直方图是否均匀标识符
2、复制通道函数
void mixChannels(const Mat *src,size_t nsrcs,Mat *dst,size_t ndsts,const int *fromTo,size_t npairs)
参数一:输入数组,所有矩阵必须有相同的尺寸和深度
参数二:参数一输入的矩阵数
参数三:输出矩阵阵列,所有数组必须初始化且磁村和深度与src[0]相同
参数四:参数三的输出矩阵数
参数五:对指定通道进行复制的数组的索引
参数六:参数五的索引数
void mixChannels(const vector<Mat>&src,vector<Mat>&dst,const int *fromTo,size_t npairs)
参数一:输入矩阵,都必须有相同的尺寸和深度
参数二:输出阵列
参数三:对指定通道进行复制的数组的索引
参数四:参数三的索引数
此函数为重排通道数提供了非常先进的机制,split() merge()函数都是调用该函数来实现通道分离和合并的。
示例:将一个rgba图像转化为rgb和alpha图像
Mat rgba(100,100,CV_8UC4,Scalar(1,2,3,4))
Mat rgb(rgba.rows,rgba.cols,CV_8UC3)
Mat alpha(rgba.rows,rgba.cols,CV_8UC1)
Mat out[] ={rgb,alpha}
//说明:rgba[0]->rgb[2] rgba[1]->rgb[1] rgba[2]->rgb[0] rgba[3]->alpha[0]
int fromTo[] ={0,2 ,1,1 ,2,0, 3,3}
mixChannels(&rgba,1,out,2,fromTo,4)
综合示例:
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#define WINDOW_NAME1 "原始图"
#define WINDOW_NAME2 "投影图"
using namespace std;
using namespace cv;
Mat g_srcImage,g_hsvImage,g_hueImage;
int g_bins = 30;
void on_binChange(int,void *);
int main(int argc,char *argv[])
{
if(argc!=2)
return -1;
g_srcImage = imread(argv[1],1);
if(g_srcImage.empty())
{
cout<<"读取图片失败,请检查该图片是否存在\n"<<endl;
return -1;
}
cvtColor(g_srcImage,g_hsvImage,COLOR_BGR2HSV);
g_hueImage.create(g_hsvImage.size(),g_hsvImage.depth());
int ch [] = {0,0};
mixChannels(&g_hsvImage,1,&g_hueImage,1,ch,1);
namedWindow(WINDOW_NAME1,WINDOW_AUTOSIZE);
createTrackbar("色调组矩",WINDOW_NAME1,&g_bins,180,on_binChange);
on_binChange(0,0);
imshow(WINDOW_NAME1,g_srcImage);
waitKey(0);
return 0;
}
void on_binChange(int,void *)
{
MatND hist;
int histSize = MAX(g_bins,2);
float hue_range[] = {0,180};
const float *ranges={hue_range};
calcHist(&g_hueImage,1,0,Mat(),hist,1,&histSize,&ranges,true,false);
normalize(hist,hist,0,255,NORM_MINMAX,-1,Mat());
MatND backProj;
calcBackProject(&g_hueImage,1,0,hist,backProj,&ranges,1,true);
imshow("反向投影图",backProj);
int w=400,h=400;
int bin_w = cvRound((double)w/histSize);
Mat histImg = Mat::zeros(w,h,CV_8UC3);
for(int i=0;i<g_bins;i++)
{
rectangle(histImg,Point(i*bin_w,h),Point((i+1)*bin_w,h-cvRound(hist.at<float>(i)*h/255.0)),Scalar(100,123,255),-1);
}
imshow("直方图",histImg);
}
来自:opencv3编程入门 毛星云pdf