Matlab: Extracting a ROI with center coordinates - matlab

I have a mammographic image of size 1024 x 1024, and I have the center coordinates of the anomaly (338.314) and the radius (56) in pixels of the circle containing the anomaly. I desire to extract a region of interest of size 128 * 128 including the anomaly. I tried with
rect = [338-64,314-64,127,127];
crop = imcrop (img, rect) ;
but I obtien an ROI that does not contain the desired anomaly.
any suggestions please.

MATLAB's matrix indices are in (row,column) format, while rectangle's indices are usually in (x,y) format.
This means that you probably need to swap the two first elements of rectangle.
rect = [314-64,338-64,127,127];
crop = imcrop (img, rect) ;

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.

How to crop the sub-image using its centroid?

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.

Geometrical transformation of a polygon to a higher resolution image

I'm trying to resize and reposition a ROI (region of interest) correctly from a low resolution image (256x256) to a higher resolution image (512x512). It should also be mentioned that the two images cover different field of view - the low and high resolution image have 330mm x 330mm and 180mm x 180mm FoV, respectively.
What I've got at my disposal are:
Physical reference point (in mm) in the 256x256 and 512x512 image, which are refpoint_lowres=(-164.424,-194.462) and refpoint_highres=(-94.3052,-110.923). The reference points are located in the top left pixel (1,1) in their respective images.
Pixel coordinates of the ROI in the 256x256 image (named pxX and pxY). These coordinates are positioned relative to the reference point of the lower resolution image, refpoint_lowres=(-164.424,-194.462).
Pixel spacing for the 256x256 and 512x512 image, which are 0.7757 pixel/mm and 2.8444 pixel/mm respectively.
How can I rescale and reposition the ROI (the binary mask) to correct pixel location in the 512x512 image? Many thanks in advance!!
Attempt
% This gives correctly placed and scaled binary array in the 256x256 image
mask_lowres = double(poly2mask(pxX, pxY, 256., 256.));
% Compute translational shift in pixel
mmShift = refpoint_lowres - refpoint_highres;
pxShift = abs(mmShift./pixspacing_highres)
% This produces a binary array that is only positioned correctly in the
% 512x512 image, but it is not upscaled correctly...(?)
mask_highres = double(poly2mask(pxX + pxShift(1), pxY + pxShift(2), 512.,
512.));
So you have coordinates pxX, and pxY in pixels with respect to the low-resolution image. You can transform these coordinates to real-world coordinates:
pxX_rw = pxX / 0.7757 - 164.424;
pxY_rw = pxY / 0.7757 - 194.462;
Next you can transform these coordinates to high-res coordinates:
pxX_hr = (pxX_rw - 94.3052) * 2.8444;
pxY_hr = (pxY_rw - 110.923) * 2.8444;
Since the original coordinates fit in the low-res image, but the high-res image is smaller (in physical coordinates) than the low-res one, it is possible that these new coordinates do not fit in the high-res image. If this is the case, cropping the polygon is a non-trivial exercise, it cannot be done by simply moving the vertices to be inside the field of view. MATLAB R2017b introduces the polyshape object type, which you can intersect:
bbox = polyshape([0 0 180 180] - 94.3052, [180 0 0 180] - 110.923);
poly = polyshape(pxX_rw, pxY_rw);
poly = intersect([poly bbox]);
pxX_rw = poly.Vertices(:,1);
pxY_rw = poly.Vertices(:,2);
If you have an earlier version of MATLAB, maybe the easiest solution is to make the field of view larger to draw the polygon, then crop the resulting image to the right size. But this does require some proper calculation to get it right.

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 change a pixel distance to meters?

I have a .bmp image with a map. What i know:
Height an Width of bmp image
dpi
Map Scale
Image Center's coordinates in meters.
What i want:
How can i calculate some points of image (for example corners) in meters.
Or how can i change a pixel distanse to meters?
What i do before:
For sure i know image center coordinates in pixels:
CenterXpix = Widht/2;
CenterYpix = Height/2;
But what i gonna do to find another corners coordinates. Don't think that:
metersDistance = pixelDistance*Scale;
is a correct equation.
Any advises?
If you know the height or width in both meters and pixels, you can calculate the scale in meters/pixel. You equation:
metersDistance = pixelDistance*Scale;
is correct, but only if your points are on the same axis. If your two points are diagonal from each other, you have to use good old pythagoras (in pseudocode):
X = XdistancePix*scale;
Y = YdistancePix*scale;
Distance_in_m = sqrt(X*X+Y*Y);