离散傅里叶变换DFT
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读入原始lena图像
img = cv2.imread('lena.png', cv2.IMREAD_GRAYSCALE)
#cv2.imshow('Original Image', img)
#cv2.waitKey(0)
plt.subplot(131)
plt.imshow(img, cmap='gray')
plt.title('Original Image')
# 进行傅里叶变换
fft = np.fft.fft2(img)
# 将零频率分量移到图像中心
fft_shifted = np.fft.fftshift(fft)
# 计算幅度谱
magnitude_spectrum = 20 * np.log(np.abs(fft_shifted))
# 显示傅里叶变换后的频谱
plt.subplot(132)
plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum')
plt.xticks([]), plt.yticks([])
# 计算阈值
threshold = np.percentile(np.abs(fft_shifted), 95)
# 将低值系数置零
fft_shifted[np.abs(fft_shifted) < threshold] = 0
# 进行逆变换
ifft_shifted = np.fft.ifftshift(fft_shifted)
ifft = np.fft.ifft2(ifft_shifted)
reconstructed_image = np.abs(ifft)
# 转换为8比特表示
reconstructed_image = np.uint8(reconstructed_image)
# 显示逆变换后的图像
plt.subplot(133)
plt.imshow(reconstructed_image, cmap='gray')
plt.title('IFFT Image')
plt.xticks([]), plt.yticks([])
plt.show()
# 计算原始图像与逆变换后图像的PSNR
def psnr(img1, img2):
mse = np.mean((img1 - img2) ** 2)
if mse == 0:
return 100
PIXEL_MAX = 255.0
return 20 * np.log10(PIXEL_MAX / np.sqrt(mse))
# 计算逆变换后图像的峰值信噪比(PSNR)
psnr_fft = psnr(img, reconstructed_image)
print('PSNR:', psnr_fft)
离散余弦变换DCT
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读入原始lena图像
img = cv2.imread('lena.png', cv2.IMREAD_GRAYSCALE)
#cv2.imshow('Original Image', img)
#cv2.waitKey(0)
plt.subplot(131)
plt.imshow(img, cmap='gray')
plt.title('Original Image')
# 进行离散余弦变换
dct = cv2.dct(np.float32(img))
# 计算幅度谱
magnitude_spectrum = 20 * np.log(np.abs(dct))
# 显示离散余弦变换后的频谱
plt.subplot(132)
plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum')
plt.xticks([]), plt.yticks([])
# 计算阈值
threshold = np.percentile(np.abs(dct), 95)
# 将低值系数置零
dct[np.abs(dct) < threshold] = 0
# 进行逆变换
idct = cv2.idct(dct)
# 转换为8比特表示
reconstructed_image = np.uint8(idct)
# 显示逆变换后的图像
plt.subplot(133)
plt.imshow(reconstructed_image, cmap='gray')
plt.title('IDCT Image')
plt.xticks([]), plt.yticks([])
plt.show()
# 计算原始图像与逆变换后图像的PSNR
def psnr(img1, img2):
mse = np.mean((img1 - img2) ** 2)
if mse == 0:
return 100
PIXEL_MAX = 255.0
return 20 * np.log10(PIXEL_MAX / np.sqrt(mse))
# 计算逆变换后图像的峰值信噪比(PSNR)
psnr_dct = psnr(img, reconstructed_image)
print('PSNR:', psnr_dct)
离散哈达玛变换DHT
import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy.linalg import hadamard
from skimage import img_as_ubyte
import math
# 读入原始lena图像
img = cv2.imread('lena.png', cv2.IMREAD_GRAYSCALE)
#cv2.imshow('Original Image', img)
#cv2.waitKey(0)
plt.subplot(131)
plt.imshow(img, cmap='gray')
plt.title('Original Image')
# 必须对读取的图像的双取值归一化到0~1之间
out = cv2.normalize(img.astype('float'), None, 0.0, 1.0, cv2.NORM_MINMAX)
# 生成512x512哈达玛矩阵,输入的值必须是 2 的幂,且要跟图像的长和宽对应。
Hada=hadamard(512)
Hada_pic = np.matmul(np.matmul(Hada,out),Hada)
# 沃尔什哈达玛变换记得/(N*N=512*512),此处只除512是为了频谱图效果好看
Hada_pic2=Hada_pic/(512)
plt.subplot(132)
plt.imshow(Hada_pic2, cmap='gray')
plt.title('Magnitude Spectrum')
plt.xticks([]), plt.yticks([])
rows, cols = Hada_pic2.shape
# 设置不同阈值 (高频部分能量低)
thresh = 0.05
num_coeffs = rows * cols
flat = Hada_pic2.flatten()
flat_sorted = np.sort(np.abs(flat))
thresh_idx = int(np.floor(thresh*num_coeffs))
thresh_val = flat_sorted[thresh_idx]
flat[np.abs(flat) < thresh_val] = 0
Hada_pic2 = flat.reshape(rows, cols)
# Hadamard逆变换,使用转置矩阵
IHada_pic = np.matmul(np.matmul(Hada.T, Hada_pic2), Hada.T)
# 沃尔什哈达玛变换记得/(N*N=512*512),此处只除512是为了频谱图效果好看
IHada_pic = IHada_pic/512
IHada_pic = np.clip(IHada_pic, -1, 1)
# 将灰度级转换为255级
IHada_pic = img_as_ubyte(IHada_pic)
IHada_pic = np.uint8(np.abs(IHada_pic))
plt.subplot(133)
plt.imshow(IHada_pic, cmap='gray')
plt.title('IHT Image')
plt.xticks([]), plt.yticks([])
plt.show()
# 计算原始图像与逆变换后图像的PSNR
def psnr(img1, img2):
mse = np.mean((img1 - img2) ** 2)
if mse == 0:
return 100
PIXEL_MAX = 255.0
return 20 * np.log10(PIXEL_MAX / np.sqrt(mse))
# 计算逆变换后图像的峰值信噪比(PSNR)
psnr_ht = psnr(img, IHada_pic)
print('PSNR:', psnr_ht)