create square in matlab on white canvas given center coordinates - matlab

I'm very new to Matlab. I need to create squares on white canvases based off specs given to me in a file squares.txt. The text document contains a matrix of numbers with 6 columns and some rows. The first two numbers in each row of the matrix are the center coordinates of the square to be drawn. The third value is the width, and the last values are RGB values. I'm having a very difficult time finding a way to draw a square on a canvas given the center coordinates.

Drawing a colored square, given the centre coordinates, the width and the RGB values, looks like:
sq = rectangle('Position', [i-width/2, j-width/2, width, width],'EdgeColor',[r g b]);
depending on whether your color values are between 0 and 1 or 0 and 255 you may have to divide r, g and b by 255
Edit:
Minimal example without using the file:
width=100;
for count = 1:2
if (count == 1)
canvas = ones(400,400,3);
else
canvas = ones(300,700,3);
end
figure, imshow (canvas);
rectangle('Position', [100-width/2, 200-width/2, width, width],
EdgeColor', [0.5 0.5 0.2]);
end

Related

Quantifying pixels from a list of coordinates

I have a list of coordinates, which are generated from another program, and I have an image.
I'd like to load those coordinates (making circular regions of interest (ROIs) with a diameter of 3 pixels) onto my image, and extract the intensity of those pixels.
I can load/impose the coordinates on to the image by using;
imshow(file);
hold on
scatter(xCoords, yCoords, 'g')
But can not extract the intensity.
Can you guys point me in the right direction?
I am not sure what you mean by a circle with 3 pixels diameter since you are in a square grid (as mentioned by Ander Biguri). But you could use fspecial to create a disk filter and then normalize. Something like this:
r = 1.5; % for diameter = 3
h = fspecial('disk', r);
h = h/h(ceil(r),ceil(r));
You can use it as a mask to get the intensities at the given region of the image.
im = imread(file);
ROI = im(xCoord-1:xCoord+1; yCoord-1:yCoord+1);
I = ROI.*h;

Finding the area of the black spots in a circle MATLAB

Is it possible to find the area of the black pixelation of an area within a circle? in other words I want to find the number of pixels (the area) of the RGB 0,0,0 (black pixels) within the circle. I do not want the areas of the white pixels (1,1,1) within the circle. I also have a radius of the circle if that helps. Here is the image:
Here is the code:
BW2= H(:,:) <0.45 ;%& V(:,:)<0.1;
aa=strel('disk',5);
closeBW = imclose(BW2,aa);
figure, imshow(closeBW)
imshow(closeBW)
viscircles([MYY1 MYX1], round(MYR2/2))
MYY1,MYX2, and the other values are calculated by my program. How can I find the area of the black pixelation in my circle?
Here is an idea:
1) Calculate the total # of black pixels in your original image (let's call it A).
2) Duplicate that image (let's call it B) and replace all pixels inside the circle with white. To do that, create a binary mask. (see below)
3) Calculate the total # of black pixels in that image (i.e. B).
4) Subtract both values. That should give you the number of black pixels within the circle.
Sample code: I used a dummy image I had on my computer and created a logical mask with the createMask method from imellipse. That seems complicated but in your case since you have the center position and radius of the circle you can create directly your mask like I did or by looking at this question/answer.
Once the mask is created, use find to get the linear indices of the white pixels of the mask (i.e. all of it) to replace the pixels in the circle of your original image with white pixels, which you use to calculate the difference in black pixels.
clc;clear;close all
A = im2bw(imread('TestCircle.png'));
imshow(A)
Center = [160 120];
Radius = 60;
%// In your case:
% Center = [MYY1 MYX1];
% Radius = round(MYR2/2);
%// Get sum in original image
TotalBlack_A = sum(sum(~A))
e = imellipse(gca, [Center(1) Center(2) Radius Radius]);
%// Create the mask
ROI = createMask(e);
%// Find white pixels
white_id = find(ROI);
%// Duplicate original image
B = A;
%// Replace only those pixels in the ROI with white
B(white_id) = 1;
%// Get new sum
NewBlack_B = sum(sum(~B))
%// Result!
BlackInRoi = TotalBlack_A - NewBlack_B
In this case I get this output:
TotalBlack_A =
158852
NewBlack_B =
156799
BlackInRoi =
2053
For this input image:

Complete partial circles in an image using MATLAB

