identifying shapes in image
Ältere Kommentare anzeigen
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

Antworten (2)
See this FEX download,
load Image;
pgons=bwlpolyshape(~BW, Visualize=true);
shapes=arrayfun(@classify,pgons(:))
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
Image Analyst
vor etwa 2 Stunden
0 Stimmen
Yeah, of course. You can't use things like aspect ratio, area, etc. to classify shapes. Aspect ratio of a rectangle will change as you rotate it. And the shapes, in general, could be of any size and you need to account for that unless you know for a fact that all your test shapes will have the same orientation and size and only the location could be different.
A more robust way to detect simple shapes like yours is to count the number of vertices. See my attached demos.
Kategorien
Mehr zu Image Data Workflows finden Sie in Hilfe-Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
