打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
OpenCV-绘制简易直方图DrawHistImg

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

需求说明

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

       下面介绍具体实现流程。

具体流程

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

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为直方图高度最大值,也是直方图图像的宽。

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

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

double maxValue;
cv::Point2i maxLoc;
cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);

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

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)函数执行完毕。 

功能函数

// 绘制简易直方图
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++测试代码

#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 直方图

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

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
反向投影(BackProjection)
【从零学习OpenCV 4】直方图均衡化
OpenCV-图像处理(25、直方图比较)
OpenCV2 直方图均衡化
对OpenCV直方图的数据结构CvHistogram的理解
Opencv学习笔记(十一)基于CAMshift算法的物体跟踪实现
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服