Tính kích thước của mặt trăng


19

Kích thước của bí ẩn mặt trăng

Tôi chắc chắn rằng bạn đã nghe nói rằng mặt trăng thay đổi kích thước của nó. Khi bạn đang yêu và bạn may mắn, mặt trăng có kích thước gần gấp đôi so với các tình huống thông thường. Một số người nói lý do là bầu không khí hoạt động như một ống kính. Những người khác nghĩ rằng đó chỉ là vấn đề so sánh với các đối tượng khác như cây cối gần đó. Bất cứ lời giải thích nào bạn đọc, nó khá chủ quan.

Kích thước của khoa học mặt trăng

Ok, chúng tôi là lập trình viên, phải không? Chúng tôi dựa vào sự thật, phải không? Vì vậy, đây là thí nghiệm:

  1. Có một máy ảnh đẹp hỗ trợ cài đặt thời gian và khẩu độ bằng tay.
  2. Đặt máy ảnh của bạn ở mức thu phóng tối đa.
  3. Đi ra ngoài, chụp một số bức ảnh về mặt trăng để phát hiện các thiết lập tốt nhất để mặt trăng sắc nét và ánh sáng tốt.
  4. Ghi nhớ các cài đặt
  5. Chụp ảnh mặt trăng với những cài đặt đó mỗi khi bạn nghĩ rằng mặt trăng lớn hay nhỏ.
  6. Tính kích thước của mặt trăng tính bằng pixel

Máy ảnh sẽ không nói dối, phải không? Bằng cách đếm các pixel sáng, chúng ta có thể đo kích thước của mặt trăng một cách hiệu quả - ít nhất là bằng pixel.

Nếu kích thước giống nhau trên tất cả các bức ảnh, thì đó là một lỗi trong não của chúng ta. Nếu kích thước khác nhau, thì có chỗ cho đầu cơ

  • mặt trăng thực sự phát triển (nhưng nó ăn gì?)
  • có hiệu ứng thấu kính khí quyển
  • mặt trăng có đường cong elip và đôi khi gần hơn, đôi khi cách xa trái đất
  • ...

Nhưng tôi sẽ để mở cho đến khi nhiệm vụ của bạn được hoàn thành. Tất nhiên bạn muốn biết trước nếu phần mềm của bạn có thể tính toán kích thước mặt trăng một cách chính xác.

Nhiệm vụ

Đưa ra một vài hình ảnh tối ưu của mặt trăng, hãy tính kích thước của mặt trăng. Tối ưu hóa là: các pixel có màu đen hoặc trắng. Không có gì ở giữa. Không khử răng cưa. Điều đó làm cho nó dễ dàng, phải không?

Lời cảnh báo: mặt trăng không phải lúc nào cũng đầy, bạn biết đấy ... nó có thể là liềm! Nhưng ngay cả trong hình dạng của một liềm, kích thước của mặt trăng lớn hơn. Vì vậy, bạn sẽ tính toán kích thước đầy đủ, xin vui lòng.

  • Chương trình của bạn lấy PNG làm đầu vào, ví dụ như đối số dòng lệnh tên tệp, được dẫn vào stdinhoặc làm đối tượng Bitmap (của thư viện khung tiêu chuẩn) nếu bạn viết hàm thay vì chương trình.
  • Chương trình của bạn hoạt động với bất kỳ kích thước bitmap đầu vào hợp lý, không nhất thiết phải là hình vuông. Chiều rộng và chiều cao tối thiểu 150 pixel được đảm bảo.
  • Trăng tròn bao phủ ít nhất 25% bức tranh.
  • Chương trình của bạn đưa ra kích thước tính toán của mặt trăng tính bằng pixel như thể đó là trăng tròn.
  • Chúng tôi cho rằng mặt trăng là một hình cầu hoàn hảo.
  • Kích thước chính xác luôn là số nguyên, nhưng bạn có thể xuất số thập phân nếu phép tính của bạn trả về số đó.
  • Độ chính xác phải nằm trong khoảng từ 98% đến 102%. (Đó chỉ là dự đoán hơn là điều tôi có thể đảm bảo có thể đạt được. Nếu bạn nghĩ rằng quá khó để tiếp cận, vui lòng để lại nhận xét.)

