ヒストグラム等化とヒストグラムマッチング

1. ヒストグラムの等化

通常、より均一なヒストグラムを持つ画像は、人間の目の視覚効果とより一致して見えます。画像内のグレースケールが暗い、明るい、または集中しているヒストグラムを、グレースケール分布が均一なヒストグラムに調整する必要がある場合は、ヒストグラム等化アルゴリズムを使用する必要があります。

ここに画像の説明を挿入します

ヒストグラム均等化とは、本質的には、画像内の階調数の分布を均等化すること、つまり階調数が一部の階調に集中しないようにすることですが、画像のヒストグラムが完全に均等に分布している場合、このときのエントロピーは画像のコントラストが最も大きく(つまり、各階調の確率分布が均衡しており)、画像のコントラストも最も大きいため、画像の可観測性が向上する。
ヒストグラム等化は、画像のコントラストを高める方法であり、その主な考え方は、画像のヒストグラム分布を累積分布関数によってほぼ均一な分布に変換し、それによって画像のコントラストを高めることです。理想的な効果は次のとおりです。
ここに画像の説明を挿入します
実際の処理効果は次のとおりです。
ここに画像の説明を挿入します
上の図から、ヒストグラム均等化後、ヒストグラムの分布の集中が緩和され、画像のコントラストも向上していることがわかります。

ヒストグラム等化の実装手順は、
(1) 画像内のグレー レベルの数をカウントする
(2) グレー レベルの累積分布確率を計算する
(3) 変換関数を通じて変換されたグレー レベルの確率密度を取得する
(4) 拡散元の Figure の場合は、元の画像
コードを次のように変更します。

# include <iostream>
#include <opencv.hpp>

using namespace cv;
using namespace std;
void GetHistogram(const Mat& srcImage, int* histogram);

int main() {
    
    
	Mat srcImage; //存放读取的原图
	Mat dstImage; //直方均衡的图像
	srcImage = imread("d://1.jpg", 0); //1RGB 0灰色

	if (!srcImage.data) 
		cout << "图片加载失败,请检查文件是否存在!" << endl;
	else
		cout << "图片加载成功!" << endl;
	CV_Assert(srcImage.type() == CV_8UC1); //判断图像是否为灰度图片,非灰色报错
	dstImage.create(srcImage.size(), srcImage.type()); //设置目标图与原图大小和类型相同

	// 计算直方图,即为每个灰度级在图像中的数目
	int histogram[256]; //存放为每一个灰度级在图像中的数目
	GetHistogram(srcImage, histogram);

	//计算累积分布函数,变换函数
	int pixelSrcImage = srcImage.cols * srcImage.rows;
	int Lut[256]; //分布函数
	Lut[0] = (1.0 * histogram[0] / pixelSrcImage) * 255;
	int sum = histogram[0];
	for (int i = 1; i < 256; ++i) {
    
    
		sum += histogram[i];
		Lut[i] = (1.0 * sum / pixelSrcImage) * 255;
	}

	//灰度变换
	uchar* srcImageDate = srcImage.data;
	uchar* dstImageDate = dstImage.data;
	for (int i = 0; i < pixelSrcImage; ++i) {
    
    
		dstImageDate[i] = Lut[srcImageDate[i]];
	}
	imshow("原始图像", srcImage);
	imshow("直方图均衡后图像", dstImage);
	//保持等待状态
	waitKey(0);//括号里可以填任意正整数,意味着,图像显示的毫秒时间

	return 0;
}
void GetHistogram(const Mat& srcImage, int* histogram) {
    
    
	memset(histogram, 0, 256 * sizeof(int)); //设置histogram数组初始全为0

	//建立直方图, 统计图像中每一灰度级数
	int pixelCount = srcImage.cols * srcImage.rows;
	uchar *srcImageDate = srcImage.data;
	for (int i = 0; i < pixelCount; ++i) {
    
    
		int grayDate = srcImageDate[i];
		histogram[grayDate]++;
	}
}

HE は画像の全体的な画像を調整する方法であり、局所的なコントラストを効果的に改善することはできません。一部の画像では、ヒストグラム等化を使用した後に一部の詳細が表示されなくなり、(適応的な) 局所的なヒストグラム等化が行われます。

2. 適応ヒストグラム等化

