画像表現の異なるレベルに応じて、画像融合は、ピクセルレベル融合、特徴レベル融合、決定レベル融合の 3 つのレベルに分けることができます。次の図は、画像融合レベルの分割図です。
このうちピクセルレベル融合は最下位に位置し、情報から特徴を抽出してそのまま利用するだけと考えることができる。正確さと堅牢性の点で他の 2 つのレベルよりも優れているのは、まさに情報を最大限に保持するためです。対照的に、ピクセルレベルのフュージョンは、より豊富な詳細情報を取得し、最も一般的に使用されるフュージョン方法です。したがって、画像融合の分野でも注目の研究テーマです。同時に、高いレジストレーション精度が必要となるため、ピクセルレベルに達する必要があります。したがって、ピクセルレベルの画像融合技術には高い機器要件があり、融合プロセスには時間がかかり、リアルタイムで処理することが困難です。ピクセルレベルの融合は通常、前処理、変換、合成、逆変換の 4 つのステップで完了します。
私が現在取り組む必要があるタスクは、Sar と Optical の光学画像の融合と分割であり、融合には、非マルチスケール変換に基づく ISH 色空間融合法と、ラプラス ピラミッド変換に基づく画像融合法の2 つの方法を使用しました。 。
非マルチスケール変換に基づくISH色空間融合法
IHS カラー モデルは、人々の直感的なカラー マッチング方法に適しているため、カラー画像処理に最も一般的に使用されるカラー モデルとなっています。強度は、画像の空間解像度に対応する、スペクトル全体の明るさを表します。色相は、スペクトルの主波長によって決定される純色の特性を表します。スペクトル間の定性的な違いです。彩度は、比率を表します。スペクトルの主波長の強度、色相、彩度は画像のスペクトル解像度を表します。
RGB モデルと比較して、IHS モデルは人間の目が色を記述および解釈する方法とより一致していますが、同時に I、H、S の 3 つの基本特性が互いに独立しているため、IHS モデルは次のようになります。この方法では、カラー画像に含まれる色情報 (色相と彩度) と無色の光の強度情報 (明るさ) が別々に処理されます。
IHS 変換式
IHS 空間画像融合法は、カラー画像を表現する際に IHS モデルを利用しており、リモート センシング画像の融合処理によく使用されます。マルチスペクトル画像の空間解像度を向上させながらそのスペクトル情報を維持するために、低空間解像度マルチスペクトル画像と高空間解像度パンクロマティック画像を IHS 空間で融合して、マルチスペクトル画像を RGB 画像モデルから IHS モデルに変換できます。 、マルチスペクトル画像の空間解像度 I を反映する成分を IHS 空間のパンクロマティック画像と融合し、次に融合結果を RGB 空間に逆変換して、融合後に空間解像度が向上したマルチスペクトル画像を取得します。
ISH 画像融合処理手順:
① マルチスペクトル画像の R、G、B バンドを IHS 空間に変換して、I、H、S の 3 つの成分を取得します; ② パンクロマティック画像と
マルチスペクトル画像の IHS 変換後に得られた輝度成分を、フュージョンルールに基づいて所定のフュージョンを行い、新たな輝度成分(フュージョン成分)I'を得る;
③輝度成分をステップ2で得たフュージョン成分I'に置き換え、Hとフュージョン成分とともにRGB空間に変換するS 成分画像を取得し、最終的に融合画像を取得します。
ISH画像融合プログラム:
img_process.py
import cv2
from PIL import Image
import numpy as np
from osgeo import gdal
class ImgProcess:
def IHS(self, data_low, data_high):
"""
基于IHS变换融合算法
输入:np.ndArray格式的三维数组
返回:可绘出图像的utf-8格式的三维数组
"""
A = [[1. / 3., 1. / 3., 1. / 3.], [-np.sqrt(2) / 6., -np.sqrt(2) / 6., 2 * np.sqrt(2) / 6],
[1. / np.sqrt(2), -1. / np.sqrt(2), 0.]]
# RGB->IHS正变换矩阵
B = [[1., -1. / np.sqrt(2), 1. / np.sqrt(2)], [1., -1. / np.sqrt(2), -1. / np.sqrt(2)], [1., np.sqrt(2), 0.]]
# IHS->RGB逆变换矩阵
A = np.matrix(A)
B = np.matrix(B)
band, w, h = data_high.shape
pixels = w * h
data_low = data_low.reshape(3, pixels)
data_high = data_high.reshape(3, pixels)
a1 = np.dot(A, np.matrix(data_high)) # 高分影像正变换
a2 = np.dot(A, np.matrix(data_low)) # 低分影像正变换
a2[0, :] = a2[0, :] *0.3 + a1[0, :]*0.7 # 用高分影像第一波段替换低分影像第一波段
# a2[0, :] = a1[0, :] # 用高分影像第一波段替换低分影像第一波段
RGB = np.array(np.dot(B, a2)) # 融合影像逆变换
RGB = RGB.reshape((3, w, h))
min_val = np.min(RGB.ravel())
max_val = np.max(RGB.ravel())
RGB = np.uint8((RGB.astype(np.float) - min_val) / (max_val - min_val) * 255)
RGB = Image.fromarray(cv2.merge([RGB[0], RGB[1], RGB[2]]))
return RGB
def imresize(self, data_low, data_high):
"""
图像缩放函数
输入:np.ndArray格式的三维数组
返回:np.ndArray格式的三维数组
"""
band, col, row = data_high.shape
data = np.zeros(((band, col, row)))
for i in range(0, band):
# data[i] = smi.imresize(data_low[i], (col, row))
data[i] = cv2.resize(data_low[i], (col, row))
return data
def gdal_open(self, path):
"""
读取图像函数
输入:图像路径
返回:np.ndArray格式的三维数组
"""
data = gdal.Open(path)
col = data.RasterXSize # 读取图像长度
row = data.RasterYSize # 读取图像宽度
data_array_r = data.GetRasterBand(1).ReadAsArray(0, 0, col, row).astype(np.float) # 读取图像第一波段并转换为数组
data_array_g = data.GetRasterBand(2).ReadAsArray(0, 0, col, row).astype(np.float) # 读取图像第二波段并转换为数组
data_array_b = data.GetRasterBand(3).ReadAsArray(0, 0, col, row).astype(np.float) # 读取图像第三波段并转换为数组
data_array = np.array((data_array_r, data_array_g, data_array_b))
return data_array
main.py
from tools.img_process import ImgProcess
if __name__ == "__main__":
img_p = ImgProcess()
path_low = '/home/workstation8/Research/segformer-pytorch-diploma/VOCdevkit/DFC2023/JPEGImages'
path_high = '/home/workstation8/Research/segformer-pytorch-diploma/VOCdevkit/DFC2023/SAR-JPEGImages-3c-temp'
save_path = '/home/workstation8/Research/segformer-pytorch-diploma/VOCdevkit/DFC2023/IHSFusion-O-S-I/'
img_p.makeDir(save_path)
for img_name in os.listdir(path_high):
data_low = img_p.gdal_open(os.path.join(path_low, img_name))
data_high = img_p.gdal_open(os.path.join(path_high, img_name))
data_low = img_p.imresize(data_low, data_high)
RGB = img_p.IHS(data_low, data_high)
RGB.save(os.path.join(save_path, img_name))
ラプラスピラミッド変換に基づく画像融合法
画像ピラミッドの概要
画像ピラミッドはマルチスケール表現の一種で、複数の解像度で画像を解釈するための効果的ですが概念的に単純な構造です。画像のピラミッドは、同じ元の画像に由来し、徐々に解像度が低下するピラミッド型に配置されたコレクションです。ラダーダウンサンプリングにより、一定の終了条件までサンプリングが停止しません。
端的に言えば、画像ピラミッドは、ピラミッドに扮した画像スケーリングです。一般に、ガウス画像ピラミッドとラプラシアン画像ピラミッドがあります。
ラプラシアン ピラミッド (バンドパス ピラミッド)
ラプラシアン ピラミッド: イメージを再構築する、つまり残差を予測して、イメージを最大限に復元するために使用されます。
小さな画像を大きな画像に再構成する原理: ガウス ピラミッドの各層から、前の層の画像のアップサンプリングとガウス畳み込み後の予測画像を減算し、LP 分解画像である一連の差分画像を取得します。
ラプラシアン ピラミッドでは、画像のダウンサンプリングとアップサンプリングの結果と元の画像の残差を計算することで、欠落している情報を実際に保存します。式は次のとおりです。
L ( i ) = G ( i ) − P yr U p ( G ( i + 1 ) ) L ( i ) = G ( i ) − P yr U p ( G ( i + 1 ) ) L ( i ) = G ( i ) − P yr U p ( G ( i + 1 ) ) L ( i ) = G ( i ) − P yr U p ( G ( i + 1 ) ) L(i) = G(i) - PyrUp( G(i + 1)) L(i)=G(i)−PyrUp(G(i+1))L ( i )=G ( i )−Pyr Up ( G ( i _ _+1 )) L ( i )=G ( i )−Pyr Up ( G ( i _ _+1 )) L ( i )=G ( i )−Pyr Up ( G ( i _ _+1 ))
つまり、ラプラシアンピラミッドは、実際には復元画像の準備となる上記の残像から構成されるピラミッドである。各画像のラプラシアン ピラミッドを取得した後、最終的に画像を復元するには、対応するレベルの画像を融合する必要があります。ラプラシアンピラミッドは画像情報を正確に復元することができます。画像を復元するプロセスが再構成プロセスです。
ラプラスピラミッド融合の手順:
① 2 つの画像のそれぞれに対してガウス ダウンサンプリングを実行します。
② 2 つの画像のラプラス ピラミッドをそれぞれ見つけます。
③ 特定の重みに従って 2 つの画像のラプラス ピラミッドを融合します。
④ 融合されたラプラス ピラミッドを再構成して、融合された画像を取得します。
L' = W 1 × L s + W 2 × L o L'= W~1~ × L~s~ + W~2~ × L~o~L '=W1 _ ×Ls _ +W2 _ ×ロ_
この融合プロジェクトでは、上記の手順③の重み付け融合は、SAR画像とOPT画像のラプラスピラミッドをそれぞれ計算した後、特定の重みw1とw2を加算して融合します。多くのパラメーター調整の結果、w1:w2 = 0.2:0.8 のときに最良の特徴が抽出されることがわかりました。
ラプラスピラミッド融合手順
fusion_process.py
# -*- coding:utf-8 -*-
__author__ = 'Microcosm'
import cv2
import matplotlib as mpl
import os
mpl.use('TKAgg')
class LP_Fusion():
def makeDir(self, path):
"""
如果path路径不存在,则创建
:param path:
:return:
"""
if not os.path.exists(path):
os.makedirs(path)
def sameSize(self, img1, img2):
"""
使得img1的大小与img2相同
"""
rows, cols, dpt = img2.shape
dst = img1[:rows, :cols]
return dst
def pyrDown(self, img, layer):
"""
下采样生成高斯金字塔
Args:
img:
layer:
Returns:
"""
G = img.copy()
gp_img = [G]
for i in range(layer):
G = cv2.pyrDown(G)
gp_img.append(G)
return gp_img
def get_lp(self, gp_img, layer):
"""
生成拉普拉斯金字塔【等于「高斯金字塔中的第i层」与「高斯金字塔中的第i+1层的向上采样结果」之差】
Args:
gp_img:
layer:
Returns:
"""
lp_img = [gp_img[layer]]
for i in range(layer, 0, -1): # [6, 5, 4, 3, 2, 1]
GE = cv2.pyrUp(gp_img[i])
L = cv2.subtract(gp_img[i - 1], self.sameSize(GE, gp_img[i - 1]))
lp_img.append(L)
return lp_img
def fusion(self, lp_img_1, lp_img_2):
"""
图像融合重建
Args:
lp_img_1:
lp_img_2:
Returns:
"""
LS = []
for la, lb in zip(lp_img_1, lp_img_2):
rows, cols, dpt = la.shape
ls = la
# print(type(ls))
ls = la*0.8 + lb*0.2
LS.append(ls)
return LS
def pyrUp(self, LS, layer):
"""
上采样 并与 拉普拉斯相加 恢复原始状态
Args:
LS:
layer:
Returns:
"""
ls_reconstruct = LS[0]
for i in range(1, layer):
# print(LS[i])
ls_reconstruct = cv2.pyrUp(ls_reconstruct)
ls_reconstruct = cv2.add(self.sameSize(ls_reconstruct, LS[i]), LS[i])
# print("ls_reconstruct {}".format(ls_reconstruct.shape))
return ls_reconstruct
main.py
from tools.fusion_process import LP_Fusion
import cv2
import os
from tqdm import tqdm, trange
from matplotlib import pyplot as plt
if __name__ == "__main__":
lp_p = LP_Fusion()
# 层数-1
layer = 1
# img_p = ImgProcess()
img1_path = '/home/workstation8/Research/segformer-pytorch-diploma/VOCdevkit/DFC2023/JPEGImages'
img2_path = '/home/workstation8/Research/segformer-pytorch-diploma/VOCdevkit/DFC2023/SAR-JPEGImages'
save_path = '/home/workstation8/Research/segformer-pytorch-diploma/VOCdevkit/DFC2023/LPFusion/LPFusion-{}L-8O-2S'.format(layer)
layer -= 1
lp_p.makeDir(save_path)
for index in tqdm(range(len(os.listdir(img2_path))), colour='BLUE'):
img_name_list = os.listdir(img2_path)
img_1 = cv2.imread(os.path.join(img1_path, img_name_list[index]))
img_2 = cv2.imread(os.path.join(img2_path, img_name_list[index]))
# 对img_1进行layer层高斯降采样
gp_img_1 = lp_p.pyrDown(img_1, layer=layer)
# 对img_2进行layer层高斯降采样
gp_img_2 = lp_p.pyrDown(img_2, layer=layer)
# 求img_1的Laplace金字塔
lp_img_1 = lp_p.get_lp(gp_img_1, layer)
# 求img_2的Laplace金字塔
lp_img_2 = lp_p.get_lp(gp_img_2, layer)
# # 对img_1和img_2的Laplace金字塔进行融合
LS = lp_p.fusion(lp_img_1, lp_img_2)
# 对融合后的Laplace金字塔重建获取融合后的结果
ls_reconstruct = lp_p.pyrUp(LS, layer+1)
# 保存
cv2.imwrite(os.path.join(save_path, img_name_list[index]), ls_reconstruct)
# # 可视化
# new_img = plt.imread(os.path.join(save_path, img_name))
# plt.imshow(new_img)
# plt.show()