identifying shapes in image

Any help with identifying the shapes in this image. they are incorrectly identified due to their rotaion. this code works great on identifying shapes in other pictures but this one it fails.
%% ========================================================================
% IMAGE PREPROCESSING + WATERSHED SEGMENTATION + RBC SHAPE CLASSIFICATION
% ========================================================================
% --- Select Image ---
[filename, pathname] = uigetfile( ...
{'*.jpg;*.jpeg;*.png;*.tif;*.tiff;*.bmp;*.gif', ...
'Image Files (*.jpg, *.jpeg, *.png, *.tif, *.tiff, *.bmp, *.gif)'; ...
'*.*','All Files (*.*)'}, ...
'Select an image');
if isequal(filename,0)
disp('No file selected.');
return;
end
imgPath = fullfile(pathname, filename);
img = imread(imgPath);
% Detect grayscale or RGB
isGray = is_image_grayscale(img);
figure('Name', filename, 'NumberTitle', 'off');
%% ========================================================================
% PATH A — GRAYSCALE IMAGE
% ========================================================================
if isGray
% Original
subplot(3,2,1); imshow(img); title('Loaded (Grayscale)');
% Ensure grayscale
GRAY = im2gray(img);
subplot(3,2,2); imshow(GRAY); title('Grayscale Image');
% Dilation (line)
se_line = strel("line",10,0);
dil1 = imdilate(GRAY, se_line);
subplot(3,2,3); imshow(dil1); title('1st Dilation');
% Dilation (disk)
se_disk2 = strel("disk",2);
dil2 = imdilate(dil1, se_disk2);
subplot(3,2,4); imshow(dil2); title('2nd Dilation');
% Erode
se_disk1 = strel("disk",1);
erode = imerode(dil2, se_disk1);
subplot(3,2,5); imshow(erode); title('Erosion');
% Binary
BW = imbinarize(erode, 25/255);
subplot(3,2,6); imshow(BW); title('Binary (Threshold 25)');
pause(2);
% Invert
BW_inv = ~BW;
subplot(3,2,6); imshow(BW_inv); title('Inverted Binary');
% ------------------ Watershed ------------------
figure;
D = -bwdist(BW);
subplot(3,2,1); imshow(D, []); title('Distance Transform');
mask = imextendedmin(D,2);
D2 = imimposemin(D,mask);
L = watershed(D2);
L(BW) = 0;
subplot(3,2,2); imshow(label2rgb(L,'jet','w','shuffle'));
title('Watershed Segmentation');
subplot(3,2,3); imshow(label2rgb(L,'jet',[0.5 0.5 0.5]));
title('Watershed Transform');
%% ========================================================================
% PATH B — RGB IMAGE
% ========================================================================
else
subplot(3,2,1); imshow(img); title('Loaded (Colour)');
% HSV saturation adjustment
HSV = rgb2hsv(img);
S = HSV(:,:,2);
gamma = 3;
S_tweaked = S.^gamma;
subplot(3,2,2); imshow(S_tweaked, []); title('Saturation (Gamma=3)');
% Convert to grayscale
GRAY = im2gray(S_tweaked);
subplot(3,2,3); imshow(GRAY); title('Grayscale');
% Morphological closing
se_close = strel("disk",10);
close_img = imclose(GRAY, se_close);
subplot(3,2,4); imshow(close_img); title('Close');
% Opening
se_open = strel("disk",3);
open_img = imopen(close_img, se_open);
subplot(3,2,5); imshow(open_img); title('Open');
% Binary image
BW = imbinarize(open_img);
subplot(3,2,6); imshow(BW); title('Binary');
pause(2);
BW_inv = ~BW;
subplot(3,2,6); imshow(BW_inv); title('Inverted Binary');
% ------------------ Watershed ------------------
figure;
D = -bwdist(~BW);
subplot(3,2,1); imshow(D,[]); title('Distance Transform');
mask = imextendedmin(D,2);
D2 = imimposemin(D,mask);
L = watershed(D2);
L(~BW) = 0;
subplot(3,2,2); imshow(label2rgb(L,'jet','w','shuffle'));
title('Watershed Segmentation');
subplot(3,2,3); imshow(label2rgb(L,'jet',[0.5 0.5 0.5]));
title('Watershed Transform');
end
%% ========================================================================
% SHAPE CLASSIFICATION (CIRCLE / TRIANGLE / SQUARE / RECTANGLE)
% ========================================================================
figure; imshow(img); hold on;
labels = unique(L);
labels(labels==0) = []; % remove background
for k = 1:length(labels)
regionMask = (L == labels(k));
% Stats
stats = regionprops(regionMask,'Area','Perimeter','BoundingBox','Centroid');
A = stats.Area;
P = stats.Perimeter;
BB = stats.BoundingBox;
C = stats.Centroid;
% RBC classification
shape = classifyPrimitive(A, P, BB);
% Put label on image
text(C(1), C(2), shape, ...
'Color', 'white', ...
'FontSize', 12, ...
'FontWeight', 'bold', ...
'HorizontalAlignment', 'center');
end
hold off;
%% ========================================================================
% FUNCTIONS
% ========================================================================
function tf = is_image_grayscale(I)
if ndims(I)==2
tf = true;
elseif ndims(I)==3 && size(I,3)==3
tf = isequal(I(:,:,1),I(:,:,2)) && isequal(I(:,:,1),I(:,:,3));
else
tf = false;
end
end
% --- RBC Primitive Classifier ---
function label = classifyPrimitive(area, perimeter, bbox)
w = bbox(3);
h = bbox(4);
%% Circle metric from RBC paper (should be ~1)
circle_metric = (perimeter^2) / (4*pi*area);
if abs(circle_metric - 1) < 0.158
label = 'Circle';
return;
end
%% Triangle metric: area approx half bounding box
bbox_area = w*h;
area_ratio = area / bbox_area;
if area_ratio > 0.30 && area_ratio < 0.65
label = 'Triangle';
return;
end
%% Square vs Rectangle
aspect_ratio = w/h;
if abs(aspect_ratio - 1) < 0.60
label = 'Square';
else
label = 'Rectangle';
end

