Ayın boyutunu hesapla


19

Ayın gizeminin büyüklüğü

Eminim ayın boyutunu değiştirdiğini duymuşsunuzdur. Aşık olduğunuzda ve şanslı olduğunuzda, ay normal durumlara kıyasla neredeyse iki kat daha büyüktür. Bazı insanlar bunun nedeninin mercek görevi gören atmosfer olduğunu söylüyor. Diğerleri bunun sadece yakındaki ağaçlar gibi diğer nesnelerle karşılaştırılma meselesi olduğunu düşünüyor. Hangi açıklamayı okursanız okuyun, oldukça özneldir.

Ay biliminin büyüklüğü

Tamam, biz programcıyız, değil mi? Gerçeklere güveniyoruz, değil mi? İşte deney:

  1. Manuel olarak ayarlanan süreyi ve diyaframı destekleyen güzel bir kamera çekin.
  2. Kameranızı maksimum zum seviyesine ayarlayın.
  3. Dışarı çıkın, ayın keskin olması ve aydınlatmanın iyi olması için en iyi ayarları tespit etmek için ayın bazı fotoğraflarını çekin.
  4. Ayarları hatırla
  5. Ayın büyük veya küçük olduğunu her düşündüğünüzde bu ayarlarla ayın fotoğrafını çekin.
  6. Ayın boyutunu piksel cinsinden hesaplayın

Kamera yalan söylemez, değil mi? Parlak pikselleri sayarak ayın boyutunu etkili bir şekilde ölçebiliriz - en azından piksel cinsinden.

Boyut tüm fotoğraflarda aynı ise, beynimizde bir hata. Boyut farklıysa, spekülasyon için yer var

  • Ay gerçekten büyür (ama ne yer?)
  • atmosferik bir lens etkisi var
  • ay eliptik bir eğriye sahiptir ve bazen daha yakın, bazen dünyadan daha uzakta
  • ...

Ama göreviniz tamamlanana kadar bunu açık bırakacağım. Elbette, yazılımınızın ay boyutunu doğru bir şekilde hesaplayıp hesaplayamayacağını önceden bilmek istersiniz.

Görev

Ayın birkaç optimize edilmiş resmi göz önüne alındığında, lütfen ayın boyutunu hesaplayın. Optimizasyon: pikseller siyah veya beyazdır. Arasında hiçbir şey yok. Kenar yumuşatma yok. Bu kolaylaşıyor, değil mi?

Uyarı: Ay her zaman dolu değildir, bilirsiniz ... orak olabilir! Ancak orak şeklinde bile, ayın büyüklüğü daha büyüktür. Yani tam bedeni hesaplayacaksınız, lütfen.

  • Program stdinyerine bir işlev yazarsanız , programınız PNG'yi girdi olarak, örneğin dosya adı komut satırı bağımsız değişkeni olarak, bir Bitmap nesnesine (standart çerçeve kitaplığının) içine veya bu nesneye aktarılır.
  • Programınız, kare olması gerekmeyen makul bir giriş bitmap boyutuyla çalışır. Minimum 150 piksel genişlik ve yükseklik garanti edilir.
  • Dolunay resmin en az% 25'ini kaplar.
  • Programınız, hesaplanan ayın boyutunu dolunaymış gibi piksel cinsinden çıktılar.
  • Ayın mükemmel bir küre olduğunu varsayıyoruz.
  • Tam boyut her zaman bir tamsayıdır, ancak hesaplamalarınız bunu döndürürse ondalık bir sayı verebilirsiniz.
  • Doğruluk% 98 ile% 102 arasında olmalıdır. (Bu, ulaşılabilir olmayı garanti edebileceğim bir şeyden ziyade bir tahmin. Ulaşmanın çok zor olduğunu düşünüyorsanız, lütfen bir yorum bırakın.)

Güncelleme :

  • Ayın merkezi mutlaka resmin ortasında değil.
  • Görünür minimum alan ayın% 5'i veya toplam piksel sayısının% 1.25'idir.
  • Resim, tüm ayın görüntüye uyacak şekilde çekilir, yani toplam piksel sayısı ay boyutu için bir üst sınırdır.
  • Ay kırpılmayacak / kırpılmayacak.

Örnekler

İsterseniz karışım dosyasını kullanarak kendi örneklerinizi oluşturabilirsiniz . Sizin için aşağıdaki resimleri oluşturdum. Görüntünün yalnızca siyah beyaz piksel içerip içermediğini ve kaç tane olduğunu kontrol etmek için PNG dosyasındaki pikselleri WhitePixelCounter.exe (.NET gerekir) kullanarak sayabilirsiniz .

Aşağıdaki 256x256 piksel görüntü, beyaz piksel miktarında farklılık gösterir, ancak tümü 16416 piksel hesaplanan ay boyutuyla sonuçlanmalıdır.

