OpenCV2 直方图均衡化

直方图的均衡化

我们先来看看原图的直方图

我们发现高亮区域的像素点很少,主要像素点集中在中低亮度区域

我们先设置一个阈值,也就是图中的那根粉色的线,

当某一亮度值的像素点的个数低于这个值时,我们认为这些像素点是无关紧要的。

灰度图的亮度值范围是0-255,若亮度值为1的像素点的个数低于阈值,我们可简单的把亮度为1的像素点的亮度

全设为0,同理,我们从高往低找,若亮度值为254的像素点的个数低于阈值,我们可以把这些像素点的亮度设为255

这样我们可以从小到大,从大到小分别找到两个亮度,它们的像素点的个数恰大于阈值

他们之间的区域,我们可以认为是有效区域,也就是蓝色框出来的区域

我们把这一区域扩展到0-255的区域去,可实现均衡化效果

编程实现为

复制代码
cv::Mat Histogram::stretch1(const cv::Mat& image, int minValue) {
    cv::MatND hist = getHistogram(image);
    int imin =0;
    for (; imin < histSize[0]; imin++) {
        if (hist.at<float>(imin) > minValue) {
            break;
        }
    }
    int imax = histSize[0] -1;
    for (; imax >=0; imax--) {
        if (hist.at<float>(imax) > minValue) {
            break;
        }
    }
    cv::Mat lookup(cv::Size(1, 256), CV_8U);
    for (int i =0; i <256; i++) {
        if (i < imin) {
            lookup.at<uchar>(i) =0;
        } elseif (i > imax) {
            lookup.at<uchar>(i) =255;
        } else {
            lookup.at<uchar>(i) = static_cast<uchar>(255.0* (i - imin)
                    / (imax - imin) +0.5);}
        }
    cv::Mat result;
    cv::LUT(image, lookup, result);
    return result;
}
复制代码

对于cv::LUT函数,我之前就介绍过了

可以看出拉伸后的直方图和原直方图形状是一致的

 

再来看看另一种直方图均衡化的思路

理想的直方图均衡化效果是希望每个亮度的像素点的个数都相同

我们设原亮度为 i 的点均衡化后亮度为S(i),原亮度为 i 的点的个数为N(i)

 其占总像素点的概率为p(i) = N(i) / SUM; SUM为像素点的总和

可以得到公式

S(0) = p(0)*255

S(1) = [p(0)+p(1)]*255

S(2) = [p(0)+p(1)+p(2)]*255

........

S(255) = [p(0)+p(1)+......+p(255)]*255 = 255

我们在原图中将亮度为 i 的像素点赋值为 S(i),就可以实现均衡化了

复制代码
cv::Mat Histogram::stretch2(const cv::Mat& image) {
    cv::MatND hist = getHistogram(image);
    float scale[256];
    float lookupF[256];
    cv::Mat lookup(cv::Size(1, 256), CV_8U);
    int pixNum = image.cols * image.rows;
    for (int i =0; i <256; i++) {
        scale[i] = hist.at<float>(i) / pixNum *255;
        if (i ==0) {
            lookupF[i] = scale[i];
        } else {
            lookupF[i] = lookupF[i -1] + scale[i];
        }
    }
    for (int i =0; i <256; i++) {
        lookup.at<uchar>(i) = static_cast<uchar>(lookupF[i]);
    }
    cv::Mat result;
    cv::LUT(image, lookup, result);
    return result;
}

cv::Mat Histogram::stretch3(const cv::Mat& image) {
    cv::Mat result;
    cv::equalizeHist(image, result);
    return result;
}
复制代码

在这里,我们定义了两个函数,一个按照刚才的思路来实现

另一个是OpenCV2 提供的标准的均衡化函数

我们来看看效果

两种方法得到的效果和直方图的形状几乎一模一样

可见,标准的均衡化方法也是按此思路实现的

具体的源代码就不研究了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值