shuffle image using matlab - image

For instance, I have a screen size of 1024x768. And, each of my image is 150 x 250, where I have 4 images in total. How can i randomize these images to appear at different positions on the screen?

What do you want exactly?
Is it to:
keep 4 predefined empty places and assign each of the 4 image to one empty place randomly,
or simply place them randomly on the screen?
The idea is to display the images and keep the handle of each figure object (H1, H2, H3, H4). The ideal would be to store them in a handle list H.
For the first idea, store the top-left corner position of each empty place in a 4 entries list POS.
Make a connectivity list LC where LC[i]=j returns the index in POS where to find the position of the handle H[i].
For example, if LC = [1 2 3 4] handle H1 is assigned to position POS1, H2 to POS[2], etc...
Then use randperm() (mathworks.com/help/techdoc/ref/randperm.html) as Ashish pointed out on the LC list. This will randomly "mix" the connectivity list, and hence shuffle the positions.
Finally, set the position of each handle:
set(H[i], 'Position', [POS(LC[i],1) POS(LC[i],2) SizeX SizeY]);
Where SizeX and SizeY are the size ratios between the figure object and the screen.

Related

Saving a MATLAB matrix as an image to a specific size and resolution

After having read this question, I wanted to use this code to save my picture as to particular size.
I_c(:,:) = cropped_matrix(i,:,:);
set(I_c, 'PaperUnits', 'inches');
x_width = 7.25;
y_width = 9.125;
set(I_c, 'PaperPosition', [0 0 x_width y_width]);
imshow(I_c);
saveas(I_c,'fig1.pdf');
I_c represents a 2D matrix (about 40x40) of uint8's.
However, I get the error:
Error using set Invalid handle
This makes me believe that I can only use this code with figures and not matrices which contain matrices. How would I go about this?
I have looked at the API for print, as suggested as the first answer of the aforementioned linked question, but it also suggests using set and 'PaperUnits'.
Note: This question also looks at this problem but suggests the same solution.
Notes About Crowley's Answer
So I just tried the code that you have given with your answer. The .jpg being produced is the one shown below. How would I get rid of all the extra white area through code?
How would I change the colourmap of the figure being produced, to greyscale when I just use image(ImData)?
And here is how the actual figure appears:
Here is the code that I have put in:
im = image(I_c);
set(gcf,'units','inches','position',[1 2 5 5]);
set(gca,'ydir','normal','units','centimeters','position',[0 0 0.5 0.5].*get(gcf,'position')) ;
filename = strcat('slice',int2str(i),'_','bead',int2str(j),'.jpg');
saveas(im,filename);
Suppose we have matrix I_c containing values and x and y the coordinates so value I_c(ii,jj) corresponds to x(ii) and y(jj) coordinates.
Then:
ImMin=min(min(I_c)); % Find the minimum value in I_c
ImData=I_c-ImMin; % Ensure non-zero values
ImMax=max(max(ImData)); % Find maximum value in ImData
ImData=ImData./ImMax; % Ensure ImData do NOT exceed 1
image(x,y,ImData*[1 1 1]) % plot the image in greyscale
set(gcf,'units','inches','position',[1 2 5 5]) % set active figure properties
set(gca,'ydir','normal','units','inches','position',[0 0 1 1].*get(gcf,'position')) % set active axes properties
export_fig(gcf,'figure-I_c','-png','-nocrop')
'ydir','normal' parameter change default (1,1) point being in top-left corner to "normal" position in bottom-left corner.
[0 0 1 1].*get(gcf,'position) will read active figure position (here [1 2 5 5]) and after element-by-element multiplication the [0 0 5 5] is passed to the position which causes that axes fit the image.
export_fig function will create figure-I_c.png image as it is shown in Matlab figure, if -nocrop is omitted the possible white space in the edges is cropped out. This function is available from MathWorks' File Exchange.

Error while converting a 3d matrix into an animated gif in Matlab

I am attempting to make a movie from a 3d matrix, which is made multiple 2d matrices and the third dimension is time.
I have read the following question witch is pretty much the same and I have attempted to do the same.
How to make a video from a 3d matrix in matlab
The 3d matrix I want to play is stored in a object instanced A.
a.movie; % 3D matrix
X = permute(a.movie,[1 2 4 3]); % 4D matrix
movie = immovie(X,map); % map is the colormap you want to use
implay(movie);
I would like to know why should a.movie be permuted? And what is the map referred?
How can I define 0 as blue and 100 as red?
The post you linked us to exactly answers that. immovie expects a m x n x 1 x k matrix where m and n are the rows and columns of 1 slice from your 3D matrix, and k is the number of slices. You currently have your 3D matrix set up to be m x n x k. Therefore, by permuting, you are artificially creating a 4D matrix from your 3D original matrix. Simply put, you can think of your 3D matrix as having a singleton 4D dimension: m x n x k x 1. The job of permute here is to swap the 3rd and 4th dimension - that's why you see the [1 2 4 3] vector in the permute call. The first and second dimensions represent the rows and columns, and you leave those empty.
Now that answers the permute question. The map is defined as a colour map. This maps each value in your 3D matrix to a unique colour. Basically, the colour map is a M x 3 matrix where row in this matrix corresponds to a unique colour. Each column represents a colour channel. Therefore, the first column represents the proportion of red you want, the second channel is the proportion of green and the last is the proportion of blue. Keep in mind that these colours should be normalized between [0,1].
The goal of the colour map is to take each value in your 3D matrix, and figure out which colour that value maps to. The way to do this is to use each value in your 3D matrix exactly as it is and use this to access the row of the colour map. This row gives you the colours you want. Now, I'm assuming that your values in the 3D matrix span from 0 to 100.
If you want the colours to span between blue and red. The blue colour has an exact colour of RGB = (0,0,1) assuming normalized coordinates and similarly, the red represents the exact colour of RGB = (1,0,0). Therefore, start off with RGB = (0,0,1), then start linearly increasing the red component while linearly decreasing the blue component until the red is 1 and the blue is 0.
What we can do is figure out how many unique values there are in your matrix, then we can create our colour map that way so we can ensure that each value in your matrix gets assigned to one colour. However, this will require that a.movie be redefined to ensure that we can assign a value to a colour.
Therefore, I'd create your colour map like this:
[unq,~,id] = unique(a.movie);
movie_IDs = reshape(id, size(a.movie));
M = numel(unq);
map = [linspace(1,0,M).', zeros(M,1), linspace(0,1,M).'];
Now, go ahead and use map with the above code to create your movie.
X = permute(movie_IDs,[1 2 4 3]); % 4D matrix
movie = immovie(X,map); % map is the colormap you want to use
implay(movie);
However, the colour map you're looking at is the jet colour map. Therefore, you can simply just create a jet colour map:
map = jet(M);
However, you must make sure you run through each value in a.movie and assign a unique integer to each value to ensure that there are no gaps in your data and every value gets assigned to a new value that goes up from 1 to M in order for the movie to properly access the right colour.
MATLAB has a bunch of built-in colour maps for you to use if you don't feel like designing your own colour map. http://www.mathworks.com/help/matlab/ref/colormap.html#inputarg_map - However, from what I see in your post, making the colour map is what you want to do.

Convert indexed image into grayscale

How can I convert an RGB or indexed images into gray scale without using B=ind2gray(A,map) from MATLAB?
I don't understand why you just can't use ind2gray.... but if you really have to implement this from first principles, that's actually not too bad. What ind2gray does (IIRC) is that it takes an indexed image and with the colour map, it converts the image into a colour image. Once you're done that, you convert the resulting colour image to grayscale. The index image is actually a grid of lookup values that span from [1,N]. Also, the colour map is a N x 3 array where each row is a RGB tuple / colour. It should be noted that the colour map is double precision where each component spans between [0,1]. Therefore, for each location in the index image, it tells you which tuple from the lookup table is mapped to this location. For example, if we had an index image such that:
X =
[1 2
3 4]
... and we had a colour map that was 4 x 3, this means that the top left corner gets the first colour denoted by the first row of the map, the top right corner gets the second colour, bottom left corner gets the third colour and finally the bottom right corner gets the fourth colour.
The easiest way to do this would be to use X to index into each column of the input map, then concatenate all of the results together into a single 3D matrix. Once you're done, you can convert the image into its luminance / grayscale counterpart. Given that you have an index image called X and its corresponding colour map, do this:
colour_image = cat(3, map(X), map(X + size(map,1)), map(X + 2*size(map,1)));
gray = sum(bsxfun(#times, colour_image, permute([0.2126 0.7152 0.0722], [3 1 2])), 3);
The first statement is very simple. Take note that map is N x 3 and X can range between [1,N]. If we use X and index directly into map, you would only be grabbing the first column of values, or the first component of the colours / red. We need to access the same values in the right order for the second column, and because MATLAB accesses elements in column-major format, we simply have to add all of the offsets by N so that we can access the values in the second column to get the second component of colours / green. Finally, you'd offset by 2N to get the third component of colours / blue. We'd take each red, green and blue channel and concatenate them together to get a 3D image.
Once we get this 3D image, it's a matter of converting the colour image into luminance. I am using the SMPTE Rec. 709 standard to convert from a colour pixel to luminance. That relationship is:
Y = 0.2126 R + 0.7152 G + 0.0722 B
That's the purpose of the second statement. We will take each component, multiply them by their respective weight and sum all of the values together. You should have your luminance image as a result.
To check to see if this works, we can use the trees dataset from the image processing toolbox. This comes with an index image X, followed by a colour map map:
load trees;
%// Previous code
colour_image = cat(3, map(X), map(X + size(map,1)), map(X + 2*size(map,1)));
gray = sum(bsxfun(#times, colour_image, permute([0.2126 0.7152 0.0722], [3 1 2])), 3);
%// Show colour image as well as resulting gray image
figure; subplot(1,2,1);
imshow(colour_image);
subplot(1,2,2);
imshow(gray);
We get:
We can actually show that this is indeed the right output by converting the image to grayscale using ind2gray, then showing the difference between the two images. If the images are equal, that means that the resulting image should be black, which means that the outputs produced by the above procedure and ind2gray are exact.
Therefore:
gray2 = ind2gray(X, map);
figure;
imshow(abs(gray-gray2));
We get:
... yup... zilch, nothing, zero, notta.... so what I implemented in comparison to ind2gray is basically the same thing.

Remove spacing in matlab subplot

How should i remove the empty space between these images?i need to combine all these images without any space.
bot=imread('bot.jpeg');
for i= 1:25
subplot(5,5,i),imshow(bot);
end
You need to specify axes' 'Position' property when you create them with subplot.
Also, you have to adjust figure aspect ratio to match that of the image, so that all figures fit without vertical or horizontal space.
If you show a different image in each subplot, all images should have the same aspect ratio, otherwise it's not possible for them to fit in the figure without empty spaces.
bot = imread('peppers.png');
for i= 1:25
subplot('Position',[(mod(i-1,5))/5 1-(ceil(i/5))/5 1/5 1/5])
imshow(bot); %// or show a different image on each subplot
end
p = get(gcf,'Position');
k = [size(bot,2) size(bot,1)]/(size(bot,2)+size(bot,1));
set(gcf,'Position',[p(1) p(2) (p(3)+p(4)).*k]) %// adjust figure x and y size
The most canonical way would be to take a look at this answer by bla here. This answer uses a function from the MATLAB File Exchange in order to achieve the answer. However, that requires learning a new function and playing around with the parameters.
If you want something working immediately, instead of showing each subimage in a separate grid on a plot, I would simply create a new image that stacks all of those images together:
bot_new = repmat(bot, [5 5]);
imshow(bot_new);
repmat takes a matrix and duplicates / stacks / tiles itself together for as many rows and as many columns (or in any dimension) that you want. In this case, I chose to stack the image so that there are 5 rows and 5 columns of it. We next show the stacked image together with imshow.
If we used an example image from MATLAB:
bot = imread('onion.png');
If we ran the above code that tiles the images together and showed the image, this is what we get:
I copy the answer from mathworks:
For each subplot, store its handle.
h = subplot(2,3,1);
Then set the 'position' property of h to be anything you want.
p = get(h, 'pos');
This is a 4-element vector [left, bottom, width, height] which
by default is in normalized coordinates (percentage of
figure window). For instance, to add 0.05 units (5% of
figure window) to the width, do this:
p(3) = p(3) + 0.05;
set(h, 'pos', p);
The SUBPLOT command picks standard values for these
parameters, but they could be anything you want. You
could put axes anywhere on the figure you want,
any size you want.
You can check for it:
http://www.mathworks.com/matlabcentral/newsreader/view_thread/144116

Displaying a subset of longitude/latitude points?

I have an array of coordinates (latitude and longitude) maded in this way:
[0] = "45.01234,9.12345"
[1] = "46.11111,9.12345"
[2] = "47.22222,9.98765"
[...] etc
In a loop, convert these coordinates in meters (UTM northing / UTM easting) and after that I convert these coords in pixel (X / Y) on screen (the output device is an iPhone) to draw a route line on a custom map.
[0] = "512335.00000,502333.666666"
[...] etc
The returning pixel are passed to a method that draw a line on screen (simulating a route calculation).
[0] = "20,30"
[1] = "21,31"
[2] = "25,40"
[...] etc
As coordinate (lat/lon) are too many, I need to truncate lat/lon array eliminating the values that doesn't fill in the map bound (the visible part of map on screen).
Map bounds are 2 couple of coords lat/lon, upper left, and lower right.
Now, what is the best way to loop on this array (NOT SORTED) and check if a value is or not in bound and after remove the value that is outside?
To return a clean array that contains only the coords visible on screen?
Note: the coords array is a very big array. 4000/5000 Couple of items.
This is a method that should be looped every drag or zoom.
How can I optimize search and controls in this array?
I'd suggest breaking this into several steps:
Convert each longitude/latitude pair into a pair of meters in your new coordinate system.
Create a kd-tree data structure holding all the points in the set. This allows you to efficiently query which points lie in a given rectangular range very efficiently.
Whenever the viewport changes, find all points in the kd-tree that will be displayed in that rectangle.
To display the points, iterate over the set of points that will be displayed and display each of them.

Resources