I have binary images and they have semi or less circles. My aim is to find these circles, make them whole circles and remove all other objects . I found this but it is for MATLAB R2013a. I am using R2011b and it doesn't have the function centers = imfindcircles(A,radius).
How can I do that in MATLAB version R2011b?
Images:
Edit:
My aim is to get whole circle. I show this below for the last image.
Too bad about imfindcircles! One thing I can suggest is to invoke regionprops and specify the 'Area' and 'BoundingBox' flags. regionprops was available in MATLAB for as long as I can remember, so we can certainly use it here.
What this will do is that whatever distinct objects that are seen in the image that are connected, we will find both their areas and their bounding boxes that bound them. After you do this, threshold on the area so that any objects that have a very large area most likely contain circles of interest. Bear in mind that I'm only assuming that you have circles in your image. Should you have any objects that have a large area, this method will extract those out too.
As such, let's read in your image directly from Stack Overflow. When you uploaded the image, it's a RGB image, so I'll have to convert to binary:
im = imread('http://i.stack.imgur.com/wQLPi.jpg');
im_bw = im2bw(im);
Next, call regionprops:
s = regionprops(im_bw, 'Area', 'BoundingBox');
Now, collect all of the areas, and let's take a look at all of the unique areas of all objects seen in this image:
areas = [s.Area].';
unique(areas)
ans =
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
19
20
23
24
25
28
29
38
43
72
73
85
87
250
465
3127
If you take a look at the very end, you'll see that we have an object that has 3127 pixels in it. This probably contains our circle. As such, let's pick out that single element that contains this object:
s2 = s(areas == 3127);
In general, you'll probably have more than one circle in your image, so you should threshold the area to select those potential circles. Something like:
s2 = s(areas > 2000);
Now, let's create a new blank image that is the same size as the original image, then simply use the BoundingBox property to extract out the area that encompasses the circle in the original image and copy it over to the same location in the output image. The BoundingBox field is structured in the following way:
[x y w h]
x and y are the top-left corner of the bounding box. x would be the column and y would be the row. w and h are the width and height of the bounding box. As such, we can use this directly to access our image and copy those pixels over into the output image.
out = false(size(im_bw));
bb = floor(s2.BoundingBox); %// Could be floating point, so floor it
out(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1) = im_bw(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1);
This is what I get:
What you should probably do is loop over the circles in case we have more than one. The above code assumes that you detected just one circle. Therefore, do something like this:
out = false(size(im_bw));
for idx = 1 : numel(s2) %// For each potential circle we have...
bb = floor(s2(idx).BoundingBox); %// Could be floating point, so floor it
%// Copy over pixels from original bw image to output
out(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1) = im_bw(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1);
end
A small thing to note is that the bounding box encompasses the entire object, but there could also be some noisy pixels that are disconnected that are within that bounding box. You may have to apply some morphology to get rid of those pixels. A binary opening could suffice.
Here's what I get with your other images. I thresholded the area to search for those that have 2000 pixels or more (I did this above):
Just for self-containment and your copy-and-pasting pleasure, here's the code in one segment:
clear all;
close all;
%im = imread('http://i.stack.imgur.com/qychC.jpg');
%im = imread('http://i.stack.imgur.com/wQLPi.jpg');
im = imread('http://i.stack.imgur.com/mZMBA.jpg');
im_bw = im2bw(im);
s = regionprops(im_bw, 'Area', 'BoundingBox');
areas = [s.Area].';
s2 = s(areas > 2000);
out = false(size(im_bw));
for idx = 1 : numel(s2) %// For each potential circle we have...
bb = floor(s2(idx).BoundingBox); %// Could be floating point, so floor it
%// Copy over pixels from original bw image to output
out(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1) = im_bw(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1);
end
imshow(out);
All three images are there in the code. You just have to uncomment whichever one you want to use, comment out the rest, then run the code. It will display an image with all of your detected circles.
Edit
You would like to draw complete circles, instead of extracting the shape themselves. That isn't a problem to do. All you need to do is determine the best "radii" that can be enclosed inside each of the bounding boxes. This is simply the maximum of the width and height of each bounding box, then divide these quantities by 2.
After, create a 2D grid of co-ordinates through meshgrid that is the same size as the original image itself, then create a binary image such that the Euclidean distance between the centre of this bounding box with any point in this 2D grid less than the radius is set to logical true while the other positions are set to logical false.
In other words, do this:
clear all;
close all;
im = imread('http://i.stack.imgur.com/qychC.jpg');
%im = imread('http://i.stack.imgur.com/wQLPi.jpg');
%im = imread('http://i.stack.imgur.com/mZMBA.jpg');
im_bw = im2bw(im);
s = regionprops(im_bw, 'Area', 'BoundingBox');
areas = [s.Area].';
s2 = s(areas > 2000);
out = false(size(im_bw));
for idx = 1 : numel(s2) %// For each potential circle we have...
bb = floor(s2(idx).BoundingBox); %// Could be floating point, so floor it
%// Copy over pixels from original bw image to output
out(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1) = im_bw(bb(2):bb(2)+bb(4)-1, bb(1):bb(1)+bb(3)-1);
end
figure;
imshow(out);
%// Image that contains all of our final circles
out2 = false(size(im_bw));
[X,Y] = meshgrid(1:size(im_bw,2), 1:size(im_bw,1)); %// Find a 2D grid of co-ordinates
for idx = 1 : numel(s2) %// For each circle we have...
bb = floor(s2(idx).BoundingBox); %// Could be floating point, so floor it
cenx = bb(1) + (bb(3) / 2.0); %// Get the centre of the bounding box
ceny = bb(2) + (bb(4) / 2.0);
radi = max(bb(3), bb(4)) / 2; %// Find the best radius
tmp = ((X - cenx).^2 + (Y - ceny).^2) <= radi^2; %// Draw our circle and place in a temp. image
out2 = out2 | tmp; %// Add this circle on top of our output image
end
figure;
imshow(out2);
This script now shows you the original extracted shapes, and the best "circles" that describes these shapes in two separate figures. Bear in mind that this is a bit different than what I showed you previously with one circle. What I have to do now is allocate a blank image, then incrementally add each circle to this new image. For each circle, I create a temporary binary image that has just a circle I'm looking for, then I add this on top of the new image. At the end, we will show all of the circles in the image that are fully drawn as you desire.
This is what I get for the best circle for each of your images:
Good luck!

