這個名字比較長,但其實說的是一系列問題:LocalNormalization這種圖像增強算法是什麼?有什麼用?如何實現?當這種圖像算法運用到動態視頻的過程中會出現什麼新的問題,如何解決問題獲得做好效果?
感謝labviewpbt(imageshop作者)的指導和幫助。
這裏是博客處理圖片,紅外光下的手臂血管圖片。
一、LocalNormalization是什麼?有什麼用?(資料來自imagej)
The local normalization tends to uniformize the mean and variance of an image around a local neighborhood. This is especially useful for correct non-uniform illumination or shading artifacts.
Local Normalization(局部正規)定義?對於光照均衡有很好的效果。
二、LocalNormalization如何實現?(來自stack overflow)
LN的定義比較簡單
其中
- f(x,y) is the original image
- mf(x,y) is an estimation of a local mean of f(x,y)
- σf(x,y) is an estimation of the local variance
- g(x,y) is the output image
那麼如何計算圖像的局部均值和局部方差了?很容易就會想到卷積的方法。具體思路可以參考上一篇博客。實際過程中採用如下方法
由於Gaussian Smooth的速度比較慢,所以在實際過程中會使用Box Filter,基於Opencv的代碼如下:
//Local Normalization input is 32f1u
cv::Mat LocalNormalization(cv::Mat float_gray,float sigma1,float sigma2){
Mat gray, blur, num, den;
float_gray.convertTo(float_gray, CV_32F, 1.0/255.0);
// numerator = img - gauss_blur(img)
boxFilter(float_gray,blur,float_gray.depth(),Size(sigma1,sigma1));
num = float_gray - blur;
boxFilter(num.mul(num),blur,num.depth(),Size(sigma2,sigma2));
// denominator = sqrt(gauss_blur(img^2))
cv::pow(blur, 0.5, den);
// output = numerator / denominator
gray = num / den;
// normalize output into [0,1]
cv::normalize(gray, gray, 0.0, 1.0, NORM_MINMAX, -1);
return gray;
}
效果如下,可以看到原先不是很明顯的血管得到了有效的增強。
進一步可以EqualHist 、Clahe甚至Frangi,但這裏不是重點。
三、這種圖像算法運用到動態視頻的過程中會出現什麼新的問題,如何解決這些問題。
現在看來,一切都很美好,預期的目的也基本實現了。但是當將代碼移動到視頻的時候就會發現一個比較嚴重的問題:屏幕閃動比較厲害,造成用戶體驗很差。
這個時候我在思考,如果出現這種情況,一般上是因爲局部的運算造成了整體的均值的變化。本來想通過一些平滑的方法去除這個變化,但是效果都不是很好。一個偶爾的機會我採用photoshop對這個此時產生的圖像進行了曲線計算。
可以發現直方圖非常的窄。這個時候我想起以前在做美顏算法的時候,有一個從GIMP中挖過來的"對比度自動調節"函數。拿來使用,對於單幅圖像,可以將對比度進行拉昇,而且效果不錯。更爲關鍵的是對於連續的視頻,很好地去除了抖動的效果。
四、小結
到目前爲止,LocalNormalization這個問題算是比較好的解決了。反思解決問題的關鍵點,一個是平時的積累,這個包括經驗的積累和資料的積累;一個是朋友和網絡的支持;還有一個就是項目的拉動。總的來說,還是“產、學、研”的協力拉動,才能夠產出好的產品。