OpenCV学习笔记(四)用直方图统计像素

1、用直方图统计像素
 

#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<iostream>
using namespace cv;

class Histogram1D
{
private:
	int histSize[1];						//直方图项目数
	float hranges[2];					//值范围
	const float* ranges[1];				//这是指向常量的指针,值范围的指针
	int channels[1];
public:
	Histogram1D()
	{
		histSize[0] = 256;
		hranges[0] = 0.0;
		hranges[1] = 256.0;
		ranges[0] = hranges;
		channels[0] = 0;
	}
	Mat getHistogrm(const Mat& image)	//计算函数
	{
		Mat hist;
		//比较特殊,这个函数的参数有好多指针
		calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
		return hist;					//这个返回值是一个一维数组,但以Mat形式存储
	}
	//这个函数按照hist数组和zoom直方图高度放大倍数来生成直方图
	static Mat getImageOfHistogram(Mat& hist, int zoom)
	{
		/*一共有255个灰度,每一个灰度都对应有不同数量的像素数,
		这两个最大值与最小值是指这255个像素数中的最大值与最小值
		hist数组当中就存储着这255个值*/ 
		double maxVal = 0.0;
		double minVal = 0.0;
		minMaxLoc(hist, &minVal, &maxVal, 0, 0);//获取一维数组hist中的最大值和最小值
		int histSize = hist.rows;				//求灰度数组的长度
		//生成一个图像,尺寸按照:灰度的个数(255)*直方图高度放大倍数
		Mat histImg(histSize*zoom, histSize*zoom, CV_8U, Scalar(0));//背景白色
		int hpt = static_cast<int>(0.9*histSize);//确定直方图的高度,是实际灰度数的90%,防止触顶

		for (int h = 0; h < histSize; h++)	 //注意,原点在左上角
		{
			float binVal = hist.at<float>(h);//获取每个灰度对应的像素数
			if (binVal > 0)					 //如果该该灰度对应的像素数不为零,就需要划线
			{
				/*intensity是每个灰度值对应的直方图高度,计算方式为:
				求这个数量占最大值的百分比,然后映射到高度上,emmm,有点归一化的味道*/
				int intensity = static_cast<int>(binVal/ maxVal*hpt);
				/*这里需要注意,背景是黑色的,绘制的线是白色的,而且直线起点在图像框的顶部
				相当于从黑色背景中腐蚀掉一部分从而得到白底黑线的直方图*/
				line(histImg, Point(h*zoom, 0), 
					Point(h*zoom, (histSize - intensity)*zoom), Scalar(255), zoom);
			}
		}
		return histImg;
	}
	Mat getHistogramImage(const Mat& image, int zoom = 2)
	{
		Mat hist = getHistogrm(image);
		return getImageOfHistogram(hist, zoom);
	}
};

int main(void)
{
	Mat image = imread("1.jpg", 0);
	Histogram1D h;
	Mat histo = h.getHistogrm(image);
	for (int i = 0; i < 256; i++)
	{
		std::cout << "Value" << i << "=" << histo.at<float>(i) << std::endl;
	}
	getchar();
	imshow("Hisrtogram", h.getHistogramImage(image));
	waitKey(0);
}

2、利用查找表修改图像外观
实际是原像素到新像素的一个映射,利用的关系式为:newIntensity = lookup[oldIntensity],过程再不写了,昨天写了以后忘了保存了,很自闭。
这种扩展可以提高图片质量

3、直方图均衡化
就是让图像直方图变得更平缓,可以提高图像的质量。

4、反向投影直方图检测特定图像内容

5、用均值平移算法查找目标
当我们已识别出一个感兴趣的物体,利用这个过程可以在新的图像中识别出这个物体。本节使用的是HSV色彩空间。注意低饱和度下色调信息会不稳定。均值偏移算法是一个迭代过程。

6、比较直方图搜索相似图像
这属于基于内容的图像检索

7、用积分图像统计像素
所谓积分图像就是取图像左上方的全部像素计算累加和,并用这个累加和替换图像中的每一个像素,所以图像的像素值会呈现出左上角的值最小,右下角的值最大的现象,然后需要计算某个区域的像素之和时,就可以进行几次加减法求出像素值之和。

自适应阈值化会用到积分图像,由于自适应阈值化时需要不断计算像素周围的像素值和,会有很大的运算量,当使用积分图像时,计算周围像素之和就会变简单,四次加减运算就可以实现,

8、总结
直方图表示物体外观的全局特征。另外使用积分图像也可以实现5中的内容,5使用的是均值平移算法。
 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值