数字图像处理 --- 二维离散余弦变换(python实战)

news2024/11/16 7:23:44

二维离散余弦变换(python实战)

(注:文中所讨论的离散余弦变换都是DCT-II)

        在上一篇文章中,我详细介绍了一维离散余弦变换的基本原理,并且以可视化的方式展示了一维DCT中用于分析输入信号的一系列基础余弦波。 在这篇文章中继续关于DCT的学习,并把DCT从一维推广到二维,最后以图像的离散余弦变换为结尾。

数字图像处理 --- 一维离散余弦变换(python实战)-CSDN博客文章浏览阅读303次,点赞6次,收藏9次。本文详细介绍了基于python实现的一维离散余弦变换,是我个人的学习笔记。https://blog.csdn.net/daduzimama/article/details/140449135

二维DCT正变换

二维DCT正变换公式如下: 

X[\mu,\nu ]=E(\mu)E(\nu)\frac{2}{N}\displaystyle\sum_{m=0}^{N-1}\displaystyle\sum_{n=0}^{N-1}x[m,n]cos\frac{(2m+1)\mu\pi}{2N}cos\frac{(2n+1)\nu\pi}{2N}

X[\mu,\nu ]=E(\mu)\sqrt{\frac{2}{N}}\displaystyle\sum_{m=0}^{N-1}cos\frac{(2m+1)\mu\pi}{2N}(E(\nu)\sqrt{\frac{2}{N}}\displaystyle\sum_{n=0}^{N-1}x[m,n]cos\frac{(2n+1)\nu\pi}{2N})

        其中,x[m,n]为输入图像的像素值,m,n=0,1,...,N-1。X[\mu ,\nu]为经过离散余弦变换后的结果,即离散余弦变换的系数,\mu,\nu=0,1,...,N-1。E(\mu),E(\nu)为归一化系数,当\mu ,\nu=0时, E(\mu),E(\nu)=\frac{1}{\sqrt{2}}。 当 \mu,\nu=1,2,3,....,N-1时, E(\mu),E(\nu)=1

        单从公式来看,我们可以知道三点。第一,频域中的每一个点X[\mu ,\nu]都要遍历整幅图像计算。二,就某个固定的\mu,\nu而言,分析每行和每列数据用的是同一组cos函数。第三,越是往频域的右下角计算,分析图像所需的cos函数的频率就越高。

以4个点的X[0,0]的计算为例,N=4,\mu ,\nu=0:

        X[0,0]=E(0)\sqrt{\frac{2}{N}}\displaystyle\sum_{m=0}^{N-1}cos\frac{(2m+1)0\pi}{2N}(E(0)\sqrt{\frac{2}{N}}\displaystyle\sum_{n=0}^{N-1}x[m,n]cos\frac{(2n+1)0\pi}{2N})

=1/\sqrt{N}\displaystyle\sum_{m=0}^{N-1}cos\frac{(2m+1)0\pi}{2N}(1/\sqrt{N}\displaystyle\sum_{n=0}^{N-1}x[m,n]cos\frac{(2n+1)0\pi}{2N})

 =1/2\displaystyle\sum_{m=0}^{N-1}(1/2\displaystyle\sum_{n=0}^{N-1}x[m,n])

=1/2\displaystyle\sum_{m=0}^{N-1}(1/2x[m,0]+1/2x[m,1]+1/2x[m,2]+1/2x[m,3])

=(1/2(1/2x[0,0]+1/2x[0,1]+1/2x[0,2]+1/2x[0,3]))+(1/2(1/2x[1,0]+1/2x[1,1]+1/2x[1,2]+1/2x[1,3]))+(1/2(1/2x[2,0]+1/2x[2,1]+1/2x[2,2]+1/2x[2,3]))+(1/2(1/2x[3,0]+1/2x[3,1]+1/2x[3,2]+1/2x[3,3]))

        这个公式表明,要想求出X[0,0]。要先让原始二维信号x[m,n]的每一行乘以幅值为1/2频率为0的余弦信号[0.5,0.5,0.5,0.5],然后再用这个结果乘以余弦信号[0.5,0.5,0.5,0.5]才能得到最终结果。下面是基于python的实现,主要是用于验证计算结果并演示计算过程:

