灰度直方图原理
灰度直方图的含义是一张灰度图上各个灰度值所占的频率大小,并将其以直方图的形式展现。下面给出一个例子,灰度值定义在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.灰度直方图的对比,可以寻找相似图片,为图片分类,提供一定的依据
如有不对请多多指正,一起学习,一起进步