EDITTED:
Hii,
sorry not mentioning it earlier, what I need to do is to display 6 images in the same figure at the same time. Besides, at every image (frame) I need to draw some points (my code tracks the moves of the face - the eyes, nose, lips.)
I have 246 images (frames)
this is the main functions I use:
// The points/ coordinates of the lips, eyes and nose of the image "i".
Points = createPointsStructure (landmarks , i , NumOfLandarkPerFrame);
// Draw landmarks and splines on the frame i (and draw/show the frame)
DrawAllPointsOnFace (pointArr , Points , img , 1 , position, i);
Any ideas how can I do it?
I need to write a code that displays 6 images in the same figure (at the same time). and lets the user to choose one of the images to edit it (by clicking on it).
Any help how can I do it?
Thanks in advance.
Here is a simple example to get you started:
function ImagesExample()
%# read images in a cell array
imgs = cell(6,1);
for i=1:6
imgs{i} = imread( sprintf('AT3_1m4_%02d.tif',i) );
end
%# show them in subplots
figure(1)
for i=1:6
subplot(2,3,i);
h = imshow(imgs{i}, 'InitialMag',100, 'Border','tight');
title(num2str(i))
set(h, 'ButtonDownFcn',{#callback,i})
end
%# mouse-click callback function
function callback(o,e,idx)
%# show selected image in a new figure
figure(2), imshow(imgs{idx})
title(num2str(idx))
end
end
Another function to look into is the MONTAGE function from the IPT Toolbox:
%# given the above cell array `imgs`
montage( cat(4,imgs{:}) )
Related
I have 225 image with put together with the montage function in matlab. And I can show them with montage. But i cannot save the montage as a complete image, please help me.
path = uigetdir;
D=dir(fullfile(path,'*.tif'));
imcell = cell(1,numel(D));
imcropped = cell(1,numel(D));
figure(1);
title('Drag square to crop picture, end with a double click',...
'FontSize', 15 , 'HandleVisibility' , 'off' ) ;
axis equal
set( gca , 'NextPlot' , 'replacechildren') ;
imcell1 = imread(D(50).name);
[~, rect] = imcrop(imcell1);
close(figure(1));
%
for i = 1:numel(D)
imcell{i} = imread(D(i).name);
imcropped{i} = imcrop(imcell{i}, rect);
end
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
The output on montage "h" is just a number.
I would like to point out a better way to do it. While Benoit_11's way is technically correct, it limits the resolution of the image to the size of your screen. When you use getframe(gca), Matlab is effectively taking a screenshot of the current axes contents, at whatever size your figure window is currently in.
A better way to do this is to use the handle, as it references the actual graphical output of montage() instead of what it displays as. To save an image from the handle, you need to get the cdata from the object it references with get:
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
MyMontage = get(h, 'CData');
imwrite(MyMontage, 'FancyName.tif', 'tif');
This way you get the full resolution of the montage, not just the resolution from displaying it.
For more information on image handles: http://www.mathworks.com/help/matlab/creating_plots/the-image-object-and-its-properties.html
You're almost there! The value 'h' is actually the handles to the image object created by the montage you made in the figure. What you can do is use getframe to capture the content of the figure (graphics object) and save it as an image. Here is a very simple example, with the code going directly after yours
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
MyMontage = getframe(gca) %// Get content of current axes. I did it with sample images.
The output is the following:
MyMontage =
cdata: [384x1024x3 uint8] % Yours will be different
colormap: []
Hence you can save the actual data, stored in cdata, in a new file and you're good to go!
imwrite(MyMontage.cdata,'FancyName.tif','tif');
Let us consider the following code (fs is sampling frequency)
function [] = AR_simulate(p,fs)
B = xlsread('data_generations1','A1','g8:g301');
for k = 1:1:p
[pxx,f] = pyulear(B,k);
plot(f,pxx);
F(k) = getframe;
end
movie(F,100);
end
which animates the power spectral density of a given B vector with different orders, namely from order k=1 to k=p.
Now I want to save each picture somewhere, but on each picture I would like to include the parameter k, for example at k=1 there was this picture, at k=2 there was different picture and so on.
This will put the title of each frame as k=1, k=2 etc. and will print each frame as an eps file to Frame1.eps, Frame2.eps, etc.
function []=AR_simulate(p,fs);
B=xlsread('data_generations1','A1','g8:g301');
for k=1:1:p
[pxx,f]=pyulear(B,k);
subplot(1,2,1)
plot(f,pxx);
F(k) = getframe;
title(['k=' num2str(k)])
subplot(1,2,2)
% 2nd plot
print('-depsc2',['Frame' num2str(k) '.eps')
end
movie(F,100);
end
You can also use text instead of title to place the text anywhere on the plot.
By default, getframe with zero input arguments captures a frame based on the current axis. If you want to capture a frame based on the figure, including a title and the axes ticks, you need to do getframe(gcf). Alternatively, use text as suggested by #David to place the label on the axes you capture.
Regarding saving of the images, you can use frame2im and imwrite, in the loop just after getframe:
im = frame2im(F);
imwrite(im,sprintf('im_k%03d.png',k))
Or to save the frames to a movie, use the VideoWriter class and call writeVideo on every iteration.
I have a GUI (using GUIDE) in Matlab, this is how it looks:
I want to rotate the image using slider and to show the change in real time.
I use axes to display the image.
how can I do this?
EDIT: I'm building OCR application. this is how the plate looks when I'm rotate it, the numbers are totally deformed.
thanks.
Here is an example GUI:
function rotationGUI()
%# read image
I = imread('cameraman.tif');
%# setup GUI
hFig = figure('menu','none');
hAx = axes('Parent',hFig);
uicontrol('Parent',hFig, 'Style','slider', 'Value',0, 'Min',0,...
'Max',360, 'SliderStep',[1 10]./360, ...
'Position',[150 5 300 20], 'Callback',#slider_callback)
hTxt = uicontrol('Style','text', 'Position',[290 28 20 15], 'String','0');
%# show image
imshow(I, 'Parent',hAx)
%# Callback function
function slider_callback(hObj, eventdata)
angle = round(get(hObj,'Value')); %# get rotation angle in degrees
imshow(imrotate(I,angle), 'Parent',hAx) %# rotate image
set(hTxt, 'String',num2str(angle)) %# update text
end
end
If you prefer to build the GUI in GUIDE, follow these steps:
create GUI, and add necessary components: axis, slider, static text (drag-and-drop)
Using the "Property Inspector", change slider properties as required:: Min/Max/Value/SliderStep. Also would help if you assign a Tag to be able to find components in the code.
In the figure's xxxx_OpeningFcn function, read and store the image in the handles structure, then show it:
handles.I = imread('cameraman.tif');
imshow(I, 'Parent',findobj(hObject,'Tag','imgAxis')) %# use tag you assigned
guidata(hObject, handles); %# Update handles structure
Create a callback event handler for your slider, and add the code:
angle = round( get(hObject,'Value') );
imshow( imrotate(handles.I,angle) )
EDIT:
Image rotation is an affine transformation which maps the position (x,y) of input image pixels onto new coordinates (x2,y2) for the output image. The problem is that the output coordinates may not always be integers. Since digital images are represented on a grid of discrete pixels, thus some form of resampling/interpolation is employed (which is why straight lines might look jagged when rotated at certain angles).
(Illustration borrowed from: Understanding Digital Image Interpolation)
If I try to rotate camera around my current figure with plot3 using
while true; camorbit(0.9,-0.1); drawnow; end
then the rotation periodically hangs for a while (example) even on 8-core MacPro.
Can I make it smooth?
EDIT1:
While there is no solution for my original question yet, I've managed to make a better movie with getframe function. It doesn't allow recording free-hand rotation, though, and is quite buggy in MATLAB2010b for Mac.
%# fix wrong figure position in MATLAB2010b for Mac - depends on your layout
correctedPosition = get(gcf,'Position') + [21 -125 0 0];
fps = 60; sec = 10;
vidObj = VideoWriter('newfile.avi');
vidObj.Quality = 100;
vidObj.FrameRate = fps;
open(vidObj);
for i=1:fps*sec
camorbit(0.9,-0.1);
writeVideo(vidObj,getframe(gcf, correctedPosition));
end
close(vidObj);
EDIT2:
I created a similar thread at MATLAB Central.
EDIT3:
You can try it yourself downloading one of my figures.
I would say it's the large number of points you are drawing that's causing the slowdown. One option is to downsample.. Also you could use lower-level functions to draw (check this related post for a comparison of plot3/scatter3/line performance).
Consider the animation below optimized for speed:
[X Y Z] = sphere(64);
X = X(:); Y = Y(:); Z = Z(:);
%# set-up figure
hFig = figure('Backingstore','off', 'renderer','zbuffer');
%# use lower-level function LINE
line(0.50*[X,X], 0.50*[Y,Y], 0.50*[Z,Z], 'LineStyle','none', 'Marker','.', 'MarkerSize',1, 'Color','r')
line(0.75*[X,X], 0.75*[Y,Y], 0.75*[Z,Z], 'LineStyle','none', 'Marker','.', 'MarkerSize',1, 'Color','g')
line(1.00*[X,X], 1.00*[Y,Y], 1.00*[Z,Z], 'LineStyle','none', 'Marker','.', 'MarkerSize',1, 'Color','b')
view(3)
%# freeze the aspect ratio to override stretch-to-fill behaviour
axis vis3d
%# fix the axes limits manually
%#set(gca, 'xlim',[-1 1], 'ylim',[-1 1], 'zlim',[-1 1])
axis manual
%# maybe even remove the tick labels
%set(gca, 'xticklabel',[], 'yticklabel',[], 'zticklabel',[])
%# animate (until figure is closed)
while ishandle(hFig); camorbit(0.9,-0.1); drawnow; end
Note how we are using the Z-buffer renderer, and turned off the Backingstore property.
EDIT:
If I understood correctly, what you are trying to do is to record a screencast (using a 3rd-party app), while you manually rotate the figure, but in your case these manual rotations are "jumpy". On the other animating your figure with CAMORBIT/VIEW in a while-loop is running smooth...
I propose an alternative solution: start by rotating the figure using the mouse and write these view configurations at each step (azimuth,elevation). Then you can replay them using the VIEW function while recording the video, something like:
v = [...]; %# matrix where each row specify Az/El of view
for i=1:size(v,1)
view( v(i,:) )
drawnow
end
The downside is that you will have to press/rotate/release using the mouse in small steps (the ROTATE3D object does not expose a mouse-motion event)
I wrote a simple function to help you in this process. It loads the saved figure, enable 3d-rotation, and keeps track of the intermediate position at each step. Once finished, press the "Done" button to return the list of views...
function v = rotationDemo(figFileName)
views = []; %# list of views (Az,El)
hFig = hgload(figFileName); %# load the saved figure
views(1,:) = get(gca,'View'); %# store initial view
%# add a button, used to terminate the process
hButton = uicontrol('Style','pushbutton', 'Position',[400 1 80 20], ...
'String','Done?', 'Callback',#buttonCallback);
set(hFig, 'Toolbar','figure') %# restore toolbar
%# start 3d rotation, and handle post-callback to record intermediate views
h = rotate3d(hFig); %# get rotation object
set(h, 'ActionPostCallback',#rotateCallback)
set(h, 'Enable','on') %# enable rotation
msgbox('Rotate the view step-by-step', 'rotate3d', 'warn', 'modal')
uiwait(hFig) %# wait for user to click button
delete(hButton) %# delete button on finish
set(h, 'Enable','off') %# disable rotation
v = round(views); %# return the list of views
%# callback functions
function rotateCallback(o,e)
views(end+1,:) = get(e.Axes,'View'); %# add current view to list
end
function buttonCallback(o,e)
uiresume(gcbf) %# uiresume(hFig)
end
end
You can call the above function, then replay the animation:
v = rotationDemo('smooth_rotation.fig');
for i=1:size(v,1)
view(v(i,:))
drawnow
end
We can smooth the transitions by simple interpolation:
v = rotationDemo('smooth_rotation.fig');
n = size(v,1);
nn = linspace(1,n,100)'; %'# use 100 steps
vv = round( [interp1(v(:,1),nn) interp1(v(:,2),nn)] );
for i=1:size(vv,1)
view(vv(i,:))
DRAWNOW %# or PAUSE(..) to slow it down
end
As a side note, I should mention that ROTATE3D and CAMORBIT have different effects. ROTATE3D changes the View property of the current axis, while CAMORBIT controls the camera properties CameraTarget/CameraPosition/CameraUpVector of the current axis.
I recognize the same jerking movements that you are talking about on a regular MATLAB Figure. But when I tried running the Amro's code, created a movie (*.AVI), it looks smooth on my Mac notebook also.
The movie making code that I used is the following:
% Added the 'Visible' property of the figure 'off' while making a movie (although I am not exactly certain if this will make the situation better) like so:
hFig = figure('Backingstore','off','visible','off','renderer','zbuffer');
% Then, I replaced Amro's while-loop with a simple AVI production loop, as follows:
aviobj=avifile('test.avi'); %creates AVI file
for I=1:360
camorbit(0.9,-0.1); drawnow;
aviobj=addframe(aviobj,hFig); %adds frames to the AVI file
end
aviobj=close(aviobj); %closes AVI file
close(hFig); %close hFig
Question:
Would it help to decimate some points or to create a density map before rendering the figure?
[Ref. on various Rendering Options: http://www.mathworks.com/support/tech-notes/1200/1201.html ]
I hope the comments above would be of any help.
I don't know if this will help your issue, but for some reason, I've had better success with pause(0.001) than drawnow to force an update of the graphics window
You might also see if rotate3d is faster.
The number of cores doesn't matter as much as you think, as many functions in matlab do not support multi-threading.
A workaround would be to proceed as you are now, but write the figure window to a movie file. Then you can play back the movie.
How to draw a grid over an image. It should become part of that image itself.
It should be able to show some rows and columns over the image itself. The lines for rows and columns can be specified.
Actually I was encouraged by the way some research paper discusses about the results they have about image warping. One of the links is this: http://www.hammerhead.com/thad/morph.html
There are a number of related questions on SO that discuss ways to modify an image. Here are the two general approaches:
1. Modify the image data directly: I discuss this in my answer to this other SO question. Since image data can be 2-D or 3-D, you can use multidimensional indexing to modify the raw image data, creating lines along given rows and columns. Here's an example that changes every 10 rows and columns in the image to black:
img = imread('peppers.png'); %# Load a sample 3-D RGB image
img(10:10:end,:,:) = 0; %# Change every tenth row to black
img(:,10:10:end,:) = 0; %# Change every tenth column to black
imshow(img); %# Display the image
And now the image data in the variable img has black lines on it, and you can write it to a file or do whatever other processing you want to it.
2. Plot the image and the lines, then turn the axes/figure into a new image: The link to Steve Eddins' blog in zellus' answer shows an example of how you can plot an image and add lines to it. However, if you want to save or perform processing on the displayed image, you will have to save the displayed image as an image matrix. How you can do this has been discussed in these other SO questions:
How can I save an altered image in MATLAB?
Turn Matlab plot into image
Superimposing line plots on images from the blog 'Steve on Image Processing' has a nice example on overlaying a grid over an image.
Actually I watched this question after doing this code by my own .... the code reads an image and draw grid on the image every input parameter
I hope it would do any good :)
Watch the matlab code :
function [ imageMatdouble ] = GridPicture( PictureName , countForEachStep )
%This function grid the image into counts grid
pictureInfo = imfinfo(PictureName); %load information about the input
[inputImageMat, inputImageMap] = imread(PictureName); % Load the image
if (pictureInfo.ColorType~='truecolor')
warning('The function works only with RGB (TrueColor) picture');
return
end
%1. convert from trueColor(RGB) to intensity (grayscale)
imageMat = rgb2gray(inputImageMat);
%2. Convert image to double precision.
imageMatdouble =im2double(imageMat);
% zero is create indicated to black
height = pictureInfo.Height ;
width = pictureInfo.Width
i=1;j=1;
while (i<=height )
for j=1:width
imageMatdouble(i,j)=1;
end
j=1;
if (i==1)
i=i+countForEachStep-1;
else
i=i+countForEachStep;
end
end
i=1;j=1;
while (i<=width )
for j=1:height
imageMatdouble(j,i)=1;
end
j=1;
if (i==1)
i=i+countForEachStep-1;
else
i=i+countForEachStep;
end
end
imwrite(imageMatdouble,'C:\Users\Shahar\Documents\MATLAB\OutputPicture.jpg')
end