基于DCT的图像量化-Python简单实现

这篇具有很好参考价值的文章主要介绍了基于DCT的图像量化-Python简单实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        一、前言

        与本科期间导师给的课题相关,暑假期间学了一些关于DCT量化的内容。上网查阅了之后发现已经有博主使用MATLAB实现了这个功能。但是少有人用Python实现,于是我就动手写了一下。

        实现起来并不复杂,主要的难点就是如何对图像进行均分快。由于二维DCT变换的性质,分割图像可以大幅提高效率。对图像进行DCT变换的主要思路就是将图像分割为多个小块,再对每一小块进行DCT变换。下面笔者先简单介绍一下DCT变换。

        二、DCT变换

        图像中的低频信号包含了图像主要信息(空间、大致轮廓、颜色等),而高频信号包含图像的细节信息(细节轮廓,噪声)等。而人眼对细节信息,也就是高频信号并不敏感。对图像信号进行DCT变换可以将大部分能量聚集于低频信号,而减少高频信号。这方便了后续进行量化的操作。

        我们常用的DCT变换的公式如下:

pytohn dct idct,计算机视觉,python,信号处理

        其中

                

        DCT变换本质上是DFT变换在输入实偶函数下的一种特殊情况。即其数学性质与DFT相同。但DCT变换在做周期延拓之前增加了镜像延拓。这有效避免了延拓后的信号出现跳变。而时域上的跳变在频域上对应着高频分量。DCT变换有效避免了高频信号带来的干扰,相比DFT有更好的能量聚集。下图很好的说明了这一点。

pytohn dct idct,计算机视觉,python,信号处理

        此外,由于DCT变换是在实信号上进行的变换,相比较DFT的即有实数部分也有虚数部分,DCT的效率比DFT要高。因此DCT就更适合于图像、声音和视频等可能需要实时处理的信号。

        因为图像属于二维信号,因此要做二维DCT变换。下面为二维DCT变换公式:

pytohn dct idct,计算机视觉,python,信号处理

        其中

   

        不难看出二维DCT变换实际上是对图像所有行做DCT变换,再对所有列做DCT变换。直觉上来看再对所有列做变换似乎是多余的。但如果只做行或列变换的话,那么行与行(或列与列)之间的连接处就可能出现信号的跳变,从而引入高频分量,这不是我们所希望的。

        因为在计算机上进行矩阵运算要比遍历乘法求和运算快得多,而二维DCT变换可以使用矩阵进行运算,下面为矩阵形式的DCT变换:

        令变换矩阵A为

pytohn dct idct,计算机视觉,python,信号处理

         那么二维DCT变换可写作

        完成DCT变换后就可以进行量化了,本文使用遮罩(mask)进行量化操作。

        三、量化 

        图像经过DCT变换后,主要的低频能量都聚集于左上角,少量的高频能量于右下角。如下图所示。左上角为低频信号所在位置,右下角为高频信号所在位置。可以看到左上角颜色更亮,而右下角颜色更暗。亮色说明系数大,能量多,反之说明系数小,能量少。

pytohn dct idct,计算机视觉,python,信号处理

        这里量化的方式为保留左上角的低频信号,过滤右下角的高频信号。本文通过遮罩进行逐元素相乘来实现过滤。如下图所示。通过乘法,将遮罩中1的位置数据保留,0的部分删除。即可实现量化。或者可以通过系数的大小进行筛选,系数大于某个值就保留,否则删除,这里不多赘述,大家可以自行实现。

pytohn dct idct,计算机视觉,python,信号处理

        四、Python实现 

# -*- coding: utf-8 -*-
"""
Created on Mon Sep  4 19:08:36 2023

@author: Icathia7
"""

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

#%%