Using rectangle in Matlab. Using Sum()

I have performed rgb2gray on an image and did a sobel edge detection on the image.
then did
faceEdges = faceNoNoise(:,:) > 50; %binary threshold
so it sets the outline of the image (a picture of a face), to black and white. Values 1 is white pixel, and 0 is black pixel. Someone said I could use this,
mouthsquare = rectangle('position',[recX-mouthBoxBuffer, recY-mouthBoxBuffer, recXDiff*2+mouthBoxBuffer/2, recYDiff*2+mouthBoxBuffer/2],... % see the change in coordinates
'edgecolor','r');
numWhite = sum(sum(mouthsquare));
He said to use two sum()'s because it gets the columns and rows of the contained pixels within the rectangle. numWhite always returns 178 and some decimal numbers.
If you have a 2D matrix M (this being -- for exmple -- an image), the way to count how many elements have the value 1 is:
count_1 = sum(M(:)==1)
or
count_1 = sum(reshape(M,1,[])==1)
If the target values are not exactly 1, but have a Δ-threshold of, let's say, +/- 0.02, then one should ask for:
count_1_pm02 = sum((M(:)>=0.98) & (M(:)<=1.02))
or the equivalent using reshape.

How can I draw this network of tubes in Matlab?

I have a distribution of tube radius r, and I would like to plot tubes for all the sampled r in single figure as shown in the figure above. The tubes have following characteristics:
The length of all tubes is constant, but radius is varying.
The narrowest tube will be completely filled
with light gray color.
The length of the light gray color from bottom in all other tubes is
inversely proportional to the radius of the tube i.e.
length of light grey color from bottom = constant/r
The remaining length of the tube will be filled with dark gray color.
Magnitudes of r and total length of each tube is of the order of 1e-005m and 1e-002 m, respectively, so they need to be standardized compared to the X and Y axes units.
The white interspaces are just spaces and not tubes.
UPDATE (Based on the answer by Boris)
This is the code from Boris in which I made certain changes based on the characteristics of the tubes that I have described above. I am having scaling issues as I am not able to visualize my network of tubes as clearly as can be seen in the figure above.
function drawGrayTube (x, r, sigma_wn, theta, del_rho, rmin, rmax,L)
% sigma_wn is in N/m (=Kg/s^2), theta is in degrees, del_rho is in Kg/m^3
% and L is in m
h=((2*sigma_wn*cos((pi/180)*theta))./(del_rho*9.81.*r));
hmin=((2*sigma_wn*cos((pi/180)*theta))./(del_rho*9.81.*rmax));
hmax=((2*sigma_wn*cos((pi/180)*theta))./(del_rho*9.81.*rmin));
rectangle ('Position',[x,0,r/rmax,h], 'FaceColor',[0.7,0.7,0.7]);
ylim([0 1]);
if L>h
rectangle ('Position',[x,L,r/rmax,L-h], 'FaceColor',[0.3,0.3,0.3]);
ylim([0 1]);
else
rectangle ('Position',[x,L,r/rmax,L], 'FaceColor',[0.3,0.3,0.3]);
ylim([0 1]);
end
end
A simple function to draw the gray tubes could be for instance
function drawGrayTube (x, w, h)
rectangle ('Position',[x,0,w,h], 'FaceColor',[0.7,0.7,0.7]);
rectangle ('Position',[x,h,w,100-h], 'FaceColor',[0.3,0.3,0.3]);
end
Hereby, x is the x position of the tube, w denotes the width and h between 0 and 100 the height of the light gray part of the tube.
You can now use it in your example by calling
drawGrayTube (x, r, 100*constant/r)
where you have to adapt the constant such that constant/r is at most 1.
You can write a similar function for the white interspaces.
Assume that you have given a vector of radii (already scaled such that the values are between 0 and 1), e.g., r=[0.5, 0.7, 0.9, 0.1, 0.5, 0.01] then on possibility to draw the tubes is
interspace = 0.5;
for i=1:length(r)
drawGrayTube(sum(r(1:i-1))+i*interspace, 100*r(i)+1e-10, r(i)+1e-10);
end
You should use the function rectangle