Code covered by the BSD License  

Highlights from
[SigGraph2002] Image Quilting/Texture Synthesize

image thumbnail
from [SigGraph2002] Image Quilting/Texture Synthesize by Li Cheng
Matlab code to do Image Quilting as presented in the SIGGRAPH 2002 paper by Efros & Freeman.

synthesize(imin, sizeout, tilesize, overlap , isdebug)
function [imout] = synthesize(imin, sizeout, tilesize, overlap ,  isdebug)
% Matlab code to do Image Quilting as presented in the SIGGRAPH 2002 paper by Efros & Freeman.
% 
% Note: this isn't Efros & Freeman's code, just my implementation of it. 
%
% Texture Synthesize
%     IMOUT = SYNTHESIZE(IMGIN , SIZEOUT, TILESIZE, OVERLAP [, ISDEBUG]) 
%                      returns an image that is Texture Synthesized
%    
%     IMGIN  
%           the code both works on grascale images or color images
%
%     SIZEOUT
%           An 1*2 array , the size of output image
%           e.g.   size(texture)*3
%           
%     TILESIZE
%           TILESIZE of each block
%
%     OVERLAP
%           size of overlap bar between blocks 
%
%     ISDEBUG
%           equals 0 (default) if no debug function
%           the algorithm will shows progress of each step, a little more
%           time will be cost in plotting.
%
%       A little confuse I meet with when the block overlaped with two
%      block, I solved it with a simple way.
%       licheng09@mails.tsinghua.edu.cn


imin = double(imin);

if(size(imin,3) ==1)
    imout = zeros(sizeout);
else
    imout = zeros([sizeout(1:2) size(imin,3)]);
end
imout(1,1,:)=255;


if nargin<5
    isdebug = 0;
end

if isdebug~=0
    h = imshow(uint8(imout));
else
    isdebug = floor(isdebug);
end



sizein = size(imin);
sizein = sizein(1:2);

temp = ones([overlap tilesize]);
errtop = getxcorr2(imin.^2, temp);
temp = ones([tilesize overlap]);
errside = getxcorr2(imin.^2, temp);
temp = ones([tilesize-overlap overlap]);
errsidesmall = getxcorr2(imin.^2, temp);

%B1overlap = zeros(overlap,tilesize);
%B2overlap = zeros(overlap,tilesize);



