下面是对于C++ OpenCV绘制简易直方图的完整攻略。
什么是直方图?
直方图是一种图表,用于表示数据集中各元素频度分布情况的统计表。在计算机视觉中,直方图一般用来表示一幅图像中各个像素值所占的比例。
OpenCV绘制简易直方图的函数
在OpenCV中,我们可以使用 cv::calcHist
函数来计算图像的直方图,然后使用 cv::normalize
函数对直方图做归一化处理,最后使用 cv::imshow
函数展示出直方图。
函数原型:
void cv::calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )
函数参数说明:
images
:输入图像的数组,可以包含一个或多个图像。nimages
:输入图像的数量。channels
:希望处理的通道,要传入一个数组。mask
:图像掩码,指定了感兴趣区域。hist
:输出直方图。dims
:直方图的维度。histSize
:直方图每个维度的划分数量。ranges
:数组大小和dims
相同,用来表示每个维度的取值范围。uniform
:是否对每个 bin 进行归一化处理。accumulate
:是否累计计算直方图。
示例1:
下面是一个简单的例子,展示如何使用 cv::calcHist
计算图像的直方图,并使用 cv::normalize
进行归一化处理,最后使用 cv::imshow
函数展示出直方图。
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
if (argc != 2) {
cerr << "usage: ./hist <image_path>" << endl;
return -1;
}
string image_path(argv[1]);
Mat image = imread(image_path, IMREAD_COLOR);
if (image.empty()) {
cerr << "failed to read image: " << image_path << endl;
return -1;
}
vector<Mat> channels;
split(image, channels); // 将彩色图像拆分成三个通道
int histSize = 256;
float range[] = {0, 256};
const float* histRanges[] = {range};
Mat hist;
calcHist(&channels[0], 1, 0, Mat(), hist, 1, &histSize, histRanges, true, false);
normalize(hist, hist, 0, image.rows, NORM_MINMAX, -1, Mat());
int histWidth = 512;
int histHeight = 400;
int binWidth = cvRound((double) histWidth / histSize);
Mat histImage(histHeight, histWidth, CV_8UC1, Scalar(0));
for (int i = 0; i < histSize; i++) {
line(histImage, Point(binWidth * i, histHeight), Point(binWidth * i, histHeight - cvRound(hist.at<float>(i))), Scalar(255), binWidth);
}
imshow("Histogram", histImage);
waitKey(0);
return 0;
}
这个例子展示了如何将一个彩色图像拆分成三个通道,并计算每个通道的直方图。最后将三个通道的直方图相加并对结果进行归一化处理,然后展示出直方图。
示例2:
下面是另一个例子,更加详细地展示了如何绘制彩色图像的直方图。
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
if (argc != 2) {
cerr << "usage: ./hist <image_path>" << endl;
return -1;
}
string image_path(argv[1]);
Mat image = imread(image_path, IMREAD_COLOR);
if (image.empty()) {
cerr << "failed to read image: " << image_path << endl;
return -1;
}
vector<Mat> bgr_planes;
split(image, bgr_planes);
int histSize = 256;
float range[] = {0, 256};
const float* histRanges[] = {range};
Mat b_hist, g_hist, r_hist;
calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, histRanges, true, false);
calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, histRanges, true, false);
calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, histRanges, true, false);
int hist_w = 512, hist_h = 400;
int bin_w = cvRound((double) hist_w / histSize);
Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
for (int i = 1; i < histSize; i++) {
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))), Point(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA);
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))), Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA);
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))), Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA);
}
imshow("Histogram of a Color Image", histImage);
waitKey(0);
return 0;
}
这个例子展示了如何绘制彩色图像的直方图。跟第一个例子一样,首先将彩色图像拆分成三个通道,计算每个通道的直方图,然后将三个通道的直方图绘制到一张三通道的图像上。最后展示出图像即可。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ OpenCV绘制简易直方图DrawHistImg - Python技术站