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

Risposte (1)

Matt J
Matt J circa 6 ore fa
Modificato: Matt J circa 6 ore fa
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

Categorie

Richiesto:

circa 15 ore fa

Modificato:

circa 11 ore fa

Community Treasure Hunt

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

Start Hunting!

Translated by