def DCT_quantify(data, block_size=8, set_mask=None):
    
    # 获取图像大小
    h, w = data.shape
    
    # 获取遮罩
    if type(set_mask)==np.ndarray:
        mask = set_mask
    else:
        # 若不设置遮罩,默认为全1矩阵
        mask = np.ones([block_size, block_size])
    
    # 填充图像以便分割
    if (h_to_pad:=(h % block_size)) != 0:
        data = np.pad(data, ((0, block_size - h_to_pad), (0, 0)))
    if (w_to_pad:=(w % block_size)) != 0:
        data = np.pad(data, ((0, 0), (0, block_size - w_to_pad)))
        
    new_h, new_w = data.shape
        
    # 计算分割份数
    v_slices_num = new_h // block_size
    h_slices_num = new_w // block_size
    
    # 按行分割
    hori_data = np.vsplit(data, indices_or_sections=v_slices_num)
    
    
    for i, row in enumerate(hori_data):
        # 按列分割
        vert_data = np.hsplit(row, indices_or_sections=h_slices_num)
        
        first_v_block = cv2.dct(vert_data[0].astype(np.float32))
        
        # 遮罩
        first_v_block = np.multiply(first_v_block, mask)
        
        first_v_iblock = cv2.idct(first_v_block)
        dct_block_rows = first_v_block
        idct_block_rows = first_v_iblock
        for j, block in enumerate(vert_data[1:]):
            # 进行DCT变换
            single_block = cv2.dct(block.astype(np.float32))
            
            # 遮罩
            single_block = np.multiply(single_block, mask)
            
            # 反变换
            single_iblock = cv2.idct(single_block)
            # 横向合并块成行
            dct_block_rows = np.hstack([dct_block_rows, single_block])
            idct_block_rows = np.hstack([idct_block_rows, single_iblock])
        
        if i == 0:
            dct_img = dct_block_rows
            idct_img = idct_block_rows
        else:
            # 纵向合并行
            dct_img = np.vstack([dct_img, dct_block_rows])
            idct_img = np.vstack([idct_img, idct_block_rows])
            
    
    return dct_img, idct_img

        此函数有三个参数data, block_size, set_mask。其中data为图像数据;block_size为每一分块的大小,单位为像素,默认为8;set_mask为遮罩,默认为None,此时置遮罩为一全1矩阵,相当于未使用遮罩。需要注意的是,对于图像长宽无法被整除的情况,函数里做了一个判断,对无法整除的图像进行填充0的处理,这使得输出图像的长和宽可能会比输入图像大几个像素。

        接下来进行测试:

        测试代码,这里先不使用遮罩。

