图像切割--Seam Carving算法

Seam Carving算法

 

一、相关理论
      Seam Carving 算法是2007年siggraph上的一篇paper,名为《Seam Carving for Content-Aware Image Resizing》,这篇paper提出了一种内容感知的图像缩放算法,这篇文章的具体思路就是,通过找水平或者垂直的分割的像素能量最少的分割线,然后把其移除,得到新图,重复这个操作。代码如下

function im=seamcarving(im,k)
%% illustrative example of Seam carving for content aware image resizing
%
%
% usage: carvedimg=seamcarving(im,k)
%
% k is how many vertical seams to remove.
% im is the image.
%
% example:
%   img=imread('peppers.png')
%   carvedimg=seamcarving(img,50)
%   image([carvedimg img]);
%   axis equal;
%
% Author: Aslak Grinsted 2007...
% Based on ideas from Avidan & Shamir:
% http://video.google.com/videoplay?docid=-6221880321193117495
% Note i havent read their paper and they have probably lots of smart tricks
% for optimizations.
%

demo=nargout==0;
if nargin==0
    fex={'peppers.png' 'liftingbody.png' 'pears.png' 'trees.tif' 'football.jpg' 'onion.png'};
    fex=fex{ceil(rand*length(fex))};
    try
        [im,map]=imread(fex);
    catch
        [im,map]=imread('street1.jpg');
    end
    k=50;
end
im=im2double(im);





if demo
    close(findobj(0,'type','figure','tag','seam carving demo'));
    figure; set(gcf,'tag','seam carving demo','name','Seam Carving','NumberTitle','off')
    axes('position', [0 0 1 1]);
    if size(im,3)==1
        im=im/max(im(:));
        him=imagesc(im);
        colormap gray
    else
        him=image(im);
    end
    origim=im;
    axis equal
    axis off
end


for jj=1:k
    G=costfunction(im);
    %find shortest path in G
    Pot=G;
    for ii=2:size(Pot,1)
        pp=Pot(ii-1,:);
        ix=pp(1:end-1)1);
        im(ii,pix(ii),:)=bitand(ii,1);
%        G(ii,pix(ii))=1;
    end

    if demo
        set(him,'CDATA',im);
        %set(him,'CDATA',G,'CDataMapping','scaled');
        drawnow;
    end

    %remove seam from im & G:
    for ii=1:size(im,1)
%        G(ii,pix(ii):end-1)=G(ii,pix(ii)+1:end);
        im(ii,pix(ii):end-1,:)=im(ii,pix(ii)+1:end,:);
    end
    im(:,end,:)=[];
%    G(:,end)=[];

end

if demo
    set(him,'CDATA',[im origim])
    axis tight
end
if nargout==0
    clear im
end


    function G=costfunction(im) %%(xi,yi)
            G=zeros(size(im,1),size(im,2));
            for ii=1:size(im,8)
                %G=G+abs(filter2([1 0 -1],im(:,:,ii)))+abs(filter2([1;0;-1],im(:,:,ii))); 
                G=G+(filter2([.5 1 .5; 1 -6 1; .5 1 .5],im(:,:,ii))).^2; %faster and reasonably good.
            end
    end
end

                                      图像切割--Seam Carving算法_第1张图片   

                      图像切割--Seam Carving算法_第2张图片
    


                                                                                                          

垂直方向裁剪

该开始学习这个算法的时候,看起来好像很高深莫测的样子,理论看起来好像牛逼哄哄,什么能量,动态规划,都把我吓到了,最后理论的东西我实在是受不鸟了,于是果断直接解读代码,看了代码以后,才知道这个算法其实非常简单,难度就比普通的图像缩放难那么一点点,其实算法的原理很简单。废话不多说,这边只介绍缩小算法,且是图像宽度缩小的算法,对于图像高度缩小,只需对图像转置处理,总之paper中其它功能的实现,大同小异,整个过程说的简单一点就是通过寻找一条线,如上面的图1所示,找到了线以后,把那条线上的像素点全部删除,从而实现缩小操作。
该过程是通过迭代实现的,每次只能移除一列,迭代直到宽度满足要求。下面介绍寻找移除能量线的方法,需要注意的是,每次移除一列,都要重新计算能量图,也就是说,梯度图要重新计算,才能进行下一轮的移除工作。

算法流程

1、算法第一步:计算图像能量图 

能量图一般是图像像素的梯度模值,为了简化计算可先转换成灰度图像,然后直接采用如下公式(直接用x、y方向上的差分取绝对值,然后相加),其实这一步就是相当于边缘检测算法一样:

2、算法第二步:寻找最小能量线

最小能量线指的是需要被移除的那一列:首先需要以图像第一行或最后一行为开始行进行迭代。下面实现的为从图像最后一行开始,往上迭代,

  

找出最后一行需要被移除的像素点后,设其坐标为P(x,y),然后往上一行寻找,寻找的点为P点的在y-1行中的三个相邻像素点中的能量最小值像素。也就是寻找的坐标为(x-1,y-1)、(x,y-1)、(x+1,y-1);

 

3、算法第三步:移除得到的最小能量线,让图片的宽度缩小一个像素

移除最小能量线,同时所有位于最小能量线右边的像素点左移一个单位,从而实现图像缩小宽度缩小一个单位。

移除的时候 为了让图像看起来自然,需要在移除缝线的地方进行平均,假设移除坐标为P(x,y),那么移除后P(x-1,y)的像素值为P(x-1,y)与P(x,y)的像素值的平均。P(x+1,y)的像素值为P(x-1,y)与P(x,y)的像素值的平均,然后才能把P(x+1,y)移动到P(x,y)的位置。

 

 对于图像的放大算法原理一样,先找到最小能量线,设能量线上点的坐标为P(x,y),则在P(x,y)、P(x+1,y)中心位置插入新的像素,像素值为P(x,y)与P(x+1,y)的平均。

参考文献:

1、《Seam Carving for Content-Aware Image Resizing》

你可能感兴趣的:(机器学习)