draw a rectangle on top of overlaid images - matlab

I would like to overlay two images in MATLAB (I and imagesc(data)) and then draw a rectangle on top of those. I2 specifies the transparency pattern in the following code. The rectangle becomes a line on top of the image. Can anyone tell me why the rectangle is not drawn correctly?
imshow(I);
hold on;
h = imagesc(data,[0,1]);
hold off;
I2 = ones(height,width) * 80;
set(h, 'AlphaData', I2);
rectangle('Position',[100,100,20,20]);

Since we can't reproduce your code exactly without all the data, here is a complete example with sample images:
%# some sample images
I = imread('coins.png');
I_transp = imread('peppers.png');
%# create a gaussian mask for transparency
[r,c,~] = size(I_transp);
M = fspecial('gaussian', [r c], mean([r c]./5));
M = (M-min(M(:)))./range(M(:));
%# show overlayed images
figure, imshow(I, 'XData',[1 c], 'YData',[1 r]), hold on
hImg = imshow(I_transp);
set(hImg, 'AlphaData',M);
%# draw a rectangle
rectangle('Position',[355 220 100 100], 'LineWidth',2, 'EdgeColor','b');

Related

Matlab: Plot colourful line over background gray image whilst retaining colorbar information

I am using MATLAB I would like to plot a colourful trajectory on top of a grayscale png image whilst retaining the colour information of the trajectory. For example with the data below, I would like to plot Data B over Image A. Without Data B turning gray and without making the colourbar represent the grayscaled image. Any help would be greatly appreciated!
%Image A
RGB = imread('peppers.png');
I = rgb2gray(RGB);
figure
imshow(I)
hold on
%Data B
x = 1:1000;
y = x;
z = zeros(size(x));
lineColor = x;
surface([x;x], [y;y], [z;z], [lineColor;lineColor],...
'FaceColor', 'no',...
'EdgeColor', 'interp',...
'LineWidth', 8);
cc = colorbar();
Many thanks!
MATLAB doesn't seem to like to do more than one colourmap pet axes. By using hold on we're plotting both the image (gray colormap) and surface (e.g. jet colormap) to the same plot. By default from the non-RGB image in imshow the colormap is set to gray, and so it is the same for the surface plot. Trying to change the colourmap by invoking colormap('jet') changes the colormap for both the image and surface.
Seems that there have been others with the same problem:
https://uk.mathworks.com/matlabcentral/answers/194554-how-can-i-use-and-display-two-different-colormaps-on-the-same-figure
The best solution appears to be defining two seperate axes to the same figure and linking them so that positional information matches. You need to specify which axis to plot to, so imshow has been replaced with imagesc which has more flexibility.Then you can define a different colourmap to each axis. Unfortunately, the colorbar probably won't play ball everytime so you gotta fiddle with its positional information a bit.
In practice for your code:
figure
%Image A
ax1 = axes;
RGB = imread('peppers.png');
I = rgb2gray(RGB);
imagesc(ax1,I)
colormap(ax1,'gray')
%Data B
ax2 = axes;
ax2.Visible = 'off'; % make transparent
x = 1:1000;
y = x;
z = zeros(size(x));
lineColor = x;
h = surface(ax2, [x;x], [y;y], [z;z], [lineColor;lineColor],...
'FaceColor', 'no',...
'EdgeColor', 'interp',...
'LineWidth', 8);
colormap(ax2,'jet') % colourful colourmap
% Gotta reposition the colourbar, tedious bit!
% Position: [left bottom width height]
cb2 = colorbar(ax2,'Position',[.91 .11 .0375 .815]);
linkaxes([ax1,ax2]) % same positions in 1st and 2nd plot
Result:

crop circles detected from imfindcircles in matlab

I'm detecting circles from an image using imfindcircles function.
Below is the code.
image here
img= imread('image.png');
imshow(img);
rmin=10
rmax=50
[centersDarkl, radiiDarkl]=imfindcircles(img,
[rmin,rmax],'ObjectPolarity','dark','Sensitivity',0.80);
viscircles(centersDarkl, radiiDarkl,'LineStyle','--')
Now, I want to crop the detected circles and save them as different figures.
Here is a solution that works for this image. I used floor and ceil to avoid the edges and rmax had to be larger than 75.
[img,map] = imread('MwBQo.png','png');
img = ind2rgb(img, map);
figure;
imshow(img);
rmin = 10;
rmax = 80;
[centersDarkl, radiiDarkl] = imfindcircles(img,...
[rmin,rmax],'ObjectPolarity','dark','Sensitivity',0.80);
viscircles(centersDarkl, radiiDarkl,'LineStyle','--')
for iCirc = 1:size(centersDarkl,1)
cropped{iCirc,1} = img(...
ceil(centersDarkl(iCirc,2)-radiiDarkl(iCirc)):...
floor(centersDarkl(iCirc,2)+radiiDarkl(iCirc)),...
ceil(centersDarkl(iCirc,1)-radiiDarkl(iCirc)):...
floor(centersDarkl(iCirc,1)+radiiDarkl(iCirc)),:);
end
figure;
subplot(1,2,1)
imshow(cropped{1})
subplot(1,2,2)
imshow(cropped{2})

