適応コントラスト増強(ACE)アルゴリズムの原理と実現


前注:
ACEは、画像処理において2つの表現が可能であり、1つは、http://blog.csdn.net/piaoxuezhong/article/details/78357815Automatic Color Equalization、すなわち自動カラーバランス;もう1つは、Adaptive Contrast Enhancement、すなわち適応コントラストの強化です.間違えないで~~
医学画像自体や撮像条件の制限により画像のコントラストが低いため,コントラスト増強アルゴリズムは医学画像において必要である.人間の目は高周波信号(エッジ)に敏感であるが、高周波信号が大量の低周波背景+ノイズ信号に埋め込まれると視覚的可視性が低下し、この場合に高周波部分を適切に高めることで視覚効果を向上させることができる.この点では,従来の線形コントラスト上昇およびヒストグラム等化が最も広範なグローバル画像増強法である.コントラストの上昇は画像のダイナミックレンジを調整することができ,ヒストグラム等化はヒストグラム分布確率を利用して画像を再マッピングするデータである.しかし、グローバルヒストグラム等化は、ノイズ信号の一部を強化する可能性がある.低周波数バックグラウンドの干渉を回避するために、「ローカル」の強化方法を採用すると、より良い効果が得られる可能性があります.
局所コントラストの増強には、2つの方法が一般的です.1つは、http://blog.csdn.net/piaoxuezhong/article/details/78271785における適応ヒストグラム等化と,本編で述べる適応コントラスト増強とを示す.
適応コントラスト強化の原理:
ACEの原理は実はとても簡単で、つまり1枚の画像を2つの部分に分けます:1つは低周波部分で、画像のローパスフィルタリング(スムーズブラー)を通じて得ることができます;二つ目は高周波部分であり、原図から低周波部分を減算して得ることができる.アルゴリズムの目標は、詳細を表す高周波部分を増強することであり、すなわち、高周波部分にゲイン値を乗算し、その後、増強された画像を再編成することである.したがってACEアルゴリズムの核心は高周波部分利得係数の計算であり,利得を固定値とし,利得値を分散に関連する量として表す方式であり,後述する式で説明する.
1枚の画像における画素点をx(i,j)とすると、(i,j)を中心として、ウィンドウサイズが(2 n+1)*(2 n+1)の領域内で、その局所平均値と分散は、
, ,
平均mxは背景部分と近似することができ、このときx-mは高周波細部部分であり、高周波に対して利得積として、以下のものがある.

利得Gについては、1より大きい定数をとり、増強効果を達成する.

スキーム2は、局所平均分散に反比例する変化値として表される.

画像の高周波領域では,局所平均分散が大きく,このとき利得値が小さく,結果が明るすぎることはない.しかし、画像が平滑な領域では、局所平均分散が小さく、この場合、ゲイン値が比較的大きいため、ノイズ信号が増幅される可能性があるため、ゲイン最大値を一定の制限をしなければ良好な効果が得られない.
適応コントラスト増強実現:上の原理部分とネット上のコードを参照してopencvで実現しました.コードは以下の通りです.
#include      
#include   

using namespace cv;
using namespace std;

Mat matrixWiseMulti(Mat &m1, Mat &m2){
	Mat dst = m1.mul(m2);
	return dst;
}

 
//float MaxCG:           ,int n:    ,int C:            
void ACE(Mat &src, int C = 3, int n = 3, float MaxCG = 7.5){
	int rows = src.rows;
	int cols = src.cols;

	Mat meanLocal; //        
	Mat varLocal;  //        
	Mat meanGlobal;//    
	Mat varGlobal; //       

	blur(src.clone(), meanLocal, Size(n, n)); 
	imshow("    ", meanLocal);
	Mat highFreq = src - meanLocal;//     
	imshow("    ", highFreq);

	varLocal = matrixWiseMulti(highFreq, highFreq);
	blur(varLocal, varLocal, Size(n, n));      
	//          
	varLocal.convertTo(varLocal, CV_32F);
	for (int i = 0; i < rows; i++){
		for (int j = 0; j < cols; j++){
			varLocal.at(i, j) = (float)sqrt(varLocal.at(i, j));
		}
	}
	meanStdDev(src, meanGlobal, varGlobal);
	Mat gainArr = 0.5 * meanGlobal / varLocal;//        

	//           
	for (int i = 0; i < rows; i++){
		for (int j = 0; j < cols; j++){
			if (gainArr.at(i, j) > MaxCG){
				gainArr.at(i, j) = MaxCG;
			}
		}
	}
	gainArr.convertTo(gainArr, CV_8U);
	gainArr = matrixWiseMulti(gainArr, highFreq);
	Mat dst1 = meanLocal + gainArr;
	imshow("     ", dst1);
	Mat dst2 = meanLocal + C*highFreq;  
	imshow("     ", dst2);
}

int main()
{
	const char* img_path = "1.bmp"; 
	Mat src = imread(img_path, 0);
	imshow("src", src);
	int C = 5;
	int n = 7;
	float MaxCG = 8;
	ACE(src, C,n, MaxCG);
	waitKey();
	return  0;
}

参照先:
http://www.cnblogs.com/Imageshop/p/3324282.html
http://www.cnblogs.com/jsxyhelu/p/4857721.html
http://blog.csdn.net/m_buddy/article/details/53365473