一、灰度直方图,就是对图像像素灰度值的统计,对于灰度图像,只有一个通道,其灰度范围为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; }下图为处理后的图片的灰度直方图,可以看出其灰度分布并没有集中在某一区域。