分段线性变换
-
优点
-
形式可以任意复杂
-
缺点
-
要求用户输入很多参数
对比度拉伸
光照不足、成像传感器的动态范围偏小、图像获取过程中镜头孔径的设置错误
点 ( r 1 , s 1 ) 和 点 ( r 2 , s 2 ) (r_1, s_1)和点(r_2, s_2) (r1,s1)和点(r2,s2)的位置控制变换函数的形状
图3,令
(
r
1
,
s
1
)
=
(
r
m
i
n
,
0
)
,
(
r
2
,
s
2
)
=
(
r
m
a
x
,
L
−
1
)
(r_1, s_1) = (r_{min}, 0), (r_2, s_2) = (r_{max}, L-1)
(r1,s1)=(rmin,0),(r2,s2)=(rmax,L−1)
图4,令
(
r
1
,
s
1
)
=
(
m
,
0
)
,
(
r
2
,
s
2
)
=
(
m
,
L
−
1
)
,
m
是
平
均
灰
度
级
(r_1, s_1) = (m, 0), (r_2, s_2) = (m, L-1),m是平均灰度级
(r1,s1)=(m,0),(r2,s2)=(m,L−1),m是平均灰度级
def stretch_3(img):
"""
constrast stretch, $(r_1, s_1) = (r_{min}, 0), (r_2, s_2) = (r_{max}, L-1)$
return image stretch
use loop can get right image, but numpy still work, but the return image is more bright(if un normalize, then can get right
result)
"""
img_min = img.min()
img_max = img.max()
#---------------------loop-----------------------------
# img_dst = np.zeros(img.shape[:2], np.uint8)
# height, width = img.shape[:2]
# for h in range(height):
# for w in range(width):
# temp = img[h, w]
# if temp <= img_min:
# img_dst[h, w] = 0
# elif temp >= img_max:
# img_dst[h, w] = 255
# else:
# img_dst[h, w] = int(((temp - img_min) / img_max ) * 255)
#-----------------------numpy-----------------------
img_dst = np.piecewise(img, [img <= img_min, img <= img_max], [0, lambda x : (((x - img_min)/ img_max) * 255).astype(np.int)])
return img_dst
def stretch_4(img):
"""
constrast stretch, $(r_1, s_1) = (r_{min}, 0), (r_2, s_2) = (r_{max}, L-1)$
return image stretch
use loop can get right image, but numpy still work, but the return image is more bright(if un normalize, then can get right
result)
"""
img_min = np.mean(img).astype(np.int)
img_max = img.max()
#---------------------loop-----------------------------
# img_dst = np.zeros(img.shape[:2], np.uint8)
# height, width = img.shape[:2]
# for h in range(height):
# for w in range(width):
# temp = img[h, w]
# if temp <= img_min:
# img_dst[h, w] = 0
# elif temp > img_min:
# img_dst[h, w] = 255
# else:
# img_dst[h, w] = int(((temp - img_min) / img_max ) * 255)
#-----------------------numpy-----------------------
img_dst = np.piecewise(img, [img >= img_min], [lambda x : 255 if x.any() < img_min else 0])
return img_dst
# 对比度拉伸
img = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH03/Fig0310(b)(washed_out_pollen_image).tif', 0)
# For ploting the stretch curve
x = [0, 96, 182, 255]
y = [0, 30, 220, 255]
# subplot 3
img_subplot3 = stretch_3(img)
img_subplot3 = np.uint8(normalize(img_subplot3) * 255)
# subplot 4
img_subplot4 = stretch_4(img)
plt.figure(figsize=(16, 16))
plt.subplot(2, 2, 1), plt.plot(x, y), plt.title('s=T(r)')
plt.ylabel('Output Value', rotation=90)
plt.xlabel('Input Value', rotation=0)
plt.subplot(2, 2, 2), plt.imshow(img, cmap='gray', vmin=0, vmax=255), plt.title('Original')
plt.subplot(2, 2, 3), plt.imshow(img_subplot3, cmap='gray', vmin=0, vmax=255), plt.title('Transform 3')
plt.subplot(2, 2, 4), plt.imshow(img_subplot4, cmap='gray', vmin=0, vmax=255), plt.title('Transform 4')
plt.tight_layout()
plt.show()
def SLT(img, x1, x2, y1, y2):
"""
利用opencv, 实现对比度拉伸
"""
lut = np.zeros(256)
for i in range(256):
if i < x1:
lut[i] = (y1/x1)*i
elif i < x2:
lut[i] = ((y2-y1)/(x2-x1))*(i-x1)+y1
else:
lut[i] = ((y2-255.0)/(x2-255.0))*(i-255.0)+255.0
img_output = cv2.LUT(img, lut)
img_output = np.uint8(img_output+0.5)
return img_output
# opencv 对比度拉伸
img = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH03/Fig0310(b)(washed_out_pollen_image).tif').astype(np.uint8)
img_x1 = 100
img_x2 = 160
img_y1 = 50
img_y2 = 255
output_img = SLT(img, img_x1, img_x2, img_y1, img_y2)
plt.figure(figsize=(18, 15))
plt.subplot(1, 2, 1), plt.imshow(img, cmap='gray', vmin=0, vmax=255), plt.title('Original')
plt.subplot(1, 2, 2), plt.imshow(output_img, cmap='gray', vmin=0, vmax=255), plt.title('Transform')
plt.tight_layout()
plt.show()
def sigmoid(x, scale):
"""
simgoid fuction, return ndarray value [0, 1]
param: input x: array like
param: input scale: scale of the sigmoid fuction, if 1, then is original sigmoid fuction, if < 1, then the values between 0, 1
will be less, if scale very low, then become a binary fuction; if > 1, then the values between 0, 1 will be more, if scale
very high then become a y = x
"""
y = 1 / (1 + np.exp(-x / scale))
return y
def sigmoid_transform(image, scale):
"""
use sigmoid function to stretch constract of the image
param: input image: [0, 255] uint8 grayscale image
param: input scale: use scale to change the slope of the stretch curve
return an [0, 255] uint8 gracyscale image
"""
img_temp = image.copy().astype(float)
img_temp = img_temp - 127 # image.max() //2 because the max of input image might not be 255, so use fixed value
img_dst = 1 / (1 + np.exp(- img_temp / scale))
img_dst = np.uint8(normalize(img_dst) * 255.)
return img_dst
# 用Sigmoid函数也可以实现对比度的拉伸,这样就不需要输入过多的参数
img = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH03/Fig0310(b)(washed_out_pollen_image).tif', 0)
# For ploting the stretch curve
x = [0, 96, 182, 255]
y = [0, 30, 220, 255]
# sigmoid function plot
scale = 20
x1 = np.arange(0, 256, 1)
x2 = x1 - x1.max() // 2 # Here shift the 0 to the x center, here is 5, so x1 = [-5, 5]
t_stretch = sigmoid(x2, scale)
# subplot 3 use sigmoid fuction to transform image
img_sigmoid = sigmoid_transform(img, scale)
plt.figure(figsize=(16, 16))
plt.subplot(2, 2, 1), plt.plot(x, y), plt.title('s=T(r)')
plt.ylabel('Output Value', rotation=90)
plt.xlabel('Input Value', rotation=0)
plt.subplot(2, 2, 2), plt.plot(x1, t_stretch), plt.title('Sigmoid')
plt.ylabel('Output Value', rotation=90)
plt.xlabel('Input Value', rotation=0)
plt.subplot(2, 2, 3), plt.imshow(img, cmap='gray', vmin=0, vmax=255), plt.title('Original')
plt.subplot(2, 2, 4), plt.imshow(img_sigmoid, cmap='gray', vmin=0, vmax=255), plt.title('Transform 3')
plt.tight_layout()
plt.show()
最大最小值拉伸
def max_min_strech(img):
"""
min max stretch
"""
max1 = np.max(img)
min1 = np.min(img)
output_img = (255.0 * (img-min1)) / (max1 - min1) # 注意255.0 而不是255 二者算出的结果区别很大
output_img = np.uint8(output_img + 0.5)
return output_img
# 最大最小值拉伸
img = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH03/Fig0310(b)(washed_out_pollen_image).tif').astype(np.uint8)
output_img = max_min_strech(img)
plt.figure(figsize=(20, 10))
plt.subplot(1, 2, 1), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.subplot(1, 2, 2), plt.imshow(output_img, cmap='gray'), plt.title('Transform')
plt.tight_layout()
plt.show()
# 最大最小值拉伸
img = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH03/Fig0354(a)(einstein_orig).tif').astype(np.uint8)
output_img = max_min_strech(img)
plt.figure(figsize=(16, 10))
plt.subplot(1, 2, 1), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.subplot(1, 2, 2), plt.imshow(output_img, cmap='gray'), plt.title('Transform')
plt.tight_layout()
plt.show()