使用Matlab实现JPEG压缩
来源:互联网 发布:sql的with语句 编辑:程序博客网 时间:2024/06/15 23:04
一、 图像压缩原理
图像分成 8*8 小块 –> DCT 变换 –>用量化表对其量化 –>编码生成压缩数据
二、 具体压缩过程
1、将原始图像分为 8 * 8 的小块, 每个 block 里有 64 个像素。
2、 将图像中每个 8 * 8 的 block 进行 DCT 变换。8 * 8 的图象经过 DCT 变换后,其低频分量都集中在左上角,高频分量分布在右下角。由于该低频分量包含了图象的主要信息(如亮度),而高频与之相比,就不那么重要了,所以我们可以忽略高频分量。
3、 利用量化表抑制高频变量。量化操作,就是将某一个值除以量化表中对应的值。由 于量化表左上角的值较小,右上角的值较大,这样就起到了保持低频分量,抑制高 频分量的目的。压缩时候将彩色图像的颜色空间由 RGB 转化为 YUV 格式。其中 Y 分量代表了亮度信息,UV 分量代表了色差信息。相比而言,Y 分量更重要一些。 我们可以对 Y 采用细量化,对 UV 采用粗量化,可进一步提高压缩比。所以量化表 通常有两张,一张是针对 Y 的标准亮度量化表;一张是针对 UV 的标准色彩量化表。
4、 经过量化之后右下角大部分数据变成了 0,左上角为非零数据。这时使用 Z 字型(如 图所示)的顺序来重新排列数据生成一个整数数组,这样 0 就位于数组都后端。找到数组最后一个非零元素,将其后的数据都舍弃,并加上结束标志。
三、 关键代码
Compress.m
function [comp_image_Y,comp_image_U,comp_image_V] = Compress(orig_image)RGB=orig_image;%下面是对 RGB 三个分量进行分离 R=RGB(:,:,1);G=RGB(:,:,2);B=RGB(:,:,3);%RGB->YUV Y=0.299*double(R)+0.587*double(G) +0.114*double(B); [xm, xn] = size(Y); U=-0.169*double(R)-0.3316*double(G)+0.5*double(B); V=0.5*double(R)-0.4186*double(G)-0.0813*double(B);%产生一个 8*8 的 DCT 变换举证 T=dctmtx(8);%进行 DCT 变换 BY BU BV 是 double 类型BY=blkproc(Y,[8 8],'P1*x*P2',T,T'); BU=blkproc(U,[8 8],'P1*x*P2',T,T'); BV=blkproc(V,[8 8],'P1*x*P2',T,T'); %低频分量量化表a=[16 11 10 16 24 40 51 61;12 12 14 19 26 58 60 55;14 13 16 24 40 57 69 55;14 17 22 29 51 87 80 62;18 22 37 56 68 109 103 77; 24 35 55 64 81 104 113 92; 49 64 78 87 103 121 120 101; 72 92 95 98 112 100 103 99;]; %高频分量量化表b=[17 18 24 47 99 99 99 99; 18 21 26 66 99 99 99 99; 24 26 56 99 99 99 99 99; 47 66 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99;];%使用量化表对三个分量进行量化 BY2=blkproc(BY,[8 8],'round(x./P1)',a); BU2=blkproc(BU,[8 8],'round(x./ P1)',b); BV2=blkproc(BV,[8 8],'round(x./P1)',b);%调用压缩函数 comp_image_Y=img2jpg(BY2,1); comp_image_U=img2jpg(BU2,2); comp_image_V=img2jpg(BV2,3);
img2jpg.m
function [ y ] = img2jpg( x,flag )[xm, xn] = size(x);%z字型读取数据顺序表order = [1 9 2 3 10 17 25 18 11 4 5 12 19 26 33 ... 41 34 27 20 13 6 7 14 21 28 35 42 49 57 50 ... 43 36 29 22 15 8 16 23 30 37 44 51 58 59 52 ... 45 38 31 24 32 39 46 53 60 61 54 47 40 48 55 ... 62 63 56 64];y = im2col(x, [8 8], 'distinct'); % 将8x8 的块转化为列xb = size(y, 2); % 分块数y = y(order, :); % 按照order的顺序排列数据eob = max(y(:)) + 1; % 设置块尾结束标志r = zeros(numel(y) + size(y, 2), 1);count = 0;for j = 1:xb % 每次处理一个块 i = max(find(y(:, j))); % 找到最后一个非零元素 if isempty(i) i = 0; end p = count + 1; q = p + i; r(p:q) = [y(1:i, j); eob]; % 加入块结束标志 count = count + i + 1; % 计数endr((count + 1):end) = []; % 删除r 中不需要的元素[r1,r2]=size(r);y = struct;y.realsize = r1;y.size = uint16([xm xn]);y.numblocks = uint16(xb);y.r = r;y.flag = flag;end
jpg2img
function [ x ] = jpg2img( y )%低频分量量化表 a=[16 11 10 16 24 40 51 61; 12 12 14 19 26 58 60 55; 14 13 16 24 40 57 69 55; 14 17 22 29 51 87 80 62; 18 22 37 56 68 109 103 77; 24 35 55 64 81 104 113 92; 49 64 78 87 103 121 120 101; 72 92 95 98 112 100 103 99;]; %高频分量量化表 b=[17 18 24 47 99 99 99 99; 18 21 26 66 99 99 99 99; 24 26 56 99 99 99 99 99; 47 66 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99; 99 99 99 99 99 99 99 99;]; order = [1 9 2 3 10 17 25 18 11 4 5 12 19 26 33 ... 41 34 27 20 13 6 7 14 21 28 35 42 49 57 50 ... 43 36 29 22 15 8 16 23 30 37 44 51 58 59 52 ... 45 38 31 24 32 39 46 53 60 61 54 47 40 48 55 ... 62 63 56 64];rev = order; % 计算反序for k = 1:length(order) rev(k) = find(order == k);endxb = double(y.numblocks); % 块的个数sz = double(y.size);xn = sz(2); % 列数xm = sz(1); % 行数x = y.r; % 压缩后的数据eob = max(x(:)); % 返回块尾标志z = zeros(64, xb); k = 1; % 生成 64 * xb 的零矩阵for j = 1:xb % x中的值放入z中,如果遇到eob就转入下一列 for i = 1:64 if x(k) == eob k = k + 1; break; else z(i, j) = x(k); k = k + 1; end endendT=dctmtx(8); %产生一个8*8的DCT变换举证 z = z(rev, :); % 按order恢复之前排列x = col2im(z, [8 8], [xm xn], 'distinct'); % 生成矩阵if y.flag==1 x = blkproc(x, [8 8], 'x .* P1', a); % 反量化,乘量化表的值else x = blkproc(x, [8 8], 'x .* P1', b);endx = blkproc(x, [8 8], 'P1 * x * P2', T', T); % 反DCT变换end
Decompress.m
function reco_image = Decompress(orig_image_Y,orig_image_U,orig_image_V) %解压缩YI=jpg2img(orig_image_Y);UI=jpg2img(orig_image_U);VI=jpg2img(orig_image_V);%YUV 转为 RGBRI=YI-0.001*UI+1.402*VI; GI=YI-0.344*UI-0.714*VI; BI=YI+1.772*UI+0.001*VI;%经过 DCT 变换和量化后的 YUV 图像 RGBI=cat(3,RI,GI,BI);RGBI=uint8(RGBI);reco_image = RGBI;
运行结果
https://github.com/geekzph/JPEGCompression
0 0
- 使用Matlab实现JPEG压缩
- Android使用JPEG实现图片压缩上传
- Jpeg压缩实现
- matlab使用神经网络实现图像压缩
- JPEG压缩编码方法与实现
- 纯C实现的JPEG压缩算法
- FPGA实现JPEG-LS无损压缩算法
- matlab读jpeg图像--jpeg toolbox的使用
- jpeg压缩
- jpeg压缩
- matlab简易实现图像压缩
- JPEG图像压缩解压算法——C++实现
- 使用libjpeg在linux内核中压缩JPEG图片
- 快速jpeg压缩与解压,libjpeg库的使用
- Google使用人工智能压缩图片,效果优于JPEG
- 使用dcm4che3对jpeg压缩的dcm文件进行解压
- 使用Matlab将一组jpeg图像合成为avi视频
- 想对jpeg格式图像进行压缩(不是缩略图),压缩后还是jpeg格式,在java中如何实现
- Python读取mat文件
- 在Intellij idea中用maven创建ssm项目
- OpenJudge noi 06寻宝(codevs1314)
- 第33周-鸟哥的Linux私房菜基础篇第三版- 第十二章、正规表示法与文件格式化处理
- CF - 540D 概率dp
- 使用Matlab实现JPEG压缩
- tab栏再改进,为了减轻后台压力,鼠标快速滑过不响应,慢慢滑过才响应
- android 5.1 打开与关闭GPS
- [收藏] 深入浅出存储性能评估方法论
- 1007 Python之List中remove,pop,del区别分析
- Matlab实现基于内容的图像检索系统
- POJ1060 数组存储多项式+多项式乘法和取余,水
- 软件的三层架构
- 简单五子棋(单机版-C)