2010-03-17 40 views
13

Cách tốt nhất để vẽ một đường thẳng trên một hình ảnh đen trắng (nhị phân) trong MATLAB, với điều kiện các tọa độ bắt đầu và kết thúc đã được biết chưa?MATLAB: Vẽ một đường trên một ảnh đen trắng

Xin lưu ý, tôi không cố gắng thêm dòng chú thích. Tôi muốn dòng trở thành một phần của hình ảnh.

Trả lời

7

Bạn có thể muốn xem my answer cho câu hỏi SO về adding a line to an image matrix. Dưới đây là một ví dụ tương tự như tôi có trong câu trả lời đó, mà sẽ làm cho một dòng trắng chạy từ hàng và cột chỉ số (10, 10)-(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 

Và đây là hình ảnh kết quả:

enter image description here

+5

Điều này hoạt động hoàn hảo cho một đường chéo, nhưng có thể thêm các pixel không mong muốn cho một đường phẳng hơn. Nếu bạn không quan tâm đến các pixel bổ sung, tôi khuyên bạn nên chọn giải pháp gnovices vì ​​nó nhanh và đơn giản. – Jonas

+0

@ Jason: Tôi đã cập nhật thuật toán để tính toán dòng tốt hơn, loại bỏ một số pixel không cần thiết. – gnovice

+0

Cảm ơn bạn đã cải thiện câu trả lời của tôi! – Jonas

5

Nếu bạn bị làm phiền bởi các trường hợp ngoại lệ của các phương pháp khác, đây là phương pháp chống đạn dẫn đến một dòng:

  • có pixel luôn chạm vào nhau trong toàn bộ chiều dài của đường (pixel là 8 hàng xóm với nhau),
  • mật độ của đường là không phụ thuộc vào thông số bổ sung, nhưng được xác định linh hoạt từ điểm đầu tiên.

Đầu vào (thuận tiện cho việc làm cho chức năng ra của mã này):

  • img - ma trận có chứa hình ảnh,
  • x1, y1, x2, y2 - tọa độ của các điểm kết thúc của dòng được vẽ.

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; 

Dưới đây là hình ảnh ví dụ với ba dòng vẽ trên nó: enter image description here

+0

Sẽ tốt hơn cho phương pháp này để xử lý các điểm vượt trội. Tôi đã sử dụng một số mã giao cắt tia để tìm các giới hạn cho một dạng đường dốc của một đường thẳng. Nó được thực hiện trước khi gọi chức năng này nhưng nó có thể dễ dàng được kết hợp thay thế. – taranaki

+0

Vâng ... Xin lỗi. Tôi đã viết từ lâu rồi. Phải mất quá nhiều công sức để cải tiến ngay bây giờ, vì hiện tại tôi không có Matlab. – plesiv

+0

Nó thậm chí có thể nhanh hơn nếu bạn loại bỏ các cuộc gọi 'interp1', xem xét bình luận của bạn ở trên tôi đã đăng một câu trả lời mới. – saastn

0

Nó thực sự chỉ là một sự sửa đổi về câu trả lời của plesiv. Tôi đang vẽ hàng ngàn dòng trên một hình ảnh và tôi cần tăng hiệu suất. Cải tiến nhất được thực hiện bằng cách bỏ qua các cuộc gọi interp1 và sử dụng các biến số nguyên làm cho nó nhanh hơn một chút. Nó thực hiện nhanh hơn 18% trên PC của tôi so với mã của 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

Nếu bạn có Hộp công cụ hệ thống tầm nhìn máy tính, bạn có thể sử dụng insertShape.

+0

'insertShape' thực sự chậm và nó chỉ trả về hình ảnh ở định dạng RGB. – saastn

Các vấn đề liên quan