nilai rata-rata dalam suatu bola

Saya mencoba menghitung nilai rata-rata piksel di dalam lingkaran. Di masa depan hal ini perlu diperluas ke 3D, tapi untuk saat ini solusi 2D sudah membantu saya.

Seperti terlihat pada gambar, ada piksel yang seluruhnya berada di dalam lingkaran, namun ada pula yang hanya sebagian di dalam lingkaran. Kelompok yang sebagian berada dalam lingkaran juga perlu memberikan kontribusi hanya sebagian terhadap nilai rata-rata. Pikselnya berbentuk persegi. Saya harap ini akan menyederhanakan matematika.

Saya dapat menghitung jarak dari sudut piksel ke titik pusat, dari sini Anda dapat menemukan piksel masuk ke dalam dan masuk ke luar. Selebihnya perlu koreksi. Tapi bagaimana menemukan koreksi ini.

[sunting] terima kasih kepada Heath Raftery masalahnya terpecahkan! [/ sunting]

integral lingkaran berjari-jari r

Sebagai contoh: Saya ingin mengetahui nilai rata-rata piksel dalam lingkaran ini. Saya tahu nilainya 0,3425, karena 34,25% lingkaran bernilai 1 dan sisanya 0.

contoh lingkaran

Berfungsi untuk memeriksa bagian piksel mana yang ada di dalam lingkaran:

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

Skrip untuk menguji fungsinya

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

hasil = 0,3425

Anda dapat melihat algoritme menemukan bagian piksel dalam lingkaran.

beban


person Gelliant    schedule 12.06.2017    source sumber


Jawaban (3)


Pertanyaannya tidak ada pertanyaannya, tapi saya berasumsi bahwa ini bukan cara menghitung apakah piksel sepenuhnya berada di dalam atau di luar lingkaran. Itu tugas yang relatif sederhana. Artinya, suatu piksel berada sepenuhnya di dalam jika sudut terjauh piksel ke pusat berjarak kurang dari satu radius dari pusat, dan suatu piksel sepenuhnya berada di luar jika sudut terdekat piksel ke pusat berjarak lebih dari satu radius. dari pusat.

Pertanyaan tentang berapa proporsi piksel pada keliling yang termasuk dalam keliling jauh lebih rumit. Ada dua solusi mendasar:

  1. Tepat dan sulit.
  2. Perkiraan dan sedikit lebih mudah.

Dalam kedua kasus tersebut, perhatikan simetri horizontal dan vertikal yang berarti hanya kuadran kanan atas yang perlu dipertimbangkan.

Kemudian, untuk (1), terjemahkan pusat lingkaran ke titik asal (0, 0) dan perlakukan keliling sebagai fungsi y(x) = sqrt(r^2 - x^2). Maka, luas piksel yang tumpang tindih di dalam lingkaran adalah integralnya:

integral(y(x) - y0, dari x0 ke x1, terhadap x)

dimana y0 adalah koordinat bawah piksel, x0 adalah koordinat kiri dan x1 adalah koordinat kanan.

Integral ini dapat diselesaikan secara eksak dengan identitas trigonometri dan substitusi trigonometri.

Untuk (2), cukup buat sekumpulan titik acak di dalam piksel dan hitung berapa banyak titik yang berada dalam keliling. Ketika himpunan semakin besar, proporsi titik-titik yang berada dalam keliling terhadap jumlah semua titik mendekati proporsi piksel dalam keliling.

person Heath Raftery    schedule 12.06.2017
comment
Saya mencoba menerapkan solusi yang tepat, tetapi ada yang tidak beres ketika saya mencoba menyelesaikannya untuk piksel yang berpotongan dengan lingkaran di x dan y. Ini menghasilkan angka negatif. Apakah Anda tahu alasannya? - person Gelliant; 12.06.2017
comment
Oh ya - jika keliling melewati bagian bawah piksel, Anda harus memotong batas interval hanya pada wilayah di mana keliling berada dalam piksel. Selesaikan terlebih dahulu x2 = sqrt(r^2 - y0^2) untuk mencari titik perpotongannya, dan jika x2 < x1, gunakan batas integrasi x0 dan x2 sebagai ganti x0 dan x1. - person Heath Raftery; 12.06.2017
comment
Besar! Sepertinya aku hampir sampai. Namun penting juga jika persimpangannya melalui atas & kanan atau kiri & bawah. Saya memperbarui pertanyaan dengan kode saya dan gambar yang dihasilkan. - person Gelliant; 13.06.2017
comment
Saya memperbarui pertanyaan saya untuk memuat jawabannya (dalam kode) juga. Dan contoh yang jelas untuk membuktikan bahwa kode tersebut berfungsi. Semoga ini bisa bermanfaat bagi orang lain juga. - person Gelliant; 14.06.2017

Anda dapat menggunakan inpolygon, untuk mendapatkan indeks yang terletak di dalam lingkaran, setelah Anda memiliki indeks tersebut, Anda bisa mendapatkan piksel dan melakukan apa yang Anda inginkan.

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
Dan jika Anda memilih radius sebagai r+0,5 atau r-0,5, hampir semua piksel akan tercakup. - person Siva Srinivas Kolukula; 12.06.2017
comment
Terima kasih, ini menghasilkan piksel di dalam lingkaran. mean(M(idx)) sederhana memberikan rata-rata. Namun tidak mengoreksi piksel yang hanya sebagian berada di dalam lingkaran. - person Gelliant; 12.06.2017
comment
Gunakan radius sebagai r+0,5 - person Siva Srinivas Kolukula; 12.06.2017
comment
Pada contoh di atas Anda menggunakan r=5. Coba r =5.5 ; - person Siva Srinivas Kolukula; 12.06.2017

Anda juga dapat menggunakan rangesearch untuk mendapatkan titik-titik yang berada dalam radius lingkaran tertentu. Seperti di bawah ini:

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
itu berfungsi jika Anda memiliki kotak peralatan dan jika Anda ingin mengetahui pusat piksel mana yang ada di dalam lingkaran. - person Gelliant; 13.06.2017
comment
Saya tahu bahwa...Saya memberikan solusi alternatif lain bersama dengan inpolygon. - person Siva Srinivas Kolukula; 13.06.2017
comment
Ya, dan untuk banyak aplikasi, hal ini sudah cukup, namun ini bukanlah solusi untuk masalah ini. - person Gelliant; 13.06.2017