Dolunay Ay Ay Ay Ay Ay

Ve bu 177x177 piksel görüntüler 10241 piksel döndürmelidir. Görüntüler temel olarak aynıdır, ancak bu sefer farklı odak uzaklığına sahip bir kamera kullanılmıştır.

Ay Ay Ay Ay Ay Ay

9988 sonucu elde edilen kare olmayan ve ortalanmayan örnekler:

Kare olmayan bir çerçevede ay Kare olmayan bir çerçevede ay Kare olmayan bir çerçevede ay Kare olmayan bir çerçevede ay Kare olmayan bir çerçevede ay

Şimdilik referans uygulamam yok ve bir şey uygulayıp uygulayamayacağımı bile bilmiyorum. Ama beynimde bana bunun matematiksel olarak çözülebilir olması gerektiğini söyleyen güçlü bir inanç var.

Kurallar

Bu Code Golf. 2015-03-30'daki en kısa kod kabul edilir.


9
Tüm örneklerde, ayın merkezi resmin içinde ortalanmış gibi görünmektedir. Ayın her zaman ortalanacağını varsayabilir miyiz?
Dijital Travma

1
alandaki% +/- 2'lik doğruluk, çaptaki% + / - 1'e karşılık gelir: örnek r = 100 piksel, alan = 10000 * pi; r = 101 piksel, alan = 10201 * pi. Küçük resminizde r = 72 olduğundan d = 144 olduğundan yalnızca mümkün olmalıdır . Ancak d = 100 altındaki görüntüler için doğruluk düzeyinin karşılanamadığını düşünüyorum.
Level River St

@DigitalTrauma: Merkezin ortada olması gerekmez.
Thomas Weller

@ MartinBüttner: Görünen minimum yüzde ayın% 5'i veya resmin% 1,25'i.
Thomas Weller

@ MartinBüttner: tamam, soruyu güncelledim, varsayılan olarak kare olmayan, ortalanmayan görüntüler üretmek için karışım dosyasını güncelledim. Tüm resimleri buradan indirebilirsiniz (* .png.zip) . Güncellenmiş piksel sayacı da: daha fazla bilgi verir ve% 1.25 kuralını denetler.
Thomas Weller

Yanıtlar:


10

Mathematica 126119 109 bayt

Mathematica, bir görüntüdeki bir bileşenin uzamasını ölçebilir. Mükemmel simetrik olan dolunay, 0 ila 1 ölçeğinde 0 uzamaya sahiptir.

Azalan bir ay giderek kabaca 0.8'e kadar uzar.

0.998 -0.788 x-0.578 x^2 uzaması göz önüne alındığında `` ayın doluluğunu (bölgeye göre) tahmin etmek için ampirik olarak belirlenmiş modeldi (büyük fotoğraflara dayanarak).

Modeli 1- 0.788 x -0.578 x^2, tamamen sıfır uzama (dolunay) ile modelin piksel ölçek faktörü için 1 döndüreceği şekilde ayarladım . 4 bayt tasarrufu sağlar ve yine de doğruluk sınırları dahilinde kalır.

Bu model her boyutta resim için kullanılır. Ay görüntüsünün ortalanması gerekmez. Ayrıca, fotoğrafın sabit bir bölümünü de kapsaması gerekmez.

Büyük görüntüler ve verilere uyacak şekilde oluşturulan parabolik model için veri noktaları (uzama, displayMoonPixels / fullMoonPixels). Doğrusal modeller uygundur, ancak kuadratik model sınırlar içinde ölmüştür (aşağıya bakınız).

Burada veriler büyük resimlerden. Model de öyle

büyük hilal


Aşağıda, veriler (kırmızı noktalar) küçük resimlerden alınmıştır. Model (mavi eğri), büyük resimler tarafından oluşturulan, yukarıda gösterilenle aynıdır.

En küçük hilal dolunay alanının% 7.5'ine sahiptir. (Büyük fotoğraflar arasındaki en küçük hilal dolunayın% 19'udur.) İkinci dereceden model küçük fotoğraflara dayansaydı, aşağıdaki uyum daha iyi olurdu, çünkü küçük hilal barındırıyordu. Çok küçük hileler de dahil olmak üzere çok çeşitli koşullar altında durabilecek sağlam bir model, çok çeşitli resimlerden daha iyi yapılabilir.

Uyum yakınlığı, modelin verilen resimler için sabit kodlanmamış olduğunu gösterir. Bir ayın uzamasının beklendiği gibi fotoğrafın boyutundan bağımsız olduğundan oldukça emin olabiliriz.

küçük hilal

fgörüntüyü igirdi olarak alır ve dolunayın öngörülen boyutunu piksel cinsinden verir. Merkez dışı çekimlerde çalışır.

