由于内容是从写好的word文件中复制过来,可能排版等会有各种问题,建议直接看github中的pdf

另外由于我写这份作业的时候还不熟悉py3,因此实际上由很多可以优化的地方,比如数组强烈建议使用numpy而不是此处的列表

github地址:https://github.com/c980129/JPEG

【代码有误,参考前请先参考评论】

JPEG压缩实现(Python3)

  1. RGB转YUV

JPEG会将彩色图像执行YUV或YIQ的颜色空间转换,二次采样JPEG采用4:2:0,所以这里使用YUV420的颜色空间。在JPEG中使用的颜色模型是YCbCr(由YUV调整而来)。对于一个2*2的块,我们会保存4个Y值,1个Cb值(取0行0列的Cb)与1个Cr值(取1行0列的Cr),6个值保存信息,因此Cb与Cr有一定损失。

其中我们用函数rgb2yuv(在RGB2YUV.py)中来实现颜色模型转换与二次采样。并分别用三个二维数组保存采取的Y、U、V值。于是我们能得到三张分别用Y、U、V生成的灰度图(由于U和V损失为原来的1/4,因此其图像的长宽也分别为原来的1/2)(为了减少绝对值将Y值减去128):

  1. 图像边长填充为8的倍数并等分

用DCT.fill(img)函数对二次采样得到的Y、U、V图像分别用0填充知道其矩阵的height和width都是8的倍数,因为DCT函数的参数是一个8*8的矩阵。同样用DCT.split(img)函数将图像以左到右,上到下的顺序分成多个8*8矩阵,并返回这些矩阵连成的数组。

  1. 离散余弦变换

用DCT.FDCT(block)函数对一个8*8矩阵进行二维离散余弦变换,保存得到的矩阵。

  1. 量化

在类Quantization中保存成员变量table0与table1作为亮度和色度的量化表,调用Quantization.quanY(img)与Quantization.quanUV(img)分别用于对Y图像与U、V图像量化。

  1. AC系数

用AC类中的ZScan(img)对一个图像进行Z型扫描,得到一个长度为63的数组(图像第一个像素并不需要,它将在DC系数中保存)。之后通过RLC(array)对上面得到的数组array进行RLC得到他们的游长编码。

  1. DC系数

用DC类中的DPCM(blocks)函数对所有图像的DC系数提取并返回它们的DPCM编码数组。

  1. 熵编码

压缩部分是无损压缩,对DC系数(一个数组)采用可变字长整数编码。将一个DC系数分成size和amplitude两部分,配合VLI(num)和toB(num)函数将一个DC系数转换为一个[size(num), s(string(B))]。

这里的s已经是二进制串了(暂且用字符串存储方便操作),size需要用哈夫曼编码压缩。这里使用JPEG推荐的哈夫曼编码(亮度与色度两个表)。

对于AC系数,我们知道AC系数采用有偿编码,由两个数runlength与value组成。先将value如同DC系数一样采用可变字长整数编码拆分成size与amplitude,然后runlength与size合并为symbol1,smplitude独立为symbol2。对于runlength大于15的数情况,在symbol1添加(15,0)表示(为了解码时能识别,应在前端添加)。然后对symbol1采用哈夫曼编码,对于symbol2则直接用上文可变字长整数编码得到的二进制码。Symbol1采用的哈夫曼编码同样用JPEG推荐的哈夫曼编码表,由于过长不在报告中贴出。最终可用函数AllCompressY与AllcompressUV(未贴出)将一个表格的数据转换为二进制字符串。参数为DC系数(一个)与AC系数(数组)。

在Test.py中将对所有函数测试(实际上每个类的python文件的下方注释部分都是对这个类中函数的单元测试,由于不方便在报告中列出因此采用这种方式)。

这是Y图像的第一个8*8矩阵:

这是该矩阵的DCT变换结果(取整):

量化结果(取整):

Z字形扫描,DC系数,AC系数(太长未列全),二进制字符串,串长:

可以看到此处二进制长217位,意思是已经将一个8*8*8(512)bit的图像压缩为217bit。

对于译码,我们需要事先保存图片的长宽(正如图片位流里会保存一样),以此计算出Y,U,V图像的矩阵数,才能对整个二进制流正确分割(在译码过程中分割)。

