calcHist() 函数详解绘制直方图的代码测试图片生成的直方图
calcHist() 函数详解具体请参考:
https://blog.csdn.net/qq_42067550/article/details/122533459
注意:这里的代码用于生产灰度图的直方图,如果要获得彩色图片多个通道的直方图,需要先分离各个通道,再分别绘制!
#include "opencv2/opencv.hpp" #include "opencv2/highgui.hpp" #include测试图片 生成的直方图using namespace std; cv::Mat getHistogramImage(cv::Mat hist) { cv::Mat histData= hist.clone(); int histSize = histData.rows; int targetPoint = 225; //int bin_w = cvRound((double)hist_w / histSize); int bin_w = 3; // 一个桶所占的宽度 int hist_w = histSize * bin_w + 50; // 加上 50 是为了在图像两边各留 25 个像素的冗余 int hist_h = cvRound(hist_w * 2 / 3) + 50; // 绘制长方形图片,同样预留边框 // 创建直方图画布 cv::Mat histImage(hist_h, hist_w, CV_8UC3, cv::Scalar(255, 255, 255)); // 绘制坐标轴 cv::line(histImage, cv::Point(hist_w - 20, hist_h - 20), cv::Point(20, hist_h - 20), cv::Scalar(0, 0, 0), 2, 4, 0); cv::line(histImage, cv::Point(20, hist_h - 20), cv::Point(20, 20), cv::Scalar(0, 0, 0), 2, 4, 0); // 绘制坐标轴刻度 int seg = 16; // 每隔开 32 个桶设一个标记,256/32=8 共 9 个标记位(加上 0) int segs = histSize / seg; for (int i = 0; i <= segs; i++) { cv::line(histImage, cv::Point(26 + i * seg * bin_w, hist_h - 20), cv::Point(26 + i * seg * bin_w, hist_h - 15), cv::Scalar(0, 0, 0), 1, 4, 0); string text = to_string(i * seg); cv::putText(histImage, text, cv::Point(20 + i * seg * bin_w, hist_h - 5), 1, 0.8, cv::Scalar(0, 0, 0), 1, 8, false); } for (int i = 0; i <= segs; i++) { cv::line(histImage, cv::Point(20, hist_h - 20 - i * (hist_h - 40) / 8), cv::Point(15, hist_h - 20 - i * (hist_h - 40) / 8), cv::Scalar(0, 0, 0), 1, 4, 0); } /// 将直方图归一化到范围 [ 0, histImage.rows ] cv::normalize(histData, histData, 0, hist_h - 50, cv::NORM_MINMAX, -1, cv::Mat()); /// 在直方图画布上画出直方图 for (int i = 1; i < histSize; i++) { cv::line(histImage, cv::Point(26 + i * bin_w, hist_h - 20 - cvRound(histData.at (i))), cv::Point(26 + (i - 1) * bin_w, hist_h - 20 - cvRound(histData.at (i-1))), cv::Scalar(10), 1, cv::LINE_AA, 0); } return histImage; } int main() { cv::Mat img = cv::imread("./dog.jpeg", 0); // 读取灰度图 cv::Mat histogram; int histSize = 256; float range[] = {0, 255}; int channels[] = {0}; const float *histRanges = { range }; bool uniform = true; bool accumulate = false; cv::calcHist(&img, 1, channels, cv::Mat(), histogram, 1, &histSize, &histRanges, uniform, accumulate); cv::Mat histImage = getHistogramImage(histogram); cv::imshow("1", histImage); cv::waitKey(0); return 0; }



