图像哈希1:基于四元数离散傅里叶变换和对数极坐标的鲁棒图像哈希算法,复现论文
图像哈希系列:
图像哈希1:基于四元数离散傅里叶变换和对数极坐标的鲁棒图像哈希算法
图像哈希2:基于环形分区和NMF的鲁棒感知图像哈希(CCF A)
图像哈希3:基于四元数离散余弦变换的鲁棒感知图像哈希研究(性能优于近年一些较好的研究)
图像哈希4:基于四元数 SVD 的奇异值的鲁棒图像哈希
未完待续…
欢迎交流
基于四元数离散傅里叶变换和对数极坐标的鲁棒图像哈希算法
论文:Robust hashing for image authentication using quaternion discrete Fourier transform and log-polar transform 论文链接
doi:https://doi.org/10.1016/j.dsp.2015.03.006
摘要:本文基于四元离散傅里叶变换(QDFT)与对数极性变换的结合,提出了一种用于图像认证的新型鲁棒图像散列方案。QDFT 为联合处理彩色图像的三个通道提供了一种可靠的方法。本方法的主要特点在于:(i) 使用对数极性变换计算二次图像;(ii) 从二次图像中提取低频 QDFT 系数的幅度。根据这些幅度系数的相关性生成最终图像哈希值,并用密钥进行加扰处理,以增强系统的安全性。为了分析和确定所提方法最合适的参数值,并从ROC曲线的角度将其性能与一些参考方法进行比较,我们进行了实验。结果表明,提出的方案对图像攻击的改变具有良好的灵敏度,对常见的攻击操作操作,尤其是大角度旋转操作具有鲁棒性。
关键词: 鲁棒图像哈希,四元离散傅里叶变换,log极性变换,图像认证
介绍
随着复杂图像编辑工具的广泛使用,图像内容很容易被篡改或伪造。因此,在许多应用中,验证图像的真实性是一个重要问题。稳健的图像散列被广泛应用于图像认证中。从原理上讲,图像散列方法提取图像的基本特征,并从中生成一个简短的二进制或实数序列(称为哈希序列)来表示图像内容。这样的哈希值应该对图像内容保护操作具有鲁棒性,同时对恶意篡改操作敏感。由于鲁棒图像散列能捕捉图像的主要特征,因此它在其他应用中也备受关注,如图像取证、图像检索、数字水印等。在图像认证方面,稳健的图像哈希值还应具有良好的抗碰撞(判别)能力,以识别视觉上不同的图像,并具有令人满意的安全级别,使对手很难伪造哈希值。要同时满足这些要求,构建鲁棒图像散列仍是一项具有挑战性的任务。
一般来说,图像哈希的构建基于三个基本步骤,即预处理、图像特征提取和哈希的构建。其中,最关键的当然是图像特征提取步骤。
当应用于彩色图像时,大多数方案都会将三个颜色通道(即红、绿、蓝或 RGB)转换为灰度图像,同时忽略色度信息。然而,利用色度信息不仅可以提高检测性能,而且由于哈希值同时包含亮度和色度信息,还可以增加图像伪造的难度。四元数可以在不放弃色度信息的情况下,为同时处理三个颜色通道提供一种合理的方法。四元数已成功应用于彩色图像配准、图像分析和水印。最近,四元离散傅里叶变换(QDFT)被用于生成图像散列并应用于图像检索 。通过遵循相同的路径,我们提出了一种基于 QDFT 和对数极性变换的新型图像散列方法,用于图像认证。QDFT 可以同时处理彩色图像的三个通道(RGB),而不会丢弃色度信息。与 DFT 相似,QDFT 的低频系数包含图像的主要能量,代表图像的基本特征。此外,QDFT 还可与对数极性变换相结合,从而获得一组旋转不变的特征。因此,我们建议利用这里使用的 QDFT 来构建一种新颖、紧凑的图像哈希算法,它对内容保护操作和几何攻击具有鲁棒性,同时对恶意篡改操作也很敏感。
基础知识
四元数
四元数是复数的泛化,有四个部分:一个实部和三个虚部,可以写成:
q
=
a
+
b
i
+
c
j
+
d
k
q=a+bi+cj+dk
q=a+bi+cj+dk
其中 a , b , c 和 d 是实数,i, j 和 k 是服从以下规则的虚部:
i
2
=
j
2
=
k
2
=
−
1
,
i
j
=
−
j
i
=
k
,
j
k
=
−
k
j
=
i
,
k
i
=
−
i
k
=
j
i^2=j^2=k^2=-1,ij=-ji=k,jk=-kj=i,ki=-ik=j
i2=j2=k2=−1,ij=−ji=k,jk=−kj=i,ki=−ik=j
四元数的乘法规则不是交换式的。四元数 q 的共轭和模数分别定义如下:
q
‾
=
a
−
b
i
−
c
j
−
d
k
,
∣
q
∣
=
a
2
+
b
2
+
c
2
+
d
2
.
\overline q=a-bi-cj-dk,\left|q\right|=\sqrt{a^2+b^2+c^2+d^2}.
q=a−bi−cj−dk,∣q∣=a2+b2+c2+d2.
具有零实部的四元数 q 称为纯四元数。空间位置(x, y)上彩色图像f的一个像素有三个分量,可以表示为纯四元数:
f
(
x
,
y
)
=
f
R
(
x
,
y
)
i
+
f
G
(
x
,
y
)
j
+
f
B
(
x
,
y
)
k
,
f(x,y)=f_R(x,y)i+f_G(x,y)j+f_B(x,y)k,
f(x,y)=fR(x,y)i+fG(x,y)j+fB(x,y)k,
f
R
(
x
,
y
)
,
f
G
(
x
,
y
)
,
f
B
(
x
,
y
)
f_R(x,y),f_G(x,y),f_B(x,y)
fR(x,y),fG(x,y),fB(x,y)分别是
f
(
x
,
y
)
f(x,y)
f(x,y)的RGB分量值。
四元数离散傅里叶变换
Ell首次在图像处理社区中引入四元数或超复傅里叶变换。由于四元数乘法的非交换性质,QDFT有三种不同类型的,即右侧、左侧和两侧。由于右侧 QDFT 可以以与左侧 QDFT 类似的方式处理,左侧 DQFT 或右侧 QDFT 的操作比两侧 QDFT 的操作要容易得多,我们决定使用左侧 QDFT。对于大小为M × M的彩色图像f(x, y), QDFT及其逆变换IQDFT定义如下:
F
(
u
,
v
)
=
1
M
∑
x
=
0
M
−
1
∑
y
=
0
M
−
1
e
−
2
μ
(
u
x
M
+
v
y
M
)
f
(
x
,
y
)
,
f
(
x
,
y
)
=
1
M
∑
μ
=
0
M
−
1
∑
v
=
0
M
−
1
e
2
μ
π
(
u
x
M
+
v
y
M
)
F
(
u
,
v
)
F(u,v)=\frac1M\sum_{x=0}^{M-1}\sum_{y=0}^{M-1}e^{-2\mu\left(\frac{ux}M+\frac{vy}M\right)}f(x,y),\\f(x,y)=\frac1M\sum_{\mu=0}^{M-1}\sum_{v=0}^{M-1}e^{2\mu\mathrm\pi\left(\frac{\mathrm{ux}}{\mathrm M}+\frac{\mathrm{vy}}{\mathrm M}\right)}F(u,v)
F(u,v)=M1x=0∑M−1y=0∑M−1e−2μ(Mux+Mvy)f(x,y),f(x,y)=M1μ=0∑M−1v=0∑M−1e2μπ(Mux+Mvy)F(u,v)
其中
μ
\mu
μ是任何单位纯四元数,可以定义为i、j和k的线性组合.
提出的方案
方案流程图
方案流程图
方案流程图
预处理
以 Lena 测试图像为例说明了我们使用的预处理程序。这一步将 I0 作为输入图像,首先将其重新缩放为固定大小的 M×M。这一步确保生成的图像哈希值长度固定,同时使其对图像缩放操作具有鲁棒性。本文选择 M = 256。第二步,为了使生成的图像哈希值更加稳健,应用了基于 ak×k 窗口的平滑(即平均滤波)操作。其目的是在去除无关紧要的细节的同时保留基本结构,而不影响图像内容。然后,考虑到图像可以旋转,我们建议只考虑图像内切圆内的平滑像素,如图 2 (d)所示。这可以通过将内切圆外的像素置零来实现。如图 2 (d) 和图 2 (e) 所示,图像及其旋转版本具有相同的像素值。因此,在图像旋转角度较大的情况下,我们可以最大限度地减少信息丢失的影响,尤其是图像边角像素的丢失。
特征提取
在预处理阶段处理图像缩放的鲁棒性,我们正在寻找的图像特征必须对图像旋转具有鲁棒性。为此,我们建议首先将预处理图像转换为对数极域,然后应用 QDFT。
论文里证明了对数极坐标抗旋转,即图像旋转之后的图像哈希序列不变。
哈希构造
把经过选择和扰乱的正方形区域的 p 个 QDFT 幅值系数表示成一个行向量
H
G
H_G
HG
H
G
=
{
1
,
i
f
z
(
i
)
−
z
(
i
+
1
)
≥
0
0
,
i
f
z
(
i
)
−
z
(
i
+
1
)
<
0
i
=
1
,
.
.
.
,
p
−
1
H_G=\left\{\begin{array}{l}1,if\;z\left(i\right)-z\left(i+1\right)\geq0\\0,if\;z(i)-z(i+1)<0\end{array}\right.\\i=1,...,p-1
HG={1,ifz(i)−z(i+1)≥00,ifz(i)−z(i+1)<0i=1,...,p−1
使用归一化汉明距离 D1 来衡量两个散列之间的相似性.
主要代码
import numpy as np #1.20.3
import quaternion as qt
import cv2
import matplotlib.pyplot as plt
import os
import pandas as pd
def read_images_from_folder(folder_path):
"""
读取文件夹中所有的图片
"""
image_list = []
image_paths = [] # 用于保存图片的文件路径
# 遍历文件夹中的所有文件
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
# 检查文件是否为图片
if file_path.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp')):
try:
# 使用OpenCV读取图片
image = cv2.imread(file_path)
image_list.append(image)
image_paths.append(file_path)
except Exception as e:
# 处理异常,例如无法读取的文件
print(f"Error reading image {file_path}: {e}")
return image_list, image_paths
def preprocessing(image):
"""
数据预处理
"""
###########1.将图像缩放到256x256像素#############
img_resized = cv2.resize(image, (256, 256))
########### 2.应用7x7的平均滤波器#########
k_size = 7
img_blurred = cv2.blur(img_resized, (k_size, k_size))
########### 3.内切圆 ##########
# 创建一个黑色图像作为掩码
mask = np.zeros_like(img_blurred, dtype=np.uint8)
# 获取图像中心坐标
center = (img_blurred.shape[1] // 2, img_blurred.shape[0] // 2)
# 获取内切圆的半径
radius = min(center[0], center[1])
# 在掩码上绘制白色的内切圆
cv2.circle(mask, center, radius, (255, 255, 255), thickness=-1)
# 将原始图像与掩码进行按位与操作
img_smoothed = cv2.bitwise_and(img_blurred, mask)
# 转换颜色通道顺序 BGR -> RGB
img_smoothed_rgb = cv2.cvtColor(img_smoothed, cv2.COLOR_BGR2RGB)
return img_smoothed_rgb
####快速傅里叶变换计算####
def exp_quaternion(u):
"""
四元数的指数运算
"""
# 手动计算四元数的模,并用它来规范化四元数
norm_u = np.abs(u)
v = u / (norm_u+(1e-80))
# 计算指数形式的指数运算
exponential_form = np.cos(norm_u) + v * np.sin(norm_u)
return exponential_form
def fft1D(signal):
"""
signal:为一维的四元数序列
return:*
"""
# 定义单位纯四元数 u = ai + bj + ck,其中 |u| = 1
# 构建单位纯四元数
# 第一种四元数论文常用单位四元数
d1=3**(1/2)
u_lum = qt.quaternion(0, 1/d1, 1/d1, 1/d1)
# 第二种单位四元数
d2=68**(1/2)
u_perc=qt.quaternion(0, 0, -2/d2, 8/d2)
N = len(signal)
if N <= 1:
return signal
even = fft1D(signal[0::2])
odd = fft1D(signal[1::2])
#一维傅里叶变换公式
T = [exp_quaternion(-2*u_lum * np.pi * k / N) * odd[k] for k in range(N // 2)]
# T = [exp_quaternion(-2 * u_perc * np.pi * k / N) * odd[k] for k in range(N // 2)]
return np.concatenate([even + T, even - T])
def fft2D(image):
"""
image:四元数矩阵(256*256)
return:返回经过傅里叶变换后的四元数矩阵
"""
M, N = image.shape
if M <= 1 and N <= 1:
return image
# FFT along rows
rows = np.array([fft1D(row) for row in image])
# FFT along columns
cols = np.array([fft1D(col) for col in rows.T]).T
return cols
def QDFT(image,k):
"""
image:预处理好的图片
k:提取图片中间K×K大小的振幅系数,从上到下和从左到右的选择序列从正方形区域确定
return:通过QDFT处理之后的振幅系数
1.对数极坐标变换(抗旋转)
2.将图片用四元数表示
3.对四元数图像进行离散傅里叶变换,然后将低频信号移到图像中间。振幅系数为四元数的绝对值
4,输出K×K大小的振幅系数
"""
#1.对数极坐标
rows, cols,_ = image.shape
center_row, center_col = (rows // 2)+1, (cols // 2)+1
log_polar_img = cv2.logPolar(image, (center_row, center_col), 50, cv2.WARP_FILL_OUTLIERS)
#2.将彩色图像的每个像素用纯四元数表示
quaternion_array = np.zeros((rows, cols), dtype=np.quaternion)
# for i in range(rows):
# for j in range(cols):
# quaternion_array[i, j] = np.quaternion(0, *log_polar_img[i,j])
#列表推导式提高运行速度
quaternion_array = np.array([[np.quaternion(0, *log_polar_img[i, j]) for j in range(cols)] for i in range(rows)])
#3.对四元数图像进行离散傅里叶变换
fft_image = fft2D(quaternion_array)
Amplitude_coefficient = np.abs(fft_image)/rows
f_transformed_shifted = np.fft.fftshift(Amplitude_coefficient)
# 4.提取K×K的振幅系数
# print(center_row, center_col)
# center_row, center_col = 129, 129
half_k = k // 2
if k % 2 == 0:
result = f_transformed_shifted[center_row - half_k:center_row + half_k,
center_col - half_k:center_col + half_k]
else:
result = f_transformed_shifted[center_row - half_k:center_row + half_k + 1,
center_col - half_k:center_col + half_k + 1]
amplitude_matrix = [result[i][j] for i in range(k) for j in range(k)]
hash=[1 if amplitude_matrix[i]-amplitude_matrix[i+1]>=0 else 0 for i in range(k*k-1)]
return hash
def normalized_hamming_distance(hash1,hash2):
distance=np.count_nonzero(np.array(list(hash1)) != np.array(list(hash2)))
return distance/len(hash1)
复现的代码中根据论文的公式,使用快速傅里叶变换来优化代码运行效率,结果并没有改变。