opencv 的norm_OpenCV——直方图

一、直方图概述

在统计学中,直方图是一种对数据分布情况的图形表示,是一种二维统计图表,他的两个坐标分别是统计样本(图像、视频帧)和样本的某种属性(亮度,像素值,梯度,方向,色彩等等任何特征)。

也可以这么理解,直方图是对数据的统计,并把统计值显示到事先设定好的bin(矩形条)中,bin中的数值是从数据中计算出的特征的统计量。总之,直方图获取的是数据分布的统计图,通常直方图的维数要低于原始数据。

图像直方图是用一表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。可以借助观察该直方图了解需要如何调整亮度分布的直方图。这种直方图中,横坐标的左侧为纯黑、较暗的区域,而右侧为较亮、纯白的区域。因此,一张较暗图片的图像直方图中的数据多集中于左侧和中间部分,而整体明亮、只有少量阴影的图像则相反。计算机视觉邻域常借助图像直方图来实现图像的二值化。

灰度直方图是一幅图像中个像素灰度值出现次数或频数的统计结果,它只反映该图像中灰度值出现的频率,而未反映某一灰度值像素所在的位置。也就是说,它只包含了该图像中某个灰度值的像素出现的概率,而丢失了其所在的位置的信息。任一幅图像,都能唯一地算出一幅与它对应的直方图。但不同的图像,可能有相同的直方图。即图像与直方图之间是多对一的映射关系。

直方图意义:

1.直方图是图像中像素强度分布的图形表达方式。

2.直方图统计了每一个强度值所具有的像素个数。

直方图术语:

dims:需要统计的特征的数目。例如:dims=1,表示我们仅统计灰度值。

bins:每个特征空间子区段的数目。

range:每个特征空间的取值范围。

二、直方图均衡化

直方图均衡化是通过拉伸像素强度的分布范围,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。

函数原型:

aaeaf1bc720321d76990d385cd9e5027.png

参数:

src:源图像,需为8位单通道图像

dst:输出图像,尺寸、类型和源图像一致

该函数采用如下步骤对输入图像进行直方图均衡化:

4909d3460985910979538d53bc0f62ad.png

效果:

964c1c0355b90eb38814fdc72a274206.png

#define HIST_SIZE 256//计算直方图数据的函数static Mat cal_histogram(const Mat& src){
      int hist[HIST_SIZE] = {
    0};  //遍历图像,对直方图对应的格子累加计算  for (int i = 0; i < src.rows; i++)  {
        for (int j = 0; j < src.cols; j++)    {
          int idx = src.ptr(i)[j];      if (idx < HIST_SIZE)      {
            hist[idx]++;      }    }  }  //把直方图数据从数组转换成只有一列的矩阵  Mat histMat(HIST_SIZE, 1, CV_32FC1);  for (int i = 0; i < HIST_SIZE; i++)  {
        histMat.ptr<float>(i)[0] = hist[i];  }  return histMat;}//定义函数把直方图以图像形式显示static void show_histogram(const Mat& src, String winName){
      //先调用计算直方图的函数得到直方图数据,并归一化到0-255  Mat hist = cal_histogram(src);  normalize(hist, hist, 0, 255, NORM_MINMAX, CV_8UC1);  //定义用于显示的图像  Mat hist2 = Mat(300, 256, CV_8UC1, Scalar(0));  //遍历直方图,一个格子的数据画一条竖线  for (int i = 0; i < HIST_SIZE; i++)  {
        //从左到右,高度相反画图线    line(hist2, Point(i, 299), Point(i, 299 - hist.at(i)), Scalar(255), 1, LINE_AA);  }  imshow(winName, hist2);}

均衡化前后强度对比:

e9c0cd65fb09073c272a8812d966c882.png

均衡化前,像素强度分布相对集中,均衡化后,分布相对散开一点,对比度就改善了。

如果图像是彩色图像,则先分离通道,分别做均衡化,再合并通道。

vectorchannels;split(src, channels);Mat blue, green, red;blue = channels.at(0);green = channels.at(1);red = channels.at(2);equalizeHist(blue, blue);equalizeHist(green, green);equalizeHist(red, red);merge(channels, dst);

效果:

ba6728c33689261d7e82ee165b55058a.png

具体实现:

static Mat histogram_equalize(Mat& src){
      //第一步,计算直方图数据  Mat hist = cal_histogram(src);  //第二步,计算累积直方图,同时进行第三步,把累积直方图的数据归一化到0-255  int hist_accumulate[HIST_SIZE];  int sum = 0;  int total_number_pixels = src.cols * src.rows;  for (int i = 0; i < HIST_SIZE; i++)  {
        sum += (int)hist.ptr<float>(i)[0];    hist_accumulate[i] = saturate_cast(sum * 255 / total_number_pixels);  }  //第四步,遍历原图像,以原图像的像素值为索引,从第三步的归一化后的直方图中取值组成最终均衡化图像  Mat dst(src.size(), CV_8UC1);  for (int i = 0; i < dst.rows; i++)  {
        for (int j = 0; j < dst.cols; j++)    {
          dst.ptr(i)[j] = hist_accumulate[src.ptr(i)[j]];    }  }  return dst;}

效果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值