📜  Python|图像上的强度变换操作

📅  最后修改于: 2022-05-13 01:55:40.491000             🧑  作者: Mango

Python|图像上的强度变换操作

对图像应用强度变换以进行对比度处理或图像阈值处理。这些在空间域中,即它们直接在手头图像的像素上执行,而不是在图像的傅里叶变换上执行。

以下是常用的强度变换:

  1. 负片(线性)
  2. 日志转换
  3. 幂律 (Gamma) 变换
  4. 分段线性变换函数

空间域过程 –
空间域过程可以使用以下等式描述: g(x, y) = T[f(x, y)]在哪里f(x, y)是输入图像, T是在点(x, y)的邻域上定义的f上的运算符,并且g(x, y)是输出。

负片 -

本文讨论了图像底片。在数学上,假设图像从强度级别 0 变为 (L-1)。通常,L = 256。然后,负变换可以用表达式s = L-1-r来描述,其中 r 是初始强度级别,s 是像素的最终强度级别。这会产生摄影负片。

日志转换 –

在数学上,对数变换可以表示为s = clog(1+r) 。这里,s是输出强度,r>=0是像素的输入强度,c是缩放常数。 c 由255/(log (1 + m))给出,其中 m 是图像中的最大像素值。这样做是为了确保最终像素值不超过 (L-1) 或 255。实际上,对数变换将窄范围的低强度输入值映射到宽范围的输出值。

考虑以下输入图像。

下面是对图像应用对数转换的代码。

import cv2
import numpy as np
  
# Open the image.
img = cv2.imread('sample.jpg')
  
# Apply log transform.
c = 255/(np.log(1 + np.max(img)))
log_transformed = c * np.log(1 + img)
  
# Specify the data type.
log_transformed = np.array(log_transformed, dtype = np.uint8)
  
# Save the output.
cv2.imwrite('log_transformed.jpg', log_transformed)

下面是对数转换后的输出。

幂律(伽玛)变换 –

幂律 (gamma) 变换可以在数学上表示为s = cr^{\gamma} .伽玛校正对于在屏幕上正确显示图像很重要,以防止从具有不同显示设置的不同类型的显示器观看时图像变白或变暗。这样做是因为我们的眼睛以伽马形曲线感知图像,而相机以线性方式捕获图像。下面是应用 gamma 校正的Python代码。

import cv2
import numpy as np
  
# Open the image.
img = cv2.imread('sample.jpg')
  
# Trying 4 gamma values.
for gamma in [0.1, 0.5, 1.2, 2.2]:
      
    # Apply gamma correction.
    gamma_corrected = np.array(255*(img / 255) ** gamma, dtype = 'uint8')
  
    # Save edited images.
    cv2.imwrite('gamma_transformed'+str(gamma)+'.jpg', gamma_corrected)

下面是不同伽玛值的伽玛校正输出。

伽玛 = 0.1:

伽玛 = 0.5:

伽玛 = 1.2:

伽玛 = 2.2:

从输出和图表中可以看出,gamma>1(由对应于图表上的“n 次方”标签的曲线表示),像素强度降低,即图像变暗。另一方面,gamma<1(由图中对应于“nth root”标签的曲线表示),强度增加,即图像变得更亮。

分段线性变换函数 –

顾名思义,这些函数本质上并不完全是线性的。但是,它们在某些 x 间隔之间是线性的。最常用的分段线性变换函数之一是对比度拉伸。

对比度可以定义为:

Contrast =  (I_max - I_min)/(I_max + I_min)

此过程扩展了图像中的强度级别范围,使其跨越相机/显示器的全部强度。下图显示了对应于对比度拉伸的图表。

以 (r1, s1), (r2, s2) 作为参数,该函数通过实质上降低暗像素的强度并增加亮像素的强度来拉伸强度级别。如果r1 = s1 = 0r2 = s2 = L-1 ,则函数在图中变成一条直线虚线(没有效果)。该函数是单调递增的,因此像素之间的强度级别的顺序得以保留。

下面是执行对比度拉伸的Python代码。

import cv2
import numpy as np
  
# Function to map each intensity level to output intensity level.
def pixelVal(pix, r1, s1, r2, s2):
    if (0 <= pix and pix <= r1):
        return (s1 / r1)*pix
    elif (r1 < pix and pix <= r2):
        return ((s2 - s1)/(r2 - r1)) * (pix - r1) + s1
    else:
        return ((255 - s2)/(255 - r2)) * (pix - r2) + s2
  
# Open the image.
img = cv2.imread('sample.jpg')
  
# Define parameters.
r1 = 70
s1 = 0
r2 = 140
s2 = 255
  
# Vectorize the function to apply it to each value in the Numpy array.
pixelVal_vec = np.vectorize(pixelVal)
  
# Apply contrast stretching.
contrast_stretched = pixelVal_vec(img, r1, s1, r2, s2)
  
# Save edited image.
cv2.imwrite('contrast_stretch.jpg', contrast_stretched)

输出: