如果一幅图像的区域中显示的是一种结构纹理或者一个独特的物体,那么这个区域的置方图可以看作一个概率函数,其表现形式是某个像素属于该纹理或物体的概率。
反向投影:是一种记录给定图像中的像素点如何适应直方图模型像素分布方式的一种方法。简单的讲,就是计算某一特征的直方图模型,然后使用模型去寻找图像中存在的该特征的方法。
使用模型直方图来检测测试图像中的区域,检测步骤:
(1)对测试图像中的每个像素(p(i, j)),获取色调数据并找到该色调 ( h i , j , s i , j ) (h_{i,j}, s_{i,j}) (hi,j,si,j)在直方图中的bin的位置。
(2)查找模型直方图对应的bin的数值。
(3)将此数值存储在新的反射投影图像中。也可以归一化直方图数值到0-255范围,这样可以直接显示反射投影图像(单通道图像)。
(4)通过对测试图像中的每个像素采用以上步骤,可以得到最终的反射投影图像。
(5)使用统计学的语言进行分析。反向投影中存储的数值代表了测试图像中该像素属于某特殊区域的概率。
用于在输入图像中查找特定图像最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。
calcBackProject()函数用来计算直方图的反向投影。
void calcBackProject( const Mat* image, int nimages, const int* channels, InputArray hist, OutputArray backPorject, const float** ranges, double scale = 1, bool uniform=true)
输入参数复制某通道到输出参数特定的通道中。
void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int * fromTo, size_t npairs)
或着
void mixChannels(const vector
示例:将一个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[0], rgba[3]->alpha[0]
int from_to[] = {0,2, 1,1, 2,0, 3,3};
mixChannels(&rgba, 1, out, 2, from_to, 4);
综合示例:反向投影
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
#define WINDOW_NAME1 "原始图"
Mat g_srcImage, g_hsvImage,g_hueImage;
int g_bins = 30; // 直方图组距
void on_BinChange(int , void*);
int main()
{
//读取原图像,并转换到HSV空间
g_srcImage = imread("../1.jpg", 1);
if(!g_srcImage.data) {
printf("获取图像路径失败!\n");
return false;
}
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);
createTrackbar("色调组距", WINDOW_NAME1, &g_bins, 180, on_BinChange);
on_BinChange(0, 0);
imshow(WINDOW_NAME1, g_srcImage);
// waitKey(0);
while (char (waitKey(0)) != 'q'){}
return 0;
}
void on_BinChange(int , void*)
{
//准备参数
Mat 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());
//计算反向投影
Mat backProject;
calcBackProject(&g_hueImage, 1, 0, hist, backProject, &ranges, 1, true);
imshow("反向投影", backProject);
//绘制直方图的参数准备
int w = 300, h = 400;
int bin_w = cvRound((double) w / histSize);
Mat histImage = Mat::zeros(w, h, CV_8UC3);
//绘制直方图
for(int i=0; i < g_bins; i++)
{
rectangle(histImage, 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("直方图窗口", histImage);
}
}