среднее значение в сфере

Я пытаюсь вычислить среднее значение пикселей внутри круга. В будущем это нужно расширить до 3D, но пока решение 2D мне уже помогло бы.

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

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

[править] благодаря Хиту Рафтери проблема решена! [/редактировать]

интеграл окружности с радиусом r< /а>

Например: я хочу узнать среднее значение пикселей в этом круге. Я знаю, что это 0,3425, так как 34,25% круга имеет значение 1, а остальные 0.

пример круга

Функция для проверки того, какая часть пикселя находится в круге:

function [ a ] = incirc( x,y,r )
%only handles the top right quadrant of a circle
if x<0||y<0,error('only positive x,y');end

%integral of sqrt(r^2-x^2) dx
F = @(x,r) (1/2)*(x*sqrt(r^2-x^2)+r^2*atan(x/sqrt(r^2-x^2)));

%find corner locations
x=[x-0.5,x+0.5];
y=[y-0.5,y+0.5];

d = sqrt(x.^2+y.^2); %distance to closed and furthest corner
if max(d)<r,a=1;return;end %inside circle
if min(d)>r,a=0;return;end %outside circle

%intersections with edges (r^2 = x^2+y^2)
inters = [sqrt(r^2-y(1)^2),sqrt(r^2-y(2)^2),sqrt(r^2-x(1)^2),sqrt(r^2-x(2)^2)]; %x(1) x(2) y(1) y(2)
%remove imaginary and out of range intersections
inters(imag(inters)~=0)=NaN;
inters(inters<1E-5)=NaN; %to find values that are zero
inters([~((x(1)<inters(1:2))&(inters(1:2)<x(2))),~((y(1)<inters(3:4))&(inters(3:4)<y(2)))])=NaN;
idx = find(~isnan(inters));
if numel(idx)~=2,error('need two intersections of circle with pixel');end

%check area of pixel inside circumference
if all(idx==[1,2]) %2 intersections on y-edge
    a=(F(y(2),r)-F(y(1),r)) - x(1); %area
elseif all(idx==[3,4]) %2 intersections on x-edge
    a=(F(x(2),r)-F(x(1),r)) - y(1); %area
elseif all(idx==[1,3]) %one intersection on y-edge one on x-edge (left&bottom)
    a=(F(inters(1),r)-F(x(1),r))- (y(1)*(inters(1)-x(1)));
elseif all(idx==[2,4]) %one intersection on y-edge one on x-edge (top&right)
    a=(inters(2)-x(1))+(F(x(2),r)-F(inters(2),r))-(y(1)*(x(2)-inters(2)));
else
    error('geometry')
end
a=real(a);
if a<0||a>1
    error('computational error');
end
end

Скрипт для проверки функции

M = ones(100); %data
M(1:50,:)=0;
pos=[50.2,50];
r = 2;
%calculate what the result should be
h=50-pos(2)+0.5;
A=pi*r^2; 
wedge = acos(h/r)/pi;
triangle = h*sqrt(r^2-h^2);
res=(A*wedge-triangle)/A

S=0;N=0;
for i = 1:size(M,1)
    for j = 1:size(M,2)
        x=abs(j-pos(1));
        y=abs(i-pos(2));
        n=incirc( x,y,r );
        M_(i,j)=n;
        S = S+M(i,j)*n;
        N = N+n;
    end
end
result = S/N

результат = 0,3425

Вы можете видеть, что алгоритм находит часть пикселя в круге.

весы


person Gelliant    schedule 12.06.2017    source источник


Ответы (3)


В вопросе отсутствует вопрос, но я предполагаю, что дело не в том, как вычислить, полностью ли пиксели находятся внутри или вне круга. Это относительно простая задача. То есть пиксель полностью находится внутри, если самый дальний угол пикселя к центру меньше радиуса от центра, и пиксель полностью снаружи, если ближайший угол пикселя к центру удален более чем на радиус. от центра.

Вопрос о том, какая доля пикселей на окружности приходится на окружность, гораздо сложнее. Есть два принципиальных решения:

  1. Точно и жестко.
  2. Приблизительно и немного проще.

Обратите внимание, что в обоих случаях горизонтальная и вертикальная симметрия означает, что необходимо учитывать только верхний правый квадрант.

Затем для (1) переместите центр окружности в начало координат (0, 0) и обработайте окружность как функцию y(x) = sqrt(r^2 - x^2). Тогда площадь перекрывающегося пикселя внутри круга является интегралом:

