c++实现直方图均衡化

直方图均衡化是一种用于图像增强的方法,通过调整图像的像素值分布,使得图像的对比度更好,细节更加显著。直方图均衡化的过程如下:
  1. 计算原始图像的灰度直方图,即统计图像中每个灰度级别的像素数量。
  2. 将灰度直方图归一化,将每个灰度级别出现的像素数量除以总像素数量,得到归一化后的直方图。
  3. 计算累积直方图,将归一化后的直方图进行累加操作,得到每个灰度级别对应的累积频率。
  4. 根据累积直方图调整原始图像的像素值。对于每个像素值v,将其映射到新的像素值v',计算公式为v' = (L - 1) * cumulative_hist(v),其中L为灰度级别的数量。
  5. 将调整后的像素值重新赋给原始图像的对应位置,完成图像均衡化。
直方图均衡化能够扩展图像的动态范围,使得图像中的像素值更均匀分布,从而提高图像的视觉效果和质量。
首先,我们选择一副较暗或者较量的图,对其进行直方图均衡化处理,首先我们先画一下下图的灰度直方图,可以看到图像整体亮度偏低,因此灰度级应该分布在较低的地方,没有充分利用到亮区的信息。

原图:直方图:

 

均衡化后的图像和直方图:

可以看到均衡化后的灰度分布就是在[0,255]上更加接近均匀分布,图像整体的对比度也增加。

#include<opencv2/core.hpp>
#include<opencv2/imgcodecs.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;

//@para gray:需要统计的图   Hist:用于存放统计数据
void GetHist(Mat gray,Mat &Hist)    //统计8Bit量化图像的灰度直方图
{
    const int channels[1] = { 0 }; //通道索引
    float inRanges[2] = { 0,255 };  //像素范围
    const float* ranges[1] = {inRanges};//像素灰度级范围
    const int bins[1] = { 256 };   //直方图的维度
    calcHist(&gray, 1, channels,Mat(), Hist,1, bins, ranges);
}

void ShowHist(Mat &Hist)
{
    //准备绘制直方图
    int hist_w = 512;
    int hist_h = 400;
    int width = 2;
    Mat histImage = Mat::zeros(hist_h,hist_w,CV_8UC3);   //准备histImage为全黑背景色
    for (int i = 0; i < Hist.rows; i++)
    {
        rectangle(histImage,Point(width*(i),hist_h-1),Point(width*(i+1),hist_h-cvRound(Hist.at<float>(i)/100)),
            Scalar(255,255,255),-1);
        //cout << "像素值为" << i << "的个数:" << Hist.at<float>(i) << endl;
    }
    namedWindow("histImage", WINDOW_AUTOSIZE);
    imshow("histImage", histImage);
    //waitKey(0);
}

//获得
void GetHistList(const Mat src,float *bin,int num)
{
    //遍历所有的像素值

    for (int r=0;r<src.rows;r++)
    {
        for (int c=0;c<src.cols;c++)
        {
            int index = src.at<uchar>(r,c);
            bin[index]++;         //bin为灰度级像素数的统计数组
        }
    }
    //归一化操作
    for (int i=0;i<num;i++)
    {
        bin[i]=bin[i]/src.rows/src.cols;
    }
    //累计操作
    for (int i=0;i<num;i++)
    {
        if (i == 0)
        {
            bin[i] = bin[i];
            continue;
        }
        bin[i] = bin[i] + bin[i - 1];
    }
    for (int i = 0; i < num; i++)
    {
        cout << bin[i] << endl;
    }
}

//
/*直方图均衡化操作
    参数: Mat src:原图
          float* bin:src灰度概率统计的累计和数组
          int num:bin数组的大小
          Mat &des:直方图均衡化后的图像
*/
void MyHisteq(const Mat src,float *bin,int num, Mat& des)
{
    //首先,先为des开辟src相同大小的空间
    des.create(src.rows,src.cols,CV_8UC1); 
    //针对每个像素值计算直方图均衡化的结果
    for (int r=0;r<src.rows;r++)
    {
        for (int c=0;c<src.cols;c++)
        {
            int index=src.at<uchar>(r,c);
            des.at<uchar>(r, c) = int(255 * bin[index]);
        }
    }
}
int main(int argc,char *argv)
{
    Mat src,gray,hist1;   //hist用于统计gray的直方图
    src=imread("dark.jpg");
    cvtColor(src,gray,CV_BGR2GRAY);

    GetHist(gray,hist1);//获得直方图
    ShowHist(hist1);
    namedWindow("gray");
    imshow("gray",gray);

    //获得灰度级统计矩阵
    float bin[256] = {0};
    int num = sizeof(bin) / sizeof(bin[0]);
    GetHistList(gray,bin,num);  //bin存放的是灰度值概率的累计和
    Mat my_hist,hist2;                //my_hist用于存放直方图均衡化的图像
    MyHisteq(gray, bin, num, my_hist);
    namedWindow("my_hist");
    imshow("my_hist",my_hist);
    GetHist(my_hist, hist2);
    ShowHist(hist2);
    waitKey(0);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值