灰度直方图及均衡化的实现
程序员文章站
2024-03-16 12:02:58
...
一、灰度直方图,就是对图像像素灰度值的统计,对于灰度图像,只有一个通道,其灰度范围为0-255,因此只需要将图像转成灰度图像,然后对不同灰度值进行像素个数统计,画出其直方图。下面借助Opencv,但为了让初学者更好的理解这个概念,直方图的代码按照自己的理解写一遍,这样也能锻炼自己的编程能力。
代码如下:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat image=imread("test.png",1);
if(image.empty())
{
cout<<"failed to read the image"<<endl;
return 0;
}
imshow("image",image);
Mat grayImage;
cvtColor(image,grayImage,CV_BGR2GRAY);
//遍历图像所有像素的灰度值
int grayVal;
vector<int> vectGrayVal;
for (int i=0;i<image.rows;i++)
{
for (int j=0;j<image.cols;j++)
{
grayVal=grayImage.at<uchar>(i,j);
vectGrayVal.push_back(grayVal);
}
}
//统计各个灰度值的像素个数
int count=0;
vector<int> vectCount;
for (int k=0;k<256;k++)
{
for (int i=0;i<vectGrayVal.size();i++)
{
if (vectGrayVal[i] == k)
{
count++;
}
}
vectCount.push_back(count);
count=0;
}
//画出直方图
int maxCount=0;
for (int k=0;k<255;k++)
{
if (maxCount<vectCount[k])
{
maxCount=vectCount[k];
}
}
namedWindow("hist",WINDOW_NORMAL);
Mat hist(maxCount,256,CV_8U,Scalar(255));
for (int k=0;k<256;k++)
{
line(hist,Point(k,maxCount),Point(k,maxCount-vectCount[k]),Scalar(0));
}
imshow("hist",hist);
waitKey(0);
return 1;
}
效果很直观,但效率很差。
二、对灰度图实行均衡化,可以使图像对比度增强。直方图均衡化增强了靠近直方图极大值附近的亮度的对比度,减小了极小值附近的对比度。直方图均衡化的数学原理可以去看《图像处理、分析与机器视觉》中的第5章,讲的很清楚,而且也有算法原理,下面贴算法原理的图:
根据上述原理,其代码如下:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
void equalizeHist(Mat& image, Mat& result)
{
if (image.channels() !=1)
{
cvtColor(image, image, CV_BGR2GRAY);
imshow("gray", image);
}
vector<int> vectGrayVal;
int grayVal;
int Row = image.rows;
int Col = image.cols;
for (int i = 0; i < Row;i++)
{
for (int j = 0; j < Col;j++)
{
grayVal = image.at<uchar>(i, j);
vectGrayVal.push_back(grayVal);
}
}
int count = 0;
vector<int> vectCount;
for (int k = 0; k < 256;k++)
{
for (int i = 0; i < vectGrayVal.size(); i++)
{
if (vectGrayVal[i]==k)
{
count++;
}
}
vectCount.push_back(count);
count = 0;
}
result = Mat(Row, Col, CV_8UC1);
//均衡化
for (int k = 0; k < 256;k++)
{
if (k!=0)
{
vectCount[k] = vectCount[k - 1] + vectCount[k];
}
}
for (int k = 0; k < 256; k++)
{
vectCount[k] = vectCount[k]*255 / (Row*Col);
}
for (int i = 0; i < Row; i++)
{
for (int j = 0; j < Col; j++)
{
result.at<uchar>(i, j) = vectCount[image.at<uchar>(i, j)];
}
}
}
void main()
{
Mat image = imread("test.png", 1);
imshow("image", image);
Mat result;
equalizeHist(image, result);
imwrite("2.png",result);
cvtColor(result, result, CV_GRAY2BGR);
imshow("result", result);
waitKey(0);
return;
}
下图为处理后的图片的灰度直方图,可以看出其灰度分布并没有集中在某一区域。