我是靠谱客的博主 淡然项链,这篇文章主要介绍C++ OpenCV绘制简易直方图DrawHistImg,现在分享给大家,希望可以做个参考。

需求说明

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

下面介绍具体实现流程。

具体流程

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

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

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

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

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

复制代码
1
2
3
double maxValue; cv::Point2i maxLoc; cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);

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

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

5)函数执行完毕。 

功能函数

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

C++测试代码

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

测试效果

图1 原图

图2 灰度图

图3 直方图

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

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

最后

以上就是淡然项链最近收集整理的关于C++ OpenCV绘制简易直方图DrawHistImg的全部内容,更多相关C++ 内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(122)

评论列表共有 0 条评论

立即
投稿
返回
顶部