Opencv学习笔记(十)直方图反向投影calcBackProject()

原理:

一般地,我们把图像的灰度图分成若干个等级区间,计算图像像素的灰度值所在各个区间对应的像素值,就能够得到我们的图像直方图。

而图像直方图的反向投影矩阵正是根据这些像素值所构成的矩阵。

具体可参考:反向投影矩阵计算方法

加入我们得到的反向投影矩阵如下:

back_Projection=

4    4    4    4

4    6    6    6

2    2    4    4

4    6    6    6

反向投影矩阵中某点的值就是它对应的原图像中的点所在区间的灰度直方图值,所以不难看出,位于某区间的像素越多,其反映在图像中就越亮。

Alt

工作过程:

假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
(1)从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像;
(2)生成临时图像的直方图;
(3)用临时图像的直方图和模板图像的直方图对比,对比结果记为c;
(4)直方图对比结果c,就是结果图像(0,0)处的像素值;
(5)切割输入图像从(0,1)至(10,11)的临时图像,对比直方图,并记录到结果图像;
(6)重复(1)~(5)步直到输入图像的右下角。

相关API:calcBackProjection()函数

void calcBackProject(
const Mat* images ,

int nimages ,

const int* channels ,

InputArray hist ,

OutputArray backProject ,

const float ranges**

double scale=1:

bool uniform=true
)

参数介绍

1、输入图像,图像深度必须位CV_8U,CV_16U或CV_32F中的一种,尺寸相同,每一幅图像都可以有任意的通道数
2、 输入图像的数量
3、 用于计算反向投影的通道列表,通道数必须与直方图维度相匹配,第一个数组的通道是从0到image[0].channels()-1
4、输入的直方图,直方图的bin可以是密集(dense)或稀疏(sparse)
5、目标反向投影输出图像,是一个单通道图像,与原图像有相同的尺寸和深度
6、直方图中每个维度bin的取值范围
7、可选输出反向投影的比例因子
8、直方图是否均匀分布(uniform)的标识符,有默认值true

使用步骤:

1、转化成HSV图像,提取其中的h通道;

2、使用calcHist()函数计算直方图,并采用normalize进行归一化处理。

3,、反向投影calcBackProject()

代码演示:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace std;
using namespace cv;

Mat src; Mat hsv; Mat hue; 
int bins = 12;
void Hist_And_Backprojection(int, void*);
int main(int argc, char** argv)
 {
 src = imread("D:/vcprojects/images/t1.jpg");
 if (src.empty())
  {
  printf("could not load image...\n");
  return -1;
 }
 const char*  window_image = "input image";
 namedWindow(window_image, CV_WINDOW_NORMAL);
 namedWindow("BackProj", CV_WINDOW_NORMAL);
 namedWindow("Histogram", CV_WINDOW_NORMAL);

cvtColor(src, hsv, CV_BGR2HSV);
 hue.create(hsv.size(), hsv.depth());
 int nchannels[] = { 0, 0 };
 mixChannels(&hsv, 1, &hue, 1, nchannels, 1);
createTrackbar("Histogram Bins:", window_image, &bins, 180, Hist_And_Backprojection);
 Hist_And_Backprojection(0, 0);

imshow(window_image, src);
 waitKey(0);
 return 0;
}

void Hist_And_Backprojection(int, void*)
 {
 float range[] = { 0, 180 };
 const float *histRanges = { range };
 Mat h_hist;
 calcHist(&hue, 1, 0, Mat(), h_hist, 1, &bins, &histRanges, true, false);
 normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat());

Mat backPrjImage;
 calcBackProject(&hue, 1, 0, h_hist, backPrjImage, &histRanges, 1, true);
 imshow("BackProj", backPrjImage);

int hist_h = 400;
 int hist_w = 400;
 Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
 int bin_w = (hist_w / bins);
 for (int i = 1; i < bins; i++) 
 {
  rectangle(histImage, 
   Point((i - 1)*bin_w, (hist_h - cvRound(h_hist.at<float>(i - 1) * (400 / 255)))),
   //Point(i*bin_w, (hist_h - cvRound(h_hist.at<float>(i) * (400 / 255)))),
   Point(i*bin_w, hist_h),
   Scalar(0, 0, 255), -1);
 }
 imshow("Histogram", histImage);
 return;
}

希望对读者有所帮助,喜欢的话可以关注一下我的公众号,我会把学习笔记发在上面,大家可以一起共同学习!

在这里插入图片描述
Alt

发布了12 篇原创文章 · 获赞 9 · 访问量 3628

猜你喜欢

转载自blog.csdn.net/Rosen_er/article/details/104212684