所谓反向投影就是首先计算某一特征的直方图模型,然后使用模型去寻找测试图像中存在的该特征。
利用Hue直方图解释反向投影原理:
1、获取测试图像中每个像素的hue数据 hi,j,并找到 hi,j 在hue直方图中的bin的位置。
2、查询hue直方图中对应bin的数值。
3、将该数值存储在新的图像中(BackProjection),也可以先归一化hue直方图数值到0-255范围,这样可以直接显示BackProjection图像(单通道图像)。
4、通过对测试图像每个像素采取以上步骤,可以得到最终的BackProjection图像。
代码如下:
backprojection.h
#ifndef BACKPROJECTION_H
#define BACKPROJECTION_H
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
//全局函数/
void hist_and_backprojection(int, void* );
#endif // BACKPROJECTION_H
backprojection.cpp
#include "backprojection.h"
extern cv::Mat src, hsv, hue;
extern int bins;
void hist_and_backprojection(int, void* )
{
cv::MatND hist;
//直方图bin的数目大小
int histSize = cv::max(bins, 2);
float hue_range[] = {0, 180};
const float *ranges = { hue_range };
//计算直方图并归一化
cv::calcHist(&hue,
1, //图像数量
0, //通道数
cv::Mat(), //不使用掩膜
hist,
1, //直方图维度
&histSize, //每一维直方图bin的数目
&ranges, //每一维直方图的范围
true,
false
);
//将直方图bin的数值归一化到0-255,可方便直接显示反向投影图
cv::normalize(hist, hist, 0, 255, cv::NORM_MINMAX, -1, cv::Mat());
//计算反向投影
cv::MatND backproj;
cv::calcBackProject(&hue,
1, //源图像的数目
0, //用于计算反向投影值的通道列表
hist, //输入直方图
backproj, //单通道反向投影图像
&ranges, //每一维直方图bin的范围
1,
true);
//显示反向投影图
cv::namedWindow("BackProjection");
cv::imshow("BackProjection", backproj);
//显示直方图
int w = 400, h = 400;
int bin_w = cvRound((double)w / histSize);
cv::Mat histImg = cv::Mat::zeros( w, h, CV_8UC3 );
for(int i = 0; i < bins; i++)
{
cv::rectangle(histImg,
cv::Point(i*bin_w, h),
cv::Point((i+1)*bin_w, h - cvRound(hist.at<float>(i) * h / 255.0) ),
cv::Scalar(0, 0, 255),
-1);
}
cv::namedWindow("Histogram");
cv::imshow("Histogram", histImg);
}
main.cpp
#include <QtCore/QCoreApplication>
#include "backprojection.h"
//全局变量/
cv::Mat src, hsv, hue;
int bins = 25;
int main(int argc, char *argv[])
{
// QCoreApplication a(argc, argv);
// return a.exec();
src = cv::imread("../image/HandIndoorColor.jpg", 1);
//转换到HSV
cv::cvtColor(src, hsv, cv::COLOR_RGB2HSV);
cv::namedWindow("hsvImg");
cv::imshow("hsvImg", hsv);
//分离Hue通道(即色相通道)
hue.create(hsv.size(), hsv.depth());
int ch[] = {0, 0};
cv::mixChannels(&hsv, 1, &hue, 1, ch, 1);
//创建Trackbar来输入bin的数目
const char *window_image = "Source image";
cv::namedWindow(window_image, cv::WINDOW_AUTOSIZE);
cv::createTrackbar("* Hue bins: ",window_image, &bins, 180,
hist_and_backprojection //回调函数
);
hist_and_backprojection(0, 0);
cv::imshow(window_image, src);
//等待用户反应
cv::waitKey(0);
return 0;
}
运行结果图:
滑动条用于调节直方图bin的数目。
HSV颜色空间图像:
调节不同bin的数目对应的Hue直方图:
调节不同bin的数目对应的反向投影(BackProjection)图像: