【欢迎关注编码小哥,学习更多实用的编程方法和技巧】
1、基本直方图计算
cpp
// 灰度图直方图
cv::Mat calculateGrayscaleHistogram(const cv::Mat& image) {
cv::Mat histogram;
int histSize = 256; // 灰度级别
float range[] = {0, 256};
const float* histRange = {range};
cv::calcHist(
&image, // 输入图像
1, // 图像数量
0, // 通道索引
cv::Mat(), // 掩膜
histogram, // 输出直方图
1, // 直方图维度
&histSize, // 直方图大小
&histRange // 像素值范围
);
return histogram;
}
// 彩色图直方图
std::vector<cv::Mat> calculateColorHistogram(const cv::Mat& image) {
std::vector<cv::Mat> histograms(3);
int histSize = 256;
float range[] = {0, 256};
const float* histRange = {range};
// 分离通道
std::vector<cv::Mat> channels;
cv::split(image, channels);
// 计算每个通道直方图
for (int i = 0; i < 3; i++) {
cv::calcHist(
&channels[i], // 输入通道
1, // 图像数量
0, // 通道索引
cv::Mat(), // 掩膜
histograms[i], // 输出直方图
1, // 直方图维度
&histSize, // 直方图大小
&histRange // 像素值范围
);
}
return histograms;
}
2、直方图可视化
cpp
class HistogramVisualizer {
public:
// 绘制直方图
static cv::Mat drawHistogram(const cv::Mat& histogram, int height = 400) {
// 归一化直方图
cv::Mat normalizedHist;
cv::normalize(histogram, normalizedHist, 0, height, cv::NORM_MINMAX);
// 创建绘图画布
int width = 512;
cv::Mat histImage(height, width, CV_8UC3, cv::Scalar(255, 255, 255));
// 绘制直方图
int binWidth = cvRound((double)width / histogram.rows);
for (int i = 1; i < histogram.rows; i++) {
cv::line(
histImage,
cv::Point(binWidth * (i - 1), height - cvRound(normalizedHist.at<float>(i - 1))),
cv::Point(binWidth * i, height - cvRound(normalizedHist.at<float>(i))),
cv::Scalar(0, 0, 0),
2
);
}
return histImage;
}
// 绘制彩色直方图
static cv::Mat drawColorHistogram(const std::vector<cv::Mat>& histograms) {
int height = 400;
int width = 512;
cv::Mat histImage(height, width, CV_8UC3, cv::Scalar(255, 255, 255));
std::vector<cv::Scalar> colors = {
cv::Scalar(255, 0, 0), // 蓝色
cv::Scalar(0, 255, 0), // 绿色
cv::Scalar(0, 0, 255) // 红色
};
// 归一化直方图
std::vector<cv::Mat> normalizedHists(3);
for (int i = 0; i < 3; i++) {
cv::normalize(histograms[i], normalizedHists[i], 0, height, cv::NORM_MINMAX);
}
// 绘制直方图
int binWidth = cvRound((double)width / histograms[0].rows);
for (int i = 1; i < histograms[0].rows; i++) {
for (int channel = 0; channel < 3; channel++) {
cv::line(
histImage,
cv::Point(binWidth * (i - 1), height - cvRound(normalizedHists[channel].at<float>(i - 1))),
cv::Point(binWidth * i, height - cvRound(normalizedHists[channel].at<float>(i))),
colors[channel],
2
);
}
}
return histImage;
}
};
3、直方图均衡化
cpp
class HistogramEqualizer {
public:
// 灰度图均衡化
static cv::Mat equalizeGrayscaleImage(const cv::Mat& image) {
cv::Mat equalizedImage;
cv::equalizeHist(image, equalizedImage);
return equalizedImage;
}
// 彩色图均衡化
static cv::Mat equalizeColorImage(const cv::Mat& image) {
// 转换到YUV空间
cv::Mat yuvImage;
cv::cvtColor(image, yuvImage, cv::COLOR_BGR2YUV);
// 分离通道
std::vector<cv::Mat> channels;
cv::split(yuvImage, channels);
// 仅均衡化亮度通道
cv::equalizeHist(channels[0], channels[0]);
// 合并通道
cv::merge(channels, yuvImage);
// 转换回BGR
cv::Mat equalizedImage;
cv::cvtColor(yuvImage, equalizedImage, cv::COLOR_YUV2BGR);
return equalizedImage;
}
// 自适应直方图均衡化(CLAHE)
static cv::Mat adaptiveHistogramEqualization(const cv::Mat& image, double clipLimit = 2.0) {
cv::Mat yuvImage;
cv::cvtColor(image, yuvImage, cv::COLOR_BGR2YUV);
std::vector<cv::Mat> channels;
cv::split(yuvImage, channels);
// 创建CLAHE对象
cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(clipLimit, cv::Size(8, 8));
clahe->apply(channels[0], channels[0]);
cv::merge(channels, yuvImage);
cv::Mat equalizedImage;
cv::cvtColor(yuvImage, equalizedImage, cv::COLOR_YUV2BGR);
return equalizedImage;
}
};
4、直方图比较
cpp
class HistogramComparator {
public:
// 直方图比较方法
enum CompareMethod {
CORRELATION = cv::HISTCMP_CORREL,
CHI_SQUARE = cv::HISTCMP_CHISQR,
INTERSECTION = cv::HISTCMP_INTERSECT,
BHATTACHARYYA = cv::HISTCMP_BHATTACHARYYA
};
// 比较两个直方图
static double compareHistograms(
const cv::Mat& hist1,
const cv::Mat& hist2,
CompareMethod method = CORRELATION
) {
return cv::compareHist(hist1 , hist2, method);
}
};
// 使用示例
cv::Mat image1 = cv::imread("image1.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat image2 = cv::imread("image2.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat hist1 = calculateGrayscaleHistogram(image1);
cv::Mat hist2 = calculateGrayscaleHistogram(image2);
double similarity = HistogramComparator::compareHistograms(hist1, hist2, HistogramComparator::CORRELATION);
std::cout << "Histogram similarity: " << similarity << std::endl; ```cpp
// 重新合并通道
cv::Mat processedImage;
cv::merge(channels, processedImage);
return processedImage;
}
// 使用示例
cv::Mat inputImage = cv::imread("input.jpg");
cv::Mat outputImage = processImageChannels(inputImage);
// 显示结果
cv::imshow("Processed Image", outputImage);
cv::waitKey(0);
cv::destroyAllWindows();
``` ```cpp
// 重新合并通道
cv::Mat processedImage;
cv::merge(channels, processedImage);
return processedImage;
}
// 使用示例
cv::Mat inputImage = cv::imread("input.jpg");
cv::Mat outputImage = processImageChannels(inputImage);
// 显示结果
cv::imshow("Processed Image", outputImage);
cv::waitKey(0);
cv::destroyAllWindows();
}