直方图匹配应用在很多场合,奈何opencv未提供可以直接拿来用的函数。直方图匹配的主要思想是计算出灰度映射矩阵,根据灰度映射实现将模板图像的风格迁移至待匹配图像。以下为依赖opencv库实现的直方图匹配
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
//定义修改图像,灰度修改图像, 修改直方图,目标图像,灰度目标图像,目标直方图, 规定化增强图像
Mat image1, image1_gray, hist1, image2, image2_gray, hist2, image_enhanced;
image1 = imread("D:\\下载\\1.jpg",0); //读取图像;
if (image1.empty())
{
cout << "读取错误" << endl;
return -1;
}
cvtColor(image1, image1_gray, COLOR_BGR2GRAY); //灰度化
imshow(" image1_gray", image1_gray); //显示灰度图像
image2 = imread("D:\\下载\\2.jpg",0); //读取图像;
if (image2.empty())
{
cout << "读取错误" << endl;
return -1;
}
cvtColor(image2, image2_gray, COLOR_BGR2GRAY); //灰度化
imshow(" image2_gray", image2_gray); //显示灰度图像
//获取两个均衡化图像的直方图
int histsize = 256;
float ranges[] = { 0,256 };
const float* histRanges = { ranges };
calcHist(&image1_gray, 1, 0, Mat(), hist1, 1, &histsize, &histRanges, true, false);
calcHist(&image2_gray, 1, 0, Mat(), hist2, 1, &histsize, &histRanges, true, false);
//计算两个均衡化图像直方图的累积概率
float hist1_cdf[256] = { hist1.at<float>(0) };
float hist2_cdf[256] = { hist2.at<float>(0) };
for (int i = 1; i < 256; i++)
{
hist1_cdf[i] = (hist1_cdf[i - 1] + hist1.at<float>(i));
hist2_cdf[i] = (hist2_cdf[i - 1] + hist2.at<float>(i));
}
for (int i = 0; i < 256; i++)
{
hist1_cdf[i] = hist1_cdf[i] / (image1_gray.rows * image1_gray.cols);
hist2_cdf[i] = hist2_cdf[i] / (image2_gray.rows * image2_gray.cols);
}
// 两个累计概率之间的差值,用于找到最接近的点
float diff_cdf[256][256];
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++)
{
diff_cdf[i][j] = fabs(hist1_cdf[i] - hist2_cdf[j]);
}
}
Mat lut(1, 256, CV_8U);
for (int i = 0; i < 256; i++)
{
//查找源灰度级为i的映射灰度和i的累积概率差最小(灰度接近)的规定化灰度
float min = diff_cdf[i][0];
int index = 0;
for (int j = 0; j < 256; j++) {
if (min > diff_cdf[i][j]) {
min = diff_cdf[i][j];
index = j;
}
}
lut.at<uchar>(i) = index;
}
LUT(image1_gray, lut, image_enhanced); //图像中进行映射
imshow("image_enhanced", image_enhanced);
waitKey(0); //暂停,保持图像显示,等待按键结束
return 0;
}
原图 模板图像 直方图匹配后图像