Colorbar resizes the subplots - image

I'm trying to plot 3 images side by side in MATLAB using subplot:
maxValue = 9;
minValue = 5;
figure(1)
subplot(1,3,1);
imshow(im1);
axis equal;
subplot(1,3,2);
imagesc(im2);colorbar;
caxis([minValue maxValue])
axis equal;
subplot(1,3,3);
imagesc(im3);colorbar;
caxis([minValue maxValue])
axis equal;
but the result looks like this:
Apparently the colorbar is resizing the image. How can I make all 3 images the same size and the colorbar fit the size of the image?

Your image is resized to maintain its aspect ratio according to the available space.
Use axis normal; for subplot(1,3,1) instead of axis equal.
You might need to maximise the figure window as well.
For im1 = imread('peppers.png');, the result is:

Here is what I ended up doing:
fig = figure(1);
set(fig, 'Position', [52 529 1869 445]); % Resize the image
subplot(1,3,1); % Add a subplot
subaxis(1,3,1, 'Spacing', 0.03, 'Padding', 0, 'Margin', 0); % Remove whitespace from subplot
imshow(im);
axis equal; % Use undistorted images
subplot(1,3,2);
subaxis(1,3,2, 'Spacing', 0.03, 'Padding', 0, 'Margin', 0);
imagesc(depth_gt);colorbar;
caxis([minValue maxValue])
axis equal;
subplot(1,3,3);
subaxis(1,3,3, 'Spacing', 0.03, 'Padding', 0, 'Margin', 0);
imagesc(depth_pred);colorbar;
caxis([minValue maxValue])
axis equal;
You can get this 'position' my manually resizing the image and then printing the output of fig in the Matlab command terminal

Related

Draw mask on image with transparency

In Matlab/Octave (Image package) is it possible to draw a slightly transparent coloured rectangle over an image region?
For example; I want to draw a red rectangle (alpha/opacity of 0.5) over the top left corner of an image.
pkg load image;
pkg load signal;
i = imread('foo.jpg');
% Somehow draw a transparent rectangle over the top left of the image
imshow(i);
You can use hold on and the property 'AlphaData' to draw a transparent overlay as follows:
image = rand(100); % a random image
imshow(image); % show the image
% create the red overlay
red = zeros(100, 100, 3);
red(:, :, 1) = 1;
% create the alpha channel with the right transparency
alpha = zeros(100); % everywhere completely transparent
alpha(1:50, 1:50) = 0.5; % except for the top left corner
hold on
h = imshow(red); % show the overlay
set(h, 'AlphaData', alpha); % apply the transparency

Overlaying MATLAB Scaled Image to Grayscale Image for selected pixels

