% ------ Begin PicPuzzle.m -------------------------- % This complicated program takes an input image defined by INFILE and attempts to % recompose this image using mini versions of the sample images in FOLDER by % minimizing the error difference between each patch of the original and the sample % images. The result is a single image OUTFILE that vaguely resembles the original % image, but is made of of miniature versions of other pictures in an artistic style. % It is best to have several hundred various pictures in the FOLDER to get the % best results, but this takes a long time to process. To minimize resizing time, % it is recommended to start with medium-sized image pieces (around 0.3MP) rather % than large images (over 1MP). % It's good to have an input image with large details (relatively low spatial % frequency). Also, setting RSKIP to around 0.75 prevents the program from reusing % the same image too many times. % In order to retain decent resolution of the small images on the output image, % the input image should be fairly large, but it can be a low quality image (I % used a 14MP upsized image set at a jpg quality of 2). % % NOTE: Requires ImageCrop.m, WaitbarRandColor.m, Sec2Time.m % % Last edit by Colin Joye, 10/21/04 tic; %------ BEGIN user input --------- % define the target image: infile = 'C:\Documents and Settings\Colin Joye\My Documents\My Pictures\Composite\ColinHeidi_big.jpg'; % define a folder of image pieces (inclide '\'): folder = 'C:\Documents and Settings\Colin Joye\My Documents\My Pictures\PicPuzzle\'; Nimage = 2200; % the rough number of image pieces to use. Imtype = 'jpg'; % type of image pieces (only supports jpg now) Rs = 3/2; % desired aspect ratio of picture pieces = x_{size}/y_{size} % If any of the above parameters are changed, you need to resize all the images % by setting RESIZE=1 (will take much longer to run); Otherwise, set RESIZE=0. RESIZE = 0; % In the comparisons, sometimes it likes to use the same image repeatedly, so this is % a image random skip percentage. 0 means never skip, 1 is always skip. Using higher % skip rate also speeds up comparisons. Choose 0 < rskip < 1. rskip = 0.77; % The error comparison method can be changed here. Compare by: % 1=color layers. 2=shape (convolution of images - Takes longer and it doesn't work!) Emethod = 1; convstep = 7; % with Emethod=2: to make the convolution faster, use only every 'convstep' pixel. % define output image: outfile = 'C:\Documents and Settings\Colin Joye\My Documents\My Pictures\Composite\Composite.jpg'; %------ END user input --------- % define folder for resized temporary images: tmpReFold = 'C:\MATLAB6p1\work\PicPuzzle\tmpReFold\'; h = waitbar(0,['PicPuzzle.m : Starting']); WaitbarRandColor(h); waitbar(0.2, h,['Finding Pieces']); % lookup pieces: fpiece = dir(folder); [f,order] = sortrows(str2mat(fpiece.name)); % Puts files in order. Lf = length(fpiece); Lt = length(Imtype); % reads in target image. Pin = imread(infile); [Py Px Pz] = size(Pin); %Pz is color layers % find sample aspect ratio: if Rs == 0, k=1; while Rs==0 & k < Lf, S = [folder fpiece(order(k)).name]; % current file path & name. if ( exist(S)~=7 ) & strcmp( S(end-2:end),Imtype ), % ignores directories and non-images. Sin = imread(S); [Sy Sx Sz] = size(Sin); %Sz is color layers Rs = Sx/Sy; % Sample aspect ratio. end k=k+1; end % while Rs end % if Rs % figure out how many pieces to use: Rp = Px/Py; % target picture aspect ratio Nsx = sqrt( Nimage*Rp/Rs ); Nsy = round( Nsx*Rs/Rp ); % number of samples in y-direction Nsx = round( Nsx ); % number of samples in x-direction waitbar(0.4, h,['Resizing input image']); % define picture block size and resize picture. hx = round(Px/Nsx); hy = round(Py/Nsy); Rt = hx/hy; % target aspect ratio for sample pictures. Pin = imresize(Pin,[Nsy*hy Nsx*hx],'nearest'); [Py Px Pz] = size(Pin); %Pz is color layers Zout = zeros(Py,Px,Pz); % predefine output image. Zout = uint8(Zout); %----------- Resize image pieces: ------------- if RESIZE==1, waitbar(0.8, h,['Entering resize: deleting old images.']); delete([tmpReFold '*.jpg']); waitbar(0.9, h,['Resizing pieces...']); for k=1:Lf, S = [folder fpiece(order(k)).name]; % current file path & name. % ignore directories and non-images: if ( exist(S)~=7 ) & strcmp( S(end-2:end),Imtype ), Sin = imread(S); [Sy Sx Sz] = size(Sin); Rs = Sx/Sy; % sample piece aspect ratio. if Rs > Rt, % then crop in x-direction to fit hx. Sample = imresize(Sin,[hy Rs*hx],'bilinear'); Sample = imageCrop(Sample,[hy hx]); elseif Rs < Rt, % then crop in y-direction to fit hy. Sample = imresize(Sin,[hx/Rs hx],'bilinear'); Sample = imageCrop(Sample,[hy hx]); else % aspect ratio is fine, just resize. Sample = imresize(Sin,[hy hx],'bilinear'); end imwrite( Sample, [tmpReFold 'piece_' int2str(k) '.' Imtype],'jpg','Quality',95 ); waitbar(k/Lf, h,['(1/2) Resizing pieces: ' num2str(k/Lf*100,3) '% done' ]); end % if exist end % for k disp(' '); disp(['Total Resize time: ' sec2time(toc)]); tic; end % if RESIZE close(h); %------------ Begin comparing: ------------- h = waitbar(0,['Starting Comparisons']); WaitbarRandColor(h); % Sort temporary directory files: ftmp = dir(tmpReFold); [f,order] = sortrows(str2mat(ftmp.name)); % Puts files in order. Lf = length(ftmp); KOPT = 0; for m = 1:Nsy, for n = 1:Nsx, % define picture patch to compare Yp = [ (m-1)*hy + (1:hy) ]; Xp = [ (n-1)*hx + (1:hx) ]; P = Pin( Yp, Xp, : ); % now we have a patch of the target picture. [py px pz]=size(P); % now compare the patch to our images: E = NaN*ones(1,Lf); for k=1:Lf, if rand > rskip, S = [tmpReFold ftmp(order(k)).name]; % current file path & name. % ignore directories and non-images: if ( exist(S)~=7 ) & strcmp( S(end-2:end),Imtype ), Sin = imread(S); % The error is comparing pictures is: Pi = double(P); Si = double(Sin); if Emethod==2, ay = [1:convstep:py]; ax = [1:convstep:px]; E(k) = 1/sum(sum(sum( convn( Pi(ay,ax,:),Si(ay,ax,:),'same') ))); else E(k) = sum(sum(sum( (Pi - Si).^2 ))); end end % if exist end % if rand. end % for k % the optimal sample S_{k} for our patch P_{mn} is: kopt = find(E==min(E)); Lkopt = length(kopt); if Lkopt > 1, a = rand(1,1)*Lkopt+0.5; kopt = kopt(round(a)); end if all(kopt~=KOPT), % keep track of how many different images are used. KOPT = [KOPT kopt]; end S = [tmpReFold ftmp(order(kopt)).name]; % current file path & name. Zout(Yp,Xp,:) = imread(S); pcnt = ( (m-1) + (n-1)/Nsx )/Nsy; waitbar( pcnt,h,['(2/2) Comparing: ' num2str(pcnt*100,3) '% done' ]); end % for m end % for n close(h); % close waitbar. figure(1) image(Pin); figure(2) image(Zout); imwrite(Zout,outfile,'jpg','Quality',95); disp(' '); disp(['Total Compare time: ' sec2time(toc)]); disp(' '); disp(['Total Images used: ' int2str(Nsx*Nsy)]); disp(['Number of unique Images used: ' int2str(length(KOPT)-1)]); % -------- END PicPuzzle.m -------------