一、反向投影
反向投影是反映直方图模型在目标图像中的分布情况,简单点说就是用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型
建立直方图模型 计算待测图像直方图并映射到模型中 从模型反向计算生成图像
二、calcBackProject
void cv:: calcBackProject ( const Mat * images,
int nimages,
const int * channels,
InputArray hist,
OutputArray backProject,
const float * * ranges,
double scale = 1 ,
bool uniform = true
)
const Mat* images:输入图像,图像深度必须位CV_8U,CV_16U或CV_32F中的一种,尺寸相同,每一幅图像都可以有任意的通道数 int nimages:输入图像的数量const int* channels:用于计算反向投影的通道列表,通道数必须与直方图维度相匹配,第一个数组的通道是从0到image[0].channels()-1,第二个数组通道从图像image[0].channels()到image[0].channels()+image[1].channels()-1计数 InputArray hist:输入的直方图,直方图的bin可以是密集(dense)或稀疏(sparse) OutputArray backProject:目标反向投影输出图像,是一个单通道图像,与原图像有相同的尺寸和深度 const float ranges**:直方图中每个维度bin的取值范围 double scale=1:可选输出反向投影的比例因子 bool uniform=true:直方图是否均匀分布(uniform)的标识符,有默认值true
三、实现步骤
加载图片imread 将图像从RGB色彩空间转换到HSV色彩空间cvtColor 计算直方图和归一化calcHist与normalize 计算反向投影图像 - calcBackProject
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat src, hsv, hue;
int bins = 25 ;
void Hist_and_Backproj ( int , void * ) ;
int main ( int argc, char * * argv)
{
src = imread ( "images/17.png" ) ;
cvtColor ( src, hsv, CV_BGR2HSV) ;
hue. create ( hsv. size ( ) , hsv. depth ( ) ) ;
int nchannels[ ] = { 0 , 0 } ;
mixChannels ( & hsv, 1 , & hue, 1 , nchannels, 1 ) ;
imshow ( "hue" , hue) ;
const char * window_image = "Source image" ;
namedWindow ( window_image, CV_WINDOW_AUTOSIZE) ;
createTrackbar ( "* Hue bins: " , window_image, & bins, 180 , Hist_and_Backproj) ;
Hist_and_Backproj ( 0 , 0 ) ;
imshow ( window_image, src) ;
waitKey ( 0 ) ;
return 0 ;
}
void Hist_and_Backproj ( int , void * )
{
MatND hist;
int histSize = MAX ( bins, 2 ) ;
float hue_range[ ] = { 0 , 180 } ;
const float * ranges = { hue_range } ;
calcHist ( & hue, 1 , 0 , Mat ( ) , hist, 1 , & histSize, & ranges, true , false ) ;
normalize ( hist, hist, 0 , 255 , NORM_MINMAX, - 1 , Mat ( ) ) ;
MatND backproj;
calcBackProject ( & hue, 1 , 0 , hist, backproj, & ranges, 1 , true ) ;
imshow ( "BackProj" , backproj) ;
int w = 400 ; int h = 400 ;
int bin_w = cvRound ( ( double ) w / histSize) ;
Mat histImg = Mat:: zeros ( w, h, CV_8UC3) ;
for ( int i = 0 ; i < bins; i++ ) {
rectangle ( histImg, Point ( i* bin_w, h) ,
Point ( ( i + 1 ) * bin_w, h - cvRound ( hist. at< float > ( i) * h / 255.0 ) ) ,
Scalar ( 0 , 0 , 255 ) , - 1 ) ;
}
imshow ( "Histogram" , histImg) ;
}