当前位置:   article > 正文

C++OpenCV图像处理的基本操作(五)——直方图_open cv 直方图 c++

open cv 直方图 c++

 

直方图的优点

        图像直方图由于其计算代价较小,且具有图像平移旋转缩放不变性等众多优点,广泛地应用于图像处理的各个领域,特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类

1.一维的直方图

函数部分如下所示:

  1. void QuickDemo::histogram_demo(Mat &image) {
  2. /*图像直方图是图像像素值的统计学特征,计算代价较小,具有图像的平移、旋转、缩放不变性的优点。
  3. Bins是指直方图的大小范围
  4. */
  5. //三通道分离
  6. std::vector<Mat>bgr_plane;
  7. split(image, bgr_plane);
  8. //定义参数变量
  9. const int channels[1] = { 0 };
  10. const int bins[1] = { 256 };//一共有256个灰度级别
  11. float hranges[2] = { 0,255 };//每个通道的灰度级别是0-255
  12. const float* ranges[1] = { hranges };
  13. Mat b_hist;
  14. Mat g_hist;
  15. Mat r_hist;
  16. //计算Blue、Green、Red通道的直方图,1表示只有一张图,因为可以支持多张图多个通道;0表示只有1个通道;raanges就是直方图的取值范围0-25
  17. calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist,1,bins, ranges);
  18. calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
  19. calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
  20. //显示直方图
  21. int hist_w = 512;
  22. int hist_h = 400;
  23. int bin_w = cvRound((double)hist_w / bins[0]);
  24. Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
  25. //归一化直方图数据
  26. normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
  27. normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
  28. normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
  29. //绘制直方图曲线
  30. for (int i = 1; i < bins[0]; i++) {
  31. line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
  32. Point(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);
  33. line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
  34. Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
  35. line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
  36. Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);
  37. }
  38. //显示直方图
  39. namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
  40. imshow("Histogram Demo", histImage);
  41. }

2.二维的直方图

函数部分如下所示:

  1. void QuickDemo::histogram_2d_demo(Mat& image) {
  2. //2D直方图
  3. Mat hsv, hs_hist;
  4. cvtColor(image, hsv, COLOR_BGR2HSV);
  5. int hbins = 30;//H一共有180,设置hbins为30可以理解为分30个类统计
  6. int sbins = 32;
  7. int hist_bins[] = { hbins,sbins };
  8. float h_range[] = { 0,180 };
  9. float s_range[] = { 0,256 };
  10. const float* hs_ranges[] = { h_range,s_range };
  11. int hs_channels[] = { 0,1 };
  12. calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false);
  13. double maxVal = 0;
  14. minMaxLoc(hs_hist, 0, &maxVal, 0, 0);
  15. int scale = 10;
  16. Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);
  17. for (int h = 0; h < hbins; h++) {
  18. for (int s = 0; s < sbins; s++) {
  19. float binVal = hs_hist.at<float>(h, s);
  20. int intensity = cvRound(binVal * 255 / maxVal);
  21. rectangle(hist2d_image, Point(h * scale, s * scale), Point((h + 1) * scale - 1, (s + 1) * scale - 1), Scalar::all(intensity), -1);
  22. }
  23. }
  24. imshow("H-S Histogram", hist2d_image);
  25. imwrite("D:/hist_2d.png", hist2d_image);
  26. }

               

对于要显示彩色的二维直方图需要加一句话如下所示:

applyColorMap(hist2d_image, hist2d_image, COLORMAP_JET);

结果如下所示:

3.灰度直方图

  1. Mat QuickDemo::histogram_grayImage(const Mat& image)
  2. {
  3. //定义求直方图的通道数目,从0开始索引
  4. int channels[] = { 0 };
  5. //定义直方图的在每一维上的大小,例如灰度图直方图的横坐标是图像的灰度值,就一维,bin的个数
  6. //如果直方图图像横坐标bin个数为x,纵坐标bin个数为y,则channels[]={1,2}其直方图应该为三维的,Z轴是每个bin上统计的数目
  7. const int histSize[] = { 256 };
  8. //每一维bin的变化范围
  9. float range[] = { 0,256 };
  10. //所有bin的变化范围,个数跟channels应该跟channels一致
  11. const float* ranges[] = { range };
  12. //定义直方图,这里求的是直方图数据
  13. Mat hist;
  14. //opencv中计算直方图的函数,hist大小为256*1,每行存储的统计的该行对应的灰度值的个数
  15. calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges, true, false);
  16. //找出直方图统计的个数的最大值,用来作为直方图纵坐标的高
  17. double maxValue = 0;
  18. //找矩阵中最大最小值及对应索引的函数
  19. minMaxLoc(hist, 0, &maxValue, 0, 0);
  20. //最大值取整
  21. int rows = cvRound(maxValue);
  22. //定义直方图图像,直方图纵坐标的高作为行数,列数为256(灰度值的个数)
  23. //因为是直方图的图像,所以以黑白两色为区分,白色为直方图的图像
  24. Mat histImage = Mat::zeros(rows, 256, CV_8UC1);
  25. //直方图图像表示
  26. for (int i = 0; i < 256; i++)
  27. {
  28. //取每个bin的数目
  29. int temp = (int)(hist.at<float>(i, 0));
  30. //如果bin数目为0,则说明图像上没有该灰度值,则整列为黑色
  31. //如果图像上有该灰度值,则将该列对应个数的像素设为白色
  32. if (temp)
  33. {
  34. //由于图像坐标是以左上角为原点,所以要进行变换,使直方图图像以左下角为坐标原点
  35. histImage.col(i).rowRange(Range(rows - temp, rows)) = 255;
  36. }
  37. }
  38. //由于直方图图像列高可能很高,因此进行图像对列要进行对应的缩减,使直方图图像更直观
  39. Mat resizeImage;
  40. resize(histImage, resizeImage, Size(256, 256));
  41. return resizeImage;
  42. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/141032
推荐阅读
相关标签
  

闽ICP备14008679号