Matlab: как избежать наложения эллипсов в изображении? - PullRequest
1 голос
/ 20 октября 2011

Я использовал файл функции [ret]=drawellipse(x,y,a,b,angle,steps,color,img). Вызов функции через файл сценария для рисования случайных эллипсов в изображении. Но как только я установил случайную центральную точку (x, y) и случайные a, b, есть большая вероятность того, что пересечение эллипсов произойдет. Как я могу предотвратить пересечение? (Я должен нарисовать эллипсы, которые все отделены друг от друга) Ну, здесь у меня есть файл функции, который должен проверить, перекрываются ли эллипсы или нет, overlap = overlap_ellipses(x0,y0,a0,b0,angle0,x1,y1,a1,b1,angle1). Если два эллипса перекрываются, тогда «перекрытие = 1», в противном случае «перекрытие = 0». Основываясь на всем этом, я протестировал в командном окне:

x=rand(4,1)*400;  % x and y are the random coodinates for the center of ellipses
y=rand(4,1)*400;
a=[50 69 30 60];  % major axis   for a and b, i intend to use random also in the future
b=[20 40 10 40];  % minor axis
angle=[30 90 45 0]; % angle of ellipse
steps=10000;
color=[255 0 0];   % inputs for another function file to draw the ellipse
img=zeros(500,500,3);

Далее я хочу отобразить эллипсы if overlap==0 и, если перекрываются == 1, уменьшать a и b, пока не будет пересечения. И наконец, чтобы показать IMG.

for i=1:length(x)
img=drawellipse(x(i),y(i),a(i),b(i),angle(i),steps,color,img);
end

Теперь у меня есть трудности с кодированием средней части. Как я могу использовать оператор if, чтобы получить значение overlap и как сделать индекс, соответствующий эллипсу, который мне нужно нарисовать.

я тестировал немного как

for k=1:(length(x)-1)
overlap = overlap_ellipses(x(1),y(1),a(1),b(1),angle(1),x(1+k),y(1+k),a(1+k),b(1+k),angle(1+k))
end

возвращает

overlap=0
overlap=0
overlap=1

это не [0 0 1]. Я не могу понять это, таким образом, застрял в процессе. Окончательное изображение должно выглядеть так, как показано на этой диаграмме эллипсов вороной . (Нет пересечения между любыми двумя эллипсами)

Ответы [ 3 ]

3 голосов
/ 20 октября 2011

Предполагая, что вы рисуете эллипсы в растровом графическом изображении, вы можете рассчитать пиксели, которые вы должны будете нарисовать для эллипса, проверить, все ли эти пиксели в изображении по-прежнему имеют цвет фона, и нарисовать эллипс, только если ответ - да, в противном случае отклоните его (потому что что-то другое, то есть другой эллипс, мешает) и попробуйте другие x, y, a и b.

В качестве альтернативы, вы можете разбить изображение на прямоугольники (необязательно одинакового размера) и поместить один эллипс в каждый из них, выбрав x, y, a, b так, чтобы ни один эллипс не превышал его прямоугольник - тогда эллипсы не могут перекрываться либо , но это зависит от того, сколько "случайности" должно иметь ваше размещение эллипса, достаточно ли этого.

Математически строгим способом было бы хранить x, y, a, b каждого нарисованного эллипса и для каждого нового эллипса делать попарные проверки с каждым из них, имеют ли они общие точки, решая систему из двух квадратных уравнений. Однако это может быть немного сложным, особенно если угол не равен 0.

Редактировать в ответ на добавленный код : Вместо того, чтобы фиксировать все x и y перед циклом, вы можете определить их внутри цикла. Так как вы знаете, сколько эллипсов вы хотите, но не столько, сколько вам нужно для выборки, вам необходим цикл while. Тестовый цикл, который вы даете, может пригодиться, но вам нужно сравнить все предыдущие эллипсы с тем, который был создан в итерации цикла, а не с первым.

