2015-08-10 5 views
0

У меня начальное изображение в оттенках серого img в формате double с рядом кругов тех же радиусов и векторов столбцов с координатами центров окружности x и y. Мне нужно скопировать все пиксели, принадлежащие окружностям, к массиву cpix. До сих пор я пришел только с самым тупым решением, используя петли for. Есть ли способ векторизовать этот код или просто заставить его работать быстрее?Быстрый способ копирования пикселей, принадлежащих кругам

% x(:) - vector with a few circles center X coordinates 
% y(:) - vector with a few circles center Y coordinates 
d = 27;     %diameter 
r = floor(d/2);   %radius 
cpix = double(zeros(d,d,size(x,1))); 

for iCent = 1:size(x,1) %for each circle 
    for ix = 1:d 
     for iy = 1:d 
      if ((ix-r)^2 + (iy-r)^2) < r^2 
       cpix(iy,ix,iCent) = img(iy+y(iCent)-r,ix+x(iCent)-r); 
      end 
     end 
    end 
end 
+0

Может ли круг быть рядом с границей изображений? и что должно произойти в этом случае? – Hoki

+0

Нет, круги больше, чем радиус 'r' вдали от границ – Cons

ответ

1

С помощью всего одного цикла (для каждого круга) вы можете использовать маску как диск для выбора соответствующих пикселей из вашего изображения. Начните с исходного кода.

% x(:) - vector with a few circles center X coordinates 
% y(:) - vector with a few circles center Y coordinates 
d = 27;     %diameter 
r = floor(d/2);   %radius 
cpix = double(zeros(d,d,size(x,1))); 

Теперь создайте маску с требуемым радиусом. Это можно сделать легко, если у вас есть Image Processing Toolbox.

h = fspecial('disk', r); 
h = h > 0; 

Затем используйте эту маску в петле для выбора нужной области.

for i = 1:size(x,1) 
    cpix(:,:,i) = h .* img(x(i)-r:x(i)+r, y(i)-r:y(i)+r); 
end 

Поскольку вы только создаете маску один раз, это должно быть быстрее, чем вычислять его для каждого круга.

Вы можете сделать это, если вы построите трехмерную маску. Если a x b - размер вашего изображения, а n - количество кругов, тогда маска будет a x b x n. Если вы repmat ваше изображение в стек размера n. Затем вы можете использовать умножение .*, чтобы получить окончательный результат. Результатом, однако, будет стопка a x b изображений, а не d x d, как вы упомянули. Не уверен, что это будет быстрее, потому что вы все равно должны его закодировать во время создания 3D-маски. Если маска построена только один раз и используется во множестве изображений, это может стоить того.

+0

Спасибо! Это идеальное решение, работает всего за 0,008290 секунд по сравнению с 4.594374 с моим исходным кодом. Единственное, что мне нужно было изменить: img indexing - y и x меняются местами, поэтому строка выглядит как 'cpix (:,:, i) = h. * Img (y (i) -r: y (i) + r, x (i) -r: x (i) + r); ' – Cons

+0

Пожалуйста, сообщите где-нибудь, что пользователям потребуется ** Image Processing Toolbox ** для запуска вашего решения. Это может привести к меньшему разочарованию, если позже пользователь попробует этот код, и он провалится, не зная почему. – Hoki

+0

Спасибо @hoki! Я добавил примечание к Image Processing Toolbox. – mparada

1

рассматривает ваше изображение в два раза и имеет 1 слой, для центра окружности будучи в [cx,cy] вы можете получить матрицу того же размера, что и основное изображение, с логическими значениями, в которых 1 указывает, что пиксель находится внутри круга (радиус = r) и 0 в противном случае.

[X,Y] = meshgrid(1:size(img,1),1:size(img,2)); 
C = bsxfun(@le,(X-cx).^2+(Y-cy).^2 ,r); 

, наконец, img(C) содержит все допустимые значения пикселей.

Пример с одной окружности:

r = 5; 
cx=100; 
cy=100; 
Id = im2double(imread('myimage.png')); 
Id1 = Id(:,:,1); 
[X,Y] = meshgrid(1:size(Id1,1),1:size(Id1,2)); 
C = bsxfun(@le,(X-cx).^2+(Y-cy).^2 ,r); 

length(Id1(C)) 
ans = 
     21 

С более чем одной окружности, вы должны иметь для цикла

cx = [100,110,120]; 
cy = [150,170,190]; 

for ii = 1:length(cx); 
    C = bsxfun(@le,(X-cx(ii)).^2+(Y-cy(ii)).^2 ,r); 
end 

Остальные части кода остаются нетронутыми ,

+0

Это один из способов, но, возможно, вы можете расширить свой пример, чтобы иметь дело с _array_ центра' cx' и 'cy'. Кажется, что у ОП есть несколько дел. – Hoki

+0

Благодарим вас за предложение, это интересный метод. Но дело в том, чтобы получить 3-мерный массив с 3-м измерением, равным количеству окружностей. – Cons

+2

Полная векторная навигация может не принести пользы здесь, так что одноконтурный выглядит оправданным для меня. Отличная работа! – Divakar

0

У меня есть библиотека с открытым исходным кодом pixelscan, которая может сканировать пиксели в различных пространственных шаблонах (круги, кольца, змеи, сетки, случайные фокусы). Существуют также различные пространственные преобразования, которые могут применяться (например, вращение, масштабирование, отсечение). Это библиотека python, но вы можете с помощью триггеров портировать соответствующий код MATLAB.

Смежные вопросы