图像对比度归一化 python

contrast normalization of image python

我想问一下如何使用python代码得到图像结果(图标),如

中所示

其中 ishade 是预处理图像,std(Ishade) 是该图像的标准差

result = ndimage.median_filter(blur, size=68)
std=cv2.meanStdDev(result)

我不确定我明白你想要什么。有不同类型的归一化公式。

最常见的方法是从图像中减去均值,然后除以标准差。 (I-mean(I))/std(I)

但是如果你想做你的公式,I/std(I),那么可以按如下方式完成:

输入:

import cv2
import numpy as np
import skimage.exposure

# load image
img = cv2.imread("lena.jpg")

# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).astype(np.float64)/255

# get local mean from blurred gray image and square it
sigma=15
mean = cv2.GaussianBlur(gray, (0,0), sigmaX=sigma, sigmaY=sigma)
mean_sq = cv2.multiply(mean,mean)

# get mean of gray image squared
gray2 = cv2.multiply(gray,gray)
mean2 = cv2.GaussianBlur(gray2, (0,0), sigmaX=sigma, sigmaY=sigma)

# get variance image from the two means
var = cv2.subtract(mean2, mean_sq)

# get the standard deviation image from the variance image
std = np.sqrt(var)
print(std.dtype, np.amax(std), np.amin(std))

# divide image by std and scale using skimage
divide = (255*cv2.divide(gray, std, scale=1)).clip(0,255).astype(np.uint8)
divide = skimage.exposure.rescale_intensity(divide, in_range='image', out_range=(0,255)).astype(np.uint8)
print(divide.dtype, np.amax(divide), np.amin(divide))

# write result to disk
cv2.imwrite("lena_std_division.jpg", divide)

# display it
cv2.imshow("std", std)
cv2.imshow("divide", divide)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果(取决于西格玛值):

我已经发布了许多示例的替代公式(称为除法归一化)是将图像除以其局部平均图像。 I/mean(I))

我试图按照您 post 编辑的参考文献中的文章以及 post 中的参考文献阅读原文。但我不明白他们到底在做什么。尽管如此,这是我的解释(除了最初的 CLAHE)。您可以根据需要调整均值和中值滤波器大小。

输入:

import cv2
import numpy as np
import skimage.exposure

# load image
img = cv2.imread("lena.jpg")

# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Gaussian blurred gray image
mean = cv2.GaussianBlur(gray, (0,0), sigmaX=5, sigmaY=5)

# apply median filter to mean image
median = cv2.medianBlur(mean, 25)

# divide mean by median
division = cv2.divide(mean.astype(np.float64)/255, median.astype(np.float64)/255)

# get global standard deviation of division
std = np.std(division)
print(std)

# divide the division by the std and normalize to range 0 to 255 as unint8
result = np.divide(division, std)
result = skimage.exposure.rescale_intensity(result, in_range='image', out_range=(0,255)).astype(np.uint8)
    
# write result to disk
cv2.imwrite("lena_std_division2.jpg", result)

# display it
cv2.imshow("mean", mean)
cv2.imshow("median", median)
cv2.imshow("division", division)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果: