引 言 网络上图像在传输过程中为节省内存空间主要采用jpeg格式。jpeg图属于有损压缩图像的一种。在图像篡改检测过程中,可以利用jpeg图像的单双压缩伪影的不同而判别图像为伪造图并可以定位伪造区域。RGB图像变成jpeg图像过程中涉及从RGB图变成YCbCr图像,DCT变换,DCT系数量化过程,和DCT系数反量化,IDCT逆变化过程。本文讲述DCT变化的公式和几种常用代码。
文章目录
- 一、DCT变换公式
- 二、DCT变化编程
- 三、总结
一、DCT变换公式
DCT最常用的变化是 8x8的块变换,变换后的图像与原始图像大小一样。
二、DCT变化编程
- 方法一
import numpy as npdef dct_transform_1(img):block = 8coef = np.zeros((block,block)).astype(np.float32)coef[0:] = np.sqrt(1.0/block)for i in range(1,block):for j in range(block):coef[i,j] = np.sqrt(2.0 /block) * np.cos((2 * j + 1) * np.pi * i / (2.0 * block))# split image to block 8*8#[h,w] -> [(h/8)*(w/8),8,8]h,w = img.shapeprint('img.shape',img.shape)input = img.reshape(h//8,8,w//8,8).transpose(0,2,1,3).reshape(-1,8,8)output = np.zeros_like(input)# for i in range(input.shape[0]):# dct_inter = np.matmul(coef,input[i,:,:])# output[i,:,:] = np.matmul(dct_inter,coef.transpose(1,0))dct_inter = np.matmul(coef,input)output = np.matmul(dct_inter,coef.transpose(1,0))return outputif __name__ == "__main__":np.random.seed(20)image = np.random.randn(16,8)*255dct_result = dct_transform_1(image)print(dct_result)print('*' * 50)
- 方法二
def dct(input):block = 8output = np.zeros_like(input)for u in range(block):for v in range(block):if u==0:alpha = np.sqrt(1.0/block)else:alpha = np.sqrt(2.0/block)if v==0:beta = np.sqrt(1.0/block)else:beta = np.sqrt(2.0/block)temp = 0.0for i in range(block):for j in range(block):temp += input[i,j]*np.cos((2*i+1)*np.pi*u/(2*block))*np.cos((2*j+1)*np.pi*v/(2*block))output[u,v] =alpha*beta*tempreturn outputdef dct_transform_2(img):block = 8# split image to block 8*8#[h,w] -> [(h/8)*(w/8),8,8]h,w = img.shapeinput = img.reshape(h//8,8,w//8,8).transpose(0,2,1,3).reshape(-1,8,8)output = np.zeros_like(input)for i in range(input.shape[0]):output[i,:,:] = dct(input[i,:,:])return outputif __name__ == "__main__":np.random.seed(20)image = np.random.randn(16,8)*255dct_result2 = dct_transform_2(image)print(dct_result2)print('*' * 50)
- 方法三
def dct_transform_3(img):h,w = img.shapeinput = img.reshape(h//8,8,w//8,8).transpose(0,2,1,3).reshape(-1,8,8)tensor = np.zeros((8, 8, 8, 8), dtype=np.float32)for x, y, u, v in itertools.product(range(8), repeat=4):tensor[x, y, u, v] = np.cos((2 * x + 1) * u * np.pi / 16) * np.cos((2 * y + 1) * v * np.pi / 16)alpha = np.array([1. / np.sqrt(2)] + [1] * 7)scale = np.outer(alpha, alpha) * 0.25output = scale * np.tensordot(input, tensor, axes=2)return outputif __name__ == "__main__":np.random.seed(20)image = np.random.randn(16,8)*255dct_result3 = dct_transform_3(image)print(dct_result3)print('*' * 50)
调用以下两句发现三个程序的运行结果相同。
print(np.round(dct_result,decimals=3) == np.round(dct_result2,decimals=3))
print(np.round(dct_result,decimals=3) == np.round(dct_result3,decimals=3))
三、总结
本文只是描述了将YCbCr图像变成DCT系数矩阵的过程,对于传统RGB图变成YCbCr图像过程的代码没有介绍。请浏览者自己查阅资料。如果本代码对于你有所帮助请记得点赞收藏呦😊