JPEG无损压缩
一. 前言
续接JPEG有损压缩流程实现接下来简单实现一下无损压缩的主要思想
二. 流程
无损压缩使用的逻辑是“预测”。由于“量化”一步骤是有损压缩中导致主要误差的一部分,因此在无损压缩中,不能够使用“量化”增大某些数值的出现频率。但是没关系,总有聪明人解决问题。
无损压缩以记录误差的方式,代替真正的图像数值。
无损压缩根据已知的像素点,对当前像素点的值进行预测,进而计算预测值与真实值之间的误差,并进行记录。
在解压缩的时候,通过预测值减去误差,得到真实值。
我们再对误差进行编码,此时误差对分布区间要比图像本身数值的分布区间小聚集得多(具体看实验中的直方图)。此时的压缩就可以达到一个比较好的效果。
三. 代码
主要运行部分,输出原图,以及直方图分布;经过不同预测方法的误差图像,以及直方图分布。
img = imread("15.jpeg");
gray = rgb2gray(img);
error1 = jpg_loss_error_gray1(gray);
error2 = jpg_loss_error_gray2(gray);
error3 = jpg_loss_error_gray3(gray);
subplot(421)
imshow(gray);
subplot(422)
histogram(img);
subplot(423)
imshow(uint8(error1));
subplot(424)
histogram(error1);
subplot(425)
imshow(uint8(error2));
subplot(426)
histogram(error2);
subplot(427)
imshow(uint8(error3));
subplot(428)
histogram(error3);
第一个函数是根据当前点(0,0)的左手边(0,-1)的像素值进行预测的
function error = jpg_loss_error_gray1(img)
[row,col] = size(img);
error = zeros(row,col);
for i = 1:row
for j = 1:col
if(i == 1)
if(j == 1)
predict = 0;
else
predict = img(i,j-1);
end
else
predict = img(i-1,j);
end
error(i,j) = img(i,j) - predict;
end
end
end
第二个是函数是根据上边(0,1)的像素值进行预测
function error = jpg_loss_error_gray2(img)
[row,col] = size(img);
error = zeros(row,col);
for i = 1:row
for j = 1:col
if(j == 1)
if(i == 1)
predict = 0;
else
predict = img(i-1,j);
end
else
predict = img(i,j-1);
end
error(i,j) = img(i,j) - predict;
end
end
end
第三个函数根据(0,-1),(-1,1),(0,1)三个像素的平均值进行预测的
function error = jpg_loss_error_gray3(img)
[row,col] = size(img);
error = zeros(row,col);
for i = 1:row
for j = 1:col
if(i == 1 || j == 1)
if(i ~= 1)
predict = img(i-1,j);
elseif(j ~= 1)
predict = img(i,j-1);
else
predict = 0;
end
else
predict = (img(i,j-1)+ img(i-1,j) + img (i-1,j-1))/3;
end
error(i,j) = img(i,j) - predict;
end
end
end
四. 效果
第一行为未进行处理的图片,可以看见分布从0到255,比较散乱。
底下三行分别为三种预测方法的误差图和分布图。从数值分布角度,可以看见大部分都聚集在0附近。
五. 结尾
真正的JPEG无损压缩的预测算法,要比上边实现的复杂。可以通过预测边缘的存在,进一步预测当前值。总之预测的越准确,压缩的越好。