Aşağıdaki verilerin gösterdiği gibi, biri hariç tüm test durumları. Aylar, doludan en küçüğe doğru düzenlenmiştir.

i_~c~t_ := Max@ComponentMeasurements[i, t][[All, 2]];
f@i_ := i~c~"Count"/(1 - 0.788 x - 0.578 x^2 /. x -> i~c~"Elongation")

Bir fotoğrafta birden fazla görüntü bileşeni ortaya çıkabilir. Diğerlerinden ayrılmış tek bir piksel bile ayrı bir bileşen olarak kabul edilecektir. Bu nedenle, daha fazla sayıda piksele sahip olanı bulmak için "tüm" bileşenleri aramak gerekir. (Küçük fotoğraflardan birinde birden fazla resim bileşeni var.)

Büyük resimler

Büyük fotoğraflardan yapılan ay boyutunun tahminleri düzgün doğruydu.

{"predicted size of full moon", f[#] & /@ large}
{"accuracy", %[[2]]/16416}

{"öngörülen dolunay boyutları", {16422., 16270.9, 16420.6, 16585.5, 16126.5, 16151.6}}

{"doğruluk", {1.00037, 0.991161, 1.00028, 1.01033, 0.982367, 0.983891}}


Küçük resimler

Küçük fotoğraflardan yapılan ay boyutunun tahminleri tek bir istisna dışında, son resimdi. Sorunun, hilalin çok dar olmasından kaynaklandığından şüpheleniyorum.

{"predicted sizes of full moon", f[#] & /@ small}
{"accuracy", %[[2]]/10241}

{"öngörülen dolunay boyutları", {10247.3, 10161., 10265.6, 10391., 10058.9, 7045.91}}
{"Doğruluk", {1.00061, 0.992192, 1.0024, 1.01465, 0.982221, 0.68801}}


Bir gün Mathematica öğrenmem gerekiyor gibi görünüyor. Golf yapmadan çözmeniz ne kadar sürdü?
Thomas Weller

1
@Thomas W Gönderiyi gördüğünüz grafiği elde edene kadar çeşitli görüntü işleme özellikleri ve diğer (doğrusal) modelleri denemek 2-3 saat sürdü. Kodlama çok zor değildi. Ve ayrı fonksiyonları tek bir fonksiyonda birleştirmek dışında neredeyse hiç golf yoktur.
DavidC

104:i_~c~t_:=Max[#2&@@@i~ComponentMeasurements~t];f@i_:=i~c~"Count"/(1-0.788x-0.578x^2/.x->i~c~"Elongation")
Martin Ender

Bilinmeyen nedenlerden dolayı #2&@@@öneri çalışmıyor
DavidC

Hah, daha sonra bakacağım. Kısaltmanın bir başka yolu cdac=Max@ComponentMeasurements[##][[All,2]]&
Martin Ender

5

J, 227207 bayt (maksimum hata% 1.9)

Ana fikrim, dolunayın konturunda bulunan ayın konturunda 3 nokta bulabilirsek , bu noktaların çemberlerini de hesaplayabiliriz . Bu daire dolunay olacak.

Maksimum mesafe ile iki beyaz nokta bulursak, bunlar her zaman dolunayda gerçek bir köşegen veya hilalin uç noktaları olacak gibi noktalar olacaktır. Herhangi bir başlangıç ​​noktasından en uzak noktayı seçip ardından seçilen noktadan en uzak noktayı seçerek, herhangi bir grafikte en büyük mesafeye sahip nokta çiftini bulabiliriz.

Önceki noktalardan uzaklıkların ürünlerinin maksimum değeri olan üçüncü bir nokta buluyoruz. Bu her zaman konturda ve bir hilal veya bir gibbousun daha büyük tarafında olacaktır.

Dairenin çapı, bir tarafın uzunluğunun karşı açının sinüsüne bölünmesiyle hesaplanır.

Bu yöntemin zaman karmaşıklığı, girdi görüntüsünün boyutunda doğrusaldır.

kod

f=.3 :0
load'graphics/png'
i=.readpng y
p=.(,i=_1)#|:,"%.0 1|:,"0/&>/<@i."*$i
s=.%:+/|:*:(-1|.]) (([,],:m@(*&d))(m@d))(m=.p{~(i.>./)@])(d=.+/@:*:@((|:p)-])) 0{p
o.*:-:({.s)%0 o.((+/-2*{.)*:s)%2**/}.s
)

İşlev, giriş dosya adını dize olarak bekler.

(Daha az okunabilir bir sürüm için düzeltme geçmişini kontrol edin.)

Kod açıklaması

  • p, beyaz piksel koordinatlarının bir listesidir (gelecekte noktalar olarak adlandırılır)
  • d fonksiyonu p elemanları ile belirli bir nokta arasındaki mesafeleri hesaplar
  • s tanımının ikinci kısmı 3 noktalı bir liste oluşturur:

    • A, listedeki ilk noktadan en uzak nokta
    • B, A'nın en uzak noktasıdır
    • C, A formunun B'den uzaklığa kadar azami mesafe değeri olan bir noktadır
  • s ABC üçgeninin yan uzunluklarıdır

  • son satır, dolunay olan ABC'nin çember çevresini hesaplar

Sonuçlar

En büyük hata% 1.9'dur.

Görüntüler sorudakiyle aynı sırada.

Output  Accuracy
----------------
  16407 0.999453 NB. Large images
16375.3 0.997523
16223.9 0.988301
16241.5 0.989369
16262.6 0.990654
16322.1 0.994279
10235.3 0.999445 NB. Small images
10235.3 0.999444
10221.2 0.998067
10220.3 0.997978
  10212 0.997169
10229.6  0.99889
9960.42 0.997239 NB. Offset images
9872.22 0.988408
10161.8   1.0174
9874.95 0.988681
 9805.9 0.981768

Yaklaşıma katılmak ve bahsetmek için +1. Merkezin ortada olması gerekmediğini belirtmediğim için üzgünüm. Yanlışlıkla örnek görüntülerin tümü ortalanır. Bu benim hatam.
Thomas Weller

@ThomasW. Düzeltene kadar cevabımı geçici olarak sildim.
randomra

2

Matlab 162156 (şu anki hata payında değil)

Her şeyden önce: Doğruluk, iki serinin her birinde bir görüntü hariç tümü için% 2'nin altındadır, burada daha büyüktür (yaklaşık% 5 ve% 14). Benim yaklaşımım, birbirinden en uzaktaki iki pikseli bulmak ve daha sonra bunu çap için bir tahmin olarak kullanmaktı.

a=imread(input(''));                 %read input image
b=a(:,:,1)>0;                        %binarize red channel
s=size(b);                           %get size of the image
[x,y]=meshgrid(1:s(1),1:s(2));       
z=(x+i*y).*b;z=z(z~=0);              %find the coordinates of all white pixels (as a list)
o=ones(size(z(:)))*z(:)';            
disp(max(max(abs(o-o.').^2))*pi/4);  %calculate the maximum of the distance between each possible pair and evaluate area formula

Bunlar doğruluk sonuçlarıdır (değişken sapma 1 - (predicted size / real size))

0.0006 0.0025 0.0169 0.0500 0.0521 0.0113 0.0006 0.0006 0.0026 0.0472 0.1383 0.0131

1

C # - 617

Bu çözüm tüm görüntüler için çalışmaz, çünkü görüntülerden birinde eğim (m) sonsuz olur.

İlkeden daha önce bahsedilmişti:

  1. Maksimum mesafeye sahip iki nokta bulun (kırmızı)
  2. Aralarında bir çizgi hayal edin (kırmızı)
  3. Ortada dikdörtgen açılı (yeşil) bir çizgi hayal edin
  4. Yeşil hat üzerinde beyaz noktalar bulun
  5. Diğer noktalardan maksimum uzaklığa sahip olanı kullanın (yeşil)
  6. Bir dairenin alanını üç noktadan hesaplayın

açıklama

Sorunlu durum, eğimin sonsuz olduğu durumdur. Görüntüyü 90 ° döndürerek veya kod halinde ydöndürmek yerine eksen üzerinde döngü yapmak mümkündür x.

Sorunlu ay

double A(Bitmap b){var a=new List<P>();for(var y=0;y<b.Height;y++)for(var x=0;x<b.Width;x++)if(b.GetPixel(x,y).R>0)a.Add(new P{x=x,y=y});double c=0.0,d=0.0,e=0.0,f=0.0,g=0.0,n=double.MaxValue;foreach(var h in a)foreach(var i in a){var t=Math.Sqrt(Math.Pow(h.x-i.x,2)+Math.Pow(h.y-i.y,2));if(t>c){d=h.x;f=i.x;e=h.y;g=i.y;c=t;}}c=(f-d)/(e-g);for(int x=0;x<b.Width;x++){int y=(int)(c*x+((e+g)/2-c*(d+f)/2));if(y>=0&&y<b.Height&&b.GetPixel(x,y).R>0){var s=(g-e)/(f-d);var q=(y-g)/(x-f);var j=(s*q*(e-y)+q*(d+f)-s*(f+x))/(2*(q-s));var k=-(j-(d+f)/2)/s+(e+g)/2;var l=(j-d)*(j-d)+(k-e)*(k-e);if(l<n)n=l;}}return Math.PI*n;}

Minimum doğruluk

  • 256 piksel görüntü için +% 1,89
  • 177 piksel görüntü için -0.55%
  • Kare olmayan görüntüler için% -1.66
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.