how to split image and fill different color

As this picture, how to use matlab code to split it into different parts, and then fill color in it? In addition, how to set gradient color in the second code ???
Here is the picture segmentation code:
clc
rgb=imread('sample1.bmp');
bw=im2bw(rgb2gray(rgb),.8);
bw=medfilt2(bw);
planes=bwareaopen(bw,800);
D=mat2gray(bwdist(imcomplement(planes)));
stats=regionprops(D>.8,'Centroid');
planes_centroid=cat(1,stats.Centroid);
planes_mask=false(size(bw));
planes_mask(sub2ind(size(bw),round(planes_centroid(:,2)),...
round(planes_centroid(:,1))))=1;
M=imimposemin(imcomplement(D),planes_mask);
L=watershed(M);
r=L & planes;
stats=regionprops(r,'BoundingBox','Centroid')
bb=cat(1,stats.BoundingBox);
c=cat(1,stats.Centroid);
figure,imshow(planes)
hold on
for i=1:length(stats)
rectangle('Position',bb(i,:),'EdgeColor','b')
plot(c(i,1),c(i,2),'r*')
text(c(i,1)-5,c(i,2)-10,num2str(i))
end
%second code
clc;clf;close all;clear all;
color=cell(4,1);
for i=1:4
input=imread(['heartspline2_4_',num2str(i)],'bmp');
figure,imshow(input);
BW=im2bw(input,graythresh(input));
[B,L]=bwboundaries(BW,'noholes');
for k=1:length(B)
boundary=B{k};
ind=size(boundary(:,2));
plot(boundary(:,2),boundary(:,1),'k','LineWidth',2);
hold on;
axis off;
if (k==1)
patch(boundary(:,2),boundary(:,1),'w');
else
patch(boundary(:,2),boundary(:,1),???);
end
end
saveas(gca,['y_','heartspline2_4_',num2str(i)],'bmp')
close(gcf)
end
You can use bwlabel to assign different index to each image region:
img = imread('http://i.stack.imgur.com/F1Iya.jpg'); %// read image
bw = img(:,:,1) > 128; %// convert to binary mask
lb = bwlabel(bw,4); %// extract distinct regions
The result:
figure; imshow(lb, [], 'border', 'tight'); colormap(rand(256,3));
If you want a gradient effect to the colors, you can
[x y] = meshgrid(linspace(0,1,size(bw,2)), linspace(0,1,size(bw,1)));
rand('seed',543310);
rgb_lb = ind2rgb(lb, rand(max(lb(:)+1),3)); %// convert to RGB color image
gx = x;
gx(lb==1)=1; %// use the horizontal gradient
gx = gx./max(gx(:));
Apply the gradient:
rgb_lb = bsxfun(#times, rgb_lb, gx);
The result:

on matlab, how can i plot centroid points on top of an rgb image?

i have a list of about 300 centroid points. these points are the centroids of the conncomps of a BW image that i have. Is there a way to plot the points of the centroids over the original rgb image?
No problem. Have this short script:
img = imread('rice.png');
bg = imopen(img,strel('disk',15));
img2 = img - bg;
mask = im2bw(img2, 0.19);
mask = bwareaopen(mask, 40);
cc = bwconncomp(mask, 4);
positionArray = regionprops(cc, {'Centroid'});
positionArray = struct2cell(positionArray);
positionArray = cellfun(#transpose, positionArray, 'UniformOutput',false);
positionArray = cell2mat(positionArray);
imshow(img);
hold on;
scatter(positionArray(1, :), positionArray(2, :), 200, 'g+');
You can vary the markersize and shape as you wish. The points in this case are stored as a 2 by n matrix with x coordinates in the first row ans y in the second.
First, the image itself is plotted using imshow. Then, scatter() is called. To put both items on the same set of axes, you have to call hold on.

Drawing the major and minor axis of an elliptical object in MATLAB

This program currently inputs an image of a coin, thresholds it, binarizes it, and finds the major and minor axis lengths of the segmented elliptical using the regionprops function. How do I output a subplot where I draw the axes used to calculate the 'MajorAxisLength' and 'MinorAxisLength' over the original image?
I have appended my code for your perusal.
% Read in the image.
folder = 'C:\Documents and Settings\user\My Documents\MATLAB\Work';
baseFileName = 'coin2.jpg';
fullFileName = fullfile(folder, baseFileName);
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
%Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows columns numberOfColorBands] = size(rgbImage);
% Display the original color image.
subplot(2, 3, 1);
imshow(rgbImage, []);
title('Original color Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'Position', get(0,'Screensize'));
% Extract the individual red color channel.
redChannel = rgbImage(:, :, 1);
% Display the red channel image.
subplot(2, 3, 2);
imshow(redChannel, []);
title('Red Channel Image', 'FontSize', fontSize);
% Binarize it
binaryImage = redChannel < 100;
% Display the image.
subplot(2, 3, 3);
imshow(binaryImage, []);
title('Thresholded Image', 'FontSize', fontSize);
binaryImage = imfill(binaryImage, 'holes');
labeledImage = bwlabel(binaryImage);
area_measurements = regionprops(labeledImage,'Area');
allAreas = [area_measurements.Area];
biggestBlobIndex = find(allAreas == max(allAreas));
keeperBlobsImage = ismember(labeledImage, biggestBlobIndex);
measurements = regionprops(keeperBlobsImage,'MajorAxisLength','MinorAxisLength')
% Display the original color image with outline.
subplot(2, 3, 4);
imshow(rgbImage);
hold on;
title('Original Color Image with Outline', 'FontSize',fontSize);
boundaries = bwboundaries(keeperBlobsImage);
blobBoundary = boundaries{1};
plot(blobBoundary(:,2), blobBoundary(:,1), 'g-', 'LineWidth', 1);
hold off;
I had the same task as you for some project I did 2 years ago. I've modified the code I used then for you below. It involved calculating the covariance matrix for the datapoints and finding their eigenvalues/eigenvectors. Note here that because of circular symmetry, the minor and major axis will be somewhat "random". Also note that I have made the image binary in a very naïve way to keep the code simple.
% Load data and make bw
clear all;close all; clc;
set(0,'Defaultfigurewindowstyle','docked')
I = imread('american_eagle_gold_coin.jpg');
Ibw = im2bw(I,0.95);
Ibw = not(Ibw);
figure(1);clf
imagesc(Ibw);colormap(gray)
%% Calculate axis and draw
[M N] = size(Ibw);
[X Y] = meshgrid(1:N,1:M);
%Mass and mass center
m = sum(sum(Ibw));
x0 = sum(sum(Ibw.*X))/m;
y0 = sum(sum(Ibw.*Y))/m;
%Covariance matrix elements
Mxx = sum(sum((X-x0).^2.*Ibw))/m;
Myy = sum(sum((Y-y0).^2.*Ibw))/m;
Mxy = sum(sum((Y-y0).*(X-x0).*Ibw))/m;
MM = [Mxx Mxy; Mxy Myy];
[U S V] = svd(MM);
W = V(:,1)/sign(V(1,1)); %Extremal directions (normalized to have first coordinate positive)
H = V(:,2);
W = 2*sqrt(S(1,1))*W; %Scaling of extremal directions to give ellipsis half axis
H = 2*sqrt(S(2,2))*H;
figure(1)
hold on
plot(x0,y0,'r*');
quiver(x0,y0,W(1),H(1),'r')
quiver(x0,y0,W(2),H(2),'r')
hold off
Look at the documentation for the Orientation attribute that regionprops() can return to you.
This gives the angle between the positive x-axis and the major axis of the ellipse. You should be able to derive the equation for the major axis line in terms of that angle, and then just make a grid of x-axis points, and compute the major axis line's value for all the points in your grid, then just plot it like you would plot any other curve in MATLAB.
To do the same for the minor axis, just note that it will be 90 degrees further counter-clockwise from the major axis, then repeat the step above.
Usually one does it with computing eigenvectors, as explained in the Wikipedia article Image moment under 'examples'. That would be the correct way.
But I wonder, if you know the centroid and the boundingbox from MATLAB, then the endpoint of the major axis must be in the upper left or upper right corner. So checking (apart from noise) these two corners, if there are pixel, would give you the major axis. The minor axis then is just orthogonal to it with respect to the centroid.
Sorry for not having MATLAB code ready.
The reasoning is not that wrong, but not so good either, using the orientation as written above is better ;)