Hello all,
I'm having some trouble with the last step of a piece of code I've written. The aim of the project is to make one of those photos made up of lots of little photos. I've got most of it sorted (enough to run it as a test at least). The problem I'm having is with the montage command, but for context here's the overall process:
- Take all the image files on my computer
- Rename them numerically (with leading zeros)
- Resize them so they are square and a set size (400 x 400px at the moment)
- Find the mean value of each of the RGB layers and save in a database with the file name
- Take a main image, and divide it into squares (4 x 4px at the moment)
- Find the mean value of each of the RGB layers in this image
- Compare the RGB values to find the closest match in the image database to each small section of the main image
- Replace each small section of the main image with the closest matching image from the database, giving a matrix of image file names
- Replace the matrix of file names with the images themselves and save the image
So, the problem is…
I have a cell array called "replacer", which at the moment is a 400 wide 300 long array of file names (complete, e.g. 'cimage05886.jpg'). I now need to make this into the final image, which I have been trying to do like this:
mainmontage=montage(replacer, 'Size', [montageheight montagewidth]);
where montageheight = 300 and montagewidth = 400, and replacer is as above.
However it doesn't seem to work. I get an image, but it has a sort of repeated pattern in the montage (seems to be 4 times across the width), which is not there in the filenames in the replacer cell array.
My question is this:
Is the montage command the best way to create the matrix of images I'm after, or is there an alternative? If it is, can anyone suggest why I might be getting the error I am. I think I could be missing something with the size stipulation, because when I change it to [3 4] as a test (or even [1 1]) I get an over limit error:
>> mainmontage2=montage(replacer, 'Size', [3 4]);Error using zerosRequested 480x480x3x120000 (77.2GB) array exceeds maximumarray size preference. Creation of arrays greater than thislimit may take a long time and cause MATLAB to becomeunresponsive. See array size limit or preference panel formore information.
I don't get this with the original code, even though that is [300 400], which is surely bigger? I'm confused. I've read the documentation on montage but can't seem to make any progress. Any help gratefully received!
My full code is copied below. I'm sure it's horrible, but it gets me to the matrix of image files so I don't think the problem lies in the earlier code (though happy to be corrected!).
Thanks very much for any assistance, and apologies for the long post.
Stu
%RENAME
dirData = dir('*.jpg');% Get the selected file data
fileNames = {dirData.name};%Create a cell array of file names
for iFile = 1:numel(fileNames)%Loop over the file names
newName = sprintf('image%05d.jpg',iFile);% Make the new name
movefile(fileNames{iFile},newName,'f');%Rename the file
end%RESHAPE TO SQUARE
for i=1:iFile;n=sprintf('%05d',i);I=imread(horzcat('image',n,'.jpg'));[height,width]=size(I(:,:,1));if height>width;diff=height-width;halfdiff=diff/2;hmin=0+halfdiff;wmin=0;%[xmin ymin width height]
J=imcrop(I,[wmin hmin width width-1]);imwrite(J,horzcat('bimage',n,'.jpg'));else if width>height;diff=width-height;halfdiff=diff/2;wmin=0+halfdiff;hmin=0;%[xmin ymin width height]J=imcrop(I,[wmin hmin height-1 height]);imwrite(J,horzcat('bimage',n,'.jpg'));else if width == height;J=I;imwrite(J,horzcat('bimage',n,'.jpg'));endendendend%PUT AVERAGE COLOUR AND VARIATION IN TABLE
%row number tells you the name (ie 1=00001 400=00400 etc)
%added for simplicity while testing - run from here on
iFile=12100;datatable=zeros(iFile,2);clear iclear Ifor i=1:iFile;n=sprintf('%05d',i);%I=imread(horzcat('bimage',n,'.jpg'));
I=imread(horzcat('cimage',n,'.jpg'));rmeanval=mean(I(:,:,1),'all');gmeanval=mean(I(:,:,2),'all');bmeanval=mean(I(:,:,3),'all');%meanval gives us the mean colour of each image
%I2=abs(I-meanval);
%meandiff=mean(I2,'all');
%meandiff gives us the mean difference from the mean
%higher means a more widely coloured image
%lower means a more homogoneous image
%datatable(1,i)=meanval;
%datatable(2,i)=meandiff;
datatable(1,i)=rmeanval;datatable(2,i)=gmeanval;datatable(3,i)=bmeanval;enddatatable3=datatable(1:3,:)'datatable3(:,4)=1:iFile;%then round to nearest whole number
colourref=round(datatable3);%GOOD TO HERE!!
%BUT WE SHOULD RESIZE OR THERE IS GOING TO BE CHAAAAOOOOSSS!!!
clear iclear Iclear Jclear nfor i=1:iFile;n=sprintf('%05d',i);I=imread(horzcat('bimage',n,'.jpg'));J=imresize(I,[40 40]);imwrite(J,horzcat('cimage',n,'.jpg'))end%% NOW WE NEED TO LOOK UP THE AVERAGE RGB CODE FOR A SMALL (4x4?) REGION OF THE MAIN IMAGE
mainimage=imread('mainimage.jpg');mainimager=mainimage(:,:,1);mainimageg=mainimage(:,:,2);mainimageb=mainimage(:,:,3);[mainh, mainw]=size(mainimage(:,:,1));pixnumber=mainw*mainh;boxdim=10;boxheight=boxdim;boxwidth=boxdim;boxnumber=pixnumber/(boxheight*boxwidth);%change that number to use larger or smaller boxes
for k=1:mainh/boxwidth;for j=1:mainw/boxwidth;meanr(k,j)=mean(mean(mainimage(((boxdim*k)-3):(boxdim*k),((boxdim*j)-3):(boxdim*j),1)));meang(k,j)=mean(mean(mainimage(((boxdim*k)-3):(boxdim*k),((boxdim*j)-3):(boxdim*j),2)));meanb(k,j)=mean(mean(mainimage(((boxdim*k)-3):(boxdim*k),((boxdim*j)-3):(boxdim*j),3)));endendmeanr=round(meanr);meang=round(meang);meanb=round(meanb);%Then replace it with the closest matching image from the database
for l=1:mainh/boxheight;%l to 750 if using 4px squares
for m=1:mainw/boxwidth;%m to 1000 for the same
[idy idx]=min((abs(meanr(l,m)-colourref(:,1))+(abs(meanr(l,m)-colourref(:,2))+(abs(meanr(l,m)-colourref(:,3))))));replacements(l,m)=idx;endendmontageheight=l;montagewidth=m;for o=1:mainh/boxheight;for p=1:mainw/boxwidth;replacer(o,p)={horzcat('cimage',sprintf('%05d',replacements(o,p)),'.jpg')};endendmainmontage=montage(replacer, 'Size', [montageheight montagewidth]);imwrite(mainmontage,'mainmontage.jpg');
Best Answer