opencv直方圖均衡化算法及實現
1、為什么要直方圖均衡化
很多時候,我們的圖片看起來的效果不是那么的清晰,這時候可以對圖像進行一些處理來擴大圖像像素值顯示的范圍。例如有些圖像整體像素值偏低,圖像中的一些特征看的不是很清晰,只是隱約看到一些輪廓痕跡,這時可以經過圖像直方圖均衡化之后使得圖像看起來亮一些,也便於后續的處理。直方圖均衡化是灰度變換的一個重要應用,它高效且易於實現,廣泛應用於圖像增強處理中。圖像的像素灰度變化是隨機的,直方圖的圖形高低不齊,直方圖均衡化就是用一定的算法使直方圖大致平和的方法。
2、opencv中直方圖均衡化算法
opencv中直方圖均衡化算法的輸入圖像需為八位單通道圖像,也就是灰度圖像。若想要處計算彩色圖像的均衡化圖,可以先將圖像用split函數進行通道分離,分別處理每一個通道的圖像,在用merge函數進行合並。算法實現步驟如下:
第一步:依次掃描原始灰度圖像的每一個像素,計算出圖像的直方圖H。’
第二步:進行歸一化處理,即將0~255像素值的每一個像素值在圖像中出現的次數除以圖像的大小,得到歸一化直方圖。
第三步:計算直方圖積分,公式:
第四步:以H’作為查詢表進行圖像變換dst(x,y)=H’(src(x,y))
#include <opencv2\opencv.hpp> #include <iostream> using namespace cv; int main() { Mat srcImg,grayImg;//聲明原始圖和灰度度 srcImg = imread("1.jpg");//載入原始圖 if(!srcImg.data) { std::cout<<"請確認路徑下存在圖片"; return -1; } imshow("原始圖",srcImg);//顯示原始圖 cvtColor(srcImg,grayImg,CV_RGB2GRAY);//將rgb圖像轉化為灰度圖 int rowNumber = grayImg.rows;//得到行 int colNumber = grayImg.cols;//得到列 int sumNumber = rowNumber*colNumber;//得到圖像整個像素個數 Mat dstImg(rowNumber,colNumber,CV_8UC1,Scalar(0,0,0));//初始化直方圖均衡化后的圖 double hist[256] = {0.00};//直方圖 double dhist[256] = {0.00};//直方圖歸一化圖 double Dhist[256] = {0.00};//直方圖積分圖,每一個像素點 for(int i = 0;i<rowNumber;i++)//遍歷原始圖像,得到直方圖 { uchar* data = grayImg.ptr<uchar>(i); for(int j = 0;j<colNumber;j++) { int temp = data[j];//得到圖像像素值 hist[temp] = hist[temp]+1;//將相應像素值在直方圖中加1 } } for(int i = 0;i<256;i++)//遍歷直方圖,得到歸一化直方圖和積分圖 { dhist[i] = hist[i]/sumNumber;//得到歸一化圖 for(int j = 0;j<=i;j++) { Dhist[i] = Dhist[i] + dhist[j]; //得到積分圖 } } for(int i = 0;i<rowNumber;i++)//以積分圖為查找表得到均衡化后的圖 { uchar* data1 = dstImg.ptr<uchar>(i); uchar* data2 = grayImg.ptr<uchar>(i); for(int j = 0;j<colNumber;j++) { int temp1 = data2[j]; //查找到原始圖相應位置的像素值 int temp2 = (int)(Dhist[temp1]*255); //在積分圖中找到相應像素值的映射值 data1[j] = temp2;//將映射值賦值給目標圖像相應值 } } imshow("均衡化后的圖",dstImg); waitKey(0); return 0; }