Cập nhật :

  • Trung tâm của mặt trăng không nhất thiết phải ở giữa bức tranh.
  • Vùng nhìn thấy tối thiểu là 5% của mặt trăng hoặc 1,25% tổng số pixel.
  • Hình ảnh được chụp theo cách mà toàn bộ mặt trăng sẽ phù hợp với hình ảnh, tức là tổng số pixel là một ranh giới trên cho kích thước mặt trăng.
  • Mặt trăng sẽ không bị cắt / cắt.

Các mẫu

Bạn có thể tạo các mẫu của riêng bạn bằng cách sử dụng tệp pha trộn nếu bạn muốn. Tôi đã tạo ra những hình ảnh sau đây cho bạn. Bạn có thể đếm pixel trong tệp PNG bằng WhitePixelCorer.exe (cần .NET) để kiểm tra xem hình ảnh chỉ chứa các pixel đen trắng và bao nhiêu pixel.

Các hình ảnh 256x256 pixel sau đây khác nhau về số lượng pixel trắng, nhưng tất cả sẽ dẫn đến kích thước mặt trăng được tính là 16416 pixel.

Trăng tròn Mặt trăng Mặt trăng Mặt trăng Mặt trăng Mặt trăng

Và những hình ảnh 177x177 pixel này sẽ trả về 10241 pixel. Các hình ảnh về cơ bản là giống nhau, nhưng lần này một máy ảnh có độ dài tiêu cự khác nhau đã được sử dụng.

Mặt trăng Mặt trăng Mặt trăng Mặt trăng Mặt trăng Mặt trăng

Các mẫu không vuông và không trung tâm với kết quả 9988:

Mặt trăng trong một khung không vuông Mặt trăng trong một khung không vuông Mặt trăng trong một khung không vuông Mặt trăng trong một khung không vuông Mặt trăng trong một khung không vuông

Ồ, bây giờ tôi không có triển khai tham chiếu và thậm chí tôi không biết liệu tôi có thể thực hiện được điều gì không. Nhưng trong não tôi có một niềm tin mãnh liệt cho tôi biết nó phải có khả năng giải toán.

Những quy định

Đây là Code Golf. Mã ngắn nhất vào 2015 / 03-30 được chấp nhận.


9
Trong tất cả các ví dụ, trung tâm của mặt trăng dường như được căn giữa trong bức tranh. Chúng ta có thể cho rằng mặt trăng sẽ luôn luôn là trung tâm?
Chấn thương kỹ thuật số

1
độ chính xác của bạn là +/- 2% trên diện tích tương ứng với +/- 1% trên đường kính: ví dụ r = 100 pixel, area = 10000 * pi; r = 101 pixel, diện tích = 10201 * pi. Hình ảnh nhỏ hơn của bạn có r = 72 do đó d = 144 vì vậy nó chỉ có thể. Đối với hình ảnh dưới d = 100, tôi nghĩ rằng độ chính xác không thể được đáp ứng, tuy nhiên.
Cấp sông St

@DigitalTrauma: trung tâm không cần phải ở giữa.
Thomas Weller

@ MartinBüttner: tỷ lệ hiển thị tối thiểu là 5% của mặt trăng hoặc 1,25% của hình ảnh.
Thomas Weller

@ MartinBüttner: ok, tôi đã cập nhật câu hỏi, cập nhật tệp pha trộn để tạo ra các hình ảnh không vuông, không tập trung theo mặc định. Bạn có thể tải xuống tất cả hình ảnh tại đây (* .png.zip) . Bộ đếm pixel cũng được cập nhật: xuất thêm một số thông tin và kiểm tra quy tắc 1,25%.
Thomas Weller

Câu trả lời:


10

Toán học 126 119 109 byte

Mathematica có thể đo độ giãn dài của một thành phần trong ảnh. Trăng tròn, đối xứng hoàn hảo, có độ giãn dài từ 0, trên thang điểm từ 0 đến 1.

Một mặt trăng giảm dần ngày càng dài ra, tối đa là khoảng 0,8.

0.998 -0.788 x-0.578 x^2 là mô hình được xác định theo kinh nghiệm (dựa trên các bức ảnh lớn) để 'dự đoán sự đầy đủ của mặt trăng (theo khu vực), với độ giãn dài của nó.

Tôi đã điều chỉnh mô hình 1- 0.788 x -0.578 x^2sao cho với độ giãn dài chính xác bằng không (trăng tròn), mô hình sẽ trả về 1 cho hệ số tỷ lệ pixel. Nó tiết kiệm 4 byte và vẫn nằm trong giới hạn chính xác.

