Find the orientation of each arbitrary object in an image
103 views (last 30 days)
I have an image like this? Does anybody have any idea how can I get the orientation of each object? I know that the objects are not suitable to assign any orientation but at least I learn how can I do that? Actually, I also want to remove some of the objects which have a strange shape.
Adam Danz on 18 Oct 2019
Edited: Adam Danz on 18 Oct 2019
I used this question to practice some of my image processing skills (still in early stages of exploration).
Here's what I did step-by-step to compute the orientation of each object and to compute the linear equation of the major axis of each object.
I downloaded the image and named it 'bwimage.png' (also attached, same image). The result is shown in a figure below where the major axis of each object is drawn through its center point (and extended a bit).
% Is the image binary?
info = imfinfo('bwimage.png'); %including the pull path is better
info.BitDepth %ans = 24; so it's not a binary image.
% Read image as RGB
I = imread('bwimage.png'); %including the pull path is better
% Convert RGB --> grayscale --> binary
BW = imbinarize(rgb2gray(I));
% Get rid of white border
BWConv = bwconvhull(~BW);
BW = BW & BWConv;
% Checkout the image to make sure the conversion made sense.
% Keep the figure because we'll add to it later
% Note the orientation of the y axis (reversed)
h = imshow(BW);
% Get the center coordinate for each object, it's orientation [-90:90 deg],
% and the lenght of its major axis (in pixels).
stats = regionprops('table',BW,'Centroid','MajorAxisLength','Orientation'
% How many objects were detected?
nObjects = size(stats,1); % = 74
% take a look at the results
head(stats) %first few objects
% Continuing with the figure created above, add the center points
ph1 = plot(stats.Centroid(:,1), stats.Centroid(:,2), 'rs');
% using orientation, compute slope and y-intercept of each major axis
% Note the reversal of the sign of the orientation! This is to account
% for the reversed y axis!
stats.Slope = atan(-stats.Orientation*pi/180);
% Compute y interceps
stats.Intercep = stats.Centroid(:,2) - stats.Slope.*stats.Centroid(:,1);
% Now that we've got the linear eq for each line, compute the bounds of each
% object along its major axis line. Add some extra length so we can see more of the lines.
% To use the exact major axis lenght, divide by 2 instead of 1.6 (both lines below)
stats.EndpointX = stats.Centroid(:,1) + [-1,1].* (stats.MajorAxisLength/1.6 .* sqrt(1./(1+stats.Slope.^2)));
stats.EndpointY = stats.Centroid(:,2) + [-1,1].* (stats.Slope .* stats.MajorAxisLength/1.6 .* sqrt(1./(1+stats.Slope.^2)));
% Plot major axis of each object that spans the length of the obj
mah = plot(stats.EndpointX.', stats.EndpointY.', 'r-')
The orientation of each object is stored in stats.Orientation. The slope and intercept of each major axis is stored in stats.Slope and stats.Intercept. The end points of each line segment draw is stored in stats.EndpointX/Y. And the center points of each object are stored in stats.Centroid.
More Answers (2)
Image Analyst on 18 Oct 2019
You can use regionprops to get shape info. One nice one is the circularity. If you want stick-like objects, you do
props = regionprops(binaryImage, 'Perimeter', 'Area', 'Orientation')
allAngles = [props.Orientation]; % Extract all orientation angles into one vector.
histogram(allAngles); % Show distribution of angles.
allAreas = [props.Area]; % Extract all areas into one vector.
allPerimeters = [props.Perimeter]; % Extract all perimeters into one vector.
circularities = allPerimeters .^ 2 ./ (4 * pi * allAreas);
Circular blobs will be close to 1 and tortuous-shaped blobs or stick-shaped blobs will have higher circularity values, like 5 or 10 or more.