数字水印 | 离散余弦变换 DCT 基本原理及 Python 代码实现

目录

      • 1 基本原理
      • 2 代码实现
      • 3 图像压缩



1 基本原理

参考博客:https://www.cnblogs.com/zxporz/p/16072580.html

D C T \mathsf{DCT} DCT 全称为 D i s c r e t e   C o s i n e   T r a n s f o r m \mathsf{Discrete\ Cosine\ Transform} Discrete Cosine Transform,即离散余弦变换。 D C T \mathsf{DCT} DCT 变换属于傅里叶变换的一种,常用于对信号和图像(包括图片和视频)进行数据压缩。 D C T \mathsf{DCT} DCT 是视频压缩史上最重要的发明之一,对于 H . 26 X \mathsf{H.26X} H.26X J P E G \mathsf{JPEG} JPEG 等压缩标准的制定至关重要。

虽然 D C T \mathsf{DCT} DCT 具有比较复杂的数学公式,但是我们这里仅做简单理解。

对一幅图像执行离散余弦变换 ( D C T ) \mathsf{(DCT)} (DCT) 相当于将图像的能量集中在变换系数的左上角,这部分系数被称为直流 ( D C ) \mathsf{(DC)} (DC) 系数。直流系数是 D C T \mathsf{DCT} DCT 最重要的输出之一,因为它携带了原始图像的大部分信息。其余的系数,分布在左上角之外的区域,被称为交流 ( A C ) \mathsf{(AC)} (AC) 系数。这些系数包含了图像的细节信息,反映了图像的纹理和边缘。

只要对这些 D C T \mathsf{DCT} DCT 系数做逆离散余弦变换 ( I D C T ) \mathsf{(IDCT)} (IDCT),理论上就可以重建出原始图像的像素矩阵。需要注意的是, D C T \mathsf{DCT} DCT 本身并不直接压缩数据。它起到的是一个准备作用,为后续的量化、编码等压缩步骤提供了有力的数学基础。量化过程会根据需要压缩的强度,减少 A C \mathsf{AC} AC 系数中的某些值,从而实现数据压缩。

假设一张图片由 3 × 3 3\times3 3×3 个像素块构成,如下图所示:

原文说的是,取一个图像中的一部分,且这个部分只包含 3 × 3 3\times3 3×3 个像素。

如上图所示,相当于是把其余格的部分信息(特征)都抽取到了第一个格。第一个格的像素值就是这个图像的低频信息,其余格的就是这个图像的高频信息。低频信息主要表示的是一张图的总体样貌,一般低频系数的值也比较大。而高频信息主要表示的是图像中人物或物体的细节,一般高频系数的数量较多。做完 D C T \mathsf{DCT} DCT 变换后,低频信息和高频信息就分离开来了。



2 代码实现

参考博客:https://blog.csdn.net/qq_41821067/article/details/114113677

import cv2
import numpy as np
from matplotlib import pyplot as plt


# 处理原始图像
img = cv2.imread('logo.jpg', 0)  # 读取图像为灰度图像
print("img.shape:", img.shape)
img1 = img.astype('float32')  # 将unit8类型转换为float类型

# 进行离散余弦变换
img_dct = cv2.dct(img1)
print("img_dct:", img_dct)
print("img_dct.shape:", img_dct.shape)

# 进行对数处理
img_dct_log = np.log(abs(img_dct))
print("img_dct_log:", img_dct_log)

# 进行逆离散余弦变换
img_recor = cv2.idct(img_dct)
print("img_recor:", img_recor)
print("img_recor.shape:", img_recor.shape)

# 判断是否相同
print("img:", img)
print("img_recor:", img_recor)
print(abs(img - img_recor) < 1)

# 画图
plt.subplot(1, 4, 1)
plt.title("Original Image", fontsize=12, loc="center")
plt.axis('off')
plt.imshow(img, cmap="gray")

plt.subplot(1, 4, 2)
plt.title("Coefficients", fontsize=12, loc="center")
plt.axis('off')
plt.imshow(img_dct, cmap="gray")

plt.subplot(1, 4, 3)
plt.title("Log", fontsize=12, loc="center")
plt.axis('off')
plt.imshow(img_dct_log, cmap="gray")

plt.subplot(1, 4, 4)
plt.title("Recovered Image", fontsize=12, loc="center")
plt.axis('off')
plt.imshow(img_recor, cmap="gray")

plt.savefig('test.jpg', dpi=400, bbox_inches='tight')
plt.show()

代码说明:

  • 根据 img.shapeimg_dct.shape 的结果可知 D C T \mathsf{DCT} DCT 并不会改变图像的大小。
  • 根据 img_dct 可知 D C T \mathsf{DCT} DCT 系数非常小,以至于在视觉上难以区分。为了更好地可视化这些系数,我们对其进行对数变换,以拉伸坐标轴的刻度,使得小的系数在图像中也能显示出来。
  • 根据 imgimg_recor 可知原始图像和还原后的图像并不完全相等,但是根据 print(abs(img - img_recor) < 1) 可知二者之间的像素差值不会超过 1 1 1

