2011-10-24 36 views

Trả lời

6

Dưới đây là một thuật toán có sử dụng các distance transform cùng với các thuật toán watershed để vẽ một sơ đồ Voronoi cho elip.

%# first, define some ellipses (for simplicity, I use 0/90 orientation) 
ellipses = [10,20,5,10;30,10,10,7;40,40,8,3]; 

%# put the ellipses into an image (few pixels, therefore pixelated) 
img = false(50); 
[xx,yy]=ndgrid(1:50,1:50); 
for e = 1:size(ellipses,1),img = img | (xx-ellipses(e,1)).^2/ellipses(e,3)^2 + (yy-ellipses(e,2)).^2/ellipses(e,4)^2 <= 1;end 

enter image description here

%# perform the distance transform 
dt = bwdist(img); 

enter image description here

%# apply the watershed algorithm. 
%# ws==0 are the lines for the Voronoi diagram 
ws = watershed(dt); 

%# create a RGB image and display 
%# note: for yellow lines, replace the last 
%# "ws==0" by "zeros(size(ws))", so that you 
%# only put ws into the red and green channel (=yellow) 
rgb = cat(3,ws==0,ws==0,ws==0)); 
%# add the ellipses into the red channel 
rgb(:,:,1) = rgb(:,:,1) | img; 
imshow(rgb) 

enter image description here

+0

Tôi có thể làm gì với các mã để kiểm soát màu của đường kẻ và hình elip? – Elsie

+0

@Ivy: 'rgb = repmat (ws == 0,1,1,3); rgb (:,:, 1) = rgb (:,:, 1) | img; imshow (rgb) ' – Jonas

+0

Làm cách nào để hiển thị cả hình elip và đường cùng một lúc trong hình ảnh? Bởi vì tôi imshow (dt), chỉ hiển thị dấu ba chấm, nếu tôi imshow (ws), chỉ dòng. và tôi đã thử rgb, đã có một lỗi cho 'repmat': quá nhiều đối số đầu vào. Tôi có thể làm gì? – Elsie

0

Tôi không biết ý bạn là gì với "dấu ba chấm" ở đây. Nhưng có một thực hiện cho sơ đồ Voronoi của trong C++ bởi Stephan tạp chí Fortune/Shane O'Sullivan,

http://www.skynet.ie/~sos/mapviewer/voronoi.php

+0

Ellipses diễn ra trong những 'điểm' (x, y) được bao quanh bởi các dòng. – Elsie

2

Chỉ trong trường hợp, đây là một ví dụ từ Mathematica hệ thống trợ giúp:

(*Generate ellipses*) 
p= [email protected]@Table[ 
      Rotate[ 
       Disk[RandomReal[10, 2],   (*Rnd position*) 
        RandomReal[{.3, 1.5}, 2]], (*Rnd radii*) 
      RandomReal[Pi]], {i, 10}]   (*Rnd rotation*) 

(*Compute Voronoi*) 

LaplacianGaussianFilter[DistanceTransform[p], 2] // ImageAdjust 

enter image description here

Nó không phải là một tính toán chính xác, nhưng đủ công bằng cho các mục đích thực tế.

1

Dựa trên các câu hỏi gần đây của bạn, tôi hiểu rằng bạn đã làm việc để vẽ các hình elip có kích thước rasterized hình elip trên đầu hình ảnh RGB. Bạn muốn có thể chỉ định vị trí, hình dạng và màu sắc của hình elip. Bạn muốn các dấu ba chấm là clipped ở ranh giới và cũng có thể là non-overlapping. Bây giờ bạn đang tìm cách vẽ các đường phân chia không gian theo cách tương tự như sơ đồ Voronoi (nhưng với các dấu ba chấm thay vì các điểm).

Đối với câu hỏi cụ thể này, như @Jonas cho thấy, giải pháp là sử dụng phép biến đổi khoảng cách cùng với thuật toán lưu vực.

Tôi nghĩ rằng tôi tiếp tục với ví dụ trước của mình và mở rộng nó với ý tưởng của Jonas, để giới thiệu toàn bộ quá trình. Hy vọng bạn sẽ thấy nó hữu ích ..