#生成随机二维信号
x2=np.random.randn(4,4)
x2

        导入opencv的dct库,计算二维DCT。后面会根据我上面推导出来的公式,计算X[0,0],并用CV库的计算结果来验证。 

import cv2
dct_matrix=cv2.dct(x2)
dct_matrix

        以下是基于上面的推导结果求得的X[0,0],整个计算过程是先用幅值为1/2频率为0的cos函数乘以二维数组的每一行并得到一个中间结果,最后用这个中间结果再次乘以cos函数得到最终结果,这一计算过程和推导一致:

A=DCT1d_matrix(4)
print("Forward transform matrix A:\n",A)

#原始信号的每一行乘以余弦信号,得到一个中间结果
step1=x2@A[0,:]
print("result of step1:",step1)

#中间结果再度乘以余弦信号,得到最终结果
step2=step1@A[0,:]
print("result of step2:",step2)

        根据计算结果来看,1,计算时所使用的cos函数为一维DCT矩阵的第一行。毕竟DCT矩阵中的每一行都是一个固定频率的cos函数。2,按照这种方法计算出来的最终结果0.8999和用cv库算出来的左上角第一个值一致。

        0,0点的例子比较特殊,现在我们再看一个点X[1,2]。还是4个点的DCT,N=4,\mu =1\nu =2

X[1,2]=E(1)\sqrt{\frac{2}{N}}\displaystyle\sum_{m=0}^{N-1}cos\frac{(2m+1)\pi}{2N}(E(2)\sqrt{\frac{2}{N}}\displaystyle\sum_{n=0}^{N-1}x[m,n]cos\frac{(2n+1)2\pi}{2N})

 =\sqrt{\frac{1}{2}}\displaystyle\sum_{m=0}^{N-1}cos\frac{(2m+1)\pi}{8}(\sqrt{\frac{1}{2}}\displaystyle\sum_{n=0}^{N-1}x[m,n]cos\frac{(2n+1)2\pi}{8})

 =\sqrt{\frac{1}{2}}\displaystyle\sum_{m=0}^{N-1}cos\frac{(2m+1)\pi}{8}(\sqrt{\frac{1}{2}}x[m,0]cos\frac{2\pi}{8}+\sqrt{\frac{1}{2}}x[m,1]cos\frac{6\pi}{8}+\sqrt{\frac{1}{2}}x[m,2]cos\frac{10\pi}{8}+\sqrt{\frac{1}{2}}x[m,3]cos\frac{14\pi}{8})

 =(\sqrt{\frac{1}{2}}cos\frac{\pi}{8}(\sqrt{\frac{1}{2}}x[0,0]cos\frac{2\pi}{8}+\sqrt{\frac{1}{2}}x[0,1]cos\frac{6\pi}{8}+\sqrt{\frac{1}{2}}x[0,2]cos\frac{10\pi}{8}+\sqrt{\frac{1}{2}}x[0,3]cos\frac{14\pi}{8}))+(\sqrt{\frac{1}{2}}cos\frac{3\pi}{8}(\sqrt{\frac{1}{2}}x[1,0]cos\frac{2\pi}{8}+\sqrt{\frac{1}{2}}x[1,1]cos\frac{6\pi}{8}+\sqrt{\frac{1}{2}}x[1,2]cos\frac{10\pi}{8}+\sqrt{\frac{1}{2}}x[1,3]cos\frac{14\pi}{8}))+(\sqrt{\frac{1}{2}}cos\frac{5\pi}{8}(\sqrt{\frac{1}{2}}x[2,0]cos\frac{2\pi}{8}+\sqrt{\frac{1}{2}}x[2,1]cos\frac{6\pi}{8}+\sqrt{\frac{1}{2}}x[2,2]cos\frac{10\pi}{8}+\sqrt{\frac{1}{2}}x[2,3]cos\frac{14\pi}{8}))+(\sqrt{\frac{1}{2}}cos\frac{7\pi}{8}(\sqrt{\frac{1}{2}}x[3,0]cos\frac{2\pi}{8}+\sqrt{\frac{1}{2}}x[3,1]cos\frac{6\pi}{8}+\sqrt{\frac{1}{2}}x[3,2]cos\frac{10\pi}{8}+\sqrt{\frac{1}{2}}x[3,3]cos\frac{14\pi}{8}))

        结合推导结果来看,要想得到X[1,2]的结果。先是要让原始二维信号的每一行都乘以频率为2/4pi的cos函数得到中间结果,这一步所使用的cos函数为:

