OpenCV实现灰度直方图,阈值分割。数字图像处理

  • Post author:
  • Post category:其他




灰度直方图原理

灰度直方图的含义是一张灰度图上各个灰度值所占的频率大小,并将其以直方图的形式展现。下面给出一个例子,灰度值定义在0-7之间的数值。

在这里插入图片描述

假设各个像素点的灰度值如上图所示,则可以统计出各个灰度值所占的频率如下:

在这里插入图片描述

根据各个灰度占的频率可以将其以直方图的形式绘制如下:

在这里插入图片描述

可以很直观的观察到各个灰度值所占的比率。而灰度直方图在灰度图像处理方面有比较多的应用。例如

1.可以为阈值分割提供一定的依据。

2.灰度直方图均值化提高灰度图像的对比度

3.反向投影直方图检测特定图像的内容

4.均值平移算法可以检测目标的移动

5.灰度直方图的对比,可以寻找相似图片,为图片分类,提供一定的依据

在此我们首先介绍灰度直方图的获取,以及阈值分割处理结果



灰度直方图实现

本文依赖的库为开源OpenCV4.0,以下为C++实现代码,代码中有注释,主要通过创建一个类实现整个过程

#pragma once
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
using namespace cv;
int menu();
class Histogram1D {
private:
	int histSize[1];//定义灰度直方图中类型的数目
	float hrange[2];//定义灰度直方图值的范围
	const float * ranges[1];//定义一个指针数组
	int channels[1];//定义检查的通道数
public:
	Histogram1D() {
		histSize[0] = 256;
		hrange[0] = 0;
		hrange[1] = 256;
		ranges[0] = hrange;
		channels[0] = 0;
	}
	//获取灰度直方图各个类型的频率
	Mat getHistogram(const Mat &image) {
		Mat hist;
		calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);
		return hist;
	}
	//画图函数
	static Mat getImageOfHistogram(const Mat &hist, int zoom)
	{
		double maxval = 0.0;
		double minval = 0.0;
		minMaxLoc(hist, &minval, &maxval, 0, 0);
		int histSize = hist.rows;
		Mat histImg(histSize*zoom, histSize*zoom, CV_8U, Scalar(255));
		int hpt = static_cast<int>(0.9*histSize);
		for (int h = 0;h < histSize;h++)
		{
			float binVal = hist.at<float>(h);
			if (binVal > 0)
			{
				int intensity = (int)(binVal*hpt / maxval);
				line(histImg, Point(h*zoom, histSize*zoom), Point(h*zoom, (histSize - intensity)*zoom), Scalar(0), zoom);
			}
		}
		return histImg;
	}
	Mat getHistogramImage(const Mat &image, int zoom = 1)
	{
		Mat hist = getHistogram(image);
		return getImageOfHistogram(hist, zoom);
	}
};
int menu()
{
	Mat image1 = imread("01.jpg", -1);
	imshow("nomal", image1);
	Mat image = imread("01.jpg", 0);
	imshow("gray", image);
	Histogram1D h;
	Mat hist = h.getHistogram(image);


	//将二值图与图的形式展现
	Mat img = h.getHistogramImage(image);

	//寻找占比例最大的灰度
	int index = 0;
	float flag = hist.at<float>(0);
	for (int i = 0;i < 256;i++)
	{	
		if (hist.at<float>(i)>flag)
		{
			flag = hist.at<float>(i);
			index = i;
		}
		//cout << "value" << i << "=" << hist.at<float>(i) << endl;
	}
	cout << "the max value of the Histgram is:" << index << endl;

	namedWindow("Histgram", WINDOW_AUTOSIZE);
	imshow("Histgram", img);

	Mat thresh;
	threshold(image, thresh, index, 255, THRESH_BINARY);
	namedWindow("thresh", WINDOW_AUTOSIZE);
	imshow("thresh", thresh);

	waitKey(0);
	//cout << "hello world" << endl;
	return 0;
}
int main()
{
	menu();
	system("pause");
	return 0;
}

以下为实现效果:

在这里插入图片描述
这是根据直方图的分布而选的阈值做的阈值分割结果,可以看到该阈值能够较好的分割图像,图像的边缘基本能够找到,这为下一步图像的边缘提取,图像的形态学处理打下了基础。

下面是图像灰度直方图:

在这里插入图片描述

灰度值频率最高的大小为

在这里插入图片描述

如此便基本完成了灰度直方图的提取和分析。后面将会持续给出灰度直方图的其他方面应用。



小结

灰度直方图在灰度图像处理方面有比较多的应用。例如

1.可以为阈值分割提供一定的依据。

2.灰度直方图均值化提高灰度图像的对比度

3.反向投影直方图检测特定图像的内容

4.均值平移算法可以检测目标的移动

5.灰度直方图的对比,可以寻找相似图片,为图片分类,提供一定的依据

如有不对请多多指正,一起学习,一起进步



版权声明:本文为AlonewaitingNew原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。