How to crop the sub-image using its centroid? - matlab

To get a sub-image there is imcrop function. but I want to crop the sub-image using its centroid, (x,y) that was achieved already.
Image = 512x512
Centroid = (x,y) = (178.92, 207.20)
Also, the imcrop function doesn't get any input as Centroid.
B = imcrop(A, [col, row, width, height];
How to crop the sub-image using its centroid ?
Also, according to the specified size and position of the rectangle that is estimated using the center of (x, y)), the sub-image is cropped but its output wasn't correct.
Ex:
To calculate the input argument of `imcrop` function, we have:
Diam of Obj = 50 pixel.
then its window = 50x50 pixel.
and so 57/2 = 28 to add and subtract of centroid.
Win_Obj = imcrop(RNod,[c(1)-28, c(2)-28, c(1)+28, c(2)+28]);

According to your post and also the docs, the function imcrop() uses a rectangle as second parameter in the form [x_min y_min width height], so you just need to change your call of imcrop to the following form:
% c is the known centroid position
Win_Obj = imcrop(RNod, [c(1)-28 c(2)-28 2*28 2*28]);
This should give you a sub-image with your object in the center.

Related

Regionprops vs. PodczeckShapes/DIPimage Circularity question - Matlab

Can someone please explain me why the 'Circularity' in Matlab is calculated by (4*Area*pi)/(Perimeter^2) while in Podczeck Shape it is Area/(Pi/4*sp^2) https://qiftp.tudelft.nl/dipref/FeatureShape.html)? Or is it just simply defined differently?
I tried to write a Podczeck Shape circularity code in Matlab and I assume that ‘MaxFeretDiameter’ is perpendicular to ‘MinFeretDiameter’, am I correct?
Code:
clc;
clear all;
close all;
Pi=pi;
Image = rgb2gray(imread('pillsetc.png'));
BW = imbinarize(Image);
BW = imfill(BW,'holes');
BW = bwareaopen(BW, 100);
imshow(BW);
[B,L] = bwboundaries(BW,'noholes');
i=2;
stat = regionprops(BW, 'Area', 'Circularity', 'MaxFeretProperties', 'MinFeretProperties');
OArea = stat(i).Area;
OMaxFeretProperties = stat(i).MaxFeretDiameter;
OMinFeretProperties = stat(i).MinFeretDiameter;
OCircularityPodzeck = OArea/(Pi/4 * (OMaxFeretProperties^2))
OCircularityMatlab = stat(i).Circularity
The 'Circularity' measure in regionprops is defined as
Circularity = (4 Area π)/(Perimeter²)
For a circle, where Area = π r² and Perimeter = 2 π r, this comes out to:
Circularity = (4 π r² π)/((2 π r)²) = (4 π² r²)/(4 π² r²) = 1
For any other shape, the perimeter will be relatively longer (this is a characteristic of the circle!), and so the 'Circularity' measure will be smaller.
Podczeck's Circularity is a different measure. It is defined as
Podczeck Circularity = Area/(π/4 Height²)
In the documentation you link it refers to Height as sp, and defines it as "Feret diameter perpendicular to s", and defines s as "the shortest Feret diameter". Thus, sp is the largest of the two sides of the minimal bounding box.
For a circle, the minimal bounding box has Height equal to the diameter. We substitute again:
Podczeck Circularity = (π r²)/(π/4 (2 r)²) = (π r²)/(π/4 4 r²) = 1
For any other shape, the height will be relatively larger, and so the Podczeck Circularity measure will be smaller.
Do note that the max and min Feret diameters are not necessarily perpendicular. A simple example is a square: the largest diameter is the diagonal of the square; the smallest diameter is the height or width; these two are at 45 degrees from each other. The Podczeck Circularity measure uses the size of the project perpendicular to the smallest projection, which for a square is equal to the smallest projection, and smaller than the largest projection. The smallest projection and its perpendicular projection form the minimal bounding rectangle (typically, though apparently this is not necessarily the case?). However, regionprops has a 'BoundingBox' that is axis-aligned, and therefore not suitable. I don't know how to get the required value out of regionprops.
The approach you would have to follow is to use the 'PixelList' output of regionprops, together with the 'MinFeretAngle'. 'PixelList' is a list of pixel coordinates that belong to the object. You would rotate these coordinates according to 'MinFeretAngle', such that the axis-aligned bounding rectangle now corresponds to the minimal bounding rectangle. You can then determine the size of the box by taking the minimum and maximum values of the rotated coordinates.

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:

How to crop face section from an image with given corner points. MATLAB

I want to crop a face section from an image but face image is not straight/vertically aligned. I am having four pixel points to crop it..
Problem is that,
If i will transform image first the pixel points cannot be used thereafter to crop the facial section out of it.
Or in other case I am not having an exact bounding box to crop the image directly using imcrop as facial sections are somewhat tilted left or right.
The four pixel points are at forehead , chin and ears of the face to be cropped.
You should look at poly2mask. This function produces a mask image from your given x and y coordinates:
BW = poly2mask(x,y,m,n);
where x and y are your coordinates, and the produced BW image is m by n. You can then use this BW image to mask your original image I by doing
I(~BW) = 0;
If you actually want to crop, then you could get the bounding box (either through the regionprops function or the code below):
x1 = round(min(x));
y1 = round(min(y));
x2 = round(max(x));
y2 = round(max(y));
and then crop the image after you have used the BW as a mask.
I2 = I(x1:x2,y1:y2);
Hope that helps.

How to detect certain moving points in a video using Matlab

I have a video of moving hose in an experiment and I need to detect certain points in that hose and calculate the amplitude of their movements, I am using the code below and I am able to extract the required point using detectSURFFeatures, the function get many unnecessary points so I am using cuba = ref_pts.selectStrongest(5); to choose only five points, the problem is I can not get a function to put a bounding box about this 5 points and get their pixel values through the video, Kindly advice what functions can be used, thanks :)
clear;
clc;
% Image aquisition from Video and converting into gray scale
vidIn = VideoReader('ItaS.mp4');
%% Load reference image, and compute surf features
ref_img = read(vidIn, 1);
ref_img_gray = rgb2gray(ref_img);
ref_pts = detectSURFFeatures(ref_img_gray);
[ref_features, ref_validPts] = extractFeatures(ref_img_gray, ref_pts);
figure; imshow(ref_img);
hold on; plot(ref_pts.selectStrongest(5));
cuba = ref_pts.selectStrongest(5);
stats1 = round(cuba.Location);
If you want to find the bounding box which covers all the five points you selected: stats1 now contains (x, y) coordinates of the selected 5 points. Find min and max for x and y coordinates. min values of x and y gives you the starting point of the rectangle. Width and height of the bounding box is now the difference of max and min in y and x directions.
If you want to extract the part of the original image inside the bounding box: just copy that part to another variable as you want. Consider the following example.
img2 = img1(y:h, x:w, :)
Here, x and y are the x and y coordinates of the top left corner of the bounding box. w and h are the width and height of the bounding box.