for i=1:tilesize-overlap:sizeout(1)-tilesize+1,
  for j=1:tilesize-overlap:sizeout(2)-tilesize+1,

    if (i > 1) & (j > 1),
    % extract top shared region
      shared = imout(i:i+overlap-1,j:j+tilesize-1,:);
      err = errtop - 2 * getxcorr2(imin, shared) + sum(shared(:).^2);
      
      % trim invalid data at edges, and off bottom where we don't want
      % tiles to go over the edge
      err = err(overlap:end-tilesize+1,tilesize:end-tilesize+1);

      % extract left shared region, skipping bit already checked
      shared = imout(i+overlap:i+tilesize-1,j:j+overlap-1,:);
      err2 = errsidesmall - 2 * getxcorr2(imin, shared) + sum(shared(:).^2);
      % sum(shared(:).^2); trim invalid data at edges, and where we
      % don't want tiles to go over the edges
      err = err + err2(tilesize:end-tilesize+overlap+1, overlap:end-tilesize+1);

      [ibest, jbest] = find(err <= 1.1*1.01*min(err(:)));
      c = ceil(rand * length(ibest));
      pos = [ibest(c) jbest(c)];
      
      
          B1overlaph = imout(i:i+overlap-1,j:j+tilesize-1,:); % shared
          B2overlaph = imin(pos(1):pos(1)+overlap-1,pos(2):pos(2)+tilesize-1,:);

          errmat = sum((B1overlaph-B2overlaph).^2,3);

          fph = zeros(overlap,tilesize);
          pathh = zeros(overlap,tilesize);

          fph(:,tilesize) = errmat(:,tilesize);

          for k = tilesize-1:-1:1
              for l = 1:overlap
                  index =  max(1,l-1):min(overlap,l+1);
                  [fph(l,k), temp_index] = min( fph(index,k+1));
                  fph(l,k) = fph(l,k) + errmat(l,k);
                  pathh(l,k) = index(temp_index);
              end
          end
          
          B1overlap = imout(i:i+tilesize-1,j:j+overlap-1,:); % shared
          B2overlap = imin(pos(1):pos(1)+tilesize-1,pos(2):pos(2)+overlap-1,:);

          errmat = sum((B1overlap-B2overlap).^2,3);

          fp = zeros(tilesize,overlap);
          path = zeros(tilesize,overlap);

          fp(tilesize,:) = errmat(tilesize,:);

          for k = tilesize-1:-1:1
              for l = 1:overlap
                  index =  max(1,l-1):min(overlap,l+1);
                  [fp(k,l), temp_index] = min( fp(k+1,index));
                  fp(k,l) = fp(k,l) + errmat(k,l);
                  path(k,l) = index(temp_index);
              end
          end
          
          allerr = fp(1:overlap,1:overlap) + fph(1:overlap,1:overlap);
          
          [tempmin,tempindminclom] = min(allerr);
          [temp, min_bound_indexj] = min(tempmin);
          min_bound_indexi = tempindminclom(min_bound_indexj);
          
          imout(i+ overlap : i+tilesize-1,j + overlap : j+ tilesize-1,:) = ...
              imin(pos(1)+overlap :pos(1)+tilesize-1,pos(2)+overlap :pos(2)+tilesize-1,:);
          
          
      
          %imout(i:i+tilesize-1,j:j+tilesize-1) = imin(pos(1):pos(1)+tilesize-1,pos(2):pos(2)+tilesize-1);
          
          min_err_bound = zeros(1,tilesize);
          min_err_boundh = zeros(1,tilesize);
      
          min_err_bound(min_bound_indexi) = min_bound_indexj;
          min_err_boundh(min_bound_indexj) = min_bound_indexi;
      
          for k=min_bound_indexi+1 :tilesize
              min_err_bound(k) = path(k-1,min_err_bound(k-1));
          end
          
          for k=min_bound_indexj+1 :tilesize
              min_err_boundh(k) = pathh(min_err_boundh(k-1),k-1);
          end
          
          for k = overlap : tilesize
            imout(i+min_err_boundh(k):i+overlap-1,j+k-1,:) = imin(pos(1)+min_err_boundh(k):pos(1)+overlap-1,pos(2)+k-1,:);
          end
          
          for k = overlap:tilesize
            imout(i+k-1,j+min_err_bound(k):j+overlap-1,:) = imin(pos(1)+k-1,pos(2)+min_err_bound(k):pos(2)+overlap-1,:);
          end
          
          
          for k = min_bound_indexi:overlap-1
              for l = min_bound_indexj:overlap-1
                  if k>=min_err_boundh(l) && l>= min_err_bound(k)
                      imout(i+k,j+l,:) = imin(pos(1)+k,pos(2)+l,:);
                  end
              end
          end
           
    elseif i > 1
      shared = imout(i:i+overlap-1,j:j+tilesize-1,:);
      err = errtop - 2 * getxcorr2(imin, shared) + sum(shared(:).^2);
      
      % trim invalid data at edges
      err = err(overlap:end-tilesize+1,tilesize:end-tilesize+1,:);

      [ibest, jbest] = find(err <= 1.01*1.1*min(err(:)));
      c = ceil(rand * length(ibest));
      pos = [ibest(c) jbest(c)];
      imout(i:i+tilesize-1,j:j+tilesize-1,:) = imin(pos(1):pos(1)+tilesize-1,pos(2):pos(2)+tilesize-1,:);
      
      
      B1overlaph = imout(i:i+overlap-1,j:j+tilesize-1,:); % shared
      B2overlaph = imin(pos(1):pos(1)+overlap-1,pos(2):pos(2)+tilesize-1,:);
      
      errmat = sum((B1overlaph-B2overlaph).^2,3);
      
      fph = zeros(overlap,tilesize);
      pathh = zeros(overlap,tilesize);
      
      fph(:,tilesize) = errmat(:,tilesize);
      
      for k = tilesize-1:-1:1
          for l = 1:overlap
              index =  max(1,l-1):min(overlap,l+1);
              [fph(l,k), temp_index] = min( fph(index,k+1));
              fph(l,k) = fph(l,k) + errmat(l,k);
              pathh(l,k) = index(temp_index);
          end
      end
      
      min_err_boundh = zeros(1,tilesize);
      
      [temp,min_err_boundh(1)] = min(fph(1,:));
      
      for k=2:tilesize
          min_err_boundh(k) = pathh(min_err_boundh(k-1),k-1);
      end
      
      for k = 1:tilesize
          imout(i+min_err_boundh(k):i+tilesize-1,j+k-1,:) = imin(pos(1)+min_err_boundh(k):pos(1)+tilesize-1,pos(2)+k-1,:);
      end
      
      
      
      
    elseif j > 1
      shared = imout(i:i+tilesize-1,j:j+overlap-1,:);
      err = errside - 2 * getxcorr2(imin, shared) + sum(shared(:).^2);
      
      % trim invalid data at edges
      err = err(tilesize:end-tilesize+1,overlap:end-tilesize+1);

      [ibest, jbest] = find(err <= 1.01*1.1*min(err(:)));
      c = ceil(rand * length(ibest));
      pos = [ibest(c) jbest(c)];
      
      B1overlap = imout(i:i+tilesize-1,j:j+overlap-1,:); % shared
      B2overlap = imin(pos(1):pos(1)+tilesize-1,pos(2):pos(2)+overlap-1,:);
      
      errmat = sum((B1overlap-B2overlap).^2,3);
      
      fp = zeros(tilesize,overlap);
      path = zeros(tilesize,overlap);
      
      fp(tilesize,:) = errmat(tilesize,:);
      
      for k = tilesize-1:-1:1
          for l = 1:overlap
              index =  max(1,l-1):min(overlap,l+1);
              [fp(k,l), temp_index] = min( fp(k+1,index));
              fp(k,l) = fp(k,l) + errmat(k,l);
              path(k,l) = index(temp_index);
          end
      end
      
      min_err_bound = zeros(1,tilesize);
      
      [temp,min_err_bound(1)] = min(fp(1,:));
      
      for k=2:tilesize
          min_err_bound(k) = path(k-1,min_err_bound(k-1));
      end
      
      for k = 1:tilesize
          imout(i+k-1,j+min_err_bound(k):j+tilesize-1,:) = imin(pos(1)+k-1,pos(2)+min_err_bound(k):pos(2)+tilesize-1,:);
      end
      
      %imout(i:i+tilesize-1,j:j+tilesize-1) = imin(pos(1):pos(1)+tilesize-1,pos(2):pos(2)+tilesize-1);
    else
      pos = ceil(rand([1 2]) .* (sizein-tilesize+1));
      imout(i:i+tilesize-1,j:j+tilesize-1,:) = imin(pos(1):pos(1)+tilesize-1,pos(2):pos(2)+tilesize-1,:);
    end



    if isdebug~=0
        set(h,'CData',uint8(imout));
        drawnow;
    end
  end
end

Contact us