25 OpenCV直方图反向投影calcBackProject

本文详细介绍了OpenCV中的反向投影原理,通过HSV色彩空间的HS直方图模型来搜索目标对象。讲解了calcBackProject函数的使用,包括参数设置和实现步骤,以及如何从RGB图像转换到HSV空间并计算直方图,最后利用直方图模型生成反向投影图像。
摘要由CSDN通过智能技术生成

一、反向投影

  • 反向投影是反映直方图模型在目标图像中的分布情况,简单点说就是用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型
    • 建立直方图模型
    • 计算待测图像直方图并映射到模型中
    • 从模型反向计算生成图像
      在这里插入图片描述

二、calcBackProject

void cv::calcBackProject    (   const Mat *     images,
        int     nimages,
        const int *     channels,
        InputArray      hist,
        OutputArray     backProject,
        const float **      ranges,
        double      scale = 1,
        bool    uniform = true 
    )
  • 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

三、实现步骤

  • 加载图片imread
  • 将图像从RGB色彩空间转换到HSV色彩空间cvtColor
  • 计算直方图和归一化calcHist与normalize
  • 计算反向投影图像 - calcBackProject
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

// 申明图像矩阵,初始化bin数目:
Mat src, hsv, hue;
int bins = 25;

void Hist_and_Backproj(int, void*);

int main(int argc, char** argv)
{
	// 1. 读取输入图像并转换到HSV 空间
	src = imread("images/17.png");
	cvtColor(src, hsv, CV_BGR2HSV);
	// 2. 使用Hue通道来创建1维直方图:
	// 分离 Hue 通道。 色调在HSV颜色空间定义取值为0°到360°,实际在OpenCV中取值为0-180
	hue.create(hsv.size(), hsv.depth());// 这里要传深度,传type会报错
	int nchannels[] = { 0, 0 };
	/*  // 将输入数组的指定通道复制到输出数组的指定通道
		mixChannels(
			const Mat* src, //输入数组或向量矩阵,所有矩阵的大小和深度必须相同。
			size_t nsrcs, //矩阵的数量
			Mat* dst, //输出数组或矩阵向量,大小和深度必须与src相同
			size_t ndsts,//矩阵的数量
			const int* fromTo,//指定被复制通道与要复制到的位置组成的索引对
			size_t npairs //fromTo中索引对的数目
		);
	*/
	mixChannels(&hsv, 1, &hue, 1, nchannels, 1);
	imshow("hue", hue);


	// 3. 创建 Trackbar 来输入bin的数目
	const char* window_image = "Source image";
	namedWindow(window_image, CV_WINDOW_AUTOSIZE);
	createTrackbar("* Hue  bins: ", window_image, &bins, 180, Hist_and_Backproj);
	Hist_and_Backproj(0, 0);

	// 现实图像
	imshow(window_image, src);

	// 等待用户反应
	waitKey(0);
	return 0;
}

void Hist_and_Backproj(int, void*)
{
	MatND hist;
	int histSize = MAX(bins, 2);
	float hue_range[] = { 0, 180 };
	const float* ranges = { hue_range };

	// 计算直方图并归一化到范围[0,255]
	calcHist(&hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false);
	normalize(hist, hist, 0, 255, NORM_MINMAX, -1, Mat());

	// 调用函数 calcBackProject 计算同一张图像的反向投影:
	MatND backproj;
	/*
		calcBackProject ( // 反向投影
			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
		)
	*/
	calcBackProject(&hue, 1, 0, hist, backproj, &ranges, 1, true);

	// 显示反向投影
	imshow("BackProj", backproj);

	// 绘制直方图
	int w = 400; int h = 400;
	int bin_w = cvRound((double)w / histSize);
	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(hist.at<float>(i)*h / 255.0)),
			Scalar(0, 0, 255), -1); //-1表示填充矩形
	}

	imshow("Histogram", histImg);
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值