[\sqrt{\frac{1}{2}}cos\frac{2\pi}{8},\sqrt{\frac{1}{2}}cos\frac{6\pi}{8},\sqrt{\frac{1}{2}}cos\frac{10\pi}{8},\sqrt{\frac{1}{2}}cos\frac{14\pi}{8}] 

此时\nu =2,然后再用这个中间结果乘以频率为1/4pi的cos函数得到最终结果。这一步所使用的cos函数为:

[\sqrt{\frac{1}{2}}cos\frac{\pi}{8},\sqrt{\frac{1}{2}}cos\frac{3\pi}{8},\sqrt{\frac{1}{2}}cos\frac{5\pi}{8},\sqrt{\frac{1}{2}}cos\frac{7\pi}{8}]

此时\mu =1,实际上这两组cos函数就是一维4点DCT变换矩阵其中的两行。

cos0=np.array([np.sqrt(1/2)*np.cos(2*np.pi/8),np.sqrt(1/2)*np.cos(6*np.pi/8),np.sqrt(1/2)*np.cos(10*np.pi/8),np.sqrt(1/2)*np.cos(14*np.pi/8)])
print("cos with freq of 2/4pi:",cos0)

cos1=np.array([np.sqrt(1/2)*np.cos(1*np.pi/8),np.sqrt(1/2)*np.cos(3*np.pi/8),np.sqrt(1/2)*np.cos(5*np.pi/8),np.sqrt(1/2)*np.cos(7*np.pi/8)])
print("cos with freq of 1/4pi:",cos1)

        最后再次基于推导结果计算X[1,2],先用\nu =2时的cos函数乘以二维信号的每一行,得到中间结果。然后再用\mu =1时的cos函数乘以中间结果,得到最终结果:

#原始信号的每一行乘以nu=2时的余弦信号,得到一个中间结果
step1=x2@A[2,:]
print("result of step1:",step1)

#中间结果再乘以mu=1时的余弦信号,得到最终结果
step2=step1@A[1,:]
print("result of step2:",step2)

 


二维DCT正变换的矩阵计算

         在上面的两个例子中,我分别列举了频域中两个点的计算,事实上,和一维DCT一样,二维信号所有点的DCT可以通过矩阵运算的方式一次性求出来,具体来说就是先对二维信号的每一行进行一维DCT,得到一个中间结果矩阵。然后对中间结果的每一列进行一维DCT,得到最终的二维DCT结果。

        1,首先,一维DCT的矩阵计算公式为:

X[\mu ]=Ax[n]

        2, 基于这一公式,我们可以先用Ax[m,n]^{T}实现对x的每行数据进行一维DCT变换。其中,Ax[m,n]^{T}可拆分成下图的计算方式,其中每个Acol是矩阵中的一列。

Ax^{T}=\begin{bmatrix} A\cdot col0 &A\cdot col1 & ... &A\cdot colN \end{bmatrix}

上面公式中的每一列A\cdot col又是按照下图的方式计算的:

