www.gusucode.com > matlab非局部均值工具箱 > matlab非局部均值工具箱/matlab非局部均值工具箱/toolbox_nlmeans/perform_synthesis_quilting.m
function Y = perform_synthesis_quilting(X, tilesize, n, overlap, err, initial_patch) % perform_synthesis_quilting - perform image synthesis % % Y = perform_synthesis_quilting(X, tilesize, n, overlap, err, initial_patch); % % The method is described in % ``Image Quilting for Texture Synthesis and Transfer'' % Alexei A. Efros and William T. Freeman % Proceedings of SIGGRAPH '01, Los Angeles, California, August, 2001. % % The implementation is by Christopher DeCoro % http://www.cs.princeton.edu/~cdecoro/imagequilting/ % % X: The source image to be used in synthesis % tilesize: the dimensions of each square tile. Should divide size(X) evenly % n: The number of tiles to be placed in the output image, in each dimension % overlap: The amount of overlap to allow between pixels (def: 1/6 tilesize) % err: used when computing list of compatible tiles (def: 0.1) X = double(X); if( length(size(X)) == 2 ) X = repmat(X, [1 1 3]); elseif( length(size(X)) ~= 3 ) error('Input image must be 2 or 3 dimensional'); end simple = 0; if( nargin < 5 ) err = 0.002; end if( nargin < 4 ) overlap = round(tilesize / 6); end if nargin<6 initial_patch = []; end use_draw = 1; use_verb = 0; if( overlap >= tilesize ) error('Overlap must be less than tilesize'); end destsize = n * tilesize - (n-1) * overlap; Y = zeros(destsize, destsize, 3); for i=1:n, for j=1:n, progressbar(j+(i-1)*n, n^2); startI = (i-1)*tilesize - (i-1) * overlap + 1; startJ = (j-1)*tilesize - (j-1) * overlap + 1; endI = startI + tilesize -1 ; endJ = startJ + tilesize -1; %Determine the distances from each tile to the overlap region %This will eventually be replaced with convolutions distances = zeros( size(X,1)-tilesize, size(X,2)-tilesize ); useconv = 1; if( useconv == 0 ) %Compute the distances from the template to target for all i,j for a = 1:size(distances,1) v1 = Y(startI:endI, startJ:endJ, 1:3); for b = 1:size(distances,2), v2 = X(a:a+tilesize-1,b:b+tilesize-1, 1:3); distances(a,b) = myssd( double((v1(:) > 0)) .* (v1(:) - v2(:)) ); %distances(a,b) = D; end end else %Compute the distances from the source to the left overlap region if( j > 1 ) distances = ssd( X, Y(startI:endI, startJ:startJ+overlap-1, 1:3) ); distances = distances(1:end, 1:end-tilesize+overlap); end %Compute the distance from the source to top overlap region if( i > 1 ) Z = ssd( X, Y(startI:startI+overlap-1, startJ:endJ, 1:3) ); Z = Z(1:end-tilesize+overlap, 1:end); if( j > 1 ) distances = distances + Z; else distances = Z; end end %If both are greater, compute the distance of the overlap if( i > 1 && j > 1 ) Z = ssd( X, Y(startI:startI+overlap-1, startJ:startJ+overlap-1, 1:3) ); Z = Z(1:end-tilesize+overlap, 1:end-tilesize+overlap); distances = distances - Z; end end if i==1 && j==1 && not(isempty(initial_patch)) % initial guess distances = distances*0+1000; distances(initial_patch(1), initial_patch(2)) = 0; end %Find the best candidates for the match best = max( min(distances(:)), 0 ); candidates = find(distances(:) <= (1+err)*best); idx = candidates(ceil(rand(1)*length(candidates))); [sub(1), sub(2)] = ind2sub(size(distances), idx); if use_verb fprintf( 'Picked tile (%d, %d) out of %d candidates. Best error=%.4f\n', sub(1), sub(2), length(candidates), best ); end %If we do the simple quilting (no cut), just copy image if( simple ) Y(startI:endI, startJ:endJ, 1:3) = X(sub(1):sub(1)+tilesize-1, sub(2):sub(2)+tilesize-1, 1:3); else %Initialize the mask to all ones M = ones(tilesize, tilesize); %We have a left overlap if( j > 1 ) %Compute the SSD in the border region E = ( X(sub(1):sub(1)+tilesize-1, sub(2):sub(2)+overlap-1) - Y(startI:endI, startJ:startJ+overlap-1) ).^2; %Compute the mincut array C = mincut(E, 0); %Compute the mask and write to the destination M(1:end, 1:overlap) = double(C >= 0); end %We have a top overlap if( i > 1 ) %Compute the SSD in the border region E = ( X(sub(1):sub(1)+overlap-1, sub(2):sub(2)+tilesize-1) - Y(startI:startI+overlap-1, startJ:endJ) ).^2; %Compute the mincut array C = mincut(E, 1); %Compute the mask and write to the destination M(1:overlap, 1:end) = M(1:overlap, 1:end) .* double(C >= 0); end if( i == 1 && j == 1 ) Y(startI:endI, startJ:endJ, 1:3) = X(sub(1):sub(1)+tilesize-1, sub(2):sub(2)+tilesize-1, 1:3); else %Write to the destination using the mask Y(startI:endI, startJ:endJ, :) = filtered_write(Y(startI:endI, startJ:endJ, :), ... X(sub(1):sub(1)+tilesize-1, sub(2):sub(2)+tilesize-1, :), M); end end if use_draw imageplot(Y); drawnow; end end end if use_draw imageplot(Y); drawnow; end function y = myssd( x ) y = sum( x.^2 ); function A = filtered_write(A, B, M) for i = 1:3, A(:, :, i) = A(:,:,i) .* (M == 0) + B(:,:,i) .* (M == 1); end %function Y = mincut(X,dir) %Computes the minimum cut from one edge of the matrix to the other % %Inputs: % X: Evalutations of 2d function to be cut along local minima % dir: 0 = vertical cut, 1 = horizontal cut % %Outputs: % C: Matrix containing entries indicating side % -1: left (or top) side of cut % 0: along the cut % 1: right (or bottom) side of cut function C = mincut(X,dir) if( nargin > 1 && dir == 1 ) X = X'; end %Allocate the current cost array, and set first row to first row of X E = zeros(size(X)); E(1:end,:) = X(1:end,:); %Starting with the second array, compute the path costs until the end for i=2:size(E,1), E(i,1) = X(i,1) + min( E(i-1,1), E(i-1,2) ); for j=2:size(E,2)-1, E(i,j) = X(i,j) + min( [E(i-1,j-1), E(i-1,j), E(i-1,j+1)] ); end E(i,end) = X(i,end) + min( E(i-1,end-1), E(i-1,end) ); end %Backtrace to find the cut C = zeros(size(X)); [cost, idx] = min(E(end, 1:end)); C(i, 1:idx-1) = -1; C(i, idx) = 0; C(i, idx+1:end) = +1; for i=size(E,1)-1:-1:1, for j=1:size(E,2), if( idx > 1 && E(i,idx-1) == min(E(i,idx-1:min(idx+1,size(E,2))) ) ) idx = idx-1; elseif( idx < size(E,2) && E(i,idx+1) == min(E(i,max(idx-1,1):idx+1)) ) idx = idx+1; end C(i, 1:idx-1) = -1; C(i, idx) = 0; C(i, idx+1:end) = +1; end end if( nargin > 1 && dir == 1 ) %E = E'; C = C'; end %function Z = ssd(X, Y) %Computes the sum of squared distances between X and Y for each possible % overlap of Y on X. Y is thus smaller than X % %Inputs: % X - larger image % Y - smaller image % %Outputs: % Each pixel of Z contains the ssd for Y overlaid on X at that pixel function Z = ssd(X, Y) K = ones(size(Y,1), size(Y,2)); for k=1:size(X,3), A = X(:,:,k); B = Y(:,:,k); a2 = filter2(K, A.^2, 'valid'); b2 = sum(sum(B.^2)); ab = filter2(B, A, 'valid').*2; if( k == 1 ) Z = ((a2 - ab) + b2); else Z = Z + ((a2 - ab) + b2); end end