您好,登录后才能下订单哦!
在图像处理中,直方图是一种非常重要的工具,用于表示图像中像素强度的分布情况。通过直方图,我们可以直观地了解图像的亮度、对比度等信息。OpenCV 是一个功能强大的计算机视觉库,提供了丰富的函数来处理图像和计算直方图。本文将介绍如何在 C++ 中使用 OpenCV 实现直方图的计算。
在开始之前,确保你已经安装了 OpenCV 库,并且配置好了开发环境。如果你还没有安装 OpenCV,可以参考官方文档进行安装。
首先,我们需要加载一张图像。OpenCV 提供了 cv::imread
函数来读取图像文件。以下是一个简单的代码示例:
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("example.jpg", cv::IMREAD_COLOR);
if (image.empty()) {
std::cerr << "Could not open or find the image!" << std::endl;
return -1;
}
// 显示图像
cv::imshow("Original Image", image);
cv::waitKey(0);
return 0;
}
在这个示例中,我们使用 cv::imread
函数读取了一张名为 example.jpg
的图像,并使用 cv::imshow
函数显示图像。
OpenCV 提供了 cv::calcHist
函数来计算图像的直方图。该函数可以计算单通道或多通道图像的直方图。以下是一个计算灰度图像直方图的示例:
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("example.jpg", cv::IMREAD_GRAYSCALE);
if (image.empty()) {
std::cerr << "Could not open or find the image!" << std::endl;
return -1;
}
// 定义直方图参数
int histSize = 256; // 直方图的 bin 数量
float range[] = {0, 256}; // 像素值范围
const float* histRange = {range};
bool uniform = true, accumulate = false;
// 计算直方图
cv::Mat hist;
cv::calcHist(&image, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
// 显示直方图
int hist_w = 512, hist_h = 400;
int bin_w = cvRound((double) hist_w / histSize);
cv::Mat histImage(hist_h, hist_w, CV_8UC3, cv::Scalar(0, 0, 0));
// 归一化直方图
cv::normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
// 绘制直方图
for (int i = 1; i < histSize; i++) {
cv::line(histImage, cv::Point(bin_w * (i - 1), hist_h - cvRound(hist.at<float>(i - 1)),
cv::Point(bin_w * (i), hist_h - cvRound(hist.at<float>(i))),
cv::Scalar(255, 255, 255), 2, 8, 0);
}
// 显示直方图图像
cv::imshow("Histogram", histImage);
cv::waitKey(0);
return 0;
}
在这个示例中,我们首先将图像转换为灰度图像,然后使用 cv::calcHist
函数计算直方图。直方图的 bin 数量设置为 256,表示每个像素强度值(0-255)都有一个对应的 bin。最后,我们使用 cv::line
函数绘制直方图,并显示出来。
对于彩色图像,我们可以分别计算每个通道的直方图。以下是一个计算彩色图像直方图的示例:
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("example.jpg", cv::IMREAD_COLOR);
if (image.empty()) {
std::cerr << "Could not open or find the image!" << std::endl;
return -1;
}
// 分离通道
std::vector<cv::Mat> bgr_planes;
cv::split(image, bgr_planes);
// 定义直方图参数
int histSize = 256;
float range[] = {0, 256};
const float* histRange = {range};
bool uniform = true, accumulate = false;
// 计算每个通道的直方图
cv::Mat b_hist, g_hist, r_hist;
cv::calcHist(&bgr_planes[0], 1, 0, cv::Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);
cv::calcHist(&bgr_planes[1], 1, 0, cv::Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate);
cv::calcHist(&bgr_planes[2], 1, 0, cv::Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate);
// 显示直方图
int hist_w = 512, hist_h = 400;
int bin_w = cvRound((double) hist_w / histSize);
cv::Mat histImage(hist_h, hist_w, CV_8UC3, cv::Scalar(0, 0, 0));
// 归一化直方图
cv::normalize(b_hist, b_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
cv::normalize(g_hist, g_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
cv::normalize(r_hist, r_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
// 绘制直方图
for (int i = 1; i < histSize; i++) {
cv::line(histImage, cv::Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
cv::Point(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i))),
cv::Scalar(255, 0, 0), 2, 8, 0);
cv::line(histImage, cv::Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
cv::Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))),
cv::Scalar(0, 255, 0), 2, 8, 0);
cv::line(histImage, cv::Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
cv::Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))),
cv::Scalar(0, 0, 255), 2, 8, 0);
}
// 显示直方图图像
cv::imshow("Histogram", histImage);
cv::waitKey(0);
return 0;
}
在这个示例中,我们首先使用 cv::split
函数将彩色图像分离为三个通道(B、G、R),然后分别计算每个通道的直方图。最后,我们使用不同的颜色绘制每个通道的直方图,并显示出来。
通过本文的介绍,我们学习了如何在 C++ 中使用 OpenCV 计算图像的直方图。无论是灰度图像还是彩色图像,OpenCV 都提供了强大的函数来帮助我们完成这些任务。直方图是图像处理中非常重要的工具,掌握它的计算方法对于进一步学习和应用图像处理技术非常有帮助。希望本文对你有所帮助!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
开发者交流群:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/4582134/blog/4582661