if __name__ == "__main__":
    
    # 读取图像
    img = plt.imread("output_png.png")
    R = img[:, :, 0]
    G = img[:, :, 1]
    B = img[:, :, 2]
    plt.figure(1)
    plt.imshow(img)
    
    
    #%%
    
    # 自定义遮罩
    mask = np.array([[1, 1, 0, 0, 0, 0, 0, 0],
                     [1, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.float32)
    
    # 分别对三个通道进行量化
    B_dct, B_idct = DCT_quantify(B)
    G_dct, G_idct = DCT_quantify(G)
    R_dct, R_idct = DCT_quantify(R)
    
    #%%
    
    # 合并三通道图像
    rebuild_img = np.stack((R_idct, G_idct, B_idct), axis=2)
    plt.figure(2)
    plt.imshow(rebuild_img)

        测试结果:

        原图:

pytohn dct idct,计算机视觉,python,信号处理

        还原后的图像:

pytohn dct idct,计算机视觉,python,信号处理

        可以看出,在不使用遮罩的情况下利用反DCT还原出来的图像与原图视觉上几乎没有差别

        接下来使用遮罩再测试一遍,代码如下:

    # 自定义遮罩
    mask = np.array([[1, 1, 0, 0, 0, 0, 0, 0],
                     [1, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.float32)
    
    # 分别对三个通道进行量化
    B_dct, B_idct = DCT_quantify(B, set_mask=mask)
    G_dct, G_idct = DCT_quantify(G, set_mask=mask)
    R_dct, R_idct = DCT_quantify(R, set_mask=mask)

        这里选择保留左上角3个系数,还原结果如下图:

pytohn dct idct,计算机视觉,python,信号处理

        压缩比约为: 1.7392

        可以看出,在保留左上三个系数的情况下,图像大致内容都被还原出来了。要提升清晰度,我们可以增加保留的系数数量。

        保留左上6个系数:

pytohn dct idct,计算机视觉,python,信号处理

       压缩比约为: 1.3274

        保留左上10个系数:

pytohn dct idct,计算机视觉,python,信号处理

        压缩比约为1.1703        

        不难看出,我们还原出的图像清晰度随着系数的增加而增加,而压缩比随之降低。

        接下来我们测试仅保留高频信息时还原出的图像:

        保留右下49个数据:

      pytohn dct idct,计算机视觉,python,信号处理

        保留右下54个系数:

pytohn dct idct,计算机视觉,python,信号处理

        保留右下58个系数:

pytohn dct idct,计算机视觉,python,信号处理 

        可以看出,即使保留高频的系数比低频多得多,视觉上能还原的数据却少的多。 说明绝大部分能量都聚集在低频部分。

reference

        详解离散余弦变换(DCT) - 知乎 (zhihu.com)

 文章来源地址https://www.toymoban.com/news/detail-765433.html

到了这里,关于基于DCT的图像量化-Python简单实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【图像隐写】基于matlab DCT数字水印嵌入+攻击+提取【含Matlab源码 1758期】

    ✅博主简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,Matlab项目合作可私信。 🍎个人主页:海神之光 🏆代码获取方式: 海神之光Matlab王者学习之路—代码获取方式 ⛳️座右铭:行百里者,半于九十。 更多Matlab仿真内容点击👇 Matlab图像处理(进阶版) 路径规划

    2023年04月08日
    浏览(52)
  • 【语音隐写】基于DCT实现音频水印嵌入提取附Matlab代码

     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进, 代码获取、论文复现及科研仿真合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab完整代码及仿真定制内容点击👇 智能优化算法       神经网络预测       雷达通信    

    2024年02月03日
    浏览(45)
  • 【Matlab系列】基于DCT和置乱算法的视频水印Matlab实现

    Date: 2022.4.5     数字水印技术一般用于版权认证。在实际使用中,嵌入水印的鲁棒性就显得非常重要。通常会采用各种方式进行攻击测试,比如加噪滤波,缩放、旋转、剪切、JPEG压缩等。本文讲述了采用置乱技术进行嵌入水印和提取水印,并加入滤波、剪切、椒盐噪声、

    2024年02月01日
    浏览(48)
  • 基于FPGA的二维DCT变换和逆变换verilog实现,包含testbench

    目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 数据导入到matlab显示图像 vivado2019.2 matlab2022a         离散余弦变换(Discrete Cosine Transform,DCT)是一种广泛应用于图像和信号处理领域的变换技术。在图像处理中,DCT常被用于

    2024年02月21日
    浏览(60)
  • 【毕业设计系列】001:基于DCT和置乱算法的视频水印Matlab实现

    Date: 2022.4.5     数字水印技术一般用于版权认证。在实际使用中,嵌入水印的鲁棒性就显得非常重要。通常会采用各种方式进行攻击测试,比如加噪滤波,缩放、旋转、剪切、JPEG压缩等。本文讲述了采用置乱技术进行嵌入水印和提取水印,并加入滤波、剪切、椒盐噪声、

    2023年04月09日
    浏览(43)
  • 10 DCT变换对灰度图像压缩(matlab程序)

    1. 简述 一、设计任务 1、在图像的变换和压缩中,常常用到离散余弦变换(DCT)。DCT变换用于图像的压缩实例。请在测试图像中验证你的结论。 2、请编程实现图像的真彩色增强。 3、通过直方图均衡化的方法实现图像的灰度变换,在测试图像中验证你的结论,分析程序结果。

    2024年02月12日
    浏览(61)
  • 压缩编码之变换的选择之离散余弦变换(DCT)和离散傅立叶变换(DFT)——数字图像处理

    变换的选择是一个关键的考量因素,它决定了数据是如何被压缩的。选择变换时考虑以下几个重要原则: 数据去关联性 :变换的目的之一是减少数据中的相关性。例如,在图像压缩中,像素间往往高度相关。通过适当的变换,如离散余弦变换(DCT),可以将这些相关性转化

    2024年02月02日
    浏览(55)
  • 计算机视觉的几个经典算法 —— 最小二乘法 + RANSAC + 哈希算法(附DCT) + 图像聚类算法

    在了解最小二乘法之前,我们有必要先说说线性回归,所谓线性回归我们最常见的例子y=2x这个一元线性回归方程中,斜率2就是回归系数,它表示的是x变动时,y与之对应的关系,而线性回归就是表示一些离散的点在总体上是最逼近某一条直线的 这跟最小二乘法有啥关系呢?

    2024年02月08日
    浏览(44)
  • 数字图像处理实验(二)|图像变换{离散傅里叶变换fft2,离散余弦变换dct2、频谱平移fftshift}(附实验代码和截图)

    1了解图像变换的原理; 2理解图像变换系数的特点; 3掌握图像变换的方法及应用; 4掌握图像的频谱分析方法; 5了解图像变换在图像数据压缩、图像滤波等方面的应用。 安装了MATLAB软件的台式或笔记本电脑 1.离散傅里叶变换 对于二维离散信号,Fourier正变换定义为: 二维离

    2024年02月06日
    浏览(54)
  • dct变换(dct变换矩阵)

    1。双离合器变速器(DCT)仍然像手动变速器一样是由众多齿轮、同步器、液压控制单元、电子控制单元和各轴等部件组成的,速比变化靠计算机控制来实现,而且各挡速比是固定不变的。 2。无论6挡DSG变速器,还是7挡DSG变速器,它们的基本原理是一致的,简单地说,就是将两套

    2023年04月08日
    浏览(78)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包