直方圖均衡化是圖像增強處理中常見的方法之一,其基本的思想是通過均衡化處理調
整圖像灰度分布,達到改善圖像對比度的目的。由於圖像對比度是決定一幅圖像主觀質量
的重要因素,因此直方圖均衡化被廣泛應用於圖像的增強處理。
總的來說就是把src源圖像中的像素s經過T轉化后到dst圖像中r,轉化的核心是 s = Int[(L-1)*s+0.5];以下是我用opencv寫的直方圖均衡化的圖像增強
核心代碼:
/* 1、圖像增強 */ //直方圖均衡化圖像增強,這里是針對單通道灰度圖像的增強 IplImage* strengthImage_Histogram(IplImage* img) { IplImage* dst = cvCreateImage(cvSize(512,512),img->depth,img->nChannels); int width = img->width; int height = img->height; int step = img->widthStep; double his[256] = {0};//灰度 double p_hist[256]={0};//灰度比例 double s_hist[256]={0};//累計灰度比例 double total = img->width*img->height;//總像素數 for(int i = 0; i < height; i++) { for(int j = 0; j < width; j++) his[((uchar*)img->imageData+i*step)[j]]++; } //p(r) = n(k)/n; k = 0、1、2。。。; //0<= r <= 1;n為總像素數,n(k)表示灰度k的像素數 for(int i = 0; i < 256; i++) { p_hist[i] = (double)his[i]/total; if(i == 0)s_hist[i] = p_hist[i]; else s_hist[i] = s_hist[i-1]+p_hist[i]; } //圖像增強 for(int i = 0; i < img->height; i++) { for(int j = 0; j < img->width; j++) { ((uchar*)(i * dst->widthStep +dst->imageData))[j] = s_hist[((uchar*)(i * img->widthStep +img->imageData))[j]]*255+0.5; } } cvShowImage("img",img); cvShowImage("dst",dst); cvWaitKey(0); return dst; }
效果圖:均衡化之前的
均衡化之后的:
圖片效果:
程序完整代碼:

#include <cv.h> #include <highgui.h> #include <stdio.h> void drawHistogram_gyh(IplImage* img, int level); IplImage* strengthImage_Histogram(IplImage* img); /* 1、圖像增強 */ //直方圖均衡化圖像增強,這里是針對單通道灰度圖像的增強 IplImage* strengthImage_Histogram(IplImage* img) { IplImage* dst = cvCreateImage(cvSize(512,512),img->depth,img->nChannels); int width = img->width; int height = img->height; int step = img->widthStep; double his[256] = {0};//灰度 double p_hist[256]={0};//灰度比例 double s_hist[256]={0};//累計灰度比例 double total = img->width*img->height;//總像素數 for(int i = 0; i < height; i++) { for(int j = 0; j < width; j++) his[((uchar*)img->imageData+i*step)[j]]++; } //p(r) = n(k)/n; k = 0、1、2。。。; //0<= r <= 1;n為總像素數,n(k)表示灰度k的像素數 for(int i = 0; i < 256; i++) { p_hist[i] = (double)his[i]/total; if(i == 0)s_hist[i] = p_hist[i]; else s_hist[i] = s_hist[i-1]+p_hist[i]; } //圖像增強 for(int i = 0; i < img->height; i++) { for(int j = 0; j < img->width; j++) { ((uchar*)(i * dst->widthStep +dst->imageData))[j] = s_hist[((uchar*)(i * img->widthStep +img->imageData))[j]]*255+0.5; } } cvShowImage("img",img); cvShowImage("dst",dst); drawHistogram_gyh(img,256); //drawHistogram_gyh(dst,256); cvWaitKey(0); return dst; } //直方圖歸一化 void drawHistogram_gyh(IplImage* img, int level) { int width = img->width; int height = img->height; int step = img->widthStep; uchar* data = (uchar*)img->imageData; int his[256] = {0}; for(int i = 0; i < height; i++) { /* 假設有 8-bit 1-通道的圖像 I (IplImage* img): I(x,y) ~ ((uchar*)(img->imageData + img->widthStep*y))[x] */ for(int j = 0; j < width; j++) his[(data+i*step)[j]]++; } /* 設置灰度等級 */ int dep = 256/level; for(int i = 1; i < 256; i++) { int step = i/dep; his[step] += his[i]; } int max = 0; for(int i = 0; i < level; i++) { if(his[i]>max) max = his[i]; } IplImage* histogram = cvCreateImage(cvSize(400,300),8,1); cvSet(histogram,cvScalarAll(255),0); //注意這里的強制類型轉換,如果不寫會造成誤差 double bin_width = (double)histogram->width/(level*2); double bin_height = (double)histogram->height/max; for(int i = 0; i < level+level; i=i+2) { CvPoint p0 = cvPoint(i*bin_width,histogram->height); CvPoint p1 = cvPoint((i+1)*bin_width,histogram->height-his[i]*bin_height); cvRectangle(histogram,p0,p1,cvScalar(i*(dep/2)),-1,8,0); } cvShowImage("Histogram_gyh",histogram); cvWaitKey(0); cvReleaseImage(&histogram); } int main(int argc,char* argv[]) { IplImage* img = cvLoadImage("lena.jpg",0); IplImage* des = cvCreateImage(cvSize(512,512),img->depth,img->nChannels); cvResize(img,des); IplImage* dst = cvCreateImage(cvSize(512,512),img->depth,img->nChannels); strengthImage_Histogram(des); cvWaitKey(0); cvReleaseImage(&des); return 0; }