Mã sử ​​dụng chức năng calculateEllipse để tính toán tọa độ của các điểm tạo thành hình elip, cũng như chức năng đặt các pixel được chỉ định của hình ảnh cho một số màu được chọn.

%# color image (canvas to draw on) 
I = imread('pears.png'); 
sz = size(I); 

%# random ellipses 
num = 20; 
centers = bsxfun(@times, rand(num,2), sz([2 1])); %# center x/y-coords 
radii = bsxfun(@times, rand(num,2), [300 50])+10; %# major/minor axis length 
angles = rand(num,1) .* 360;      %# angle of rotation 
ex = cell(num,1);         %# vertices x-coords 
ey = cell(num,1);         %# vertices y-coords 

%# label image, used to hold rasterized ellipses 
L = zeros(sz(1),sz(2)); 

%# randomly place ellipses one-at-a-time, skip if overlaps previous ones 
flag = false(num,1); 
for i=1:num 
    %# ellipse we would like to draw directly on image matrix 
    [ex{i},ey{i}] = calculateEllipse(centers(i,1),centers(i,2), ... 
     radii(i,1),radii(i,2), angles(i), 100); 

    %# create mask for image pixels inside the ellipse polygon 
    mask = poly2mask(ex{i},ey{i}, sz(1),sz(2)); 

    %# check if there is no existing overlapping ellipse 
    if all(L(mask)==0) 
     %# use the mask to place the ellipse in the label image 
     L(mask) = sum(flag)+1; %# assign value using an increasing counter 
     flag(i) = true; 
    end 
end 

%# filter ellipses to only those that made through the overlap test 
num = sum(flag); 
centers = centers(flag,:); 
radii = radii(flag,:); 
angles = angles(flag); 
ex = ex(flag); 
ey = ey(flag); 

%# rasterized voroni diagram of the ellipses [Jonas] 
E = (L ~= 0);        %# ellipses as binary image 
WS = watershed(bwdist(E));    %# distance transform + watershed 
WS = (WS == 0);       %# WS==0 corresponds voronoi diagram 
WS = bwmorph(WS, 'thicken',1);   %# thicken the lines 

%# set pixels corresponding to voronoi diagram to white 
II = I; 
II = imoverlay(II, WS, [1 1 1]);   %# you can customize the color here 

%# set pixels corresponding to ellipses using specified colors 
clr = hsv(num);       %# color of each ellipse 
for i=1:num 
    mask = bwperim(L==i,8);    %# get perimeter of the ellipse mask 
    mask = bwmorph(mask, 'thicken',1); %# thicken the ellipse perimeter 
    II = imoverlay(II, mask, clr(i,:)); %# set those pixels with RGB color 
end 

%# show final rasterized image (image + ellipses + voronoi diagram) 
figure, imshow(II, 'InitialMagnification',100, 'Border','tight') 

screenshot

+0

Tôi đã cố gắng vẽ hình elip rắn, vì vậy tôi lấy ra dòng 'mask = bwperim (L == i, 8);' để lấy chu vi hình elip, nhưng đầu ra xuất hiện với một hình elip chỉ có hình elip rắn. Tại sao điều này lại xảy ra? Có một số loại lỗi hợp lý không? – Elsie

+0

@Ivy: nếu bạn muốn vẽ hình elip cứng, bạn cũng nên xóa đường thẳng ngay sau nó (làm dày chu vi), do đó bạn chỉ có: 'mask = (L == i);' – Amro

+0

Có, sau khi xóa hai dòng, thay đổi 'II = imoverlay (II, mặt nạ, clr (i, :));' thành 'II = imoverlay (II, L, clr (i, :));' cũng sẽ hoạt động. Nhân tiện, nếu tôi là 'I = số không' (500,500,3) ', làm thế nào để thay đổi màu nền từ màu đen sang (giả sử) cyan [1 0 1]? Tôi có cần phải áp dụng các imoverlay một lần nữa? hoặc có một cách nhanh chóng? – Elsie

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