OpenCV calcHist 功能強大但參數繁多,常用原型:
void 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:輸入圖像指針數組(可多圖),深度需一致(CV_8U/CV_32F)。channels:統計的通道索引數組,如 {0} 灰度、{0,1,2} BGR。mask:可選掩碼(CV_8U),非零像素參與統計。dims:直方圖維度(1D/2D/3D),最大 32。histSize:每維箱數,如 {256}。ranges:每維取值範圍,uniform=true 時每維兩值 {min, max}。class Histogram1D {
int histSize[1] = {256};
float hranges[2] = {0, 255};
const float* ranges[1] = {hranges};
int channels[1] = {0};
public:
cv::MatND getHistogram(const cv::Mat& image) {
cv::MatND hist;
cv::calcHist(&image, 1, channels, cv::Mat(), hist, 1, histSize, ranges);
return hist;
}
cv::Mat getHistogramImage(const cv::Mat& image) {
cv::MatND hist = getHistogram(image);
double minVal, maxVal;
cv::minMaxLoc(hist, &minVal, &maxVal);
cv::Mat histImg(histSize[0], histSize[0], CV_8U, cv::Scalar(255));
int hpt = cvRound(0.9 * histSize[0]);
for (int h = 0; h < histSize[0]; ++h) {
float binVal = hist.at<float>(h);
int intensity = cvRound(binVal * hpt / maxVal);
cv::line(histImg, cv::Point(h, histSize[0]),
cv::Point(h, histSize[0] - intensity), cv::Scalar(0));
}
return histImg;
}
};
class ColorHistogram {
int histSize[3] = {256, 256, 256};
float hranges[2] = {0, 255};
const float* ranges[3] = {hranges, hranges, hranges};
int channels[3] = {0, 1, 2};
public:
cv::MatND getHistogram(const cv::Mat& image) {
cv::MatND hist;
cv::calcHist(&image, 1, channels, cv::Mat(), hist, 3, histSize, ranges);
return hist;
}
cv::SparseMat getSparseHistogram(const cv::Mat& image) {
cv::SparseMat hist(3, histSize, CV_32F);
cv::calcHist(&image, 1, channels, cv::Mat(), hist, 3, histSize, ranges);
return hist; // 稀疏矩陣節省空間
}
};
Mat img = imread("lena.jpg");
Histogram1D h;
MatND hist = h.getHistogram(img);
Mat histImg = h.getHistogramImage(img);
imshow("Histogram", histImg);
SparseMat 稀疏存儲。mask 可實現 ROI 區域統計(如皮膚檢測、目標追蹤)。accumulate=true 可累加多圖直方圖(背景建模)。