直方图均衡原理及OpenCV实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SakuraMashiro/article/details/80322121

一、概念

直方图均衡,空域图像处理中最常用的技术之一,属于灰度变换的范畴,旨在通过一个灰度变换的函数,将原图像的每个灰度级映射到一个新的灰度级,提高灰度级的动态范围,使图像的直方图(即不同灰度出现次数的概率分布图)在整个灰度级的范围内趋于均匀,从而增强图像整体的对比度。

二、映射函数

灰度变换的目的就是找到一个合适的映射函数s=T(r)
这里写图片描述
对于离散的数字图像而言,就变成了累积求和
这里写图片描述
其中L是指图像的灰度范围,对于8位的灰度图而言就是256.

三、步骤

  1. 扫描原图像的所有像素
  2. 统计每个灰度出现的次数,并除以像素的总数(归一化)。
  3. 根据上面的公式对灰度的概率进行累加求和,并乘以255(L-1),就得到了变换后的新的灰度。
  4. 根据映射表将原图像的灰度替换成新的灰度。

四、VS2015+OpenCV实现

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
    Mat src = imread("timg.jpg",0);
    if (src.empty()) {
        cout << "图像读取失败";
        return -1;
    }
    imshow("直方图均衡前的图片", src);

    int nr = src.rows;
    int nc = src.cols;
    //像素总数
    int total = nr * nc;
    //转换后的目标矩阵
    Mat dst_2(nr, nc, CV_8U);

    //获取原图像直方图
    uchar *p_1 = NULL;
    //存储直方图统计结果的数组
    unsigned int hist[256] = { 0 };
    //扫描原图像
    for (int i = 0; i < nr; i++) {
        //获取第i行像素数组首指针
        p_1 = src.ptr<uchar>(i);
        for (int j = 0; j < nc; j++) {
            hist[p_1[j]] ++;
        }
    }

    //计算灰度变换函数
    //transf_fun存储均衡前像素值与均衡后像素值的映射关系
    uchar transf_fun[256] = { 0 };
    transf_fun[0] = (uchar)(255 * hist[0] / total);
    //累积
    for (int i = 1; i < 256; i++) {
        hist[i] = hist[i - 1] + hist[i];
        transf_fun[i] = (uchar)(255 * hist[i] / total);
    }

    uchar * p_2 = NULL;
    for (int i = 0; i < nr; i++) {
        //获取第i行像素数组首指针
        p_2 = dst_2.ptr<uchar>(i);
        p_1 = src.ptr<uchar>(i);
        //根据映射关系将原图像灰度替换成直方图均衡后的灰度
        for (int j = 0; j < nc; j++) {
            p_2[j] = transf_fun[p_1[j]];
        }
    }

    imshow("直方图均衡后的图像",dst_2);

    waitKey(0);

    return 0;
}

变换前
这里写图片描述
变换后
这里写图片描述

猜你喜欢

转载自blog.csdn.net/SakuraMashiro/article/details/80322121