在Compress类的encoding函数中,参数是位流(字符串形式)与宽,高(整型)。我们根据宽高得到Y、U、V图像的8*8矩阵的数量(我们知道U和V是一样多的),然后从位流头部开始移动两个指针。我们需要先得到上面使用的四个哈夫曼编码表的反向映射(这里用字典)。我们知道两个指针之间的二进制码的含义必定在几个状态之间转换:读取DC系数的size(通过不断比较两个指针之间的位流是否为字典的key,是的话得到其value(这里指字典的value),即size,不是则移动尾指针);通过size得到新的头尾指针,得到amplitude;然后开始读取AC系数的(runlength,size),如同上面得到DC系数的size一样,获得size后以此得到amplitude;循环读取AC系数直到读取翻译到的(runlength, value)为(0,0)或得到63个AC系数为止,将DC系数与AC系数都加进各自的列表中(这两列表将存储全部Y矩阵的DC系数与AC系数)。U与V同理,最终我们得到Y、U、V的DC系数与AC系数的数据(由于这段代码比较长不贴出,在Compress.py中)

然后通过DC类中的DPCM2(DC)函数,传入各自的DC系数,得到三个其元素是一个矩阵的列表,每个矩阵的[0][0]都通过DC系数还原为编码前

然后对每个矩阵分别通过对应的DC系数还原为63个数(AC.RLE(array))

再Z形填进矩阵中(AC.Z2Tab函数)(这段较长不贴出)

分别逆量化(Quantization.reY(img)与Quantization.reUV(img))(因为亮度与色度量化表不一样因此要分别操作)

