原理
- 反向投影表示的是一种(给定的一幅图的直方图)和(需要匹配的图的像素)匹配程度。
- 举例:如果已知一副图像的直方图,图中有特征区域, 根据此直方图能在其他图像中检测到相似的特征区域
步骤:
- 先对特征图片计算它的直方图(可能是多维)
- 遍历匹配图像,找到每一个像素点对应特征图的直方图中的bin
- 将此bin中的值保存到新图像(最后的back projection)
代码
官网代码
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat hue;
int bins=25;
void Hist_and_Backprj(int,void*);
int main(void)
{
Mat src = imread("../res/hand.jpg");
if(src.empty())
{
cout << "can't load the image" << endl;
}
Mat hsv;
cvtColor(src,hsv,cv::COLOR_BGR2HSV);
hue.create(src.size(),src.depth());
int ch[] = {0,0};
cv::mixChannels(&hsv,1,&hue,1,ch,1);
const char* window_image = "sourc image";
namedWindow(window_image);
createTrackbar("Hue bins:", window_image,&bins,180,Hist_and_Backprj);
imshow(window_image,src);
waitKey();
return 0;
};
void Hist_and_Backprj(int,void*)
{
int histSize = MAX(bins,2);
float hue_range[] = {0,180};
const float* ranges = {hue_range};
Mat hist;
calcHist(&hue,1,0,Mat(),hist,1,&histSize,&ranges,true,false); //对于hue计算它的直方图
normalize(hist,hist,0,255,NORM_MINMAX,-1,Mat()); //规范化到0-255之间,因为Back Projection需要bin里面的值形成一幅图
Mat backproj;
cv::calcBackProject(&hue,1,0,hist,backproj,&ranges,1,true);//计算back projection
imshow("BackProj",backproj);
//画直方图
int w=400,h=400;
int bin_w = cvRound((double)w/histSize);
Mat histImg = Mat::zeros(h,w,CV_8UC3);
for(int i=0; i<bins; i++)
{
cv::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),FILLED);
}
imshow("Histogram",histImg);
}
结果:
OpenCV API
- 复制输入图像的一个通道到输出图像的一个通道
void cv::mixChannels
(
const Mat * src, // 输入图像的数组,每个图像都必须相同size和depth
size_t nsrcs, //输入图像的个数
Mat * dst, //输出图像数组,所有图像必须是已经被分配好大小、深度,和src[0]的size和depth一样
size_t ndsts, //输出图像的个数
const int * fromTo, // channel 配对的 编号 ,见下面解释
size_t npairs //复制的对数(1,0)意味着一对,从输入图像1channel 到输出图像的0channel
)
下面代码是将BGRA的一副图像,转化成 3通道的RGB图和单通道的alpha图
第一行:创建bgra图像
第二行:先将输出的图像分配好
第三行:创建输出图像数组,作为参数传递
第四行:就是上面函数的fromTo参数,通道的编号是连续的,比如输出图像RGB通道编号为0,1,2;alpha图编号为3,
- 计算一个直方图的反向投影
void cv::calcBackProject
(
const Mat * images, //输入图像数组,有相同的szie、depth。可以有不同的channels
int nimages, //输入图像的个数
const int * channels, // 输入图像channels的数组,{[0,1],[2,3,4]}意味着两张图,图片一有2通道,图片二有3个通道
InputArray hist, //输入的直方图
OutputArray backProject, //输出的反向投影的数组,每个元素都是单通道,size和depth和image[0]一样
const float ** ranges, // 直方图每个维度bin的rang(参考上一个例程)
double scale = 1, // 每个像素输出的反向投影值的scale
bool uniform = true // range是否是均匀分布
)
来源:CSDN
作者:zzyczzyc
链接:https://blog.csdn.net/zzyczzyc/article/details/86648469