Mô hình này được sử dụng cho bất kỳ hình ảnh kích thước. Hình ảnh mặt trăng không cần phải tập trung. Nó cũng không cần che một tỷ lệ cố định của ảnh.

Dưới đây là các điểm dữ liệu (độ giãn dài, displayMoonPixels / fullMoonPixels) cho các hình ảnh lớn và mô hình parabol được tạo ra để phù hợp với dữ liệu. Các mô hình tuyến tính phù hợp với ok, nhưng mô hình bậc hai đã chết, trong giới hạn (xem bên dưới).

Đây là dữ liệu từ những bức tranh lớn. Mô hình cũng vậy

crescents lớn


Dưới đây, dữ liệu (các điểm màu đỏ) là từ các hình ảnh nhỏ. Mô hình (đường cong màu xanh) là mô hình được tạo bởi các hình ảnh lớn, giống như mô hình được hiển thị ở trên.

Lưỡi liềm nhỏ nhất có 7,5% diện tích của trăng tròn. . Một mô hình mạnh mẽ, có thể đứng vững trong một loạt các điều kiện, bao gồm cả crescents rất nhỏ, sẽ được làm tốt hơn từ nhiều hình ảnh lớn hơn.

Sự gần gũi của sự phù hợp cho thấy rằng mô hình không được mã hóa cứng cho các hình ảnh đã cho. Chúng ta có thể khá chắc chắn rằng độ giãn dài của mặt trăng không phụ thuộc vào kích thước của bức ảnh, như người ta mong đợi.

crescents nhỏ

flấy hình ảnh, ilàm đầu vào và đầu ra kích thước dự đoán của trăng tròn, tính bằng pixel. Nó hoạt động cho các bức ảnh ngoài trung tâm.

Như dữ liệu dưới đây cho thấy, tất cả các trường hợp thử nghiệm ngoại trừ một trường hợp. Các mặt trăng được sắp xếp từ đầy đủ đến giảm dần.

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")

Nhiều thành phần hình ảnh có thể xuất hiện trong ảnh. Ngay cả một pixel tách biệt với các pixel khác sẽ được coi là một thành phần riêng biệt. Vì lý do này, cần phải tìm kiếm các thành phần "tất cả", để tìm ra thành phần có số lượng pixel lớn hơn. (Một trong những bức ảnh nhỏ có nhiều thành phần hình ảnh.)

Hình ảnh lớn

Dự đoán kích thước mặt trăng được thực hiện từ các bức ảnh lớn là chính xác thống nhất.

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

{"kích thước dự đoán của trăng tròn", {16422., 16270.9, 16420.6, 16585.5, 16126.5, 16151.6}}

{"chính xác", {1.00037, 0.991161, 1.00028, 1.01033, 0.982367, 0.983891}}


Hình ảnh nhỏ

Dự đoán kích thước mặt trăng được tạo ra từ những bức ảnh nhỏ được thống nhất, với một ngoại lệ lớn, bức ảnh cuối cùng. Tôi nghi ngờ vấn đề bắt nguồn từ thực tế là lưỡi liềm rất hẹp.

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

{"kích thước dự đoán của trăng tròn", {10247.3, 10161., 10265.6, 10391., 10058.9, 7045.91}}
{"chính xác", {1.00061, 0.992192, 1.0024, 1.01465, 0.982221, 0.68801}}


Có vẻ như tôi nên học Mathicala một ngày. Mất bao lâu để bạn giải quyết nó mà không cần chơi golf?
Thomas Weller

1
@Thomas W Phải mất 2-3 giờ thử nghiệm với nhiều loại tính năng xử lý hình ảnh và các mô hình (tuyến tính) khác cho đến khi tôi thu được biểu đồ mà bạn thấy được đăng. Việc mã hóa không quá khó khăn. Và hầu như không có môn đánh gôn nào ngoài việc hợp nhất các chức năng riêng biệt thành một chức năng duy nhất.
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

Vì lý do không rõ, #2&@@@đề xuất không hoạt động
DavidC

