• 对比度限制直方图均衡化CLHE


    其实实现了半个月了,不过一直没更新,囧。

    上次讲到对比度限制的直方图均衡化,纠结了一段时间。

    不知道为什么思维总是会想到改变图像的像素值,其实CLHE的目的是获取一个不那么陡峭的转换的映射函数,所以操作只要在直方图层面完成就行了。

    确定阀值,切割直方图,将大于阀值的面积平均分到各个bins(之前就在纠结这里……),得到一个CL的直方图之后再求映射函数,并不用对原图进行操作。

    代码:

    这里的实现是多出来的面积按平局分布到各个bins,其实可以用高斯分布,效果可能会更好。

    //核心部分
    /*
    
    
                //限制对比度
            {
                
                //获取最大值
                cvGetMinMaxHistValue(histo_src,&histmin,&histmax);
                thresh*=histmax;
                cout<<thresh<<"\n";
    
                //遍历get顶部面积
                S=0;
                for(i=1;i<=255;i++)
                {
                    if(cvQueryHistValue_1D(histo_src,i)>thresh)
                        {
                            S+=(cvQueryHistValue_1D(histo_src,i)-thresh);
                            cvSetReal1D(histo_src->bins,i,thresh);
                        }
                }
                S/=255;
    
                //遍历+平均面积;
                for(i=1;i<=255;i++)
                {
                            cvSetReal1D(histo_src->bins,
                                        i,
                                        S+cvQueryHistValue_1D(histo_src,i)
                                        );
                }
                
    
            }
    
    */
    
    //程序部分---------------------------------------------------------------------------------------------
    
    //滑块调节CLHE
    #include <iostream>
    #include <string>
    #include <io.h>
    #include <opencv2/opencv.hpp>
    #include<math.h>
    #include<cv.h>
    
    using namespace std;
    using namespace cv;
    
    //全局变量2个
      int position;
      float thresh;
    
    //好吧,全部都是全局变量
      //变量定义
            //图片类
            IplImage *src , *dst;
            IplImage *histframesrc , *histframedst;
            CvSize     size;
            //直方图类
            CvHistogram *histo_src , *histo_dst;
            int scale;
            float histmin,histmax;
    
            int bins=256;
            float range[]={0,255};
            float *ranges[]={range};
            //杂家
            int i,j,k,m,n;                                //循环变量……而已 
            float s_r[256];                                //S(r)映射函数
            float  S;                                   //顶部面积
    
      void on_trackbar(int position)
     {
         thresh=float(position)/100;
         cout<<thresh<<"\t";
            
         cvCalcHist(&src,histo_src,0,0);                //计算直方图
            cvNormalizeHist(histo_src,255);                //归一
    
    
    
                //限制对比度
            {
                
                //获取最大值
                cvGetMinMaxHistValue(histo_src,&histmin,&histmax);
                thresh*=histmax;
                cout<<thresh<<"\n";
    
                //遍历get顶部面积
                S=0;
                for(i=1;i<=255;i++)
                {
                    if(cvQueryHistValue_1D(histo_src,i)>thresh)
                        {
                            S+=(cvQueryHistValue_1D(histo_src,i)-thresh);
                            cvSetReal1D(histo_src->bins,i,thresh);
                        }
                }
                S/=255;
    
                //遍历+平均面积;
                for(i=1;i<=255;i++)
                {
                            cvSetReal1D(histo_src->bins,
                                        i,
                                        S+cvQueryHistValue_1D(histo_src,i)
                                        );
                }
                
    
            }
    
            ////////////////////////////////
    
            //累加,求S(r)映射
            s_r[0]=cvQueryHistValue_1D(histo_src,0);
            for(i=1;i<=255;i++)
            {
                    s_r[i]=s_r[i-1]+cvQueryHistValue_1D(histo_src,i);    
            }
    
    
    
            //遍历图像并由sr关系进行直方图均衡化啦
            CvScalar s;
            for(m=0;m<size.height;m++)
            {
                for(n=0;n<size.width;n++)
                {
                    s=cvGet2D(src,m,n);
                    i=s.val[0];//得到像素值
                    i=s_r[i];//得到映射值
                    s.val[0]=i;//设置像素通道值
                    cvSet2D(dst,m,n,s);
                }
            }
            
            //SHOWOFF一下啦
            cvSmooth(dst,dst,CV_GAUSSIAN );
            cvShowImage("dst",dst);
            
            //计算dst直方图
            cvCalcHist(&dst,histo_dst,0,0);
            cvNormalizeHist(histo_dst,255);
            
            scale=2;
            //画出src和dst的直方图
            histframesrc=cvCreateImage( cvSize(bins*scale,256),8,1);
            histframedst=cvCreateImage( cvSize(bins*scale,256),8,1);
    
            //src的
            cvGetMinMaxHistValue(histo_src , &histmin , &histmax , 0 , 0 );
            for(int i = 0; i < bins; i++)
                {
                    
                    /** 获得直方图中的统计次数,计算显示在图像中的高度 */
                    float bin_val = cvGetReal1D(histo_src->bins,i);
                    bin_val=bin_val*255/histmax;
                    s.val[0]=cvRound(bin_val);
                    cvRectangle(histframesrc,cvPoint(i*scale,256),cvPoint((i+1)*scale,256-bin_val),s,-1,8,0);
                }
            cvShowImage("src's hisogram",histframesrc);
    
            //dst的
            cvGetMinMaxHistValue(histo_dst , &histmin , &histmax , 0 , 0 );
            for(int i = 0; i < bins; i++)
                {
                    
                    /** 获得直方图中的统计次数,计算显示在图像中的高度 */
                    float bin_val = cvGetReal1D(histo_dst->bins,i);
                    bin_val=bin_val*255/histmax;
                    s.val[0]=cvRound(bin_val);
                    cvRectangle(histframedst,cvPoint(i*scale,256),cvPoint((i+1)*scale,256-bin_val),s,-1,8,0);
                }
            cvShowImage("dst's hisogram",histframedst);
            
    
    
    
    
     }
    
    
    
    
    void main(int argc, char** argv)
    {
        
            
            
            src=cvLoadImage("11.jpg",0);                //图片变量初始化
            cvShowImage("src",src);
            size=cvGetSize(src);
            dst=cvCreateImage(size,8,1);
    
            histo_src=cvCreateHist(1,&bins,CV_HIST_ARRAY,ranges);        //直方图初始化
            histo_dst=cvCreateHist(1,&bins,CV_HIST_ARRAY,ranges);
            
            cvNamedWindow("dst");
            cvCreateTrackbar("\%","dst",&position,100,on_trackbar);//创建滑动条
            on_trackbar(position);//回调滑动条
    
            for(;;)if(cvWaitKey(0)==27)break;
            /////////////////////////////////////
    
    }


     

    实现结果:

    阀值=0.14

    阀值=0.91

    在CLHE之后对图像进行了高斯平滑,所以直方图会比较奇怪。

    对比结果可以得出CLHE之后的直方图并没有平均布满整个空间,从而达到了对比度限制的目的。

    另:

    1、关于上次的AHE,因为试用了区块加速,所以不可避免的出现了区块效应,实际中的AHE需要对每个像素周围MxN范围内外的图像求映射,并按特定比例相加,耗时慢。

    2、接下来可能会实现SIFT或者是霍夫变换,前者掌握的比较早,但是后者实现更加简单,应该会先做后者。尽量在Matlab上实现。

  • 相关阅读:
    红黑树
    二叉搜索树
    散列表
    快速排序
    堆排序
    归并排序
    插入排序
    Shell脚本之:函数
    Shell脚本之:退出循环
    ACM刷题之路(四)2018暑假实验室集训——深广搜专题题解
  • 原文地址:https://www.cnblogs.com/Ponys/p/3109496.html
Copyright © 2020-2023  润新知