opencv----彩色圖像對比度增強


 

圖像對比度增強的方法可以分成兩類:一類是直接對比度增強方法;另一類是間接對比度增強方法。

直方圖拉伸和直方圖均衡化是兩種最常見的間接對比度增強方法。

直方圖拉伸是通過對比度拉伸對直方圖進行調整,從而“擴大”前景和背景灰度的差別,以達到增強對比度的目的,這種方法可以利用線性或非線性的方法來實現;

直方圖均衡化則通過使用累積函數對灰度值進行“調整”以實現對比度的增強。

1.直方圖拉伸

 就是擴大將圖像灰度的域值的一個過程,但是經常是基於灰度圖像進行處理,以前在MATlab上對比度增強調用直方圖函數就幾行代碼,但都是灰度圖像上處理,需要在彩色圖像進行處理,看別人的思想是從RGB-YUV-RGB的過程,在YUV空間增強再轉回來,我跟着原理寫代碼,出了很多問題。詳見http://blog.csdn.net/abcjennifer/article/details/7428737

/*
*@Function: Color image contrast enhancement
*@Date: 2012-4-5
*@Author: 張睿卿
*/

int ImageStretchByHistogram(IplImage *src1,IplImage *dst1)
/*************************************************
Function:      通過直方圖變換進行圖像增強,將圖像灰度的域值拉伸到0-255
src1:               單通道灰度圖像                  
dst1:              同樣大小的單通道灰度圖像 
*************************************************/
{
    assert(src1->width==dst1->width);
    double p[256],p1[256],num[256];

    memset(p,0,sizeof(p));
    memset(p1,0,sizeof(p1));
    memset(num,0,sizeof(num));
    int height=src1->height;
    int width=src1->width;
    long wMulh = height * width;

    //statistics
    for(int x=0;x<src1->width;x++)
    {
        for(int y=0;y<src1-> height;y++){
            uchar v=((uchar*)(src1->imageData + src1->widthStep*y))[x];
            num[v]++;
        }
    }
    //calculate probability
    for(int i=0;i<256;i++)
    {
        p[i]=num[i]/wMulh;
    }

    //p1[i]=sum(p[j]);    j<=i;
    for(int i=0;i<256;i++)
    {
        for(int k=0;k<=i;k++)
            p1[i]+=p[k];
    }

    // histogram transformation
    for(int x=0;x<src1->width;x++)
    {
        for(int y=0;y<src1-> height;y++){
            uchar v=((uchar*)(src1->imageData + src1->widthStep*y))[x];
            ((uchar*)(dst1->imageData + dst1->widthStep*y))[x]= p1[v]*255+0.5;            
        }
    }
    return 0;
}

void CCVMFCView::OnYcbcrY()
{
    IplImage* Y = cvCreateImage(cvGetSize(workImg),IPL_DEPTH_8U,1);
    IplImage* Cb= cvCreateImage(cvGetSize(workImg),IPL_DEPTH_8U,1);
    IplImage* Cr = cvCreateImage(cvGetSize(workImg),IPL_DEPTH_8U,1);
    IplImage* Compile_YCbCr= cvCreateImage(cvGetSize(workImg),IPL_DEPTH_8U,3);
    IplImage* dst1=cvCreateImage(cvGetSize(workImg),IPL_DEPTH_8U,3);

    int i;
    cvCvtColor(workImg,dst1,CV_BGR2YCrCb);
    cvSplit(dst1,Y,Cb,Cr,0);

     ImageStretchByHistogram(Y,dst1);
 
     for(int x=0;x<workImg->height;x++)
     {
         for(int y=0;y<workImg->width;y++)
         {
             CvMat* cur=cvCreateMat(3,1,CV_32F);
             cvmSet(cur,0,0,((uchar*)(dst1->imageData+x*dst1->widthStep))[y]);
             cvmSet(cur,1,0,((uchar*)(Cb->imageData+x*Cb->widthStep))[y]);
             cvmSet(cur,2,0,((uchar*)(Cr->imageData+x*Cr->widthStep))[y]);
 
             for(i=0;i<3;i++)
             {
                 double xx=cvmGet(cur,i,0);
                 ((uchar*)Compile_YCbCr->imageData+x*Compile_YCbCr->widthStep)[y*3+i]=xx;
             }
         }
     }
 
    cvCvtColor(Compile_YCbCr,workImg,CV_YCrCb2BGR);
     m_ImageType=3;
     Invalidate();
}

 其中int ImageStretchByHistogram(IplImage *src1,IplImage *dst1)  是可以運行的,實現了灰度圖像增強;

void CCVMFCView::OnYcbcrY()  我處理不好,只好呼喚睿卿 本人了。附上一個基於opencv已經實現灰度圖像增強的代碼.http://blog.csdn.net/zhaiwenjuan/article/details/6596011

#include "stdafx.h" 

#include "cv.h"
#include "highgui.h"
#include 
#include 
int ImageStretchByHistogram(IplImage *src,IplImage *dst); 