Huh, tôi sẽ xem xét điều đó sau. Một cách khác để rút ngắn cc=Max@ComponentMeasurements[##][[All,2]]&
Martin Ender

5

J, 227 207 byte (lỗi tối đa 1,9%)

Ý tưởng chính của tôi là nếu chúng ta có thể tìm thấy 3 điểm trên đường viền của mặt trăng nằm trên đường viền của mặt trăng thì chúng ta có thể tính đường tròn của các điểm này. Vòng tròn đó sẽ đến trăng tròn.

Nếu chúng ta tìm thấy hai điểm trắng với khoảng cách tối đa thì đó sẽ luôn là những điểm như vậy chúng sẽ là một đường chéo thực trong trăng tròn hoặc điểm cuối của hình lưỡi liềm. Chúng ta có thể tìm thấy cặp điểm có khoảng cách lớn nhất trong bất kỳ biểu đồ nào bằng cách chọn điểm xa nhất từ ​​bất kỳ điểm bắt đầu nào và sau đó chọn điểm xa nhất từ ​​điểm đã chọn.

Chúng tôi tìm thấy một điểm thứ ba với giá trị tối đa của các sản phẩm của khoảng cách từ các điểm trước đó. Điều này sẽ luôn luôn ở trên đường viền và ở phía bên ngoài của một lưỡi liềm hoặc phía lớn hơn của một con vượn.

Đường kính của đường tròn được tính là chiều dài của một bên chia cho xoang của góc đối diện.

Độ phức tạp thời gian của phương pháp này là tuyến tính theo kích thước của hình ảnh đầu vào.

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
)

Hàm này dự kiến ​​tên tệp đầu vào là một chuỗi.

(Để có (một) phiên bản dễ đọc hơn, hãy kiểm tra lịch sử sửa đổi.)

Giải thích mã

  • p là danh sách tọa độ pixel trắng (được gọi là điểm trong tương lai)
  • hàm d tính khoảng cách giữa các phần tử của p và một điểm đã cho
  • phần thứ hai của định nghĩa s tạo danh sách 3 điểm:

    • A là điểm xa nhất từ ​​điểm đầu tiên trong danh sách
    • B là điểm xa nhất từ ​​A
    • C là một điểm có giá trị cực đại của khoảng cách A lần khoảng cách từ B
  • s là độ dài cạnh của tam giác ABC

  • dòng cuối cùng tính diện tích đường tròn ngoại tiếp ABC là trăng tròn

Các kết quả

Lỗi lớn nhất là 1,9%.

Hình ảnh theo thứ tự như trong câu hỏi.

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

+1 để tham gia và đề cập đến cách tiếp cận. Tôi xin lỗi tôi đã không xác định rằng trung tâm không cần phải ở giữa. Vô tình các hình ảnh mẫu là tất cả trung tâm. Đó là lỗi của tôi.
Thomas Weller

@ThomasW. Tạm thời xóa câu trả lời của tôi cho đến khi tôi sửa nó.
ngẫu nhiên

2

Matlab 162 156 (không hoàn toàn trong lề lỗi hiện tại)

Trước hết: Độ chính xác dưới 2% cho tất cả trừ một hình ảnh trong mỗi hai loạt, trong đó độ chính xác cao hơn (khoảng 5% và 14%). Cách tiếp cận của tôi là tìm hai pixel của mặt trăng cách xa nhau nhất, và sau đó sử dụng nó làm ước tính cho đường kính.

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

Đây là các kết quả chính xác (độ lệch tương đối 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

Giải pháp này không hoạt động đối với tất cả các hình ảnh, bởi vì trên một trong các hình ảnh, độ dốc (m) trở nên vô hạn.

Nguyên tắc đã được đề cập trước đây:

  1. Tìm hai điểm có khoảng cách tối đa (màu đỏ)
  2. Hãy tưởng tượng một đường giữa chúng (màu đỏ)
  3. Hãy tưởng tượng một đường thẳng có góc hình chữ nhật ở giữa (màu xanh lá cây)
  4. Tìm điểm trắng trên đường màu xanh lá cây
  5. Sử dụng điểm có khoảng cách tối đa từ các điểm khác (màu xanh lá cây)
  6. Tính diện tích hình tròn từ ba điểm

Giải trình

Trường hợp có vấn đề là cái này, trong đó độ dốc là vô cùng. Có thể giải quyết bằng cách xoay hình ảnh 90 ° hoặc bằng mã, lặp qua ytrục thay vì x.

Mặt trăng có vấn đề

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;}

Độ chính xác tối thiểu là

  • + 1,89% cho hình ảnh 256 pixel
  • -0,55% cho hình ảnh 177 pixel
  • -1,66% cho hình ảnh không vuông
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.