I use the tiledlayout(2,2) command to create a plot in Matlab. The first three title fields filled with normal plots. The fourth and last field is a field with an image. I used the commands IMG = 'mypic.tif'and imshow(IMG).I wonder why I can not change the size of my image. Is this not possible with the tiledlayoutcommand? I have looked up the documentary for tiledlayout and imshow(), but found nothing which helps me.
It indeed seems as if this is not possible using the tiledlayout functionality. However, it is possible using the subplot functionality. Below, I will give an example how this works.
Consider the following script:
% Generate some dummy data for the four plots
x = linspace(0, 2*pi, 25);
y = sin(x);
% Load sample image
image = imread('ngc6543a.jpg');
% Generate the figure
fig = figure(1);
% The three subplots
for i = 1:3
subplot(2,2,i);
plot(x, y);
end
% The image
subplot(2,2,4);
imshow(image);
% Increase size of the image
size_factor = 1.4; % 1.0 is original size
im_ax = fig.Children(1); % axes belonging to image
dims = im_ax.Position(3:4); % current dimensions
dims_new = size_factor * dims; % scale old dimensions
dxdy = (dims_new - dims) / 2; % offset for left bottom corner of image
im_ax.Position = [im_ax.Position(1:2) - dxdy, dims_new]; % update position
In this script, we start by generating some dummy data for the three 'normal' plots and loading a sample image (this image came with my MATLAB installation). Subsequently, we create a figure. After the figure has been created, I add the three dummy plots to the figure using a for loop and the subplot functionality. Then, we plot the image using imshow in the fourth subplot.
Now, the interesting part begins. First of all, I define a scale factor for the image (size_factor). Then, I retrieve the axes in which the image is plotted and store it in im_ax. From this axes, I retrieve the last two elements of the Position field and store them in dims. These two elements define the size of the axes. Based on the value of size_factor, I calculate the new size of the axes and store this in dims_new. To ensure that the axes (and thus the image) remains centered, we need to calculate by how much we need to shift the left bottom corner of the axes (whose coordinates are stored in the first two elements of the Position field). This result is stored in dxdy. The last thing we do is simply updating the Position field of the axes in which the image is plotted.
Now, to show you some results:
size_factor equals 1.0:
size_factor equals 1.4:
size_factor equals 0.55:
Related
I'm trying to plot a circle in a function using viscircles, and then come back to that function later on to plot another circle like the figure shown below:
At the moment, I can only plot single circles using these lines of code:
figure
center = [numberX numberY];
xlim([-0.1 10.1])
ylim([-0.1 10.1])
axis square
artwork = viscircles(center,size,'Color',colorControl)
After plotting the first viscircles, control rolls back over to a prompts function to get data for the next viscircles, but when it comes back around to plotting, the original viscircles is overwritten, even when I tried using hold on. Any advice would be much appreciated.
viscircles by default will flush the figure and draw only the circles specified by the inputs you provide it so hold on will not work.
What you can do instead is keep appending to your data so that the original data is displayed followed by a new circle each time you prompt for new data.
As such, do something like this. Assuming that you have a function called getNewCenter that returns a new center, the size of the circle and the colour, and matrices that contain the centers to display as well as their sizes:
centers = [];
sizes = []; % Matrices that contain the centers and sizes
while true % Keep iterating...
[numberX, numberY, size, colorControl] = getNewCenter; % Get new center, size and colour
% Add to the data
centers = [centers; numberX numberY];
sizes = [sizes; size];
% Plot the circles
xlim([-0.1 10.1]);
ylim([-0.1 10.1]);
axis square;
artwork = viscircles(centers, sizes, 'Color', colorControl);
end
I have written a program to process and print a 81x81 2D surface plot, which needs to be used as an input. Saving the plot made by Matlab includes side axes as well as white margins on the sides.
How do I crop this image to get just the (81pixels)x(81pixels) output as an image?
Try placing this after your figure code, it will remove the margins around your figure.
set(gca,'units','pixels') % set the axes units to pixels
xx = get(gca,'position'); % get the position of the axes;
set(gcf,'units','pixels') % set the figure units to pixels
yy = get(gcf,'position'); % get the figure position;
set(gcf,'position',[yy(1) yy(2) xx(3) xx(4)]) % set the position of the figure to the length and width of the axes
set(gca,'units','normalized','position',[0 0 1 1]) % set the axes units to pixels
You can avoid using surf plot and just save your array as image. So, you have 81x81 array. I'll use this one for the example:
a = magic(81);
Now you need to normalize image in order to have values from 0 to 255:
a = (a - min(min(a)))/(max(max(a))-min(min(a)))*255;
Finally you use imwrite to save your array as image.
imwrite(a,jet(256),'SO_4.png')
The first argument is your 81x81 array. The second argument is colormap. You can specify any colormap you want, but I like the heatmap jet(256). You can skip this argument, in this case the image would be grayscale. From here you can find what colormaps are available and what they look like. The last argument is image name. The result is shown below:
Hope that helps, good luck.
Due to my limited knowledge in Matlab i am struggling to plot mean of medians on the image coordinates. I have a gray scale image in Matlab. I want to plot its mean of the medians of its columns on that image so that it divides the image into two parts horizontally. I have obtained mean by using Matlab's 'Mean' command. But i am struggling to get image coordinates where i can plot the mean of medians.
After slight modification in Marcin's code i was able to get this output which shows median of columns of a grayscale image.
The modified code is,
load clown
M = median(X, 1);
figure();
imshow(uint8(X)); one=zeros(1,numel(M));
hold on;
for columnIdx = 1:numel(M)
medianValue = M(columnIdx);
% find locations of gray-scale lavel values equal to the median
idx = find(X(:, columnIdx) == medianValue);
selectone=floor(length(idx)/2); % selecting the middle value
% create a vector containing median values for each column
if (isempty(idx) == 1);
one(1,columnIdx)=svone;
else
one(1,columnIdx)=idx(selectone);
end
% in case when median value doesn't matches columns values use the
% previous column median value
svone=one(1,columnIdx);
end
plot(1:numel(M), one, '-g');
The output is,
I want to plot the mean of the medians of the columns so that it should divide the image horizontally in two parts. Can anyone help me in this or give an idea about it!
So if i understand you correctly, you want to plot another line in that figure over the same xrange as the green line, just with a constant y-value. That constant value shall be the mean of the y-values of the green line, this can be done with line or plot where we just need to define start and ending point:
plot([1, numel(M)], [mean(one), mean(one)], 'r-')
Problem
I am trying to make a 2D figure in Matlab which consists of multiple images and a graph with plot data (which I could eventually convert into an image too). For these images and graph, I need to be able to specify where they are located in my cartesion coordinate system.
For my specific case, it is sufficient to be able to "tell" Matlab where the left-bottom corner of the image is.
So for the example above. I would need some "trick" to let "bird1.jpg" start at position (a,b), "bird2.jpg" at position (c,d) and my plot at position (e,f) in one Matlab figure.
Solution to problem
Thanks to chappjc I was able to find a solution for my problem. Here is the code I used such that other people can use it in the future too.
figure_color = [.741 .717 .42];
axe_color = [1 1 1];
Screen.fig = figure('units','pixels',...
'name','Parallel projection',...
'menubar','none',...
'numbertitle','off',...
'position',[100 100 650 720],...
'color',figure_color,...
'busyaction','cancel',...
'renderer','opengl');
Screen.axes = axes('units','pix',...
'position',[420 460 200 200],... % (420,460) is the position of the first image
'ycolor',axe_color,...
'xcolor',axe_color,...
'color',axe_color,...
'xtick',[],'ytick',[],...
'xlim',[-.1 7.1],...
'ylim',[-.1 7.1],...
'visible','On');
Screen.img = imshow(phantom);
Screen.axes2 = axes('units','pix',...
'position',[0 0 200 200],... % (0,0) is the position of the second image
'ycolor',axe_color,...
'xcolor',axe_color,...
'color',axe_color,...
'xtick',[],'ytick',[],...
'xlim',[-.1 7.1],...
'ylim',[-.1 7.1],...
'visible','On');
Screen.img2 = imshow(phantom);
Basically what I do is first creating a (big) figure, and then create a first axe at a certain position in this big picture, and make it the default axe. In this axe I display my first image (made with the phantom function). After that I make a new axe at a another position and make it again the default axe. After I have done that, I place an image there too (the same picture, but you can also use another one if you want). You can also use handles which is the more clean method, as chappjc describes.
Positioning axes in a figure
One approach would be to manipulate the Position property of multiple axes in a figure. To make multiple axes in a figure:
hf = figure;
ha0 = axes('parent',hf,'Position',[x0 y0 w0 h0]);
ha1 = axes('parent',hf,'Position',[x1 y1 w1 h1]);
Then display your images and plots into the axes by specifying the handle (i.e. ha0 or ha1). For example: image(img0,'Parent',ha0) or imshow(img1,'parent',ha1).
Single Large Image
Another approach is to make a single large image and simply display it with image/imshow/etc.
First for the plots, you can use getframe followed by frame2im to get an image in a matrix format.
Next, decide what goes into your combined image and compute the largest box required to circumscribe the images (using their origins and sizes find the largest x and y coordinate), which includes the origin presumably. Use this info to make a blank image (e.g. img = zeros(h,w,3) for and RGB image).
I have displayed an image and plotted a rectangle over all the useless areas. Now i need to save this image in the form of a matrix, so that i can use it further.
figure,imshow(colz);
hold on;
for i=1:num
if(i~=n)
img=rectangle('Position',box(i,:),'FaceColor','k');
end
end
This is a part of my whole code. I'm covering all the undesired parts with zeros. so now I'm left with my desired area and a background. How can i save the pixel values in another matrix so as to create a new image that contains this enhanced data?
Thanks
here try this
F = getframe(gcf);
% gcf is your figure currently displaying your image with the rectangle
%
y = F.cdata;
hold off
figure(2),imshow(y);