int _tmain(int argc, _TCHAR* argv[])
{
    IplImage * pImg;    
    pImg=cvLoadImage("c:/lena.jpg",-1); 

//創建一個灰度圖像
    IplImage* GrayImage = cvCreateImage(cvGetSize(pImg), IPL_DEPTH_8U, 1);
    IplImage* dstGrayImage = cvCreateImage(cvGetSize(pImg), IPL_DEPTH_8U, 1);
    cvCvtColor(pImg, GrayImage, CV_BGR2GRAY);
    ImageStretchByHistogram(GrayImage,dstGrayImage); 

  cvNamedWindow( "dstGrayImage", 1 ); //創建窗口
        cvNamedWindow( "GrayImage", 1 ); //創建窗口
        cvShowImage( "dstGrayImage", dstGrayImage ); //顯示圖像
        cvShowImage( "GrayImage", GrayImage ); //顯示圖像
        cvWaitKey(0); //等待按鍵 

  cvDestroyWindow( "dstGrayImage" );//銷毀窗口
        cvDestroyWindow( "GrayImage" );//銷毀窗口
        cvReleaseImage( &pImg ); //釋放圖像
        cvReleaseImage( &GrayImage ); //釋放圖像
        cvReleaseImage( &dstGrayImage ); //釋放圖像 

  return 0;
} 

int ImageStretchByHistogram(IplImage *src,IplImage *dst)
/*************************************************
  Function:        
  Description:     因為攝像頭圖像質量差,需要根據直方圖進行圖像增強,
                   將圖像灰度的域值拉伸到0-255
  Calls:          
  Called By:      
  Input:           單通道灰度圖像                  
  Output:          同樣大小的單通道灰度圖像 
  Return:          
  Others:           http://www.xiaozhou.net/ReadNews.asp?NewsID=771
  DATE:               2007-1-5
*************************************************/
{
    //p[]存放圖像各個灰度級的出現概率;
    //p1[]存放各個灰度級之前的概率和,用於直方圖變換;
    //num[]存放圖象各個灰度級出現的次數; 

    assert(src->width==dst->width);
    float p[256],p1[256],num[256];
    //清空三個數組
    memset(p,0,sizeof(p));
    memset(p1,0,sizeof(p1));
    memset(num,0,sizeof(num)); 

    int height=src->height;
    int width=src->width;
    long wMulh = height * width; 

    //求存放圖象各個灰度級出現的次數
    // to do use openmp
    for(int x=0;x    {
        for(int y=0;y        {
            uchar v=((uchar*)(src->imageData + src->widthStep*y))[x];
            num[v]++;
        }
    } 

    //求存放圖像各個灰度級的出現概率
    for(int i=0;i<256;i++)
    {
        p[i]=num[i]/wMulh;
    } 

    //求存放各個灰度級之前的概率和
    for(int i=0;i<256;i++)
    {
        for(int k=0;k<=i;k++)
            p1[i]+=p[k];
    } 

    //直方圖變換
    // to do use openmp
    for(int x=0;x    {
        for(int y=0;y        {
            uchar v=((uchar*)(src->imageData + src->widthStep*y))[x];
            ((uchar*)(dst->imageData + dst->widthStep*y))[x]= p1[v]*255+0.5;            
        }
    } 

    return 0; 

} 

2.既然直方圖拉伸這條路走不通,只好試試,另一條,直方圖均衡化了,還好我比較熟。

//圖像增強- 彩色直方圖均衡化
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include"opencv2/imgproc/imgproc.hpp"

using namespace std;
//彩色圖像的直方圖均衡化
IplImage* EqualizeHistColorImage(IplImage *pImage)
{
    IplImage *pEquaImage = cvCreateImage(cvGetSize(pImage), pImage->depth, 3);
    
    // 原圖像分成各通道后再均衡化,最后合並即彩色圖像的直方圖均衡化
    const int MAX_CHANNEL = 4;
    IplImage *pImageChannel[MAX_CHANNEL] = {NULL};

    int i;
    for (i = 0; i < pImage->nChannels; i++)
        pImageChannel[i] = cvCreateImage(cvGetSize(pImage), pImage->depth, 1);

    cvSplit(pImage, pImageChannel[0], pImageChannel[1], pImageChannel[2], pImageChannel[3]);
    
    for (i = 0; i < pImage->nChannels; i++)
        cvEqualizeHist(pImageChannel[i], pImageChannel[i]);

    cvMerge(pImageChannel[0], pImageChannel[1], pImageChannel[2], pImageChannel[3], pEquaImage);

    for (i = 0; i < pImage->nChannels; i++)
        cvReleaseImage(&pImageChannel[i]);

    return pEquaImage;
}
int main( int argc, char** argv )
{    
    const char *pstrWindowsSrcTitle = "原圖";
    const char *pstrWindowsHisEquaTitle = "直方圖均衡化后"// 從文件中加載原圖
    IplImage *pSrcImage = cvLoadImage("lena.jpg", CV_LOAD_IMAGE_UNCHANGED);
    IplImage *pHisEquaImage = EqualizeHistColorImage(pSrcImage);
     
    cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);
    cvNamedWindow(pstrWindowsHisEquaTitle, CV_WINDOW_AUTOSIZE);
    cvShowImage(pstrWindowsSrcTitle, pSrcImage);
    cvShowImage(pstrWindowsHisEquaTitle, pHisEquaImage);


    cvWaitKey(0);

    cvDestroyWindow(pstrWindowsSrcTitle);
    cvDestroyWindow(pstrWindowsHisEquaTitle);
    cvReleaseImage(&pSrcImage);
    cvReleaseImage(&pHisEquaImage);
    return 0;
}

 


免責聲明!

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



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