Matlab对图像进行裁剪。seam carving

近期学习数字图像处理,当对图像进行缩小时,如何保存图像的内容?这就用到了有名的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

如果有帮助就点个赞吧!

上一篇:1915739-87-5,DSPE-PEG2-Mal一种 PROTAC linker,属于 PEG 类


下一篇:社科院中外合作办学硕士|社科院美国杜兰大学能源硕士MME申请流程