一、简介
首先TIF是Two-Scale Image Fusion的缩写,论文《Two-Scale Image Fusion of Infrared and Visible Images Using Saliency Detection (TIF)》,作者在论文中提到TIF算法主要通过以下三个步骤实现融合:
-
图像分解,图像分解使用的是均值滤波器获取图像的基础(base)和细节(detail)层;
-
图像融合,对待基础和细节层分别使用不同的融合算法;
-
图像重建 ,从融合后的基础和细节层重建图像。
二、详细介绍
2.1 图像分解
考虑到原始的同样大小(宽高)两幅图像 ϕ 1 ( x , y ) \phi_{1}(x,y) ϕ1(x,y) , ϕ 2 ( x , y ) \phi_{2}(x,y) ϕ2(x,y),将这两幅图像分解为基础层(base)和细节(detail)层,作者在文中使用了均值滤波器来生成基础层和细节层(文中作者通过验证,使用的均值滤波窗口大小为35)。
ϕ 1 B ( x , y ) = ϕ 1 ( x , y ) ∗ μ ( x , y ) \phi_{1}^{B}(x, y)=\phi_{1}(x, y) * \mu(x, y) ϕ1B(x,y)=ϕ1(x,y)∗μ(x,y)
ϕ 2 B ( x , y ) = ϕ 2 ( x , y ) ∗ μ ( x , y ) \phi_{2}^{B}(x, y)=\phi_{2}(x, y) * \mu(x, y) ϕ2B(x,y)=ϕ2(x,y)∗μ(x,y)
在得到基础层之后,通过原始图像与基础层图像得到细节层图像。
ϕ 1 D ( x , y ) = ϕ 1 ( x , y ) − ϕ 1 B ( x , y ) \phi_{1}^{D}(x, y)=\phi_{1}(x, y) - \phi_{1}^{B}(x, y) ϕ1D(x,y)=ϕ1(x,y)−ϕ1B(x,y)
ϕ 2 D ( x , y ) = ϕ 2 ( x , y ) ∗ ϕ 2 B ( x , y ) \phi_{2}^{D}(x, y)=\phi_{2}(x, y) * \phi_{2}^{B}(x, y) ϕ2D(x,y)=ϕ2(x,y)∗ϕ2B(x,y)
基于可视显著检测理论,作者在文中使用了一种很有效的可视显著检测方法,就是用均值滤波(作者通过验证,使用的中值窗口大小为3)得到的图像减去中值滤波得到的图像,并取绝对值。
ξ ( x , y ) = ∣ ϕ u ( x , y ) − ϕ η ( x , y ) ∣ \xi(x,y)=|\phi_u(x,y)-\phi_\eta(x,y)| ξ(x,y)=∣ϕu(x,y)−ϕη(x,y)∣
如果是RGB图像的话,使用L2-norm或欧拉距离的方法:
ξ ( x , y ) = d e ( ϕ u , ϕ η ) = ( ϕ u R − ϕ η R ) 2 + ( ϕ u G − ϕ η G ) 2 + ( ϕ u B − ϕ η B ) 2 \xi(x,y)=de(\phi_u,\phi_\eta)=\sqrt{(\phi_u^R-\phi_\eta^R)^2+(\phi_u^G-\phi_\eta^G)^2+(\phi_u^B-\phi_\eta^B)^2} ξ(x,y)=de(ϕu,ϕη)=(ϕuR−ϕηR)2+(ϕuG−ϕηG)2+(ϕuB−ϕηB)2
对于原始的输入图像 ϕ 1 ( x , y ) \phi_{1}(x,y) ϕ1(x,y) , ϕ 2 ( x , y ) \phi_{2}(x,y) ϕ2(x,y),通过分别计算可以得到 ξ 1 ( x , y ) \xi_{1}(x,y) ξ1(x,y) , ξ 2 ( x , y ) \xi_{2}(x,y) ξ2(x,y)通过这两个矩阵,得到detail层的融合系数矩阵。
ψ 1 ( x , y ) = ξ 1 ( x , y ) ξ 1 ( x , y ) + ξ 2 ( x , y ) \psi_1(x,y)=\frac{\xi_1(x,y)}{\xi_1(x,y)+\xi_2(x,y)} ψ1(x,y)=ξ1(x,y)+ξ2(x,y)ξ1(x,y)
ψ 2 ( x , y ) = ξ 2 ( x , y ) ξ 1 ( x , y ) + ξ 2 ( x , y ) \psi_2(x,y)=\frac{\xi_2(x,y)}{\xi_1(x,y)+\xi_2(x,y)} ψ2(x,y)=ξ1(x,y)+ξ2(x,y)ξ2(x,y)
2.2 图像融合
基础层的融合,使用平均的策略进行融合:
ϕ B ( x , y ) = 1 2 ( ϕ 1 B ( x , y ) + ϕ 2 B ( x , y ) ) \phi^B(x,y)=\frac{1}{2}(\phi_1^B(x,y)+\phi_2^B(x,y)) ϕB(x,y)=21(ϕ1B(x,y)+ϕ2B(x,y))
细节层的融合,使用加权平均的策略进行融合,二加权矩阵就是之前求得的 ψ 1 ( x , y ) \psi_1(x,y) ψ1(x,y), ψ 2 ( x , y ) \psi_2(x,y) ψ2(x,y)
ϕ D ( x , y ) = ψ 1 ( x , y ) ϕ 1 D ( x , y ) + ψ 2 ( x , y ) ϕ 2 D ( x , y ) \phi^D(x,y)=\psi_1(x,y)\phi_1^D(x,y)+\psi_2(x,y)\phi_2^D(x,y) ϕD(x,y)=ψ1(x,y)ϕ1D(x,y)+ψ2(x,y)ϕ2D(x,y)
2.3 图像重建
在得到基础层和细节层之后,通过简单的加法多基础层和细节层进行融合:
γ ( x , y ) = ϕ B ( x , y ) + ϕ D ( x , y ) \gamma(x,y)=\phi^B(x,y)+\phi^D(x,y) γ(x,y)=ϕB(x,y)+ϕD(x,y)
三、python实现
python
import numpy as np
import cv2
import argparse
def TIF_GRAY(img_r, img_v):
img_r_blur = cv2.blur(img_r, (35,35))
img_v_blur = cv2.blur(img_v, (35,35))
img_r_median = cv2.medianBlur(img_r, 3)
img_v_median = cv2.medianBlur(img_v, 3)
img_r_detail = img_r*1. - img_r_blur*1.
img_v_detail = img_v*1. - img_v_blur*1.
img_r_the = cv2.pow(cv2.absdiff(img_r_median,img_r_blur), 2)
img_v_the = cv2.pow(cv2.absdiff(img_v_median ,img_v_blur),2)
img_r_weight = cv2.divide(img_r_the*1.,img_r_the*1.+img_v_the*1.+0.000001)
img_v_weight = 1- img_r_weight
img_base_fused = (img_r_blur*1. + img_v_blur*1.) / 2
img_detail_fused = img_r_weight * img_r_detail + img_v_weight * img_v_detail
img_fused_tmp = (img_base_fused + img_detail_fused).astype(np.int32)
#first method to change <0 to 0 and > 255 to 255
img_fused_tmp[img_fused_tmp<0] = 0
img_fused_tmp[img_fused_tmp>255]=255
#second method to change value to[0,255] using minmax method
#cv2.normalize(img_fused_tmp,img_fused_tmp,0,255,cv2.NORM_MINMAX)
img_fused = cv2.convertScaleAbs(img_fused_tmp)
return img_fused
def TIF_RGB(img_r, img_v):
fused_img = np.ones_like(img_r)
r_R = img_r[:,:,2]
v_R = img_v[:,:,2]
r_G = img_r[:,:,1]
v_G = img_v[:,:,1]
r_B = img_r[:,:,0]
v_B = img_v[:,:,0]
fused_R = TIF_GRAY(r_R, v_R)
fused_G = TIF_GRAY(r_G, v_G)
fused_B = TIF_GRAY(r_B, v_B)
fused_img[:,:,2] = fused_R
fused_img[:,:,1] = fused_G
fused_img[:,:,0] = fused_B
return fused_img
def TIF(_rpath, _vpath):
img_r = cv2.imread(_rpath)
img_v = cv2.imread(_vpath)
if not isinstance(img_r, np.ndarray) :
print('img_r is null')
return
if not isinstance(img_v, np.ndarray) :
print('img_v is null')
return
if img_r.shape[0] != img_v.shape[0] or img_r.shape[1] != img_v.shape[1]:
print('size is not equal')
return
fused_img = None
if len(img_r.shape) < 3 or img_r.shape[2] ==1:
if len(img_v.shape) < 3 or img_v.shape[-1] ==1:
fused_img = TIF_GRAY(img_r, img_v)
else:
img_v_gray = cv2.cvtColor(img_v, cv2.COLOR_BGR2GRAY)
fused_img = TIF_GRAY(img_r, img_v)
else:
if len(img_v.shape) < 3 or img_v.shape[-1] ==1:
img_r_gray = cv2.cvtColor(img_r, cv2.COLOR_BGR2GRAY)
fused_img = TIF_GRAY(img_r_gray, img_v)
else:
fused_img = TIF_RGB(img_r, img_v)
cv2.imshow('fused image', fused_img)
cv2.imwrite("fused_image_tif.jpg", fused_img)
cv2.waitKey(0)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-r', type=str, default='ir.png' ,help='input IR image path', required=False)
parser.add_argument('-v', type=str, default= 'vr.png',help='input Visible image path', required=False)
args = parser.parse_args()
TIF(args.r, args.v)