视觉图像:基于直方图均衡化的图像增强

2025-11-03 18:48:50

1、直方图均衡化算法的步骤:

①统计原始图像各灰度级的像素数目nk,k=0,1,…,L-1;

②计算原始图像的直方图,即各灰度级的概率密度pr(rk)=nk/n;

③计算各灰度级的累积概率分布:

④计算最后的输出灰度级:

其中,Int[*]代表取整运算符;

⑤利用rk和sk的映射关系,修改原图的灰度级,获得增强图像,使得图像直方图为近似均匀分布。

故,实质是把src原图像中像素s经过T变换转化后到dst源图像中r;

视觉图像:基于直方图均衡化的图像增强

2、OpenCV中直方图均衡化函数:

彩色图像的直方图均衡化实现:

#include <opencv2/highgui/highgui.hpp>     

#include <opencv2/imgproc/imgproc.hpp> 

#include <iostream> 

using namespace cv; 

int main(int argc, char *argv[]) 

    Mat image = imread("Test.jpg", 1); 

    imshow("原图像", image); 

    Mat imageRGB[3]; 

    split(image, imageRGB); 

    for (int i = 0; i < 3; i++) 

    { 

        equalizeHist(imageRGB[i], imageRGB[i]); 

    } 

    merge(imageRGB, 3, image); 

    imshow("直方图均衡化图像增强效果", image); 

    waitKey(); 

    return 0; 

}  

视觉图像:基于直方图均衡化的图像增强

视觉图像:基于直方图均衡化的图像增强

3、opencv编写直方图均衡化程序:

Mat ImageHistogramEqualize(Mat img)

{

       int wid = img.cols;

       int heig = img.rows;

      

       double hist[256] = {0};//灰度

       double p_hist[256] = {0};//灰度比例

       double sum_hist[256] = {0};//累积灰度比例

       double pixel_total = img.rows*img.cols;//总像素数

       for (int i = 0;i < heig;i++)//hang

       {

              unsigned char *u_data = (unsigned char *)img.data + i*img.cols;

              for (int j=0;j<wid;j++)//lie

              {

                     hist[ u_data[j] ]++;//1.统计各灰度等级的像素数量

              }

       }

 

       //p(r) = n(k)/n; k = 0、1、2...;

       //0<= r <= 1;n为总像素数,n(k)表示灰度k的像素数

       for (int i=0;i<256;i++)

       {

              p_hist[i] = (double)(hist[i]/pixel_total);//2.各灰度级的概率密度

              if (i==0)

                     sum_hist[i] = p_hist[i];

              else

                     sum_hist[i] = sum_hist[i-1]+p_hist[i];//3.计算各灰度级的累积概率分布

       }

 

       Mat dst_img=Mat::zeros(img.rows,img.cols,CV_8UC1);

       for (int i=0;i<heig;i++)//hang

       {

              unsigned char *dst_data = (unsigned char *)dst_img.data +i*dst_img.cols;

              unsigned char *src_data = (unsigned char *)img.data +i*img.cols;

              for (int j=0;j<wid;j++)//lie

              {

                     dst_data[j] = (sum_hist[ src_data[j] ]*255+0.5);//4.增强图像

              }

       }

       imshow("src_img",img);

       imshow("dst_img",dst_img);

       return dst_img;

}

视觉图像:基于直方图均衡化的图像增强

视觉图像:基于直方图均衡化的图像增强

4、直方图绘制:

步骤:

首先,统计各灰度等级数量;

其次,初始化绘制直方图大小,高400,宽256;

最后,将各灰度等级数量值缩放到图像内;

//

//绘制直方图

//

void DrawHistogram(Mat img)

{

       int hist_size = 256;

       int width = hist_size;//绘制直方图的宽度==hist_size 

       int height = 400;//定义绘制直方图的高度 

       int hist[256]={0};

       for (int i = 0;i < img.rows;i++)//hang

       {

              unsigned char *u_data = (unsigned char *)img.data + i*img.cols;

              for (int j=0;j<img.cols;j++)//lie

              {

                     hist[ u_data[j] ]++;//1.统计各灰度等级的像素数量

              }

       }

       int max_val =0;

       for(int i=0;i<256;i++)

       {

              if (hist[i]>max_val)

              {

                     max_val = hist[i];//最大灰度等级数量

              }

       }

      

       Mat hist_img = Mat::zeros(height,width, CV_8UC3);

       for (int i = 0; i < width; i++)//lie 

       {

              float bin_value = (float)hist[i];

              float real_value = (bin_value / max_val)*height; 

              //cout << "i: " << i << " ,binValue: " << bin_value << endl;

              //cout << "i: " << i << " ,realValue: " << real_value << endl; 

      

              line(hist_img, Point(i, height - 1), Point(i, height - 1 - real_value), Scalar(255,0,0), 1); 

       }  

       imshow("dstHist", hist_img);

}

视觉图像:基于直方图均衡化的图像增强

视觉图像:基于直方图均衡化的图像增强

