opencv学习笔记(二十七)直方图反向投影

1.反向投影概念

(1)反向投影:反映直方图模型在目标图像中的分布情况,用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型。

(2)API生成步骤:

建立直方图模型

计算待测图像直方图并映射到模型中

从模型反向计算生成图像

2.实现步骤和相关API介绍

(1)实现步骤:

加载图片imread

将图像从RGB色彩空间转换到HSV色彩空间cvtColor

计算直方图和归一化calcHistnormalize

Mat与MatND其中Mat表示二维数组,MatND表示三维或者多维数据,此处均可以用Mat表示

计算反向投影图像 - calcBackProject

(2)void mixChannels(const Mat* src,size_t nsrcs,Mat* dst,size_t ndsts,const int* fromTo,size_t npairs  );

详细参考:https://blog.csdn.net/akadiao/article/details/79006929

src:输入数组或向量矩阵,所有矩阵的大小和深度必须相同

nsrcs:输入矩阵数量

dst:输出数组或矩阵向量,大小和 深度必须与src[0]相同

ndsts:输出矩阵数量

fromTo:指定被复制通道与要复制到的位置组成的索引对

npairs:fromTo中索引对的数目

(3)void cv::calcBackProject (const Mat * images, int nimages,const int * channels, InputArray hist,OutputArray backProject,const float **ranges,double scale = 1, bool uniform = true)

详细参考:https://blog.csdn.net/keith_bb/article/details/70154219#commentBox

const Mat* images:输入图像,图像深度必须位CV_8U,CV_16U或CV_32F中的一种,尺寸相同,每一幅图像都可以有任意的通道数 

int nimages:输入图像的数量 

const int* channels:用于计算反向投影的通道列表,通道数必须与直方图维度相匹配,第一个数组的通道是从0到image[0].channels()-1,第二个数组通道从图像image[0].channels()到image[0].channels()+image[1].channels()-1计数 

InputArray hist:输入的直方图,直方图的bin可以是密集(dense)或稀疏(sparse) 

OutputArray backProject:目标反向投影输出图像,是一个单通道图像,与原图像有相同的尺寸和深度 

const float ranges**:直方图中每个维度bin的取值范围 

double scale=1:可选输出反向投影的比例因子 

bool uniform=true:直方图是否均匀分布(uniform)的标识符,有默认值true

3.代码实现

#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;

Mat src, hsv,hc;
vector<Mat> bgrChannels;//存放待测试单通道图像
int bins = 12;//初始bins级数
char inputName[] = "input name";
char outputName[] = "output name";
void HistBin(int, void *);
int main()
{
	
	src = imread("D:/demo.jpg");
	if (src.empty())
	{
		cout << "找不到图像!" << endl;
		return -1;
	}
	namedWindow(inputName, CV_WINDOW_AUTOSIZE);
	namedWindow(outputName, CV_WINDOW_AUTOSIZE);
	namedWindow("BackProj", CV_WINDOW_AUTOSIZE);
	namedWindow("Histgram", CV_WINDOW_AUTOSIZE);
	imshow(inputName, src);
	split(src, bgrChannels);
	//先转为hsv图像
	cvtColor(src, hsv, CV_BGR2HSV);
	hc.create(src.size(), src.depth());
	int channels[] = { 0,0 };
	cout << channels << endl;
	mixChannels(&hsv, 1, &hc, 1, channels, 1);//mixChannels()函数用于将输入数组的指定通道复制到输出数组的指定通道

	createTrackbar("Histtogram bins", outputName, &bins, 180, HistBin);
	HistBin(0, 0);
	waitKey(0);
	return 0;
}
void HistBin(int, void *)
{
	float range[] = { 0,180 };
	const float *histRange = { range };
	Mat h_hist;
	calcHist(&hc, 1, 0, Mat(), h_hist, 1, &bins, &histRange, true, false);
	normalize(h_hist, h_hist, 0, 255, NORM_MINMAX);
	Mat backProj;
	calcBackProject(&bgrChannels[0], 1, 0, h_hist, backProj, &histRange, 1, true);
	imshow("BackProj", backProj);

	//绘制直方图
	int w = 400;
	int h = 400;
	int bin_w = cvRound((double)w / bins);
	Mat histImg = Mat::zeros(w, h, CV_8UC3);
	for (int i = 0; i < bins; i++)
	{
		rectangle(histImg, Point(i*bin_w, h), Point((i + 1)*bin_w, h - cvRound(h_hist.at<float>(i)*h / 255.0)), Scalar(255, 0, 0), 2, LINE_AA);
	}
	imshow("Histgram", histImg);
}

4.运行结果

左边为h通道生成的直方图模型,右上为原图B通道的图像(检测图像),右下为反投影结果。

发布了53 篇原创文章 · 获赞 9 · 访问量 3274

猜你喜欢

转载自blog.csdn.net/weixin_41039168/article/details/96845156