その原理はヒストグラム等化と同じですが、マッピング中に画像の局所領域の累積分布関数が選択される点が異なります。また、ノイズがある場合には、ノイズが増幅されることも考慮してください。この状況を回避するには、コントラスト制限を使用します。小さなブロックごとに、ヒストグラム内のビンがコントラストの上限を超える場合、ピクセルは他のビンに均等に分散され、ヒストグラムが均等化されます。
ここに画像の説明を挿入します
Contrast Limited Adaptive Histogram Equalization (CLAHE) アルゴリズムは、元々は画像強調アルゴリズムとして提案されましたが、現在では画像の曇り止め、低照度の画像強調、および水中画像効果の調整やデジタル写真の改善に使用されています。
これは OpenCV の createCLAHE 関数を通じて実装され、C++ によって呼び出されるコードは次のとおりです (注: 入力画像は 8 ビット画像である必要があります)。

Mat adaptiveEqualizeHist(Mat src)
{
    
    
	src.convertTo(src, CV_8UC1);
	Mat temp, clahe_img;
	temp = src.clone();

	cv::Ptr<cv::CLAHE> clahe = createCLAHE();
	clahe->setClipLimit(4.);    // (int)(4.*(8*8)/256)
	clahe->setTilesGridSize(Size(8, 8)); // 将图像分为8*8块
	clahe->apply(temp, clahe_img);
	temp.release();
	clahe_img.copyTo(temp);
	return temp;
}

Python の呼び出しは次のとおりです。

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
 
src = cv.imread("pic.png", 0)  # 直接以灰度图方式读入
img = src.copy()
 
# 创建一个自适应均衡化的对象,并应用于图像
clahe = cv.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
dst = clahe.apply(img)
 
# 显示图像
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img, cmap=plt.cm.gray)
axes[0].set_title("原图")
axes[1].imshow(dst, cmap=plt.cm.gray)
axes[1].set_title("自适应均衡化后的图像")
plt.show()

3. ヒストグラムマッチング

上記の導入を通じて、ヒストグラム イコライゼーションは本質的に、累積分布関数を通じてマッピングされた変換関数であり、ルックアップ テーブル LUT を通じて実現できることはすでにわかりました。
ヒストグラム等化は、グレースケール範囲全体で画像をブーストすることですが、場合によっては、この範囲全体にわたるブーストが最適ではない場合があり、特定のグレースケール分布に従う必要がある場合があります。マッチング(標準化)。
ヒストグラム マッチングは、ヒストグラム仕様とも呼ばれ、特定のパターンに従って画像のグレースケール分布を変換する操作です。
この原理はヒストグラム等化に基づいて実装されます。実装手順は次のとおりです。
ここに画像の説明を挿入します

コードの実装手順

  1. ソース画像の累積ヒストグラムを計算します。
  2. 指定された画像の累積ヒストグラムを計算します。
  3. ソース画像の累積ヒストグラムの各グレー レベルと指定された画像の累積ヒストグラムの各グレー レベル間の差の絶対値を計算します。
  4. ステップ 3 で、各レベルの絶対値に対応する最小値を見つけます。最小値に対応するグレー レベルがマップされた値です。
#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("lena.png");  //读取图像;
	if (image1.empty())
	{
    
    
		cout << "读取错误" << endl;
		return -1;
	}

	cvtColor(image1, image1_gray, COLOR_BGR2GRAY);  //灰度化
	imshow(" image1_gray", image1_gray);   //显示灰度图像

	image2 = imread("1043.jpg");  //读取图像;
	if (image2.empty())
	{
    
    
		cout << "读取错误" << endl;
		return -1;
	}

	cvtColor(image2, image2_gray, COLOR_BGR2GRAY);  //灰度化
	imshow(" image2_gray", image2_gray);   //显示灰度图像

	//均衡化处理
	equalizeHist(image1_gray, image1_gray);
	equalizeHist(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;
}

参考文献
[1]ヒストグラム等化の原理と実装
[2]画像の空間領域強調 - ヒストグラム等化アルゴリズムの原理と実装
[3] https://www.cnblogs.com/yanshw/p/15429887 .html
[4] https ://blog.csdn.net/mmmmmk_/article/details/82927411
[5] https://zhuanlan.zhihu.com/p/618170011

おすすめ

転載: blog.csdn.net/qq_44924694/article/details/132480400