离散余弦变换是图像处理中非常常用的算法,可以用于jpg图像压缩等领域。数学原理我就不扯了,网上一大堆。但介于网上实在没有关于python+opencv来实现DCT的好文章(至少木盏没有搜到过)。于是稍微写一个博文做一个总结,给后人便利。

要用到的模块是opencv,安装方法看另一篇文章《opencv快速安装

python==3.6.5

opencv==3.1.0

scipy==1.1.0

numpy==1.14.3

本实验对模块版本要求不严格,上述版本为作者使用环境,仅供参考。用到的函数是cv2.dct(),初学者很容易犯以下错误:

OpenCV Error: Assertion failed (type == CV_32FC1 || type == CV_64FC1) in cv::dct, file ..\..\..\modules\core\src\dxt.cpp, line 3603
(117, 128, 3)
Traceback (most recent call last):
  File "dct.py", line 15, in <module>
    img_dct = cv2.dct(img1)         #\u8fdb\u884c\u79bb\u6563\u4f59\u5f26\u53d8\u6362
cv2.error: ..\..\..\modules\core\src\dxt.cpp:3603: error: (-215) type == CV_32FC1 || type == CV_64FC1 in function cv::dct

因为调用这个函数很容易犯两个错:1. 把输入维度搞错;2. 数值精度错误

先给一个较通用的脚本demo:

"""
author: muzhan
"""
 
import cv2
import numpy as np
 
 
img = cv2.imread('t0.jpg')
img = img[:, :, 0] # 获取rgb通道中的一个
print(img.shape)
img = np.float32(img) # 将数值精度调整为32位浮点型
img_dct = cv2.dct(img)  # 使用dct获得img的频域图像       
print(img_dct.shape)
img_recor2 = cv2.idct(img_dct)  # 使用反dct从频域图像恢复出原图像(有损) 

dct计算的矩阵是一个二维矩阵,所以直接把三维图像塞进来的话容易报错如上,所以我们可以把rgb三个维度一个一个丢进来dct,最后合成一个三维矩阵保存成彩色图像。

同时,需要注意的是,要用np.float32把矩阵转换成32位浮点精度,这才是dct能处理的精度。所以必不可少。

cv2.idct是反离散余弦变换,是将图像恢复出来的算法。我们可以用matplotlib可视化出来: