zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    移动端开发-禁止横屏
    奇葩的对象创建方式(更新中)
    每日积累之8.8
    每日积累 8.6
    折半查找
    linux中的amount的解释
    Redis集群错误
    每日积累 8.6
    Redis中在程序中的应用
    每日积累 8.4
  • 原文地址:https://www.cnblogs.com/Anita9002/p/3889487.html
Copyright © 2011-2022 走看看