效果如下:

在这里插入图片描述



3 图像压缩

import cv2
from matplotlib import pyplot as plt


# 处理原始图像
img = cv2.imread('logo.jpg', 0)  # 读取图像为灰度图像
img1 = img.astype('float32')  # 将unit8类型转换为float类型

# 进行离散余弦变换
img_dct = cv2.dct(img1)

# 压缩图像
zip_len = [10, 20, 50, 100, 200, 300, 500, 800]  # 压缩后的图像大小

for i in range(len(zip_len)):
    # 进行逆离散余弦变换:仅保留左上角的部分数据
    img_recor = cv2.idct(img_dct[0:zip_len[i], 0:zip_len[i]])
    print("img_recor.shape:", img_recor.shape)

    # 画图
    plt.subplot(2, int(len(zip_len) / 2), i + 1)
    plt.title("zip_len={zip_len}".format(zip_len=zip_len[i]), fontsize=12, loc="center")
    plt.axis('off')
    plt.imshow(img_recor, cmap="gray")

plt.savefig('compress.jpg', dpi=400, bbox_inches='tight')
plt.show()

核心代码:

cv2.idct(img_dct[0:zip_len[i], 0:zip_len[i]])

使用 D C T \mathsf{DCT} DCT 进行图片压缩的本质,就是仅保留部分左上角的 D C T \mathsf{DCT} DCT 系数,通过逆变换构建被压缩了的图像。

效果如下:

在这里插入图片描述



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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

堆结构知识点复习——玩转堆结构

前言:堆算是一种相对简单的数据结构&#xff0c; 本篇文章将详细的讲解堆中的知识点&#xff0c; 包括那些我们第一次学习堆的时候容易忽略的内容&#xff0c; 本篇文章会作为重点详细提到。 本篇内容适合已经学完C语言数组和函数部分的友友们观看。 目录 什么是堆 建堆算法…

蓝桥杯2023(十四届)省赛——接龙数列(DP)

接龙数列&#xff08;DP&#xff09; 1.接龙数列 - 蓝桥云课 (lanqiao.cn) 琢磨半天&#xff0c;本来是开一个三维的&#xff0c;dp[i][j][k] 表示 前i个&#xff0c;以j为首项&#xff0c;k为尾项的最大子集个数&#xff0c;但是实际上用二维即可。想求的是删除个数&#xf…

java并发工具类都有哪些

Java中的并发工具类包括&#xff1a; CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成某些操作。它通常用于线程间的同步&#xff0c;例如在一个线程完成其工作后通知其他线程继续执行。 CyclicBarrier CyclicBarrier是一个同步辅助类&#xff0c;它允许一…

STM32H743+USBHID+CubeMX配置

一、环境准备 电脑系统&#xff1a;Windows 10 专业版 20H2 IDE&#xff1a;Keil v5.35、STM32CubeMX v6.5.0 测试硬件&#xff1a;正点原子阿波罗STM32H743 二、测试步骤 1、使用用例工程 配置STM32H743定时器功能-CSDN博客https://blog.csdn.net/horse_2007s/article/d…

基于51单片机的电压表-数码管显示

一.硬件方案 本设计基于STC89C52单片机的一种电压测量电路&#xff0c;该电路采用ADC0832A/D转换芯片,实现数字电压表的硬件电路与软件设计。该系统的数字电压表电路简单, 可以测量0&#xff5e;9V的电压值,并在四位LED数码管上显示电压值。 二.设计功能 &#xff08;1&…

HNCTF

HNCTF 文章目录 HNCTFBabyPQEZmathez_Classicf(?*?)MatrixRSABabyAESIs this Iso? BabyPQ nc签到题&#xff0c;跟端口连接拿到n和phin n 8336450100232098099043686671148282601664696810002345240872579498695511770993195704402414029892029461830476866385453475141207…

211大学计算机专业不考408,新增的交叉专业却考408!南京农业大学计算机考研考情分析!

南京农业大学信息科技学院可追溯至1981年成立的计算中心和1985年筹建的农业图书情报专业。1987年设立了农业图书情报系&#xff0c;1993 年农业图书情报系更名为信息管理系&#xff0c;本科专业名称也于1999年更名为信息管理与信息系统专业。1994年计算中心开始招收计算机应用专…

SpringBootTest测试框架四

dubbo调用mock 同理,为了实现dubbo的mock,也是要在dubbo调用的过程中添加拦截器 dubbo原始的执行拦截器 Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)) 这里代码写死了,没办法了,只能将整个JavassistProxyFactory 替换掉 public class J…