интеграл(y(x) - y0, от x0 до x1, относительно x)

где y0 — нижняя координата пикселя, x0 — левая координата, а x1 — правая координата.

Этот интеграл можно точно решить с помощью тригонометрического тождества и тригонометрической замены.

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

person Heath Raftery    schedule 12.06.2017
comment
Я пытался реализовать точное решение, но что-то идет не так, когда я пытаюсь решить его для пикселей, которые окружность пересекает как по x, так и по y. В результате получаются отрицательные числа. У вас есть идея, почему? - person Gelliant; 12.06.2017
comment
Ах да, если окружность пересекает нижнюю часть пикселя, вам нужно будет обрезать ограничения интервала только до области, где окружность находится в пикселе. Сначала решите x2 = sqrt(r^2 - y0^2), чтобы найти точку пересечения, и если x2 < x1, то используйте пределы интегрирования x0 и x2 вместо x0 и x1. - person Heath Raftery; 12.06.2017
comment
Большой! Я почти там, кажется. Но также имеет значение, являются ли пересечения верхним и правым или левым и нижним. Я обновил вопрос своим кодом и полученным изображением. - person Gelliant; 13.06.2017
comment
Я обновил свой вопрос, чтобы он также содержал ответ (в коде). И наглядный пример, подтверждающий, что код работает. Надеюсь, это может быть полезно и кому-то другому. - person Gelliant; 14.06.2017

Вы можете использовать inpolygon, чтобы получить индексы, лежащие внутри круга. Когда у вас есть эти индексы, вы можете получить свои пиксели и делать то, что хотите.

M = rand(100); %data
[nx,ny] = size(M) ;
[X,Y] = meshgrid(1:ny,1:nx) ;

pos=[20,20];
r = 5;
phi=linspace(0,2*pi,100);
imagesc(M);
axis image
hold on
plot(pos(1),pos(2),'rx')
xc = pos(1)+r*sin(phi) ;
yc = pos(2)+r*cos(phi) ;
plot(xc,yc,'-r');
% hold off
%% get indices which are inside the circle
idx = inpolygon(X(:),Y(:),xc,yc) ;
xi = X(idx) ; yi = Y(idx) ;
plot(xi,yi,'.r')
mypixels = M(idx) ;
person Siva Srinivas Kolukula    schedule 12.06.2017
comment
И если вы выберете радиус как r+0,5 или r-0,5, почти все пиксели будут покрыты. - person Siva Srinivas Kolukula; 12.06.2017
comment
Спасибо, это дает пиксели внутри круга. Простой mean(M(idx)) дает среднее значение. Но не исправляет пиксели, которые только частично находятся внутри круга. - person Gelliant; 12.06.2017
comment
Использовать радиус как r+0.5 - person Siva Srinivas Kolukula; 12.06.2017
comment
В приведенном выше примере вы использовали r=5. Попробуйте r = 5,5 ; - person Siva Srinivas Kolukula; 12.06.2017

Вы также можете использовать поиск диапазона, чтобы получить точки, лежащие в пределах заданного радиуса круга. Как показано ниже:

M = rand(100); %data
[nx,ny] = size(M) ;
[X,Y] = meshgrid(1:ny,1:nx) ;

pos=[20,20];
r = 5;
phi=linspace(0,2*pi,100);
imagesc(M);
axis image
hold on
plot(pos(1),pos(2),'rx')
xc = pos(1)+r*sin(phi) ;
yc = pos(2)+r*cos(phi) ;
plot(xc,yc,'-r');
% hold off
%% Use nearest neighbour search
idx = rangesearch([X(:),Y(:)],pos,r) ;
xi = X(idx{1}) ; yi = Y(idx{1}) ;
plot(xi,yi,'.r')
mypixels = M(idx{1}) ;
person Siva Srinivas Kolukula    schedule 13.06.2017
comment
это работает, если у вас есть набор инструментов и вы хотите знать, какие пиксельные центры находятся внутри круга. - person Gelliant; 13.06.2017
comment
Я знаю это... Я даю другое альтернативное решение вместе с inpolygon. - person Siva Srinivas Kolukula; 13.06.2017
comment
Да, и для многих приложений этого было бы достаточно, но это не решение этой проблемы. - person Gelliant; 13.06.2017