直方图均衡化、规定化——用一句话说明

直方图均衡化本质就是找到一个映射函数T,将图像的每个灰度值映射到新的灰度值空间。
对T的要求是单调递增,映射后值域一般在[0, 255],或根据实际图像的值域确定映射后图像的值域。
实际操作中选用原图的直方图的概率密度函数累积函数作为T。

直方图规定化本质是得到直方图均衡化的图像之后,再利用目标图像的概率密度函数累积函数作为映射函数对原图均衡化后的图像进行映射。

#include <opencv2/highgui.hpp>

#include <map>

int main()
{
    const int kGrayLevel = 256;   /* 灰度阶数目,图像灰度值取值范围[0, 256-1];
                                     该值可根据实际情况灵活选用,可选用常用的灰度图范围[0,255],
                                     也可根据实际情况选择所处理图像的实际灰度值范围 */

    cv::Mat img = cv::imread("src.jpg", 0);                       // 原图
    int img_width = img.cols;
    int img_height = img.rows;

    cv::Mat img_equalization(img_height, img_width, CV_8UC1);    // 直方图均衡化后的图

    // 原图灰度值统计,计算出每个灰度阶像素个数,即直方图
    std::map<int, int> hist;
    for (int i = 0; i < kGrayLevel; ++i)
    {
        hist[i] = 0;
    }
    int min_val = INT_MAX;
    int max_val = -INT_MAX;
    for (int i = 0; i < img_height; ++i)
    {
        for (int j = 0; j < img_width; ++j)
        {
            int val = img.at<uchar>(i, j);
            hist[val]++;

            if (min_val > val)
            {
                min_val = val;
            }
            if (max_val < val)
            {
                max_val = val;
            }
        }
    }
    // 求对应概率,即直方图的概率表示,亦即输入图像的概率密度函数
    int area = img_width * img_height;
    std::map<int, float> hist_prob;
    for (auto it : hist)
    {
        hist_prob[it.first] = it.second * 1.0f / area;
    }

    std::map<int, float> sum_hist_prob;     // 直方图的概率密度函数累积函数
    for (int i = 0; i < kGrayLevel; ++i)
    {
        float sum = 0.0f;
        for (int j = 0; j <= i; ++j)
        {
            sum += hist_prob[j];
        }
        sum_hist_prob[i] = sum;
    }

    /* 使用原图的概率密度函数累积函数对原图进行映射得到直方图均衡化的图像,
        其中(max_val - min_val) + min_val也可以直接改为只乘以一般灰度图的灰度值的最大值256,需根据实际情况选择 */
    for (int i = 0; i < img_height; ++i)
    {
        for (int j = 0; j < img_width; ++j)
        {
            img_equalization.at<uchar>(i, j) =
                sum_hist_prob[img.at<uchar>(i, j)] * (max_val - min_val) + min_val;
        }
    }
    cv::imwrite("img_equalization.jpg", img_equalization);

    /************************************************************************/
    /*        该分界线以上是直方图均衡化部分,以下是直方图规定化部分               */
    /************************************************************************/
    cv::Mat img_dst = cv::imread("dst.jpg", 0);
    cv::Mat img_specification(img_height, img_width, CV_8UC1);
    // 求目标图像的灰度值统计,直方图的像素个数表示
    std::map<int, int> hist_dst;
    for (int i = 0; i < kGrayLevel; ++i)
    {
        hist_dst[i] = 0;
    }
    min_val = INT_MAX;
    max_val = -INT_MAX;
    for (int i = 0; i < img_dst.rows; ++i)
    {
        for (int j = 0; j < img_dst.cols; ++j)
        {
            int val = img_dst.at<uchar>(i, j);
            hist_dst[val]++;

            if (min_val > val)
            {
                min_val = val;
            }
            if (max_val < val)
            {
                max_val = val;
            }
        }
    }
    // 求对应直方图的概率表示亦即概率密度函数
    std::map<int, float> hist_prob_dst;
    for (auto it : hist_dst)
    {
        hist_prob_dst[it.first] = it.second * 1.0f / area;
    }

    // 求目标图像的概率密度函数累积函数
    std::map<int, float> sum_hist_prob_dst;
    for (int i = 0; i < kGrayLevel; ++i)
    {
        float sum = 0.0f;
        for (int j = 0; j <= i; ++j)
        {
            sum += hist_prob_dst[j];
        }
        sum_hist_prob_dst[i] = sum;
    }

    /* 使用目标图像的概率密度函数累积函数对原图的均衡化后的图像进行映射得到直方图规定化的图像,
       其中(max_val - min_val) + min_val也可以直接改为只乘以一般灰度图的灰度值的最大值256,需根据实际情况选择 */
    for (int i = 0; i < img_height; ++i)
    {
        for (int j = 0; j < img_width; ++j)
        {
            img_specification.at<uchar>(i, j) =
                sum_hist_prob_dst[img_equalization.at<uchar>(i, j)] * (max_val - min_val) + min_val;
        }
    }
    cv::imwrite("img_specification.jpg", img_specification);

    return 0;
}

原图:
请添加图片描述
原图直方图均衡化后的图:
请添加图片描述
目标图:
请添加图片描述
原图向目标图直方图均衡化后的图:
请添加图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值