在圖像處理中,直方圖是一種非常重要的工具,用于表示圖像中像素強度的分布情況。通過直方圖,我們可以直觀地了解圖像的亮度、對比度等信息。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 都提供了強大的函數來幫助我們完成這些任務。直方圖是圖像處理中非常重要的工具,掌握它的計算方法對于進一步學習和應用圖像處理技術非常有幫助。希望本文對你有所幫助!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。