首页 > 代码库 > opencv----彩色图像对比度增强

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-255src1:               单通道灰度图像                  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;}