opencv2对于读书笔记——背投影图像的直方图来检测待处理的内容

一些小的概念


1.直方图是图像内容的一个重要特性。

2.假设一幅图像的区域中显示的是一种独特的纹理或是一个独特的物体,那么这个区域的直方图能够看作是一个概率函数,它给出的是某个像素属于该纹理或物体的概率。

3.反投影直方图的作用是在于替换一个输入图像中每个像素值,使其变成归一化直方图中相应的概率值。


这是一个什么样的过程


名字听起来感觉非常高端,事实上这个一个非常easy的过程。

1.首先我们截取一个区域,作为目标区域。

2.然后将目标区域取直方图。并将其直方图归一化,并得到这个区域的概率。

3.利用calcBackProject函数在图像中检索。当中函数会利用区域概率,对图像中的像素点经行映射,映射到[0,1]区间,所以要扩大255倍显示。

4.这样一来由于是负图像,所以越暗的地方相似概率越大。


calcBackProject函数


其结构


cv::calcBackProject(&image,//目标图像
				1,            // 图像个数
				channels,     // 通道数量
				histogram,   // 进行反投影的直方图
				result,       // 结果图像
				ranges,       // 每一个维度的阈值
				255.0         // 放缩因子
				);


该过程的实例


我们举个样例来说明上面说到的过程,我两个小婴儿的图像中我们截取婴儿头部皮肤,来检測婴儿全身皮肤在图像中的位置。


代码


#include "cv.h"
#include "highgui.h"
#include "histogram.h"
#include <iostream>
using namespace std;

#include <opencv2corecore.hpp>
#include <opencv2imgprocimgproc.hpp>

class ObjectFinder {

private:

	float hranges[2];
	const float* ranges[3];
	int channels[3];

	float threshold;
	cv::MatND histogram;
	cv::SparseMat shistogram;

public:

	ObjectFinder() : threshold(0.1f){

		ranges[0]= hranges; 
		ranges[1]= hranges; 
		ranges[2]= hranges; 
	}

	// 设置阈值
	void setThreshold(float t) {

		threshold= t;
	}

	// 返回阈值
	float getThreshold() {

		return threshold;
	}

	// 设置目标直方图,进行归一化
	void setHistogram(const cv::MatND& h) {
		histogram= h;
		cv::normalize(histogram,histogram,1.0);
	}

	// 查找属于目标直方图概率的像素
	cv::Mat find(const cv::Mat& image) {

		cv::Mat result;

		hranges[0]= 0.0;	
		hranges[1]= 255.0;
		channels[0]= 0;		
		channels[1]= 1; 
		channels[2]= 2; 

		cv::calcBackProject(&image,
				1,            
				channels,     
				histogram,    
				result,       
				ranges,   
				255.0       
			);

		// 通过阈值投影获得二值图像
		if (threshold>0.0)
			cv::threshold(result, result, 255*threshold, 255, cv::THRESH_BINARY);

		return result;
	}

};

int main()
{
	//读取圆图像
	cv::Mat initimage= cv::imread("../2.jpg");
	if (!initimage.data)
		return 0; 

	//显示原图像
	cv::namedWindow("原图像");
	cv::imshow("原图像",initimage);

	//读取灰度图像
	cv::Mat image= cv::imread("../2.jpg",0);
	if (!image.data)
		return 0; 

	//设置目标区域
	cv::Mat imageROI;
	imageROI= image(cv::Rect(262,151,113,150)); // 区域为小孩的脸部区域

	//显示目标区域
	cv::namedWindow("目标区域图像");
	cv::imshow("目标区域图像",imageROI);

	//计算目标区域直方图
	Histogram1D h;
	cv::MatND hist= h.getHistogram(imageROI);
	cv::namedWindow("目标区域直方图");
	cv::imshow("目标区域直方图",h.getHistogramImage(imageROI));

	//创建检查类
	ObjectFinder finder;
	//将目标区域直方图传入检測类
	finder.setHistogram(hist);

	//初始化阈值
	finder.setThreshold(-1.0f);

	//进行反投影
	cv::Mat result1;
	result1= finder.find(image);

	//创建负图像并显示概率结果
	cv::Mat tmp;
	result1.convertTo(tmp,CV_8U,-1.0,255.0);
	cv::namedWindow("负图像概率结果图像越暗概率越大");
	cv::imshow("负图像概率结果图像越暗概率越大",tmp);

	//得到二值反投影图像
	finder.setThreshold(0.01f);
	result1= finder.find(image);

	//在图像中绘制选中区域
	cv::rectangle(image,cv::Rect(262,151,113,150),cv::Scalar(0,0,0));

	//显示原图像
	cv::namedWindow("原图像的灰度图");
	cv::imshow("原图像的灰度图",image);

	//二值结果图
	cv::namedWindow("二值结果图");
	cv::imshow("二值结果图",result1);

	cv::waitKey();
	return 0;
}

输出结果














               -END-



版权声明:本文博主原创文章。博客,未经同意不得转载。

原文地址:https://www.cnblogs.com/blfshiye/p/4801056.html