Respuestas (1)

Matt J
Matt J hace alrededor de 13 horas
Editada: Matt J hace alrededor de 13 horas
See this FEX download,
load Image;
pgons=bwlpolyshape(~BW, Visualize=true);
shapes=arrayfun(@classify,pgons(:))
shapes = 8×1 string array
"Square" "Triangle" "Rectangle" "Rectangle" "Circle" "Square" "Triangle" "Square"
function shape=classify(pgon)
Lengths=vecnorm(diff(pgon.Vertices([end,1:end],:)),2,2); %Side lengths
Lengths(Lengths<max(Lengths)/20)=[]; %Tolerance on shortest side length
N=numel(Lengths); %Number of sides (after tolerance)
if N==3
shape="Triangle";
elseif N==4
shape="Rectangle";
if max(Lengths)-min(Lengths)<3 %Tolerance on side length equality
shape="Square";
end
elseif N>10
shape="Circle";
end
[cx,cy]=centroid(pgon);
drawpoint(Position=[cx,cy],Label=shape,LabelText="white");
end

2 comentarios

Daniel
Daniel hace 14 minutos
im having trouble getting the bwlpolyshape to work, did you just add the downloaded code to the image toolbox codes in here C:\Program Files\MATLAB\R2025b\toolbox\images\images
Matt J
Matt J hace 10 minutos
It should work if its anywhere on your Matlab path, but I wouldn't recommend adding things to built-in toolbox folders.

Iniciar sesión para comentar.

Categorías

Etiquetas

Preguntada:

hace alrededor de 17 horas

Comentada:

hace 10 minutos

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by