目录
- 分段线性变换
- 对比度拉伸
- 最大最小值拉伸
分段线性变换
-
优点
-
形式可以任意复杂
-
缺点
-
要求用户输入很多参数
对比度拉伸
光照不足、成像传感器的动态范围偏小、图像获取过程中镜头孔径的设置错误
点(r1,s1)和点(r2,s2)(r_1, s_1)和点(r_2, s_2)(r1,s1)和点(r2,s2)的位置控制变换函数的形状
图3,令(r1,s1)=(rmin,0),(r2,s2)=(rmax,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,令(r1,s1)=(m,0),(r2,s2)=(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 stretchuse loop can get right image, but numpy still work, but the return image is more bright(if un normalize, then can get rightresult)"""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 stretchuse loop can get right image, but numpy still work, but the return image is more bright(if un normalize, then can get rightresult)"""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)*ielif i < x2:lut[i] = ((y2-y1)/(x2-x1))*(i-x1)+y1else:lut[i] = ((y2-255.0)/(x2-255.0))*(i-255.0)+255.0img_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, 1will be less, if scale very low, then become a binary fuction; if > 1, then the values between 0, 1 will be more, if scalevery 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 imageparam: input image: [0, 255] uint8 grayscale imageparam: input scale: use scale to change the slope of the stretch curvereturn 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 valueimg_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()