MATLAB: Drawing a line over a black and white image

18,494

Solution 1

You may want to look at my answer to an SO question about adding a line to an image matrix. Here's a similar example to the one I have in that answer, which will make a white line running from row and column index (10, 10) to (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

And here's the resulting image:

enter image description here

Solution 2

If you are bothered by exceptional cases of other methods here's a bullet-proof method that results in a line:

  • whose pixels always touch each other during the whole length of the line (pixels are 8-neighbors to each other),
  • density of the line is not dependent on the additional parameter, but is determined flexibly to accommodate guarantee from the first point.

Inputs (convenient for making function out of this code):

  • img - matrix that contains image,
  • x1, y1, x2, y2 - coordinates of the end points of the line to be drawn.

Code:

% 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;

Here's the example image with three lines drawn on it: enter image description here

Solution 3

This algorithm offers one approach.

Solution 4

It actually is just a modification on plesiv's answer. I'm drawing thousands of lines over an image and I need to increase the performance. The most improvement made by omitting interp1 calls and using integer variables made it slightly faster. It performs about 18% faster on my PC comparing to plesiv's code.

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
Share:
18,494

Related videos on Youtube

Richard
Author by

Richard

Updated on April 16, 2022

Comments

  • Richard
    Richard about 2 years

    What is the best way to draw a line over a black and white (binary) image in MATLAB, provided the start and end coordinates are known?

    Please note, I am not trying to add an annotation line. I would like the line to become part of the image.

  • Jonas
    Jonas about 14 years
    This works perfectly for a diagonal line, but may add unwanted pixels for a flatter line. If you don't care about the additional pixels, I suggest choosing gnovices solution because it is fast and simple.
  • taranaki
    taranaki over 9 years
    It would be nice for this method to gracefully handle out-of-bounds points. I used some ray-intersection code to find the bounds given a point-slope form of a line. It's done before calling this function but it could easily be incorporated instead.
  • plesiv
    plesiv over 9 years
    Yeah... Sorry. I wrote this long time ago. It takes too much effort to make improvements now, since I don't have Matlab currently.
  • gnovice
    gnovice about 7 years
    @Jonas: I've updated the algorithm to compute the line better, which removes some unnecessary pixels.
  • Jonas
    Jonas about 7 years
    Thank you for improving my answer!
  • saastn
    saastn about 7 years
    insertShape is really slow and it only returns images in RGB format.
  • saastn
    saastn about 7 years
    It can be even faster if you remove interp1 calls, considering your comment above I posted a new answer.