如果一幅图像中的区域显示的是一种结构纹理或者一个独特的物体,那么这个区域的直方图就可以作为一个概率函数,其表现形式是某个像素属于该纹理或者物体的概率。
反向投影就是一种记录给定图像中的像素点如何适应直方图模型像素分布的方法。首先计算某一直方图的模型,然后使用模型去寻找存在的该特征的方法。
反向投影的作用有:用于在输入图像中查找与特定图像(模板)最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。其结果是包含了以每个图像像素点为起点的直方图对比结果。可以是一个二维的浮点型数组,二维矩阵或者单通道浮点型图像。
反向投影示例:
#include"stdafx.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include<opencv2/photo/photo.hpp>
#include <string>
#include <vector>
#include <iostream>
using namespace cv;
using namespace std;
Mat g_srcImage, g_hsvImage, g_hueImage;
//直方图组距
int g_bins = 30;
void on_BinChange(int, void*);
int main()
{
system("color 2F");
g_srcImage = imread("E:\\pictures\\For_Project\\New_opencv\\hand.jpg",1);
if (!g_srcImage.data) {
cout << "读取图片错误,请检查是否存在该图片" << endl;
return false;
}
//转换为HSV空间图
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);
//创建滑动条
namedWindow("原始图", WINDOW_AUTOSIZE);
createTrackbar("色调组距", "原始图", &g_bins, 255, on_BinChange);
on_BinChange(0, 0);
imshow("原始图", g_srcImage);
while((char)waitKey(0)!='q'){}
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 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);
}