直方图匹配+c语言+opencv
调用:
cv::Mat ref_glass, src_glass; cv::Mat dst_glass = cv::Mat::zeros(src_glass.rows, src_glass.cols, src_glass.type()); HistSpecify(src_glass, ref_glass, dst_glass);
class Histogram1D
{
private:
int histSize[1]; // 项的数量
float hranges[2]; // 统计像素的最大值和最小值
const float* ranges[1];
int channels[1]; // 仅计算一个通道
public:
Histogram1D()
{
// 准备1D直方图的参数
histSize[0] = 256;
hranges[0] = 0.0f;
hranges[1] = 255.0f;
ranges[0] = hranges;
channels[0] = 0;
}
cv::Mat getHistogram(const cv::Mat &image)
{
cv::Mat hist;
// 计算直方图
calcHist(&image,// 要计算图像的
1, // 只计算一幅图像的直方图
channels, // 通道数量
cv::Mat(), // 不使用掩码
hist, // 存放直方图
1, // 1D直方图
histSize, // 统计的灰度的个数
ranges); // 灰度值的范围
return hist;
}
cv::Mat getHistogramImage(const cv::Mat &image)
{
cv::Mat hist = getHistogram(image);
//查找最大值用于归一化
double maxVal = 0;
minMaxLoc(hist, NULL, &maxVal);
//绘制直方图的图像
cv::Mat histImg(histSize[0], histSize[0], CV_8U, cv::Scalar(255));
// 设置最高点为最大值的90%
double hpt = 0.9 * histSize[0];
//每个条目绘制一条垂直线
for (int h = 0; h < histSize[0]; h++)
{
//直方图的元素类型为32位浮点数
float binVal = hist.at<float>(h);
int intensity = static_cast<int>(binVal * hpt / maxVal);
line(histImg, cv::Point(h, histSize[0]),
cv::Point(h, histSize[0] - intensity), cv::Scalar::all(0));
}
return histImg;
}
};
/**
* @brief HistSpecify 对灰度图像进行直方图规定化
* @param src 输入图像
* @param ref 参考图像,解析参考图像的直方图并用于规定化
* @param result 直方图规定化后的图像
* @note 手动设置一个直方图并用于规定化比较麻烦,这里使用一个参考图像来进行
*/
static void HistSpecify(const cv::Mat &src, const cv::Mat &ref, cv::Mat &result)
{
Histogram1D hist1D;
cv::Mat src_hist = hist1D.getHistogram(src);
cv::Mat dst_hist = hist1D.getHistogram(ref);
float src_cdf[256] = { 0 };
float dst_cdf[256] = { 0 };
// 直方图进行归一化处理
src_hist /= (src.rows * src.cols);
dst_hist /= (ref.rows * ref.cols);
// 计算原始直方图和规定直方图的累积概率
for (int i = 0; i < 256; i++)
{
if (i == 0)
{
src_cdf[i] = src_hist.at<float>(i);
dst_cdf[i] = dst_hist.at<float>(i);
}
else
{
src_cdf[i] = src_cdf[i - 1] + src_hist.at<float>(i);
dst_cdf[i] = dst_cdf[i - 1] + dst_hist.at<float>(i);
}
}
// 累积概率的差值
float diff_cdf[256][256];
for (int i = 0; i < 256; i++)
for (int j = 0; j < 256; j++)
diff_cdf[i][j] = fabs(src_cdf[i] - dst_cdf[j]);
// 构建灰度级映射表
cv::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 = 1; j < 256; j++)
{
if (min > diff_cdf[i][j])
{
min = diff_cdf[i][j];
index = j;
}
}
lut.at<uchar>(i) = static_cast<uchar>(index);
}
// 应用查找表,做直方图规定化
LUT(src, lut, result);
}

浙公网安备 33010602011771号