近期学习数字图像处理,当对图像进行缩小时,如何保存图像的内容?这就用到了有名的seam carving算法。
下面是代码。
%基本思路:
%读出的是一个矩阵,先计算能量图,删除最小的缝隙,
%重新计算能量图,继续删除,直到我们的图像和我们想要得到的图像大小一致即可。
%偏F比偏x=F[x+1,y]-F[x,y];偏F比偏y=F[x,y+1]-F[x,y],可以试试边缘检测函数
%整体程序思路:
%通过梯度图生成能量图和路径图,删除最小的缝之后.Col不应该是最小的应该换成倒数第二小的
%以此类推,主要是计算最后一行的列值!
%先试试缩放灰度图
img=imread('Sky.png');
img=rgb2gray(img);
Timg=img;
%生成边缘检测模板
%偏y
hy=fspecial('sobel');
%偏x
hx=hy';
%记录列号
[p,q]=size(img);
Dic=zeros(p,1);
Line=zeros(p,q);
for f=1:200
%Timg是不断变化的
[m,n]=size(Timg);
Iy=imfilter(double(Timg),hy);
Ix=imfilter(double(Timg),hx);
%生成梯度图
Is=sqrt(Iy.^2+Ix.^2);
%能量图与最小能量对应的路径图
Energy=zeros(m,n);
Path=zeros(m,n);
temp=0;
%获取能量图与路径图
%第一行保存不变,
%第一列最小的在上面和右边找,最后一列最小的在上面和左边找,其它的处理相同
for i=1:m
for j=1:n
if(i==1)
Energy(i,j)=Is(i,j);
%第一行的路径设为0,第一行的路径可由第二行的temp找到
Path(i,j)=0;
else
%第一列
if(j==1)
temp=SRMin2(Energy(i-1,j),Energy(i-1,j+1));
Energy(i,j)=Is(i,j)+Energy(i-1,j+temp);
%path记录当前点的上一行相邻的最小点用 j+temp就是最小点的纵坐标
Path(i,j)=temp;
elseif(j==n)
temp=SLMin2(Energy(i-1,j-1),Energy(i-1,j));
Energy(i,j)=Is(i,j)+Energy(i-1,j+temp);
Path(i,j)=temp;
else
temp=LSRMin3(Energy(i-1,j-1),Energy(i-1,j),Energy(i-1,j+1));
Energy(i,j)=Is(i,j)+Energy(i-1,j+temp);
Path(i,j)=temp;
end
end
end
end
%记录最小值的列号和最小值
LastRow=(Energy(m,:));
Col=1;
Min=LastRow(1);
for i=1:n
if LastRow(i)<Min
Col=i;
end
end
%有了Col和temp就有了最小路径
for i=m:-1:2
%代码比较巧妙,先获取t,t的值决定了上一行最小值的列数
Dic(i,1)=Col;
t=Path(i,Col);
%记录最短路径的坐标
Col=Col+t;
if i==2
Dic(1,1)=Col;
end
end
%记录白线
for i=1:p
if(f==1)
Line(i,f)=Dic(i,1);
else
%后一次生成的列号小于前一次的
if Dic(i,1)<TDic(i,1)
Line(i,f)=Dic(i,1);
else
Line(i,f)=Dic(i,1)+f-1;
end
end
end
TDic=Dic;
%删除缝后的图片
Img2=zeros(m,n-1);
for i=1:m
x=0;
for j=1:n-1
x=x+1;
if j==Dic(i,1)
x=x+1;
Img2(i,j)=Timg(i,x);
else
Img2(i,j)=Timg(i,x);
end
end
end
%对于这张新的照片Img2,重复进行操作!
Timg=Img2;
Timg=uint8(Timg);
end
Img1=img;
[a,b]=size(Line);
for i=1:a
for j=1:200
Img1(i,Line(i,j))=255;
end
end
subplot(2,2,1),imshow(img);
title("Original Picture");
subplot(2,2,2),imshow(Img1);
title("Energy Line Picture");
subplot(2,2,3),imshow(uint8(Img2));
title("After Cut Picture");
%定义三个函数,分别找两个里面最小的和三个里面最小的
%上右
function temp=SRMin2(a,b)
if(a<b)
temp=0;
else
temp=1;
end
end
%上左
function temp=SLMin2(a,b)
if(a<b)
temp=-1;
else
temp=0;
end
end
%左上右
function temp=LSRMin3(a,b,c)
if(min([a,b,c])==a)
temp=-1;
elseif(min([a,b,c])==b)
temp=0;
else
temp=1;
end
end
% %返回最后一行第 w 小的能量图的列值Col
% function Col=CountMin(Row,w)
% %先排序,得出第w小的能量的值
% Matrix=sort(Row);
% temp=Matrix(w);
% for i =1:n
% if temp==Row(i)
% Col=i;
% break;
% end
% end
% end
如果有帮助就点个赞吧!