1. 程式人生 > >反向投影

反向投影

反向投影用於在輸入影象中查詢與特定影象最匹配的點或者區域,也就是定位模板影象出現在輸入影象的位置。

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