i=1;
while (i<=4) %# or length(a), or, more elegantly, some pre-defined max
    x(i) = rand*400; y(i) = rand*400; %# or take x and y as givren and decrease a and b
    %# now, check overlap for given center
    overlap = false;
    for k=1:(i-1)
       overlap = overlap || overlap_ellipses(x(i),y(i),a(i),b(i),angle(i),x(k),y(k),a(k),b(k),angle(k))
    end
    if (~overlap)
        img = drawellipse(x(i),y(i),a(i),b(i),angle(i),steps,color,img);
        i = i+1; %# determine next ellipse
    end %# else x(i) and y(i) will be overwritten in next while loop iteration
end

Конечно, если фиксированы a и b, может случиться так, что ни один эллипс не будет соответствовать размерам изображения, если, к сожалению, уже размещены уже существующие, что приведет к бесконечному циклу. Что касается вашего плана оставить центр неподвижным и уменьшать размер эллипса до тех пор, пока он не будет соответствовать: откуда взялся ваш метод overlap_ellipses? Может быть, его можно адаптировать, чтобы он возвращал коэффициент, на который один эллипс нужно сжать, чтобы он соответствовал другому (и 1, если он уже подходит)?

1 голос
/ 26 октября 2011

Решение, предложенное @arne.b (первым), является хорошим способом растеризации непересекающихся эллипсов.

Позвольте мне проиллюстрировать эту идею на примере.Я буду расширять свой предыдущий ответ :

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

%# parameters of ellipses
num = 7;
h = zeros(1,num);
clr = lines(num);             %# color of each ellipse
x = rand(num,1) .* sz(2);     %# center x-coords
y = rand(num,1) .* sz(1);     %# center y-coords
a = rand(num,1) .* 200;       %# major axis length
b = rand(num,1) .* 200;       %# minor axis length
angle = rand(num,1) .* 360;   %# angle of rotation

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

%# randomly place ellipses one-at-a-time, skip if overlaps previous ones
figure, imshow(I)
axis on, hold on
for i=1:num
    %# ellipse we would like to draw directly on image matrix
    [ex,ey] = calculateEllipse(x(i),y(i), a(i),b(i), angle(i), 100);

    %# lets plot the ellipse (overlayed)
    h(i) = plot(ex,ey, 'LineWidth',2, 'Color',clr(i,:));

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

    %# get the perimter of this mask
    mask = bwperim(mask,8);

    %# skip if there is an existing overlapping ellipse
    if any( BW(mask)~=0 ), continue, end

    %# use the mask to place the ellipse in the label image
    BW(mask) = i;
end
hold off
legend(h, cellstr(num2str((1:num)','Line%d')), 'Location','BestOutside')    %'

%# set pixels corresponding to ellipses using specified colors
clr = im2uint8(clr);
II = I;
for i=1:num
    BW_ind = bsxfun(@plus, find(BW==i), prod(sz(1:2)).*(0:2));
    II(BW_ind) = repmat(clr(i,:), [size(BW_ind,1) 1]);
end
figure, imshow(II, 'InitialMagnification',100, 'Border','tight')

all_overlayed_ellipses rasterized_nonoverlapping_ellipses

Обратите внимание, как выполняется тест перекрытия в порядке добавления эллипсов,таким образом, после рисования Line1 (синий) и Line2 (зеленый) Line3 (красный) будет пропущен, поскольку он перекрывает один из предыдущих и так далее для остальных ...

1 голос
/ 20 октября 2011

Один из вариантов - отслеживать все уже нарисованные эллипсы и следить, чтобы следующий набор [x,y,a,b] не создавал новый эллипс, который пересекается с существующими.Вы можете вызывать случайные числа, пока не найдете набор, который удовлетворяет условию, или, если у вас есть набор, который нарушает условие, уменьшайте значения a и / или b до тех пор, пока не произойдет пересечение.

...