Matlab - Creating a figure of different sized subplots - image

I have an array of images and I need to plot them side by side, with each image having a different size. Although the actual image sizes are quite large, I would want to do something like imresize to plot the size that I want.
I have tried doing the subplot strategy like
subplot(1, 4, 1);
imshow(...);
subplot(1, 4, 2);
imshow(...);
subplot(1, 4, 3);
imshow(...);
subplot(1, 4, 4);
imshow(...);
But all the images show up as the same size. I want something like this
This for some reason seems non-trivial. Would really appreciate some help.

It's possible to make subplots of different sizes by specifying a multiple-element vector for the grid position argument p in the syntax subplot(m,n,p).
Your example can be constructed with the following:
subplot(4,10,[1:4 11:14 21:24 31:34]);
subplot(4,10,[5:7 15:17 25:27]);
subplot(4,10,[8:9 18:19]);
subplot(4,10,[10]);

You can add 4 axeses to the figure, and set the position of each axes:
I = imread('cameraman.tif');
scrsz = get(groot, 'ScreenSize'); %Get screen size
f = figure('Position', [scrsz(3)/10, scrsz(4)/5, scrsz(4)/2*2.4, scrsz(4)/2]); %Set figure position by screen size.
positionVector1 = [-0.25, 0.95-0.9, 0.9, 0.9]; %position vector for largest image.
positionVector2 = [0.23, 0.95-0.6, 0.6, 0.6];
positionVector3 = [0.555, 0.95-0.4, 0.4, 0.4];
positionVector4 = [0.775, 0.95-0.267, 0.267, 0.267]; %position vector for smallest image.
axes(f, 'Position', positionVector1);
imshow(I, 'border', 'tight');
axes(f, 'Position', positionVector2);
imshow(I, 'border', 'tight');
axes(f, 'Position', positionVector3);
imshow(I, 'border', 'tight');
axes(f, 'Position', positionVector4);
imshow(I, 'border', 'tight');
Setting the position manually is not the best solution.
There must be a way to compute the position of each axes.
Result:

Related

Sample covariance matrix for each pixel (taking the neighboring pixel) and applying for entire image dimension

