2010-03-17 10 views
13

¿Cuál es la mejor manera de trazar una línea sobre una imagen en blanco y negro (binaria) en MATLAB, siempre que se conozcan las coordenadas de inicio y fin?MATLAB: Dibujando una línea sobre una imagen en blanco y negro

Tenga en cuenta que no estoy tratando de agregar una línea de anotación. Me gustaría que la línea se convierta en parte de la imagen.

Respuesta

7

Es posible que desee mirar my answer a una pregunta sobre SO sobre adding a line to an image matrix. Aquí está un ejemplo similar a la que tengo en esa respuesta, lo que hará que una línea blanca que se ejecuta desde la fila y la columna de índice (10, 10) a (240, 120):

img = imread('cameraman.tif'); % Load a sample black and white image 
x = [10 240];     % x coordinates 
y = [10 120];     % y coordinates 
nPoints = max(abs(diff(x)), abs(diff(y)))+1; % Number of points in line 
rIndex = round(linspace(y(1), y(2), nPoints)); % Row indices 
cIndex = round(linspace(x(1), x(2), nPoints)); % Column indices 
index = sub2ind(size(img), rIndex, cIndex);  % Linear indices 
img(index) = 255; % Set the line points to white 
imshow(img);  % Display the image 

Y aquí está la imagen resultante:

enter image description here

+5

Esto funciona perfectamente para una línea diagonal, pero puede agregar píxeles no deseados para una línea más plana. Si no te importan los píxeles adicionales, te sugiero que elijas la solución de gnovices porque es rápida y sencilla. – Jonas

+0

@Jonas: He actualizado el algoritmo para calcular mejor la línea, lo que elimina algunos píxeles innecesarios. – gnovice

+0

¡Gracias por mejorar mi respuesta! – Jonas

5

Si le molestan casos excepcionales de otros métodos, aquí hay un método a prueba de balas que da como resultado una línea:

  • cuyos pixeles siempre se tocan durante toda la longitud de la línea (píxeles son 8-vecinos entre sí),
  • densidad de la línea es no depende de la parámetro adicional, pero se determina de manera flexible para dar cabida a garantía desde el primer punto

Entradas (conveniente para hacer la función de este código):

  • img - matriz que contiene la imagen,
  • x1, y1, x2, y2 - coordenadas de los puntos extremos de la línea que se dibujará.

Código:

% distances according to both axes 
xn = abs(x2-x1); 
yn = abs(y2-y1); 

% interpolate against axis with greater distance between points; 
% this guarantees statement in the under the first point! 
if (xn > yn) 
    xc = x1 : sign(x2-x1) : x2; 
    yc = round(interp1([x1 x2], [y1 y2], xc, 'linear')); 
else 
    yc = y1 : sign(y2-y1) : y2; 
    xc = round(interp1([y1 y2], [x1 x2], yc, 'linear')); 
end 

% 2-D indexes of line are saved in (xc, yc), and 
% 1-D indexes are calculated here: 
ind = sub2ind(size(img), yc, xc); 

% draw line on the image (change value of '255' to one that you need) 
img(ind) = 255; 

Aquí está la imagen de ejemplo con tres líneas dibujadas en él: enter image description here

+0

Sería bueno que este método manejara con gracia los puntos fuera de límites. Usé un código de intersección de rayos para encontrar los límites dados una forma de pendiente de punto de una línea. Está hecho antes de llamar a esta función, pero podría incorporarse fácilmente en su lugar. – taranaki

+0

Sí ... Lo siento. Escribí esto hace mucho tiempo. Se necesita demasiado esfuerzo para hacer mejoras ahora, ya que actualmente no tengo Matlab. – plesiv

+0

Puede ser aún más rápido si elimina llamadas 'interp1', teniendo en cuenta su comentario anterior, publiqué una nueva respuesta. – saastn

0

lo que realmente es simplemente una modificación sobre la respuesta de plesiv. Estoy dibujando miles de líneas sobre una imagen y necesito aumentar el rendimiento. La mayor mejora realizada al omitir las llamadas interp1 y el uso de variables enteras lo hizo un poco más rápido. Se realiza aproximadamente un 18% más rápido en mi PC en comparación con el código de Plesiv.

function img = drawLine(img, x1, y1, x2, y2) 
x1=int16(x1); x2=int16(x2); y1=int16(y1); y2=int16(y2); 
% distances according to both axes 
xn = double(x2-x1); 
yn = double(y2-y1); 

% interpolate against axis with greater distance between points; 
% this guarantees statement in the under the first point! 
if (abs(xn) > abs(yn)) 
    xc = x1 : sign(xn) : x2; 
    if yn==0 
     yc = y1+zeros(1, abs(xn)+1, 'int16'); 
    else 
    yc = int16(double(y1):abs(yn/xn)*sign(yn):double(y2)); 
    end 
else 
    yc = y1 : sign(yn) : y2; 
    if xn==0 
     xc = x1+zeros(1, abs(yn)+1, 'int16'); 
    else 
    xc = int16(double(x1):abs(xn/yn)*sign(xn):double(x2)); 
    end 
end 

% 2-D indexes of line are saved in (xc, yc), and 
% 1-D indexes are calculated here: 
ind = sub2ind(size(img), yc, xc); 

% draw line on the image (change value of '255' to one that you need) 
img(ind) = 255; 
end 
0

Si usted tiene la Visión por Computador System Toolbox, puede utilizar insertShape.

+0

'insertShape' es realmente lento y solo devuelve imágenes en formato RGB. – saastn

Cuestiones relacionadas