Nvidia Orin/Jetson +GMSL/RLINC/VbyOne/FPDLink 同轴AI多相机同步车载视觉解决方案

在本次演讲中&#xff0c;介绍了多相机同步技术在自主机器中的应用情况&#xff0c;围绕无人配送小车、控制器视觉传感器方案升级、人形机器人三个典型案例中如何为客户提供高效的多相机同步解决方案进行了详细的讲解&#xff0c;并进一步介绍如何通过创新的多相机同步技术&…

Facebook的心灵之镜:探寻数字社交的灵魂深处

在当今数字化时代&#xff0c;社交媒体已经成为了人们生活的一部分&#xff0c;而Facebook作为其中的佼佼者&#xff0c;更是承载了数以亿计的用户情感和交流。然而&#xff0c;Facebook不仅仅是一个简单的社交平台&#xff0c;它更像是一面心灵之镜&#xff0c;反映着数字社交…

TS(TypeScript)中Array数组无法调出使用includes方法,显示红色警告

解决方法 打开tsconfig.json文件&#xff0c;添加"lib": ["es7", "dom"]即可。 如下图所示。

基于Qt的网上购物系统的设计与实现

企鹅&#xff1a;2583550535 代码和论文都有 第1章 绪论... 1 1.1 项目背景... 1 1.2 国内外研究现状... 1 1.3 项目开发意义... 3 1.4 报告主要内容... 3 第2章 关键技术介绍... 4 2.1 后端开发技术... 4 2.1.1 C. 4 2.1.2 Qt框架... 4 2.1.3 MySQL数据库... 5 2.2 …

Java开发大厂面试第20讲:什么是分布式锁?Redi 怎样实现的分布式锁?

“锁”是我们实际工作和面试中无法避开的话题之一&#xff0c;正确使用锁可以保证高并发环境下程序的正确执行&#xff0c;也就是说只有使用锁才能保证多人同时访问时程序不会出现问题。 我们本课时的面试题是&#xff0c;什么是分布式锁&#xff1f;如何实现分布式锁&#xf…

DSP开发入门

视频&#xff1a; 创龙TI 最新DSP CPU核心架构 C66x 以及 KeyStone I 架构 DSP TMS320C6655/57以及TMS320C6678视频教程全集_哔哩哔哩_bilibili 2024年硬汉科技手把手教您学DSP28335视频教程持续更新中_哔哩哔哩_bilibili DSP芯片介绍 DSP选型 TI的DSP 分为三大系列&#…

comfyui电商场景工作流总结

eSheep(内测中) - 一站式的AIGC社区eSheep.com 是国内知名的AIGC在线画图网站,提供海量模型,并支持在线AI画图。用户会上传自己的AIGC作品到网站上,进行交流。eSheep让AIGC更轻松,让更多人在AIGC中找到快乐https://www.esheep.com/apphttps://openart.ai/workflows/all

单链表OJ题(课堂总结)

1.链表的带环问题 上图就是一个典型的带环链表 1.1如何判读链表是否带环&#xff1f; 最常见的方法就是利用快慢指针&#xff0c;快指针追加慢指针&#xff0c;当二者相等的时候即可判断链表带环 其实现的代码如下&#xff1a; bool hasCycle(struct ListNode*head) { s…

万博智云×华为云 | HyperBDR云容灾上架,开启联营联运新篇章

日前&#xff0c;万博智云HyperBDR云容灾正式入驻华为云云商店&#xff0c;成为华为云基础软件领域联营联运合作伙伴。通过联营联运&#xff0c;双方将进一步加深在产品、解决方案、渠道拓展等多方面的强强联合&#xff0c;为企业提供更加安全、高效的数据保护解决方案&#xf…

全面解析Java.lang.ClassCastException异常

全面解析Java.lang.ClassCastException异常 全面解析Java.lang.ClassCastException异常&#xff1a;解决方案与最佳实践 &#x1f680;&#x1f4da;摘要引言1. 什么是Java.lang.ClassCastException&#xff1f;代码示例 2. 报错原因2.1 类型不兼容2.2 泛型类型擦除2.3 接口和实…

HTTP -- HTTP概述

HTTP概述 HTTP使用的是可靠的数据传输协议。 web内容都是存储在web服务器上的&#xff0c;web服务器所使用的是http协议&#xff0c;故被称为http服务器。 web服务器是web资源的宿主&#xff0c;web资源是web内容的源头。 因特网上有数以千种的数据类型&#xff0c;http仔细的…

文心智能体之情感领航员:你的智能情感导师

文章目录 引言情感领航员的诞生与定位情感领航员的优势与特点专业性个性化便捷性隐私保护 如何创建自己的智能体创建方式智能体名称和设定基础配置角色与目标指导原则限制澄清个性化 高级配置保存 /发布流量数据分析智能体调优 总结 引言 在现代社会中&#xff0c;情感问题的普…