\begin{bmatrix} .& . & .\\ . &A &. \\ . & . & . \end{bmatrix}\begin{bmatrix} .\\ col\\ . \end{bmatrix}=\begin{bmatrix} .\\ .\\ . \end{bmatrix}

        上图的意思是矩阵A的每一行都是一组cos基础函数,每行cos函数乘以col中的数据就是col的DCT系数。又因为col中所装的都来自于x^{T},即x的转置。因此,矩阵A所乘的每一列col就是原始二维数据中的每一行。A乘col的结果是一个列向量。

        3,上一步中Ax[m,n]^{T}的结果是一个与x尺寸相同的矩阵,是中间结果。该矩阵中的每一列都是原始二维矩阵x每行一维DCT的结果。首先,我们要对中间结果转置,即,(Ax[m,n]^{T})^{T},转置后矩阵中每一行都是x每一行DCT的结果。然后再对转置后的中间结果的每一列做一维DCT,直接套用一维DCT的矩阵计算公式即可,得到:

A(Ax[m,n]^{T})^{T}=Ax[m,n]A^{T}

 最终得到二维DCT的矩阵运算公式:

X[\mu ,\nu ]=Ax[m,n]A^{T}

用python代码实现如下: 

X2=(A@x2)@A.T
X2

这一计算结果与之前用cv2库计算所得的结果一致! 


(全文完)

作者 --- 松下J27

 参考文献:

1,《数字图像处理技术详解与Visual C++实践》---左飞

2,dct — SciPy v1.14.0 Manual

3,dct

4,https://en.wikipedia.org/wiki/Discrete_cosine_transform

5,https://en.wikipedia.org/wiki/Cross-correlation

6,Amplitude, Period, Phase Shift and Frequency

版权声明:文中的部分图片,文字或者其他素材,可能来自很多不同的网站和说明,在此没法一一列出,如有侵权,请告知,立即删除。欢迎大家转载,但是,如果有人引用或者COPY我的文章,必须在你的文章中注明你所使用的图片或者文字来自于我的文章,否则,侵权必究。 ----松下J27 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1960985.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【简单图解 最强计网八股】HTTP 和 HTTPS 的区别

HTTP(HyperText Transfer Protocol 超文本传输协议) HTTPS(Hypertext Transfer Protocol Secure,超文本传输安全协议) 通过 传输内容加密 和 身份认证 保证了传输过程的安全性 协议传输内容加密身份认证响应效率端口号…

​LLM大模型从入门到精通(7)--企业大模型开发流程​

一、大模型项目开发的两种方式 2023年以来,随着ChatGPT的火爆,使得LLM成为研究和应用的热点,但是市面上大部分LLM都存在一个共同的问题:模型都是基于过去的经验数据进行训练完成,无法获取最新的知识,以及各…

Axure中继器:数据动态展示的强大工具

在Axure RP这一强大的原型设计工具中,中继器(Repeater)无疑是一颗璀璨的明珠。它以其独特的功能和广泛的应用场景,成为设计师在创建数据密集型原型时的首选。本文将深入探讨Axure中继器的特点、使用方式及其在数据动态展示中的重要…

新手小白如何投放知乎信息流广告推广?

随着越来越多的企业开始寻求更有效的方式来触达目标客户,知乎作为一个集知识分享、社交互动于一体的平台,已经成为众多品牌青睐的广告投放渠道之一。特别是知乎的信息流广告,因其高度融合的内容形式和精准的目标用户定向,成为了品…

ReactHooks(完结)

上期戳here ReactHooks[三] 一.memo 函数1.1 语法格式 二. useMemo2.1 问题引入2.2 语法格式2.3 使用 useMemo 解决刚才的问题 三.useCallback3.1 useMemo和useCallback区别3.2 语法格式 四.useTransition4.1 问题引入4.2 语法格式4.3 使用 isPending 展示加载状态4.4 注意事项…

Python3 | 练气期,捕获错误异常 、自定义异常处理!

[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] 0x00 前言简述 在我们开始学习 Python 编程语言的时候, 我们经常会遇到各种错误, 比如:语法错误,运行时错误,逻辑错误等等, 这些错误在开发学习中是不可避免的, 但是随着我们学习的深入可以发现 Python 可以很好的处理…

Java 8-函数式接口

目录 一、概述 二、 函数式接口作为方法的参数 三、函数式接口作为方法的返回值 四、 常用的函数式接口 简单总结 简单示例 4.1 Consumer接口 简单案例 自我练习 实际应用场景 多线程处理 4.2 Supplier接口 简单案例 自我练习 实际应用场景 配置管理 4.3 Func…