5、OpenCV中calcHist()函数:

功能:计算图像直方图;

格式:

void calcHist(const Mat* arrays,

int narrays,

const int* channels,

InputArray mask,

OutputArray hist,

int dims,

const int* histSize,

const float** ranges,

bool uniform=true,

bool accumulate=false );

 参数:

arrays:输入的图像的指针,可以是多幅图像,所有的图像必须有同样的深度(CV_8U or CV_32F)。同时一副图像可以有多个channes。

narrays:输入的图像的个数。

channels:用来计算直方图的channes的数组,比如输入是2副图像,第一副图像有0,1,2共三个channel,第二幅图像只有0一个channel,那么输入就一共有4个channes,如果int channels[3] = {3, 2, 0},那么就表示是使用第二副图像的第一个通道和第一副图像的第2和第0个通道来计算直方图。

mask:掩码,如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和arrays[i]的大小相同,值为1的点将用来计算直方图。

hist:计算出来的直方图

dims:计算出来的直方图的维数。

histSize:在每一维上直方图的个数。简单把直方图看作一个一个的竖条的话,就是每一维上竖条的个数。

ranges:用来进行统计的范围。比如 float rang1[] = {0, 20}; float rang2[] = {30, 40};  const float *rangs[] = {rang1, rang2};那么就是对0,20和30,40范围的值进行统计。

uniform:每一个竖条的宽度是否相等。

accumulate:  是否累加。如果为true,在下次计算的时候不会首先清空hist。

6、opencv计算直方图程序:

int img_Hist() 

       //1.灰度直方图均衡化 

       Mat src_img = imread("raw.jpg",0);

       Mat dst_img; 

       equalizeHist(src_img,dst_img); 

       imshow("src_img",src_img); 

       imshow("dst_img",dst_img);

      

       //2.计算直方图 

       int nimages = 1;//图像的个数 

       int channels = 0;//需要统计通道的索引 

       Mat mask = Mat(); 

       Mat hist_src;//存放srcImg输出的直方图 

       Mat hist_dst;//存放dstImg输出的直方图 

       int dims = 1;//计算的直方图的维度 

       int hist_size = 256;//计算的直方图的分组数 

       float range[] = { 0, 256 };//表示直方图每一维度的取值范围[0,256) 

       const float* ranges[] = { range };//参数形式需要,表示每一维度数值的取值范围 

       calcHist(&src_img, nimages, &channels, mask, hist_src, dims, &hist_size, ranges);//计算srcImg直方图 

       calcHist(&dst_img, nimages, &channels, mask, hist_dst, dims, &hist_size, ranges);//计算dstImg直方图 

      

       //3绘制srcImg的直方图 

       double min_value = 0; 

       double max_value = 0; 

       minMaxLoc(hist_src, &min_value, &max_value);//得到计算出的直方图中的最小值和最大值 

       int width = hist_size;//定义绘制直方图的宽度,令其等于histSize 

       int height = 400;//定义绘制直方图的高度 

       Mat show_src = Mat::zeros(Size(width, height), CV_8UC3);//宽为histSize,高为height 

       for (int i = 0; i < hist_size; i++)//遍历histImg 

       { 

              float bin_value = hist_src.at<float>(i);//得到histImg中每一分组的值 

              cout << "i: " << i << " ,binValue: " << bin_value << endl; 

              float real_value = (bin_value / max_value)*height;//归一化数据,缩放到图像的height之内 

              cout << "i: " << i << " ,realValue: " << real_value << endl; 

              //用直线方法绘制直方图,注意两端点坐标的计算 

              line(show_src, Point(i, height - 1), Point(i, height - 1 - real_value), Scalar(255, 0, 0), 1); 

       } 

       imshow("srcHist", show_src); 

       imwrite("srcHist.bmp",show_src);

      

       //4绘制dstImg的直方图 

       double minValue_dst = 0; 

       double maxValue_dst = 0; 

       minMaxLoc(hist_dst, &minValue_dst, &maxValue_dst);//得到计算出的直方图中的最小值和最大值 

       Mat Show_dst = Mat::zeros(Size(width, height), CV_8UC3);//宽为histSize,高为height 

       for (int i = 0; i < hist_size; i++)//遍历histImg 

       {  

              float bin_value = hist_dst.at<float>(i);//得到histImg中每一分组的值 

              cout << "i: " << i << " ,binValue: " << bin_value << endl; 

              float real_value = (bin_value / maxValue_dst)*height;//归一化数据,缩放到图像的height之内 

              cout << "i: " << i << " ,realValue: " << real_value << endl; 

              //用直线方法绘制直方图,注意两端点坐标的计算 

              line(Show_dst, Point(i, height - 1), Point(i, height - 1 - real_value), Scalar(255, 0, 0), 1); 

       } 

      

       imshow("dstHist", Show_dst); 

       imwrite("dstHist.bmp",Show_dst);

       return 0; 

}  

视觉图像:基于直方图均衡化的图像增强

视觉图像:基于直方图均衡化的图像增强

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