再二维逆离散余弦变换(DCT.IDCT(img)。

这段操作每个函数的对象都是单个8*8矩阵

通过对所有矩阵进行同样的操作我们能得到所有当初刚分割完的8*8矩阵(不算损失的话)。

同样通过对这些矩阵进行合拼并将当初填充的0割掉,得到Y、U、V图像(这段代码较长不贴出,在DCT.py的DCT.merge()中,注意需要图像的长宽作为参数)

经此我们能得到YUV420的原图像。

关于测试代码,可以直接运行Test.py,会打印得到对每个函数的测试,或者运行Main.py,将执行对图像从压缩到解压的全部操作。Main.py会打印压缩得到的位流长,并在代码的上一层目录中创建一个txt.txt文件用字节形式保存每个位的数据(主要是用于测试解压代码时可以免去压缩过程迅速开始测试)。

运行Main.py会打印位流的长度,图片的高度与宽度(因此推荐在终端窗口中运行而不是直接运行py文件),并显示解压后的图片

我们直到682*1024个像素,如果直接用RGB的24位保存将要16760832bit

而这里压缩后得到的位流是1388439bit(虽然这里是字符串形式而非位流形式,但为了方便省去了以位流写文件的步骤,我们直接通过字符串的长度来对比)。压缩率是8.3%。

然而压缩的代价也十分明显(如图)。其中黑色变为其他颜色的点主要是YUV420中大量色度损失导致的(直接将图片从RGB转为YUV420再直接转为RGB就会有这些点的损失,因此如此推断),颜色也同样有不少损失,远处的云能看到明显的格子化。

解压后:

原图:

③ 结果对比:

压缩率约为8.3%的JPEG图(忽略文件信息等真正JPEG文件可能会造成的误差)

体积大约为170KB。与原文件接近,或许是我二度采样哪里理解错了或者写错了导致失真严重。

用PS使压缩的GIF也接近170KB(调整损失),得到的图像明显颜色(只有256)不足导致颜色接近的区块容易模糊融在一起。但整体色彩比起jpeg更接近原图,但是缺少细节。因此像照片这种细节多的图片,在体积相同的情况下还是选择JPEG更合适。或许是我的代码或者算法不够好导致的损失,也可能是我的二度采样是在原JPEG已经压缩过的二度采样的基础上的再次二度采样导致的损失,实际上原图jpg也是170KB体积,但表现效果十分好,比起我的压缩解压以及PS的转换为GIF都是如此。

GIF与JPEG文件保存在根目录下。代码保存在py文件夹中。


补充:色差原因请参考评论的朋友的描述,未测试

利用opencv与python3 JPEG压缩与解压实现相关推荐

  1. Java利用Gzip对字符串进行压缩与解压

    在某些业务场景下,可能需要对字符串进行压缩与解压,压缩字符串可以使用 GZIPOutputStream 输出流来实现,而解压可以使用 GZIPInputStream 输入流来实现,下面先给出具体的参考 ...

  2. 利用huffman编码对文本文件进行压缩与解压(java实现)

    利用huffman编码对文本文件进行压缩与解压 输入:一个文本文件 输出:压缩后的文件 算法过程: (1)统计文本文件中每个字符的使用频度 (2)构造huffman编码 (3)以二进制流形式压缩文件 ...

  3. python3 zlib 实现压缩与解压字符串与文件数据流

    关于python3 zlib 压缩解压情况总结如下: 字符串:使用zlib.compress方法压缩字符串,使用zlib.decompress方法解压字符串. 数据流:压缩:zlib.compress ...

  4. linux 压缩文件夹格式,Linux下常见文件格式的压缩、解压小结

    Linux下常见文件格式的压缩.解压小结 .tar 解包: tar xvf FileName.tar 打包:tar cvf FileName.tar DirName (注:tar是打包,不是压缩!) ...

  5. Linux操作系统中,*.zip、*.tar、*.tar.gz、*.tar.bz2、*.tar.xz、*.jar、*.7z等格式的压缩与解压...

    转:http://www.cnblogs.com/yejianfei/archive/2013/10/04/3351626.html zip格式 压缩: zip -r [目标文件名].zip [原文件 ...

  6. 按压缩格式整理打包(解包)和压缩(解压)命令

    文章目录 一.zip 格式 (一)使用命令 zip 压缩文件 (二)使用命令 unzip 解压 zip 包 二.tar 格式 (一)打包文件 (二)解包 tar 包 三.tar.gz 格式 方式一:利 ...

  7. 如何在 C# 中用 SharpZipLib 进行 ZIP 压缩与解压(转)

    转自:http://www.cftea.com/c/2008/04/A1FQ34RYSYNLFT47.asp SharpZipLib 是一个免费的组件,可以利用它对 ZIP 等多种格式进行压缩与解压. ...

  8. linux 常用压缩格式,Linux常见压缩格式之压缩与解压

    Linux常见压缩格式之压缩与解压 zip格式 压缩:zip -r [目标文件名].zip [原文件/目录名] 解压:unzip [原文件名].zip 注:-r参数代表递归 # Extract arc ...

  9. linux-应用-压缩与解压小结

    linux下的压缩与解压 摘要:主要说明在linux下的常用的压缩和解压程序的用法. 在压缩指令中最早的要算是compress了,但现在它基本上不是预设的压缩指令了. 后来被gzip和bzip代替了, ...

  10. linux快速解压缩,快速了解linux压缩与解压

    旨在快速了解linux文档压缩与解压,如需详细理解某个命令可用man一下,或者google一下. GUN-zip(gz) 压缩:gzip testfile       #压缩testfile文件,生成 ...

最新文章

  1. P1083 借教室(标记永久化线段树/二分+前缀和)难度⭐⭐⭐★
  2. linux安装系统配置环境变量,Linux系统安装jdk及配置环境变量的方法
  3. java更新无法正常安装_Java无法安装
  4. php有个qrcode类,一个PHP的QRcode类与大家分享
  5. MySQL高级 - 日志 - 错误日志
  6. MIPS投RISC-V是龙芯新征程的开始
  7. WidsMob Viewer Pro Mac如何批量调整照片大小及格式
  8. unity 加载关卡_Unity手游实战:从0开始SLG——本地化篇(四)提取本地化元素
  9. 台达b3伺服参数设置方法_台达B2系列伺服电机的调试方法和注意事项
  10. dcdc芯片效率不高的原因_影响DC-DC转换器效率的主要因素
  11. 显示器偏色测试软件,显示器偏色,如何解决显示器偏色?
  12. 由于目标计算机积极拒绝,无法连接。 Could not connect to Redis at 127.0.0.1:6379: 由于目标计算机积极拒绝,无法连接
  13. 字节架构师:来说说 Kafka 的消费者客户端详解,你都搞懂了吗。
  14. 记一次RATEL脱壳配合Il2CppDumper解密完成的样本分析
  15. ug中许可证服务器,ug教程:ug服务器许可证(LMTOOLS)设置教程
  16. RK系列(RK3568) 收音机tef6686芯片驱动,i2c驱动
  17. [模拟电路]ADI放大器笔记 - 差分放大器单端输入电阻设计
  18. matplotlib绘制3D图像
  19. 51单片机距离测试软件,单片机超声波传感器测量距离
  20. google日历的农历循环提醒

热门文章

  1. 目标检测、语义分割性能指标
  2. [试错题库]中国政企网络安全服务上岗证
  3. 关于FTP的两种连接模式
  4. windows命令行下ftp连接超时的可能原因
  5. HTML5响应式手机模板:MUI手机app前端页面开发框架模板HTML+CSS+JavaScript
  6. 程序员 需要什么ssd固态_什么是固态驱动器(SSD),我需要一个吗?
  7. MySQL进阶书籍推荐
  8. DSP烧写程序的步骤流程
  9. 开源免费etl作业批量调度必备软件 Taskctl Free应用版
  10. python空值填充_pandas妙招之 DataFrame基础运算以及空值填充