The following is the code for sample covariance matrix for the single pixel. I have taken 10 neighboring pixels for the (1,1) including the first pixel of the stacked image. y_1, y_2, y_3 and y_4 are my four images. Kindly do let me know if the question is not clear.
y_cal=cat(3, y_1, y_2, y_3, y_4);
Y_new=reshape(y_cal, [5586, 4]);
Y_new_cov=Y_new(1:10,:);
Y_new_cell = arrayfun(#(ri) Y_new_cov(ri, :)', 1:10, 'UniformOutput', 0);
Y_new_cell_tr= cellfun(#ctranspose, Y_new_cell , 'UniformOutput', 0);
Y_covariance_initial = cellfun(#mtimes, Y_new_cell,Y_new_cell_tr, 'UniformOutput', 0);
Y_covariance_final = Y_covariance_initial{1,1}+Y_covariance_initial{1,2}+Y_covariance_initial{1,3}+Y_covariance_initial{1,4}+Y_covariance_initial{1,5}+Y_covariance_initial{1,6}+Y_covariance_initial{1,7}+Y_covariance_initial{1,8}+Y_covariance_initial{1,9}+Y_covariance_initial{1,10};
Here 10 pixels were taken manually where covariance is implemented. I have the image dimension as 114 X 49. So the final covariance matrix generated is 114 X 49 x 4 X 4. How should I apply a square window to select the neighboring pixels for a target pixel and continue for other pixels also?
Kindly provide necessary assistance as it took me two months to write this code being from a non coding background. Your help will be highly appreciated.
Regards
The standard way would be to use nlfilter. For this function, you supply your function (the one to compute covariance), and it will apply it to a sliding window of your size. For example:
octave> img = rand (64, 64);
octave> img_cov = nlfilter (img, [10 10], #(x) cov (x(:)));
Will call cov (x(:)) for each sliding block of size [10 10] (after padding the original image with zeros), and return an array of size [64 64] (same as the input image) with those results. Since you are using Octave, your window and image may have any number of dimensions. So you can do this:
octave> img = rand (64, 64, 3, 4);
octave> img_cov = nlfilter (img, [10 10 3 4], #(x) cov (x(:)));
An alternative is to get all the sliding windows from your n dimensional image into a column (using im2col), use a function that will work along each column, and then build an image back with col2im. This may, or may not, be faster but does give you a bit more flexibility if you can warp your head around it:
octave> img = rand (64, 64);
octave> im_cols = im2col (img, [10 10], "sliding");
octave> im_cov = you_nd_cov_function (im_cols);
octave> img_cov = col2im (cov (im_cols), [1 1], [55 55], "sliding");

How to do bar plot in the same scale and dimension as an image?

I have an image, then I am projecting it on one of it's edges by some aggregation functions like mean. I am getting 1D digitized data this way. How to plot it exactly below source image in exactly the same horizontal or vertical scale?
Sample code:
% loading image
image = imread('..\..\FruitSample_small.png');
%computing gradients
dx=double(image(1:end-1,2:end,:))-double(image(1:end-1,1:end-1,:));
dy=double(image(2:end,1:end-1,:))-double(image(1:end-1,1:end-1,:));
% computing total magnitude
a=sqrt(sum(dx.^2,3)+sum(dy.^2,3));
% projection on bottom
h = mean(a,1);
% drawing
figure;
subplot(2,1,1);
imshow(image);
subplot(2,1,2);
bar(h);
axis image;
I want bar plot here to be of the same width as image above. Also I want histogram to spread exactly to the same horizontal coordinate, as image does.
The challenge here is that "axis image" enforces an aspect ratio on the image axis, which allows the display size of the image to vary from its set dimensions. My suggestion is to forget the auto-sizing capabilities that come from normalized units, and adjust the sizes based on pixel sizing. If you set the size of the image axis to exactly the size of the image in pixels, then it will have the correct aspect ratio, and you can use the same size for the bar plot.
load clown; % use a built-in demo image. Note the image is now in X
%computing gradients
dx=double(X(1:end-1,2:end,:))-double(X(1:end-1,1:end-1,:));
dy=double(X(2:end,1:end-1,:))-double(X(1:end-1,1:end-1,:));
% computing total magnitude
a=sqrt(sum(dx.^2,3)+sum(dy.^2,3));
% projection on bottom
h = mean(a,1);
% drawing
figure;
subplot(2,1,1);
imagesc(X);
size_x = size(X,2);
size_y = size(X,1);
set(gcf, 'Units', 'pixels')
fp=get(gcf, 'Position');
set(gca, 'Units', 'pixels');
set(gca, 'Position', [(fp(3)-size_x) / 2, (fp(4)-size_y) / 2 + 100, ...
size_x, size_y]);
subplot(2,1,2);
bar(h);
set(gca, 'Units', 'pixels');
set(gca, 'Position', [(fp(3)-size_x) / 2, 100, size_x, 100]);
set(gca, 'XLim', [1 size_x]);
I'm computing the offsets automatically from the figure size, to center the results on the figure. This is not resizeable. You'd have to rerun the set('Position') stuff to readjust the locations if you resize the figure itself. If you need it to be dynamically resizeable, you'd have to add a handler for a resize event, and adjust the sizes on every resize.

MATLAB: image AlphaData changes figure size

I have two images: im2 needs to be overlayed over im1 with a constant alpha map of 0.5. Whenever I set the 'AlphaData' for im2 (to reveal im1 below), the size of the figure/axes changes slightly. If my axes occupies the whole figure, some border pixels go missing. The following example demonstrates this problem by two example images, where im2 has a yellow border so you can clearly notice this problem:
close all;
frame_sz = [106 777];
% create a white im1
im1 = ones([frame_sz 3]);
% create im2 with a yellow border
im2 = zeros([frame_sz 3]);
im2(:,1,[1 2]) = 1;
im2(:,end,[1 2]) = 1;
im2(1,:,[1 2]) = 1;
im2(end,:,[1 2]) = 1;
% create the figure at a specific location with size equal to image
screen_sz = get(0,'ScreenSize');
fg_h = figure('units', 'pixels', 'position', ...
[screen_sz([3 4])-frame_sz([2 1])-40 frame_sz([2 1])], ...
'paperpositionmode', 'auto');
ax_h = axes('Parent',fg_h);
% show first image
imshow(im1, 'Parent',ax_h, 'InitialMagnification','fit');
hold on;
% display im2 ontop of im1
h = image(im2, 'Parent',ax_h);
% set the axis such that image occupies the whole figure
set(ax_h, 'Units','normalized', ...
'position', [0 0 1 1], 'visible', 'off');
axis off;
%%%%%%%%%%%% PROBLEM HAPPENS HERE %%%%%%%%%%%%%
% as soon as I set the AlphaData couple of pixels
% go missing from the right and bottom side
set(h, 'AlphaData', ones(frame_sz([1 2]))*0.5);
The problem occurs regardless of if I am overlaying using image() or just simply using image() to display an image. As soon as I set the AlphaData, the sizing of the axes slightly changes and chops off some borders.
How do I fix this?

Plotting over displayed image in GNU Octave

I am developing some routines in Octave and need to display an image, then plot a curve on top which will hopefully overlay some image features.
However, I cannot work out how to match the origin/scale of the image and the plot. For example, given a 1024x1024 pixel image I can do:
a=imread('image.png');
x=linspace(1,1024,100);
y=x;
imshow(a);
hold on;
plot(x,y);
But the line is not scaled to the image and does not start at a corner. (I know that the image and plot should have origins in different corners). When I examine the graphic coordinates from the cursor position, the image is clearly not at the origin, so I guess this is the basis of the problem.
Use image() instead of imshow() in this case
a = imread ('image.png');
x = linspace (1, 1024, 100);
y = x;
image (a);
hold on
plot (x, y);
axis square
You can plot functions over images this way:
Create an image called stuff.jpg like this, any size is possible but I made mine roughly 6x6 pixels so I could test:
You can plot functions over other functions this way:
octave> x = 0:1:5;
octave> plot(x, (3/2).^x, "linewidth", 2, "color", "blue");
octave> hold on
octave> plot(x, 2.^x, "linewidth", 2, "color", "red");
octave> plot(x, factorial(x), "linewidth", 2, "color", "green");
octave> plot(x, x.^3, "linewidth", 2, "color", "black");
octave>
For me it shows this:
Found that here, it has a walkthrough:
http://ericleschinski.com/c/algorithm_complexity_big_o_notation/
Which plots my power level given my age. It's already over nine thousand.
The problem with image is that it puts (0,0) (rather (min_x,min_y)) at upper-left while we usually expect (0,0) to be at bottom-left.
Also it only uses max and min values of the x and y vectors so doing y(end:-1:1) doesn't work.
im = imread('file.png'); %read the file
image([xmin xmax],[ymin ymax],im(end:-1:1,:,:)); %put the image on the screen upside down
axis('xy'); % flip the image by putting (0,0) at bottom left. Image now right side up
axis('square'); if you want to aspect ratio of the image to be 1:1
hold on;
plot([xmin xmax],[ymin ymax]) % this should draw a diagonal from bottom left to upper right.
% plot whatever you want to overlay

Outlining a defect in an image?

I have the following image on which i have applied bilateral filtering and subtracted it from my original image
Is it possible to outline the glass defect as shown
After apply Hough i got the following result not perfect :/
My matlab code :
im = imread('C:\Users\SUJIT\Desktop\image003.jpg');
im=rgb2gray(im);
h = fspecial('gaussian', size(im), 1.0);
g = imfilter(im, h);
im=im2double(g);
im=imadjust(im);
imgauss = imfilter(im, fspecial('gaussian',[7 7], 6),'conv');
imbi = bilateralfilter(im, [5 5], 3, 3);
imbi= im - imbi;
imshow(imbi,[]); title('Bilateral Filted Image');
I = imcrop(imbi, [30 30 450 350]);
J = imfilter(I, fspecial('gaussian', [17 17], 5), 'symmetric');
BW = edge(J, 'canny');
%# Hough Transform and show matrix
[H T R] = hough(BW);
imshow(imadjust(mat2gray(H)), [], 'XData',T, 'YData',R, ...
'InitialMagnification','fit')
xlabel('\theta (degrees)'), ylabel('\rho')
axis on, axis normal, hold on
colormap(hot), colorbar
%# detect peaks
P = houghpeaks(H, 10);
plot(T(P(:,2)), R(P(:,1)), 'gs', 'LineWidth',2);
%# detect lines and overlay on top of image
lines = houghlines(BW, T, R, P);
figure, imshow(I), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1), xy(:,2), 'g.-', 'LineWidth',2);
end
hold off
Please help am i doing something wrong here?
It is a bit hard to give a general answer based on only one image and no other information, but I can give a specific answer based on your sample image.
Assuming that what you want to find is the vertical blurry line in the middle of the image, this my approach. I won't go into specific implementation details, but only an outline on how I would do it.
Find the windows. There are multiple approaches to this. Some ideas are to either find the corners, or to find the rectangular structure itself. The Hough transform is a possible tool.
For each window, check if there are vertical structures in it.

Resources