UCC5320SCDWVR驱动SIC的功耗计算

驱动功耗可以通过分析器件的电气特性和推荐的电源电压来估算。以下是一些关键信息,用于估算功耗: 电源电流: 输入电源静态电流(IVCC1​):最小值为1.67 mA,典型值为2.4 mA。输出电源静态电流&am…

day33

类类型接口 静态属性和静态方法 区分方法就是必须要有 new什么东西 完成什么类 第二种类类型接口 字面量类类型接口 接口继承 接口继承接口 继承多个接口 接口可以继承多个,但是类只能继承一个 接口不能继承对象 接口继承类,仅继承类中对于实…

力扣高频SQL 50题(基础版)第二十六题

文章目录 力扣高频SQL 50题(基础版)第二十六题1667.修复表中的名字题目说明实现过程准备数据实现方式结果截图总结 力扣高频SQL 50题(基础版)第二十六题 1667.修复表中的名字 题目说明 表: Users ----------------…

Day7-指针专题二

1. 字符指针与字符串 C语言通过使用字符数组来处理字符串 通常,我们把char数据类型的指针变量称为字符指针变量。字符指针变量与字符数组有着密切关系,它也被用来处理字符串 初始化字符指针是把内存中字符串的首地址赋予指针,并不是把该字符串…

TCP/UDP通信

1、TCP/IP四层模型 TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP…

【Linux】make/Makefile的理解

1.make是一个命令,makefile是一个文件, 依赖关系和依赖方法. a.快速使用一下 i.创建一个Makefile文件(首字母也可以小写) b.依赖关系和依赖方法 i.依赖关系: 我为什么要帮你? mybin:mytest.c ii.依赖方法: 怎么帮? gcc -o mybin mytest.c make之前要注意先创建…

每期一个小窍门: 使用Gin 与 client-go 操作k8s (中)

本文承接上文 每期一个小窍门: 使用Gin 与 client-go 操作k8s (上) 后面应该还会有个下 应该是个operator的全程demo 项目结构如下 client.go package clientimport ("k8s.io/client-go/discovery""k8s.io/client-go/kubernetes"…

使用easypoi读取Excel模板

1、只读取一个脚本号Excel2、读取多个脚本号的sheet…Excel 1、只读取sheet0(只读取一个脚本号的Excel) 前言&#xff1a;引入pom文件 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</…

OV SSL证书申请指南

OV SSL证书除了验证域名所有权外还需要验证组织信息&#xff0c;这类证书适用于对公司官网、品牌、安全性等有较高程度要求的企业级用户。具体申请流程如下&#xff1a; 一 、注册账号 注册账号填写230919注册码即可获得大额优惠券和全程一对一技术支持https://www.joyssl.co…

网页速度如何优化?从10s到0.5s

如何排除网页速度慢的故障&#xff1f; 优化运行缓慢的网页涉及多个层面的改进&#xff0c;可分为硬件、前端和后台优化。下面是一份全面的指南&#xff1a; 01 硬件优化 服务器资源 升级服务器&#xff1a;确保服务器能为流量提供足够的资源&#xff08;CPU、内存、带宽等&a…

【Windows】Mountain Duck(FTP服务器管理工具)软件介绍

软件介绍 Mountain Duck是一款基于Cyberduck开发的应用程序&#xff0c;它允许用户通过FTP、SFTP、WebDAV、S3和OpenStack Swift等协议连接到云存储和远程服务器&#xff0c;并在本地文件浏览器中以熟悉的方式访问和管理这些文件。 功能特点 支持多种协议: Mountain Duck支持…

右键没有压缩选项

想压缩文件选中右键没有压缩选项。 打开任意rar文件 选择选项-》设置&#xff0c;添加到winrar到开始菜单即可

HTML+CSS+JavaScript实现烟花绽放的效果源码

源码 复制粘贴代码 在同级别下放一张图片fire.png接可以了 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…