OpenCV3 4.5 反向投影直方图检测特定图像内容

反向投影直方图功能

  • 根据特定感兴趣区域(ImageROI)的直方图特征,计算原图中属于各直方图箱子的概率,推断原图属于感兴趣区域的部分。

反向投影直方图原理

  1. 划定感兴趣区域(ImageROI)并计算直方图,可以设定箱子数量(如8)。
  2. 对直方图进行归一化处理cv::normalize,得到属于各箱子的概率。
  3. 对于原图的每个像素,都在对应直方图的箱子中找到概率,并*255赋值给对应像素,并生成图像。
  4. 可以设定阈值概率来生成二值图。

封装的ContentFinder类

//------------------【程序说明】----------------------
//本头文件为反向映射直方图等功能封装ContentFinder类
//创建时间:2020/12/21  作者:Eric 南京航空航天大学
//----------------------------------------------------

//-------------【修改和读取参数接口】-----------------
//1.设定阈值
//2.读取阈值
//3.设置参考直方图
//4.设置参考直方图(稀疏矩阵)
//----------------------------------------------------

//-----------------【具体功能】-----------------------
//1.反向投影直方图简易版本
//2.反向投影直方图复杂版本
//----------------------------------------------------
#pragma once
#include<opencv2/opencv.hpp>

class ContentFinder 
{
private:
	//直方图参数
	float hranges[2];			//值范围(三个维度用一个值)
	const float* ranges[3];		//值范围的指针,用于指向值范围
	int channels[3];			//要计算的通道

	float threshold;            //判断阈值
	cv::Mat histogram;          //输入直方图
	cv::SparseMat shistogram;   //输入稀疏矩阵类直方图
	bool isSparse;				//判定是否为稀疏矩阵

public:
	//默认构造
	ContentFinder()
	{
		threshold = 0.1f;
		isSparse = false;
		hranges[0] = 0.0;		//默认范围从0(含)
		hranges[1] = 256.0;		//到256(不含)
		ranges[0] = hranges;	//值范围指针指向值范围
		ranges[1] = hranges;	//三个通道范围都相等
		ranges[2] = hranges;
		channels[0] = 0;		//通道B
		channels[1] = 1;		//通道G	
		channels[2] = 2;		//通道R
	}

	//设定阈值
	void setThreshold(float t) 
	{
		threshold = t;
	}

	//读取阈值
	float getThreshold() 
	{
		return threshold;
	}

	//设置参考直方图
	void setHistogram(const cv::Mat& h) 
	{
		isSparse = false;
		cv::normalize(h, histogram, 1.0);
	}

	//设置参考直方图(稀疏矩阵)
	void setHistogram(const cv::SparseMat& h) 
	{
		isSparse = true;
		cv::normalize(h, shistogram, 1.0, cv::NORM_L2);
	}

	//反向投影直方图简易版本
	//使用全部通道,范围为[0,256)
	cv::Mat find(const cv::Mat& image) 
	{
		cv::Mat result;

		hranges[0] = 0.0;	//默认范围从0(含)
		hranges[1] = 256.0; //到256(不含)

		//调用反向投影直方图复杂版本
		return find(image, hranges[0], hranges[1]);
	}

	//反向投影直方图复杂版本
	//使用全部通道,可设定范围
	cv::Mat find(const cv::Mat& image, float minValue, float maxValue) 
	{
		cv::Mat result;

		hranges[0] = minValue;
		hranges[1] = maxValue;

		//如果不是稀疏矩阵
		if (!isSparse) 
		{ 
			//调用反向投影直方图
			cv::calcBackProject
			(	&image,		  //源图像地址
				1,            //一幅图像
				channels,     //通道(地址)
				histogram,    //使用的直方图
				result,       //反向投影的结果矩阵
				ranges,       //像素范围(双地址)
				255.0         //缩放因子的选择使得直方图值1映射到255
			);
		}
		else 
		{
			//调用稀疏矩阵反向投影直方图
			cv::calcBackProject
			(	&image,		  //源图像地址
				1,            //一幅图像
				channels,     //通道(地址)
				shistogram,   //使用的直方图
				result,       //反向投影的结果矩阵
				ranges,       //像素范围(双地址)
				255.0         //缩放因子的选择使得直方图值1映射到255
			);
		}

		//阈值反投影得到二值图像
		if (threshold > 0.0)
			cv::threshold(result, result, 255.0 * threshold, 255.0, cv::THRESH_BINARY);

		return result;
	}
};

补充:cv::calcBackProject函数的使用

函数签名

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

参数分别是:源图像地址,一幅图像,通道地址,输入直方图,输出图像,范围双指针,换算系数(这里由于归一化了要设为255),每个箱子均匀(1)。

实际演示(需要4.2的ColorHistogram类)

void reverseSkyProjection()
{
	cv::Mat prairie = cv::imread("prairie.jpg");
	ColorHistogram hc;
	//提取天空区域
	cv::Mat ImageROI = prairie(cv::Rect(0, 0, 500, 200));
	cv::imshow("sky", ImageROI);
	hc.setSize(8);
	//得到天空区域直方图
	cv::Mat shist = hc.getHistogram(ImageROI);

	//创建反向映射直方图类
	ContentFinder finder;
	finder.setHistogram(shist);
	//阈值概率设为0.05
	finder.setThreshold(0.05);
	cv::Mat result = finder.find(prairie);
	cv::imshow("prairie", prairie);
	cv::imshow("projected sky", result);
}

void reverseCloudProjection()
{
	cv::Mat prairie = cv::imread("prairie.jpg");
	ColorHistogram hc;
	//提取云朵区域
	cv::Mat ImageROI = prairie(cv::Rect(50, 50, 100, 100));
	cv::imshow("cloud", ImageROI);
	hc.setSize(8);
	//得到云朵区域直方图
	cv::Mat shist = hc.getHistogram(ImageROI);

	//创建反向映射直方图类
	ContentFinder finder;
	finder.setHistogram(shist);
	//阈值概率设为0.05
	finder.setThreshold(0.05);
	cv::Mat result = finder.find(prairie);
	cv::imshow("prairie", prairie);
	cv::imshow("projected cloud", result);
}

效果

提取天空
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
提取云朵
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值