opencv 基於直方圖均衡化的圖像增強


直方圖均衡化是圖像增強處理中常見的方法之一,其基本的思想是通過均衡化處理調
整圖像灰度分布,達到改善圖像對比度的目的。由於圖像對比度是決定一幅圖像主觀質量
的重要因素,因此直方圖均衡化被廣泛應用於圖像的增強處理。

總的來說就是把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;
}

 效果圖:均衡化之前的

均衡化之后的:

圖片效果:

 

程序完整代碼:

View Code
#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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM