图像线性及非线性变换、图像融合
图像的线性、非线性变换
-
逐像素运算
逐像素运算就是对图像中的每个像素点的亮度值,通过一定的函数关系转换到新的亮度值。这个转换可以由函数关系表示 s = f ( r ) s=f(r) s=f(r)其中,r 表示原来的像素值,s 表示新的像素值。
通常采用单调函数进行变换。 -
线性变换
s ( x , y ) = k r ( x , y ) + c s(x,y)=kr(x,y) + c s(x,y)=kr(x,y)+c -
非线性变换
s ( x , y ) = a + l n ( r ( x , y ) + 1 ) b l n c s(x,y)=a+\frac{ln(r(x,y)+1)}{b\space lnc} s(x,y)=a+b lncln(r(x,y)+1)
其中a,b,c为常数 -
Gamma变换
s ( x , y ) = c r ( x , y ) γ s(x,y)=c\space r(x,y)^\gamma s(x,y)=c r(x,y)γgamma函数中 c=1 时,不同 γ \gamma γ值对应的函数图像如下
- 线性变换
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
def show(img):
if img.ndim == 2:
plt.imshow(img, cmap='gray')
else:
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.show()
img = cv.imread('cat.jpg', 0)
# 线性变换:s(x,y) = b + kr(x,y)
b = 20
k = 2
img2 = b + k * img.astype(np.float32) # 避免在变换过程中由超过255的值会继续循环到新的值
img2 = np.clip(img2, 0, 255) # 将img中小于0的值转为0,大于255的值转为255
show(np.hstack([img, img2]))
img3 = cv.convertScaleAbs(img, alpha=1.5, beta=10) # cv中的图像线性变换api:fx = alpha * img + bata
show(np.hstack([img, img2, img3]))
- 非线性变换
# 非线性变换:s(x,y)=a+(ln(r(x,y)+1))/(b*ln(c))
img4 = 10 + np.log(img.astype(np.float32) + 1) / 0.1
img4 = np.clip(img4, 0, 255)
show(img4)
3. Gamma变换
# Gamma变换:s(x,y)=cr(x,y)^Gamma
img01 = img / 255
img05 = np.power(img01, 0.5) * 255
img15 = np.power(img01, 1.5) * 255
show(np.hstack([img05, img, img15]))
图像融合
# 图像融合
A = cv.imread("flower.png")
B = cv.imread('hedgehog.png')
M = cv.imread('mask.png')
show(np.hstack([A, B, M]))
# 选中刺猬
M = M / 255
Bs = B * M
# 选中花
As = A * (1 - M)
# 两图融合
nice = As * 0.9 + Bs * 0.8 # 乘系数是为了边缘过渡自然
show(nice.astype(np.uint8))
cv.imwrite('nice.jpg', nice) # 保存图像
完整代码
# https://www.bilibili.com/video/BV1YA411K7pp?p=11
"""
图像的线性和非线性变换
逐像素运算就是对图像中的每个像素点的亮度值,通过一定的函数关系转换到新的亮度值,
这个转换可以由函数表示 s=f(r) 其中r为原来的像素值,s为新的像素值。通常采用的函数为单调函数进行变化。
线性变换: s(x,y) = b + kr(x,y)
非线性变换:s(x,y)=a+(ln(r(x,y)+1))/(b*ln(c))
其中,a,b,c为常数。
Gamma变换:s(x,y)=cr(x,y)^Gamma
"""
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
def show(img):
if img.ndim == 2:
plt.imshow(img, cmap='gray')
else:
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.show()
img = cv.imread('cat.jpg', 0)
# 线性变换:s(x,y) = b + kr(x,y)
b = 10
k = 1.5
img2 = b + k * img.astype(np.float32) # 转换数值为np.float32,避免在变换过程中由超过255的值会继续循环到新的值
img2 = np.clip(img2, 0, 255) # 将img中小于0的值转为0,大于255的值转为255
# show(np.hstack([img, img2]))
img3 = cv.convertScaleAbs(img, alpha=1.5, beta=10)
# show(np.hstack([img, img2, img3]))
# 非线性变换:s(x,y)=a+(ln(r(x,y)+1))/(b*ln(c))
img4 = 10 + np.log(img.astype(np.float32) + 1) / 0.1
img4 = np.clip(img4, 0, 255)
# show(img4)
# Gamma变换:s(x,y)=cr(x,y)^Gamma
img01 = img / 255
img05 = np.power(img01, 0.5) * 255
img15 = np.power(img01, 1.5) * 255
# show(np.hstack([img05, img, img15]))
# 图像融合
A = cv.imread("flower.png")
B = cv.imread('hedgehog.png')
M = cv.imread('mask.png')
show(np.hstack([A, B, M]))
# 选中刺猬
M = M / 255
Bs = B * M
# 选中花
As = A * (1 - M)
# 两图融合
nice = As * 0.9 + Bs * 0.8 # 乘系数是为了边缘过渡自然
show(nice.astype(np.uint8))
cv.imwrite('nice.jpg', nice) # 保存图像