OpenCV中图像直方图与应用

Posted OpenCV学堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV中图像直方图与应用相关的知识,希望对你有一定的参考价值。


OpenCV中图像直方图与应用

图像直方图数据在图像处理中应用十分广泛,根据直方图数据不同常见的有如下三种:

- 图像像素直方图、

- 像素梯度直方图

- 像素角度直方图

后面两个在图像特征提取SIFT与HOG中均有应用。最常见的图像直方图一般都是图像像素值统计直方图。通常我们把每个直方图的单元叫做BIN,对RGB图像来说像素的取值范围为0~255之间,BIN的个数是对取值范围的间隔区分,可以为32、64、128、256。OpenCV中提供了几个非常有用的直方图操作函数,实现了直方图统计计算、到直方图均衡化、直方图反向投影等功能。

图像像素直方图

OpenCV3.1.0中计算直方图的对应函数calcHist

原图如下:

OpenCV中图像直方图与应用

计算得到的直方图如下:

OpenCV中图像直方图与应用

直方图统计与绘制代码如下:

 
   
   
 
  1.    // 加载图像

  2.    Mat src = imread("D:/gloomyfish/flower.png");

  3.    if (src.empty()) {

  4.        printf("could not load image...\n");

  5.        return -1;

  6.    }

  7.    namedWindow("refer faces", CV_WINDOW_AUTOSIZE);

  8.    imshow("refer faces", src);

  9.    // 三通道分离

  10.    vector<Mat> bgr_plane;

  11.    split(src, bgr_plane);

  12.    // 定义参数变量

  13.    const int channels[1] = { 0 };

  14.    const int bins[1] = { 256 };

  15.    float hranges[2] = { 0,255 };

  16.    const float* ranges[1] = { hranges };

  17.    Mat b_hist;

  18.    Mat g_hist;

  19.    Mat r_hist;

  20.    // 计算Blue, Green, Red通道的直方图

  21.    calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);

  22.    calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);

  23.    calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);

  24.    // 显示直方图

  25.    int hist_w = 512;

  26.    int hist_h = 400;

  27.    int bin_w = cvRound((double)hist_w / bins[0]);

  28.    Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

  29.    // 归一化直方图数据

  30.    normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

  31.    normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

  32.    normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

  33.    // 绘制直方图曲线

  34.    for (int i = 1; i < bins[0]; i++) {

  35.          line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),

  36.              Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);

  37.        line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),

  38.            Point(bin_w*(i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);

  39.        line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),

  40.            Point(bin_w*(i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);

  41.    }

  42.    // 显示直方图

  43.    namedWindow("Histogram Demo", WINDOW_AUTOSIZE);  

  44.    imshow("Histogram Demo", histImage);

直方图均衡化

直方图均衡化是利用统计得到的直方图数据实现直方图分布的调整,然后根据调整之后的直方图对原图像建立查找表,重新映射得到新的像素值,基本原理就是这样。OpenCV中的API函数为 equalizeHist

  • src参数表示输入的图像,必须是8位灰度图像

  • dst参数表示均衡化之后的图像,大小和类型必须跟输入图像一致

输入原图如下:

OpenCV中图像直方图与应用

直方图均衡化的结果如下:

OpenCV中图像直方图与应用

对于三通道的彩色图像,可以先拆分通道对各个通道进行直方图均衡化之后再合并通道即可。实现代码如下: // 直方图均衡化处理

 
   
   
 
  1.    vector<Mat> dst_bgr(3);

  2.    equalizeHist(bgr_plane[0], dst_bgr[0]);

  3.    equalizeHist(bgr_plane[1], dst_bgr[1]);

  4.    equalizeHist(bgr_plane[2], dst_bgr[2]);

  5.    Mat dst = Mat::zeros(bgr_plane[0].size(), CV_8UC3);

  6.    merge(dst_bgr, dst);

  7.    imshow("EH Demo", dst);

直方图反向投影

直方图反向投影直观的理解就是生成一个模板直方图,然后用它在一副更大的图像上去匹配相似区域,说白了就跟模板匹配类似。为了消除光照对直方图的影响,通常会先对取得的直方图做归一化之后在去做直方图反向投影。直方图反向投影的基本步骤可以分为如下三步

  • 获取图像特征的区域-ROI

  • 根据ROI生成直方图特征

  • 利用直方图特征进行反向投影,在未知图像上寻找特征


OpenCV3.1.0中对应的直方图反向投影API函数为 calcBackProject, 参数就不再赘述啦,各位自己看一下API文档吧! 这里以车牌识别中获取车牌区域为例,通过直方图反向投影可以获取。首先看模板图像

OpenCV中图像直方图与应用

测试图像

OpenCV中图像直方图与应用

直方图反向投影结果

从上面可以根据直方图反向投影结果直接获取车牌ROI区域,只要对车牌模板的蓝色通道直方图生成模板,反向投影即可。反向投影的演示代码如下:

 
   
   
 
  1.    // 归一化直方图数据

  2.    normalize(b_hist, b_hist, 1.0, 0.0);

  3.    // 直方图反向映射 - 加载测试图片

  4.    Mat testImg = imread("D:/gloomyfish/5.jpg");

  5.    if (testImg.empty()) {

  6.        printf("could not load test image...\n");

  7.        return -1;

  8.    }

  9.    imshow("test image", testImg);

  10.    // 反向映射

  11.    vector<Mat> bgr;

  12.    split(testImg, bgr);

  13.    Mat result;

  14.    calcBackProject(&bgr[0], 1, channels, b_hist, result, ranges, 255);

  15.    // 将结果进行阈值化

  16.    threshold(result, result, 255*0.1, 255, THRESH_BINARY);

  17.    imshow("Histogram Back Projection Result", result);

特别声明 

更多精彩内容请关注扫码

+OpenCV学习群 376281510

进群暗号:OpenCV


以上是关于OpenCV中图像直方图与应用的主要内容,如果未能解决你的问题,请参考以下文章

Opencv中图像的遍历与像素操作

Python-OpenCV中图像合并显示

[OpenCV-Python] OpenCV 中图像特征提取与描述 部分 V

OpenCV中图像的读取,显示与保存

OpenCV 完整例程47. 图像增强—直方图匹配

OpenCV 完整例程51. 图像增强—直方图反向追踪