Se avete la Image Processing Toolbox, c'è una funzione chiamata cornermetric
che può implementare un rilevatore di angolo Harris o il metodo autovalore minimo Shi e Tomasi di. Questa funzione è presente dalla versione 6.2 di Image Processing Toolbox (versione MATLAB R2008b).
Utilizzando questa funzione, ho trovato un approccio leggermente diverso dalle altre risposte. La soluzione di seguito si basa sull'idea che un'area circolare centrata su ciascun punto d'angolo "vero" si sovrapporrà al poligono di una quantità inferiore rispetto a un'area circolare centrata su un punto d'angolo errato che si trova effettivamente sul bordo. Questa soluzione può anche gestire casi in cui sono rilevati più punti nello stesso angolo ...
Il primo passo è quello di caricare i dati:
rawImage = imread('oxyjj.png');
rawImage = rgb2gray(rawImage(7:473, 9:688, :)); % Remove the gray border
subplot(2, 2, 1);
imshow(rawImage);
title('Raw image');
Avanti, calcolare l'angolo metriche utilizzando cornermetric
. Si noti che sto mascherando la metrica dell'angolo con il poligono originale, in modo che cerchiamo i punti d'angolo che sono all'interno del poligono (vale a dire cercando di trovare i pixel angolari del poligono). imregionalmax
viene quindi utilizzato per trovare i massimi locali. Dato che puoi avere cluster di più di 1 pixel con la stessa metrica angolare, aggiungo rumore ai massimi e ricalcolo in modo da ottenere solo 1 pixel in ciascuna regione massima.Ogni regione massima viene quindi all'etichetta bwlabel
:
cornerImage = cornermetric(rawImage).*(rawImage > 0);
maxImage = imregionalmax(cornerImage);
noise = rand(nnz(maxImage), 1);
cornerImage(maxImage) = cornerImage(maxImage)+noise;
maxImage = imregionalmax(cornerImage);
labeledImage = bwlabel(maxImage);
Le regioni marcate vengono quindi dilatate (usando imdilate
) con un elemento discoidale strutturazione (creati utilizzando strel
):
diskSize = 5;
dilatedImage = imdilate(labeledImage, strel('disk', diskSize));
subplot(2, 2, 2);
imshow(dilatedImage);
title('Dilated corner points');
Ora che l'etichetta le regioni d'angolo sono state dilatate, si sovrappongono parzialmente al poligono originale. Le regioni su un lato del poligono avranno una sovrapposizione di circa il 50%, mentre le regioni che si trovano su un angolo avranno una sovrapposizione di circa il 25%. La funzione regionprops
può essere utilizzata per trovare le aree di sovrapposizione per ogni regione etichettata, e le 4 regioni che hanno la minor quantità di sovrapposizione può quindi essere considerato come i veri angoli:
maskImage = dilatedImage.*(rawImage > 0); % Overlap with the polygon
stats = regionprops(maskImage, 'Area'); % Compute the areas
[sortedValues, index] = sort([stats.Area]); % Sort in ascending order
cornerLabels = index(1:4); % The 4 smallest region labels
maskImage = ismember(maskImage, cornerLabels); % Mask of the 4 smallest regions
subplot(2, 2, 3);
imshow(maskImage);
title('Regions of minimal overlap');
E ora siamo in grado di ottenere il coordinate pixel degli angoli utilizzando find
e ismember
:
[r, c] = find(ismember(labeledImage, cornerLabels));
subplot(2, 2, 4);
imshow(rawImage);
hold on;
plot(c, r, 'r+', 'MarkerSize', 16, 'LineWidth', 2);
title('Corner points');
ed ecco una prova con una regione a forma di diamante:
0.123.
Ho appena realizzato che si dispone già di un'immagine binaria BW. Pertanto, puoi saltare direttamente alla parte di ottenere i limiti iniziando con la chiamata a ** bwboundaries ** – Amro
+1 - per la firma del confine. Ma ci sono alcune preoccupazioni che ho dettagliato nel post modificato. – Jacob
si prega di consultare la mia modifica sopra. – Amro