欢迎浏览本博客
大家好,我是:我菜就爱学一名刚刚入行OpenCV的小白
从事方向:计算机视觉
我菜就爱学,分享有误,欢迎大佬指出
本篇介绍:直方图反向投影
反向投影就是一种记录给定图像中的像素点适应直方图模型像素分布方式的一种方法。也就是计算某一特征的直方图模型,然后使用模型去寻找图像中存在的该特征的方法
反向投影用于输入图像中查找与特定图像最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。
反向投影的结果包含了以输入图像像素点为起点的直方图对比结果。可以看作一个二维的浮点型数组、二维矩阵,或者单通道的浮点型图像。
void calcBackProject(const Mat * images,int nimages,const int* channels,InputArray hist,OutputArray backProject,const float** ranges,double scale=1,bool uniform=true)
说明:此函数由输入参数复制某通道到输出参数特定的通道中。该函数是为重排图像通道提供比较先进的机制。之前接触的split()和merge()以及cvtColor()都是mixChannels()函数一部分
void mixChannels(const Mat * src,size_t nsrcs,Mat * dst,size_t ndsts,const int * fromTo,size_t npairs)
第一个参数:输入的数组(hsv),所有的矩阵必须有相同的尺寸和深度
第二个参数:第一个参数src输入的矩阵数
第三个参数:输出数组(hue),所有矩阵必须初始化,大小和深度必须与src[0]相同
hue.create(hsv.szie(),hsv.depth())
第四个参数:第三个参数dst的输出矩阵数
第五个参数:对指定的通道进行复制的数组索引
第六个参数:第五个参数fromTo的索引数
示例说明:将一个4通道的RGBA图像转化为3通道BGR和一个单独的Alpha通道图像
Mat rgba(100,100,CV_8UC4,Scalar(1,2,3,4));
Mat bgr(rgba.rows,rgba.cols,CV_8UC3);
Mat alpha(rgba.rows,rgba.cols,CV_8UC1);
//组成矩阵数组来进行操作
Mat out[]={bgr,alpha};
//将rgba[0]->bgr[2]
//将rgba[1]->bgr[1]
//将rgba[2]->bgr[1]
//将rgba[3]->alpha[0]
int fromTo[]={0,2,1,1,2,0,3,3};
mixChannels(&rgba,1,out,2,fromTo,4);
#include
#include
using namespace std;
using namespace cv;
#define WINDOW_NAME1 "【原始图】"
#define WINDOW_NAME2 "【反射投影图】"
Mat g_srcImage; Mat g_hsvImage; Mat g_hueImage;
int g_bins = 30;//直方图组距
void on_BinChange(int, void *);
int main()
{
g_srcImage = imread("E:\\Pec\\手.jpg", 1);
cvtColor(g_srcImage, g_hsvImage, COLOR_BGR2HSV);
//分离Hue色调通道
g_hueImage.create(g_hsvImage.size(), g_hsvImage.depth());
int ch[] = { 0,0 };
mixChannels(&g_hsvImage, 1, &g_hueImage, 1, ch, 1);
//创建Trackbar来输入bin数目
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
createTrackbar("色调组距:", WINDOW_NAME2, &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;//Mat表示二维数组,MatND表示三维或者以上
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());
//计算反射投影
Mat backproj;
calcBackProject(&g_hueImage, 1, 0, hist, backproj, &ranges, 1, true);
imshow(WINDOW_NAME2, backproj);
//绘制直方图
int hist_w = 400, hist_h = 400;
//cvRound:对double类型的数四舍五入并返回一个整型
int bin_w = cvRound((double)hist_w / histSize);
Mat histImage = Mat::zeros(hist_w, hist_h, CV_8UC3);
for (int i = 0; i < g_bins; i++)
{
//pt1 -- 矩形的一个顶点。pt2 -- 矩形对角线上的另一个顶点
rectangle(histImage, Point(i*bin_w, hist_h),
Point((i + 1)*bin_w, hist_h - cvRound(hist.at<float>(i)*hist_h / 255.0)),
Scalar(100, 123, 255),-1);
}
imshow("直方图", histImage);
}
(1)原图展示
(2)组距bin为 6 的反向投影