第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波4 - 分段线性变换 - 对比度拉伸

分段线性变换

  • 优点

  • 形式可以任意复杂

  • 缺点

  • 要求用户输入很多参数

对比度拉伸

光照不足、成像传感器的动态范围偏小、图像获取过程中镜头孔径的设置错误

( 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,L1)
图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,L1)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()

在这里插入图片描述

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jasneik

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值