I am new to MATLAB Image Processing and currently I have two images - one is a grayscale image of my object and the second is the scaled image generated from MATLAB using imagesc function. I am trying to overlay this scaled image on top of my grayscale image to get a spatial resolution for easier observation. Attached are the two images:
A) Grayscale Image:
B) Scaled Image:
There were a few difficulties that I encountered. Firstly, the scaled image is not saved in the same pixel dimensions, but I can get around that using the imwrite function:
im = imagesc(ScaledDiff);
imwrite(get(im,'cdata'),'scaleddiff.tif')
However, doing so will result in a loss of colorbar and the colormap. Secondly, even if I manage to shrink the scaled image to the size of the grayscale image, overlaying it is still a challenge. Ideally, I would like to set the transparency (or 'alpha') to 0 for those pixels with < 0.02 in scaled image value.
Any idea on how to do this will be greatly appreciated! Sorry if I was unclear!
UPDATE:
Thanks to Rotem, I have managed to overlay the grayscale image and a particular region of my heatmap:
However, I need to display the colorbar corresponding to the heatmap values, because otherwise the information is lost and the overlay will be useless. How should I do this? Below is a snippet of my code, where ScaledIntDiff contains the values from 0 to 0.25 that is displayed on the heatmap:
Brightfield = imread('gray.jpg'); % read background image
I1 = ind2rgb(gray2ind(Brightfield), gray); % convert indices into RGB scale
scale = 1000;
ScaledIntDiff2 = round(ScaledIntDiff.*scale);
I2 = ind2rgb(ScaledIntDiff2, jet(256)); % this is for the heatmap
threshold = 0.02;
I2R = I2(:,:,1); I2G = I2(:,:,2); I2B = I2(:,:,3);
I1R = I1(:,:,1); I1G = I1(:,:,2); I1B = I1(:,:,3);
% Replace pixels in I2 with pixels in I1 if the value of ScaledIntDiff of those pixels is below the threshold
I2R(ScaledIntDiff<threshold) = I1R([ScaledIntDiff<threshold]);
I2G(ScaledIntDiff<threshold) = I1G([ScaledIntDiff<threshold]);
I2B(ScaledIntDiff<threshold) = I1B([ScaledIntDiff<threshold]);
I2(:,:,1) = I2R; I2(:,:,2) = I2G; I2(:,:,3) = I2B;
figure
imshow(I2)
I know that the code above is highly inefficient, so suggestions on how to improve it will be very welcomed. Thank you!
Check the following:
I = imread('CKbi2Ll.jpg'); %Load input.
%Convert I to true color RGB image (all pixels R=G=B are gray color).
I1 = ind2rgb(I, gray(256));
%Convert I to true color RGB image with color map parula (instead of using imagesc)
I2 = ind2rgb(I, parula(256));
%Set the transparency (or 'alpha') to 0 for those pixels with < 0.02 in scaled image value.
%Instead of setting transparency, replace pixels with values from I1.
threshold = 0.02; %Set threshold to 0.02
I2(I1 < threshold) = I1(I1 < threshold);
%Blend I1 and I2 into J.
alpha = 0.3; %Take 0.3 from I2 and 0.7 from I1.
J = I2*alpha + I1*(1-alpha);
%Display output
imshow(J);
Adding a colorbar with ticks labels from 0 to 0.25:
Set color map to parula - it doesn't affect the displayed image, because image format is true color RGB.
Crate array of add 6 ticks from 0 to 250.
Create cell array of 6 TickLabels from 0 to 0.25.
Add colorbar with Ticks and TickLabels properties created earlier.
Add the following code after imshow(J);:
colormap(parula(256));
TLabels = cellstr(num2str((linspace(0, 0.25, 6))'));
T = linspace(1, 250, 6);
colorbar('Ticks', T', 'TickLabels', TLabels);
imshow('ClmypzU.jpg');
colormap(jet(256));
TLabels = cellstr(num2str((linspace(0, 0.25, 6))'));
T = linspace(1, 250, 6);
colorbar('Ticks', T', 'TickLabels', TLabels);

How to convert a point in image imrotated with loose option to a point in image imrotated with crop option in Matlab?

How to find the relation between image imrotated with loose option Image 1 and image imrotated with crop option Image 2 ? the angle of rotation is not necessary -45° ...
I = imread('cameraman.tif');
Im1 = imrotate(I,-45); % bbox option sets to 'loose' by default
Im2 = imrotate(I,-45,'nearest','crop'); % bbox option sets to 'crop'
figure(1);
subplot(2,1,1), imagesc(Im1), axis image;
subplot(2,1,2), imagesc(Im2), axis image;
I mean if I choose a point (x1,y1) from Im1 what is the equation of its relation with (x2,y2) in Im2 ?? I am looking for loose2crop() equation ?
I found a solution , please feel free to check it for fun :)
I = imread('cameraman.tif');
Im1 = imrotate(I,-45); % Image imrotated with loose option
Im2 = imrotate(I,-45,'nearest','crop');% Image imrotated with crop option
% draw image 1 loose
figure(1);
subplot(2,1,1), imagesc(Im1), axis image;
drawnow;
%%Get a point
title('Select a point'); hold on;
[p1] = ginput;
plot (p1(1),p1(2),'k*');
drawnow;
% convert loose p1 to crop image
p2 = loose2crop(Im1,Im2,p1)
% draw Image 2 cropped
subplot(2,1,2), imagesc(Im2), axis image, hold on;
plot (p2(1),p2(2),'r*');
drawnow;
function p2 = loose2crop(Im1, Im2, p1)
[h1,w1] = size(Im1);
[h2,w2] = size(Im2);
shift_h = (h1 - h2)/2 ;
shift_w = (w1 - w2)/2 ;
p2(1) = p1(1) - shift_h ;
p2(2) = p1(2) - shift_w ;

how to add png file to matlab plot

how do i add an image to a plot i made in matlab? the image is from wikipedia:
And below is the code i came up with for the plot i made.
x= 7:0.1:27;
y= normpdf(x,17,exp(1));
title('Normal Distribution')
hold on
xlabel('x')
ylabel('y')
plot(x,y)
I think the script i need to use should be something like this but it's not working. Any ideas? thanks
title('addition: $1+1=2$', 'interpreter', 'latex')
Are you trying to get the image itself to show up in your axes? Or are you trying to have the equation in the image show up in your axes as text? Because to do the first one you'd need:
x= 7:0.1:27;
y= normpdf(x,17,exp(1));
title('Normal Distribution')
hold on
xlabel('x')
ylabel('y')
plot(x,y)
img = imread('http://upload.wikimedia.org/math/7/3/a/73ad15f79b11af99bd2477ff3ffc5a35.png');
img = cat(3, img, img, img);
img = max(img(:)) - img;
img(img == max(img(:))) = 255;
hold on
xRange = [21 29];
yRange = [0.13 0.1];
imgHandle = image(linspace(xRange(1), xRange(2), size(img, 1)), ...
linspace(yRange(1), yRange(2), size(img, 2)), img, 'Parent', gca);
hold off
which reads in the image from the URL given, tweaks it so it shows up as black text on white and then adds it to the axis as an object.
If instead you just want the text of the equation, which is what I think you're after as it is much more elegant, you'd do it this way:
x= 7:0.1:27;
y= normpdf(x,17,exp(1));
title('Normal Distribution')
hold on
xlabel('x')
ylabel('y')
plot(x,y)
text(19, .145, '$f(x, \mu, \sigma) = \frac{1}{\sigma\sqrt{2\pi}}e^{-\frac{(x-\mu)^{2}}{2\sigma^{2}}}$', ...
'interpreter', 'latex', 'FontSize', 14)

Gaussian blurring with OpenCV: only blurring a subregion of an image?

Is it possible to only blur a subregion of an image, instead of the whole image with OpenCV, to save some computational cost?
EDIT: One important point is that when blurring the boundary of the subregion, one should use the existing image content as much as possible; only when the convolution exceeds the boundary of the original image, an extrapolation or other artificial border conditions can be used.
To blur the whole image, assuming you want to overwrite the original (In-place filtering is supported by cv::GaussianBlur), you will have something like
cv::GaussianBlur(image, image, Size(0, 0), 4);
To blur just a region use Mat::operator()(const Rect& roi) to extract the region:
cv::Rect region(x, y, w, h);
cv::GaussianBlur(image(region), image(region), Size(0, 0), 4);
Or if you want the blurred output in a separate image:
cv::Rect region(x, y, w, h);
cv::Mat blurred_region;
cv::GaussianBlur(image(region), blurred_region, Size(0, 0), 4);
The above uses the default BORDER_CONSTANT option that just assumes everything outside the image is 0 when doing the blurring.
I am not sure what it does with pixels at the edge of a region. You can force it to ignore pixels outside the region (BORDER_CONSTANT|BORDER_ISOLATE). SO it think it probably does use the pixels outside the region. You need to compare the results from above with:
const int bsize = 10;
cv::Rect region(x, y, w, h);
cv::Rect padded_region(x - bsize, y - bsize, w + 2 * bsize, h + 2 * bsize)
cv::Mat blurred_padded_region;
cv::GaussianBlur(image(padded_region), blurred_padded_region, Size(0, 0), 4);
cv::Mat blurred_region = blurred_padded_region(cv::Rect(bsize, bsize, w, h));
// and you can then copy that back into the original image if you want:
blurred_region.copyTo(image(region));
Here's how to do it in Python. The idea is to select a ROI, blur it, then insert it back into the image
import cv2
# Read in image
image = cv2.imread('1.png')
# Create ROI coordinates
topLeft = (60, 140)
bottomRight = (340, 250)
x, y = topLeft[0], topLeft[1]
w, h = bottomRight[0] - topLeft[0], bottomRight[1] - topLeft[1]
# Grab ROI with Numpy slicing and blur
ROI = image[y:y+h, x:x+w]
blur = cv2.GaussianBlur(ROI, (51,51), 0)
# Insert ROI back into image
image[y:y+h, x:x+w] = blur
cv2.imshow('blur', blur)
cv2.imshow('image', image)
cv2.waitKey()
Before -> After
Yes it is possible to blur a Region Of Interest in OpenCV.
size( 120, 160 );
OpenCV opencv = new OpenCV(this);
opencv.loadImage("myPicture.jpg");
opencv.ROI( 60, 0, 60, 160 );
opencv.blur( OpenCV.BLUR, 13 );
image( opencv.image(), 0, 0 );
For more information, check out this link.
Good luck,
If you are using javacv provided by bytecode
then you can do like this way. It will only blur particular ROI.
Mat src = imread("xyz.jpg",IMREAD_COLOR);
Rect rect = new Rect(50,50,src.size().width()/3,100);
GaussianBlur(new Mat(src, rect), new Mat(src, rect), new Size(23,23), 30);

Resources