直方图均衡化-彩色图

RGB彩色图像的直方图和均衡化

对与RGB彩色图像,这里理解就是分为R、G、B三个通道,并不考虑保留图像的原有色调。每个通道的情况和灰度图像一样,都是用灰度值来衡量某个颜色的比重。对每个通道采用与上述代码相同的方法处理:(主要注意的是RGB图像在Mat中存储的顺序是BGR)

#include <cv.h>
#include <highgui.h>

using namespace cv;

// show histogram of grey image with sticks or continuous curve
void myShowHist(Mat & src, string winname, bool save = false, int style=0, int rows=400,int cols=512)
{
    int histCnt[256]={0};

    for(int y=0; y < src.rows; y++) {
        for(int x=0; x < src.cols; x++) {
            uchar grey=*(src.data+y*src.cols+x);
            (histCnt[grey])++;
        }
    }

    Mat histImage(rows,cols,CV_8UC3,Scalar(188,188,188));

    int maxcnt=histCnt[0];
    for(int i=0; i<=255; i++){
        if(histCnt[i]>maxcnt) maxcnt=histCnt[i];
    }

    int lineType = 8;
    if(style==0) { //sticks
        int thickness = 1;
        for(int i=0; i<=255; i++){
            if(histCnt[i]!=0){
                line(histImage,
                    Point((int)((float)i*(float)cols/256.0f),rows),
                    Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)histCnt[i]*(float)rows/(float)maxcnt)),
                    Scalar(255,0,0),thickness,lineType);
            }
        }
    }else{ // continuous curve
        int thickness = 2;
        int i=0;
        int start=0;
        while(histCnt[i]==0)
        {
            start=i;
            i++;
        }
        for(i=start+1; i<=255; i++) {
            int cnt=histCnt[i];
            if(cnt!=0) {
                line(histImage,
                    Point((int)((float)(start)*(float)cols/256.0f),rows-(int)((float)histCnt[start]*(float)rows/(float)maxcnt)),
                    Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)cnt*(float)rows/(float)maxcnt)),
                    Scalar(255,0,0),thickness,lineType);
                start=i;
            }
        }
    }

    namedWindow(winname);
    imshow(winname, histImage);
    if(save)    imwrite(winname+".jpg",histImage);
}

// show histogram of RGB image with continuous curve
void myShowHistRGB(Mat & src, string winname,bool save = false, int rows=400,int cols=512)
{
    // get dst histogram
    int histCnt[3][256]={0};
    for(int y=0; y < src.rows; y++) {
        for(int x=0; x < src.cols; x++) {
            for(int k=0; k<3; k++){
                uchar grey=*(src.data+y*src.cols*3+x*3+k);
                (histCnt[k][grey])++;
            }
        }
    }

    Mat hist(rows,cols,CV_8UC3,Scalar(188,188,188));

    int maxcnt=histCnt[0][0];
    for(int k=0; k<3; k++){
        for(int i=0; i<=255; i++){
            if(histCnt[k][i]>maxcnt) maxcnt=histCnt[k][i];
        }
    }
    int thickness = 2;
    int lineType = 8;
    int k;
    int i;
    int start;// find where existed gery start
    // B
    k=0;
    i=0;
    start=0;
    while(histCnt[k][i]==0)
    {
        start=i;
        i++;
    }
    for(int i=start+1; i<=255; i++) {
        int cnt=histCnt[k][i];
        if(cnt!=0) {
            line(hist,
                Point((int)((float)(start)*(float)cols/256.0f),rows-(int)((float)histCnt[k][start]*(float)rows/(float)maxcnt)),
                Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)cnt*(float)rows/(float)maxcnt)),
                Scalar(255,0,0),thickness,lineType);
            start=i;
        }
    }
    // G
    k=1;
    i=0;
    start=0;
    while(histCnt[k][i]==0)
    {
        start=i;
        i++;
    }
    for(int i=start+1; i<=255; i++) {
        int cnt=histCnt[k][i];
        if(cnt!=0) {
            line(hist,
                Point((int)((float)(start)*(float)cols/256.0f),rows-(int)((float)histCnt[k][start]*(float)rows/(float)maxcnt)),
                Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)cnt*(float)rows/(float)maxcnt)),
                Scalar(0,255,0),thickness,lineType);
            start=i;
        }
    }
    // R
    k=2;
    i=0;
    start=0;
    while(histCnt[k][i]==0)
    {
        start=i;
        i++;
    }
    for(int i=start+1; i<=255; i++) {
        int cnt=histCnt[k][i];
        if(cnt!=0) {
            line(hist,
                Point((int)((float)(start)*(float)cols/256.0f),rows-(int)((float)histCnt[k][start]*(float)rows/(float)maxcnt)),
                Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)cnt*(float)rows/(float)maxcnt)),
                Scalar(0,0,255),thickness,lineType);
            start=i;
        }
    }
    namedWindow(winname);
    imshow(winname, hist);
    if(save)    imwrite(winname+".jpg",hist);
}

int main( void)
{
    Mat src = imread("lena.jpg",1);
    if(!src.data) return -1;

    Mat dst = Mat::zeros(src.size(),src.type());
    int rows=src.rows,cols=src.cols;

    int srcHist[3][256]={0};
    int tmpCDF[3][256]={0};
    uchar mingrey[3]={255,255,255};
    // get src histogram
    for(int y=0; y < src.rows; y++) {
        for(int x=0; x < src.cols; x++) {
            for(int k=0; k<3; k++){
                uchar grey=*(src.data+y*src.cols*3+x*3+k);
                (srcHist[k][grey])++;
                if(grey<=mingrey[k]) mingrey[k]=grey;
            }
        }
    }
    // get CDF
    for( int k=0; k<3; k++) {
        tmpCDF[k][0]=srcHist[k][0];
        for(int i=1; i<=255; i++) {
            tmpCDF[k][i]=tmpCDF[k][i-1]+srcHist[k][i];
        }
    }

    // get dst
    for(int y=0; y < dst.rows; y++) {
        for(int x=0; x < dst.cols; x++) {
            for(int k=0; k<3; k++){
                uchar grey=*(src.data+y*src.cols*3+x*3+k);
                if(tmpCDF[k][grey]!=0) {
                    float tmp=255.0f/(float)(rows*cols-srcHist[k][mingrey[k]]);
                    *(dst.data+y*dst.cols*3+x*3+k) = (uchar)((float)(tmpCDF[k][grey]-srcHist[k][mingrey[k]])*tmp);
                }
            }
        }
    }


    // Show src
    namedWindow("Src");
    imshow("Src", src);
    // Show dst
    namedWindow("Dst");
    imshow("Dst", dst);

    myShowHistRGB(src,"SrcHist");
    myShowHistRGB(dst,"DstHist");


    imwrite("dst.jpg",dst);
    // Wait until user press some key
    waitKey();
    return 0;
}

结果:
原图:原图结果图:结果图
原图的彩色直方图:原直方图
结果的彩色直方图:结构直方图

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值