赞
踩
直方图均衡是图像增强的基础算法,本质上是一种非线性拉伸,使图像的灰度级分布变得较为均匀,从而增强图像的对比度,使这些不够明显的图像细节清晰可见。掌握一种算法,必须要弄清楚它的优势和缺点,要知道它的适用场合,这样才能灵活的运用这些算法。
直方图均衡算法的优势:对于背景和前景都太亮或者太暗的图像非常有用,计算量不大,完全可以满足实时。并且是可逆操作,也就是说如果已知均衡化函数,那么就可以恢复原始的直方图。放张图片吧:
直方图均衡算法的缺点:它也有缺陷,它对数据的处理是不加选择的,也就是说,它可能会增加背景噪声的对比度并且降低有用信号的对比度。所以对于特征提取要求比较高的场合慎用,看下图:
直方图均衡的目标是要让图像的灰度级分布均匀,但是同时需要保证输出的灰度级不少于相应的输入灰度级(少了就丢失信息了),且保证输出的灰度范围与输入灰度范围相同,因此对于变换函数f(x)需要满足如下条件:
那么根据冈萨雷斯的书中介绍,在图像处理中,有一个重要的函数,能够满足上面的条件:
那么为什么经过它变换后的直方图是均匀的呢,这就涉及了概率论的知识,具体的推导可以看这篇:
https://blog.csdn.net/qianqing13579/article/details/52422364
我们注意到,图像是离散的,可以使用求和代替积分,差分代替微分,所以上述的变换函数就是:
其中h(xi)表示直方图中每个灰度级像素的个数, ww和 hh分别表示图像的宽和高。
上式就被称为直方图均衡化。
- #include <iostream>
- #include <opencv2/core.hpp>
- #include <opencv2/highgui.hpp>
- #include <opencv2/imgproc.hpp>
-
- void Histogram_equalization(cv::Mat& src, cv::Mat& dst){
- CV_Assert(src.depth() == CV_8U);
- src.copyTo(dst);
- int nr = src.rows;
- int nc = src.cols;
- int pixnum = nr*nc;
- if (src.channels() == 1){
- //统计直方图
- int gray[256] = { 0 };
- for (int i = 1; i < nr; ++i){
- const uchar* ptr = src.ptr<uchar>(i);
- for (int j = 0; j < nc; ++j){
- gray[ptr[j]]++;
- }
- }
- //计算分布函数
- int LUT[256];
- int sum = 0;
- for (int k = 0; k < 256; k++){
- sum = sum + gray[k];
- LUT[k] = 255 * sum / pixnum;
- }
- //灰度变换(赋值)
- for (int i = 1; i < nr; ++i){
- const uchar* ptr_src = src.ptr<uchar>(i);
- uchar* ptr_dst = dst.ptr<uchar>(i);
- for (int j = 0; j < nc; ++j){
- ptr_dst[j] = LUT[ptr_src[j]];
- }
- }
- }
- else{
- //统计直方图
- int B[256] = { 0 };
- int G[256] = { 0 };
- int R[256] = { 0 };
- for (int i = 0; i < nr; ++i){
- for (int j = 0; j < nc; ++j){
- B[src.at<cv::Vec3b>(i, j)[0]]++;
- G[src.at<cv::Vec3b>(i, j)[1]]++;
- R[src.at<cv::Vec3b>(i, j)[2]]++;
- }
- }
- //计算分布函数
- int LUT_B[256], LUT_G[256], LUT_R[256];
- int sum_B = 0, sum_G = 0, sum_R = 0;
- for (int k = 0; k < 256; k++){
- sum_B = sum_B + B[k];
- sum_G = sum_G + G[k];
- sum_R = sum_R + R[k];
- LUT_B[k] = 255 * sum_B / pixnum;
- LUT_G[k] = 255 * sum_G / pixnum;
- LUT_R[k] = 255 * sum_R / pixnum;
- }
- //灰度变换(赋值)
- for (int i = 0; i < nr; ++i){
- for (int j = 0; j < nc; ++j){
- dst.at<cv::Vec3b>(i, j)[0] = LUT_B[src.at<cv::Vec3b>(i, j)[0]];
- dst.at<cv::Vec3b>(i, j)[1] = LUT_G[src.at<cv::Vec3b>(i, j)[1]];
- dst.at<cv::Vec3b>(i, j)[2] = LUT_R[src.at<cv::Vec3b>(i, j)[2]];
- }
- }
- }
- }
-
- int main(){
- cv::Mat src = cv::imread("..../art.jpg");
- if (src.empty()){
- return -1;
- }
- cvtColor(src, src, CV_RGB2GRAY);
- cv::Mat dst;
-
- Histogram_equalization(src, dst);//直方图均衡
-
- cv::namedWindow("src");
- cv::imshow("src", src);
- cv::namedWindow("dst");
- cv::imshow("dst", dst);
- cv::waitKey(0);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。