web-dev-qa-db-fra.com

Comment dessiner un cercle sur une image dans MATLAB?

J'ai une image dans MATLAB:

im = rgb2gray(imread('some_image.jpg');
% normalize the image to be between 0 and 1
im = im/max(max(im));

Et j’ai effectué certains traitements qui ont abouti à un certain nombre de points que je souhaite souligner:

points = some_processing(im);

points est une matrice de la même taille que im avec les uns dans les points intéressants.

Maintenant, je veux tracer un cercle sur l'image à tous les endroits où points est 1.

Y at-il une fonction dans MATLAB qui fait cela? Le mieux que je puisse trouver est:

[x_p, y_p] = find (points);

[x, y] = meshgrid(1:size(im,1), 1:size(im,2))
r = 5;

circles = zeros(size(im));

for k = 1:length(x_p)
    circles = circles + (floor((x - x_p(k)).^2 + (y - y_p(k)).^2) == r);
end

% normalize circles
circles = circles/max(max(circles));

output = im + circles;

imshow(output)

Cela semble plus qu'un peu inélégant. Existe-t-il un moyen de dessiner des cercles similaires à la fonction line?

11
Nathan Fellman

Vous pouvez utiliser la commande normale PLOT avec un marqueur circular :

[x_p,y_p] = find(points);
imshow(im);         %# Display your image
hold on;            %# Add subsequent plots to the image
plot(y_p,x_p,'o');  %# NOTE: x_p and y_p are switched (see note below)!
hold off;           %# Any subsequent plotting will overwrite the image!

Vous pouvez également ajuster ces autres propriétés du marqueur de tracé: MarkerEdgeColor , MarkerFaceColor , MarkerSize .

Si vous voulez ensuite enregistrer la nouvelle image avec les marqueurs tracés dessus, vous pouvez regarder cette réponse que j'ai donnée à une question sur le maintien des dimensions de l'image lors de l'enregistrement d'images à partir de figures.

REMARQUE: Lors du traçage de données d'image avec IMSHOW (ou IMAGE , etc.), l'interprétation normale des lignes et des colonnes est essentiellement inversée. Normalement, la première dimension des données (c’est-à-dire les rangées) est considérée comme celle qui se trouverait sur l’axe des x. C’est probablement pourquoi vous utilisez x_p comme premier ensemble de valeurs renvoyées par la fonction FIND . Cependant, IMSHOW affiche la première dimension des données d'image le long de axe des ordonnées, de sorte que la première valeur renvoyée par FIND finit par être la valeur de la coordonnée y dans ce cas.

20
gnovice

Ce fichier par Zhenhai Wang de File Exchange de Matlab Central fait l'affaire. 

%----------------------------------------------------------------
% H=CIRCLE(CENTER,RADIUS,NOP,STYLE)
% This routine draws a circle with center defined as
% a vector CENTER, radius as a scaler RADIS. NOP is 
% the number of points on the circle. As to STYLE,
% use it the same way as you use the rountine PLOT.
% Since the handle of the object is returned, you
% use routine SET to get the best result.
%
%   Usage Examples,
%
%   circle([1,3],3,1000,':'); 
%   circle([2,4],2,1000,'--');
%
%   Zhenhai Wang <[email protected]>
%   Version 1.00
%   December, 2002
%----------------------------------------------------------------
2
Nathan Fellman

Marrant! Il y a 6 réponses ici, aucune n'indique la solution évidente: la fonction rectangle.

De la documentation :

Tracez un cercle en définissant la propriété Curvature sur [1 1]. Tracez le cercle de manière à ce qu'il remplisse la zone rectangulaire entre les points (2,4) et (4,6). La propriété Position définit le plus petit rectangle contenant le cercle.

pos = [2 4 2 2];
rectangle('Position',pos,'Curvature',[1 1])
axis equal

Donc dans votre cas:

imshow(im)
hold on
[y, x] = find(points);
for ii=1:length(x)
  pos = [x(ii),y(ii)];
  pos = [pos-0.5,1,1];
  rectangle('position',pos,'curvature',[1 1])
end

Contrairement à la réponse acceptée, ces cercles s’adapteront à l’image, vous pourrez zoomer et marquer toujours le pixel entier. 

1
Cris Luengo

Avec MATLAB et Image Processing Toolbox R2012a ou une version plus récente, vous pouvez utiliser la fonction viscircles pour superposer facilement des cercles sur une image. Voici un exemple:

% Plot 5 circles at random locations
X = Rand(5,1);
Y = Rand(5,1);
% Keep the radius 0.1 for all of them
R = 0.1*ones(5,1);
% Make them blue
viscircles([X,Y],R,'EdgeColor','b');

Découvrez également la fonction imfindcircles qui implémente la transformation circulaire de Hough. La documentation en ligne des deux fonctions (liens ci-dessus) contient des exemples montrant comment trouver des cercles dans une image et comment afficher les cercles détectés sur l'image.

Par exemple:

% Read the image into the workspace and display it.
A = imread('coins.png');
imshow(A)

% Find all the circles with radius r such that 15 ≤ r ≤ 30.
[centers, radii, metric] = imfindcircles(A,[15 30]);

% Retain the five strongest circles according to the metric values.
centersStrong5 = centers(1:5,:);
radiiStrong5 = radii(1:5);
metricStrong5 = metric(1:5);

% Draw the five strongest circle perimeters.
viscircles(centersStrong5, radiiStrong5,'EdgeColor','b');
0

Dans les versions plus récentes de MATLAB (j'ai 2013b), la boîte à outils System Vision de Computer Vision contient le vision.ShapeInserter Objet système qui peut être utilisé pour dessiner des formes sur des images. Voici un exemple de dessin de cercles jaunes à partir de la documentation:

yellow = uint8([255 255 0]); %// [R G B]; class of yellow must match class of I
shapeInserter = vision.ShapeInserter('Shape','Circles','BorderColor','Custom','CustomBorderColor',yellow);
I = imread('cameraman.tif'); 
circles = int32([30 30 20; 80 80 25]); %// [x1 y1 radius1;x2 y2 radius2]
RGB = repmat(I,[1,1,3]); %// convert I to an RGB image
J = step(shapeInserter, RGB, circles);
imshow(J);
0
buzjwa

Hmm je devais les changer à nouveau dans cet appel:

k = convhull(x,y);
figure;
imshow(image);         %# Display your image
hold on;            %# Add subsequent plots to the image
plot(x,y,'o');  %# NOTE: x_p and y_p are switched (see note below)!
hold off;           %# Any subsequent plotting will overwrite the image!

En réponse aux commentaires:

x et y sont créés à l'aide du code suivant:

temp_hull = stats_single_object (k) .ConvexHull; 
 pour k2 = 1: longueur (temp_hull) 
 i = i + 1; 
 [x (i, 1)] = temp_hull ( k2,1); 
 [y (i, 1)] = temp_hull (k2,2); 
 fin;

il se peut que le ConvexHull soit l'inverse et donc que l'intrigue soit différente. Ou que j'ai commis une erreur et qu'elle devrait être

[x (i, 1)] = temp_hull (k2,2); 
 [y (i, 1)] = temp_hull (k2,1);

Cependant, la documentation ne précise pas quelle colonne = x OR y: Citation: "Chaque ligne de la matrice contient les coordonnées x et y d'un sommet du polygone."

Je lis ceci comme x est la première colonne et y est la deuxième colonne.

0
Ramon Fincken