经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++ OpenCV绘制简易直方图DrawHistImg
来源:jb51  时间:2021/12/9 11:45:42  对本文有异议

需求说明

在对图像进行处理时,经常会有这类需求:想要观察图像的直方图分布,例如灰度图中0-255区间数值的分布情况,从而可以进行后续的操作,如阈值分割二值化、直方图均衡化等等。本文设计了一个能绘制简易直方图的简单函数DrawHistImg,可以帮助大家快速掌握绘制的原理,可以根据自己的创意对其进行改善和补充。

下面介绍具体实现流程。

具体流程

1)取图像的灰度图,并遍历统计0-255各个灰度值所出现的次数。

  1. cv::Mat src = imread("test.jpg", 0);
  2. cv::Mat hist = cv::Mat::zeros(1, 256, CV_32FC1);
  3. for (int i = 0; i < src.rows; ++i)
  4. {
  5. for (int j = 0; j < src.cols; ++j)
  6. {
  7. hist.at<float>(0, src.at <uchar>(i, j))++;
  8. }
  9. }

2)定义直方图图像histImage,并初始化一些参数。其中bins是数值最大值,即255;scale为每个灰度值所对应的直方图宽度;histHeight为直方图高度最大值,也是直方图图像的宽。

  1. cv::Mat histImage = cv::Mat::zeros(540, 1020, CV_8UC1);
  2. const int bins = 255;
  3. int scale = 4;
  4. int histHeight = 540;

3)利用minMaxLoc函数得出哪个灰度值的出现次数最高,为归一化做准备。

  1. double maxValue;
  2. cv::Point2i maxLoc;
  3. cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);

4)遍历hist中每个灰度值,并根据其出现次数绘制直方图,height是归一化后的高度。

  1. for (int i = 0; i < bins; i++)
  2. {
  3. float binValue = (hist.at<float>(i));
  4. int height = cvRound(binValue * histHeight / maxValue);
  5. cv::rectangle(histImage, cv::Point(i * scale, histHeight),
  6. cv::Point((i + 1) * scale - 1, histHeight - height), cv::Scalar(255), -1);
  7. }

5)函数执行完毕。?

功能函数

  1. // 绘制简易直方图
  2. cv::Mat DrawHistImg(cv::Mat &src)
  3. {
  4. cv::Mat hist = cv::Mat::zeros(1, 256, CV_32FC1);
  5. for (int i = 0; i < src.rows; ++i)
  6. {
  7. for (int j = 0; j < src.cols; ++j)
  8. {
  9. hist.at<float>(0, src.at <uchar>(i, j))++;
  10. }
  11. }
  12. cv::Mat histImage = cv::Mat::zeros(540, 1020, CV_8UC1);
  13. const int bins = 255;
  14. double maxValue;
  15. cv::Point2i maxLoc;
  16. cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);
  17. int scale = 4;
  18. int histHeight = 540;
  19. for (int i = 0; i < bins; i++)
  20. {
  21. float binValue = (hist.at<float>(i));
  22. int height = cvRound(binValue * histHeight / maxValue);
  23. cv::rectangle(histImage, cv::Point(i * scale, histHeight),
  24. cv::Point((i + 1) * scale - 1, histHeight - height), cv::Scalar(255), -1);
  25. }
  26. return histImage;
  27. }

C++测试代码

  1. #include <iostream>
  2. #include <time.h>
  3. #include <opencv2/opencv.hpp>
  4. using namespace std;
  5. using namespace cv;
  6. cv::Mat DrawHistImg(cv::Mat &hist);
  7. int main()
  8. {
  9. cv::Mat src = imread("test.jpg", 0);
  10. // 绘制均衡化后直方图
  11. cv::Mat hrI = DrawHistImg(src);
  12. imshow("original", src);
  13. imshow("hist", hrI);
  14. waitKey(0);
  15. return 0;
  16. }
  17. // 绘制简易直方图
  18. cv::Mat DrawHistImg(cv::Mat &src)
  19. {
  20. cv::Mat hist = cv::Mat::zeros(1, 256, CV_32FC1);
  21. for (int i = 0; i < src.rows; ++i)
  22. {
  23. for (int j = 0; j < src.cols; ++j)
  24. {
  25. hist.at<float>(0, src.at <uchar>(i, j))++;
  26. }
  27. }
  28. cv::Mat histImage = cv::Mat::zeros(540, 1020, CV_8UC1);
  29. const int bins = 255;
  30. double maxValue;
  31. cv::Point2i maxLoc;
  32. cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);
  33. int scale = 4;
  34. int histHeight = 540;
  35. for (int i = 0; i < bins; i++)
  36. {
  37. float binValue = (hist.at<float>(i));
  38. int height = cvRound(binValue * histHeight / maxValue);
  39. cv::rectangle(histImage, cv::Point(i * scale, histHeight),
  40. cv::Point((i + 1) * scale - 1, histHeight - height), cv::Scalar(255), -1);
  41. }
  42. return histImage;
  43. }

测试效果

图1 原图

图2 灰度图

图3 直方图

如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~?

以上就是C++ OpenCV绘制简易直方图DrawHistImg的详细内容,更多关于C++ OpenCV绘制直方图的资料请关注w3xue其它相关文章!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号