ค่าเฉลี่ยในทรงกลม

ฉันกำลังพยายามคำนวณค่าเฉลี่ยของพิกเซลภายในวงกลม ในอนาคตสิ่งนี้จำเป็นต้องขยายเป็น 3D แต่สำหรับตอนนี้ โซลูชัน 2D จะช่วยฉันได้แล้ว

ดังที่เห็นในภาพ บางพิกเซลอยู่ในวงกลมทั้งหมด แต่บางพิกเซลอยู่ในวงกลมเพียงบางส่วนเท่านั้น ส่วนที่อยู่ในวงกลมก็ต้องมีส่วนทำให้ค่าเฉลี่ยเพียงบางส่วนเท่านั้น พิกเซลเป็นสี่เหลี่ยมจัตุรัส นี่จะทำให้คณิตศาสตร์ที่ฉันหวังง่ายขึ้น

ฉันสามารถคำนวณระยะห่างจากมุมพิกเซลถึงจุดศูนย์กลางได้ จากนี้คุณจะพบพิกเซลที่เข้าไปด้านในและด้านนอก ส่วนที่เหลือต้องการการแก้ไข แต่จะหาการแก้ไขนี้ได้อย่างไร

[แก้ไข] ขอบคุณ Heath Raftery ปัญหาได้รับการแก้ไขแล้ว! [/แก้ไข]

อินทิกรัลของวงกลมที่มีรัศมี 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

คุณยังสามารถใช้ rangesearch เพื่อหาจุดที่อยู่ในรัศมีที่กำหนดของวงกลม ดังต่อไปนี้:

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