Обчисліть розмір Місяця


19

Розмір місячної таємниці

Я впевнений, що ви чули, що Місяць змінює свої розміри. Коли ви закохані і вам пощастило, Місяць майже вдвічі більший порівняно зі звичайними ситуаціями. Деякі люди кажуть, що причина - атмосфера, яка виступає в ролі лінзи. Інші вважають, що це лише питання порівняння з іншими об’єктами, такими як дерева поблизу. Яке б пояснення ви не читали, воно досить суб'єктивне.

Розмір місячної науки

Гаразд, ми програмісти, чи не так? Ми покладаємось на факти, правда? Отже ось експеримент:

  1. Візьміть гарну камеру, яка підтримує час налаштування та діафрагму вручну.
  2. Встановіть камеру на максимальний рівень збільшення.
  3. Вийдіть, зробіть кілька фотографій Місяця, щоб виявити найкращі настройки, щоб місяць був різким, а освітлення було чудовим.
  4. Запам’ятайте налаштування
  5. Робіть фотографії Місяця з тими налаштуваннями щоразу, коли вам здається, що місяць великий чи малий.
  6. Обчисліть розмір Місяця в пікселях

Камера не бреше, чи не так? Підраховуючи яскраві пікселі, ми можемо ефективно виміряти розмір Місяця - принаймні в пікселях.

Якщо розмір однаковий на всіх фотографіях, то це помилка в нашому мозку. Якщо розмір відрізняється, то є місце для спекуляцій

  • Місяць справді росте (але що це їсть?)
  • є атмосферний ефект лінзи
  • Місяць має еліптичну криву і іноді ближче, іноді далі від землі
  • ...

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

Завдання

З огляду на кілька оптимізованих зображень Місяця, будь ласка, обчисліть розмір Місяця. Оптимізація така: пікселі або чорні, або білі. Нічого між ними. Ніякого антиалійного. Це робить його легко, чи не так?

Застереження: місяць не завжди повний, знаєте ... це може бути серп! Але навіть у формі серпа розмір Місяця більший. Тож ви підрахуєте повний розмір, будь ласка.

  • Ваша програма приймає PNG як вхідний файл, наприклад, як аргумент командного рядка імені файлів, переданий в stdinоб'єкт Bitmap або як об'єкт Bitmap (стандартної бібліотеки фреймворків), якщо ви пишете функцію замість програми.
  • Ваша програма працює з будь-яким розумним вхідним растровим розміром, не обов'язково квадратним. Мінімальна ширина та висота 150 пікселів гарантуються.
  • Повний місяць охоплює щонайменше 25% малюнка.
  • Ваша програма виводить обчислений розмір Місяця в пікселях так, ніби це був повний місяць.
  • Ми припускаємо, що Місяць - це досконала сфера.
  • Точний розмір завжди є цілим числом, але ви можете виводити десятковий номер, якщо ваш розрахунок повертає це.
  • Точність повинна бути від 98% до 102%. (Це швидше здогадка, ніж те, що я міг би гарантувати, що можна досягти. Якщо ви вважаєте, що це занадто важко досягти, залиште коментар.)

Оновлення :

  • Центр Місяця не обов’язково посередині малюнка.
  • Мінімальна видима площа - 5% місяця або 1,25% від загальної кількості пікселів.
  • Знімок зроблений таким чином, щоб цілий місяць відповідав зображенню, тобто загальна кількість пікселів - це верхня межа розміру місяця.
  • Місяць не буде обрізаний / обрізаний.

Зразки

Ви можете генерувати власні зразки, використовуючи файл blend, якщо хочете. Я створив для вас наступні малюнки. Ви можете порахувати пікселі у PNG-файлі за допомогою WhitePixelCounter.exe (потрібен .NET), щоб перевірити, чи містить зображення лише чорно-білі пікселі та скільки їх.

Наведені нижче зображення розміром 256x256 пікселів відрізняються кількістю білих пікселів, але все це повинно спричинити обчислений розмір місяця 16416 пікселів.

Повний місяць Місяць Місяць Місяць Місяць Місяць

І ці зображення розміром 177x177 пікселів повинні повертати 10241 пікселів. Зображення в основному однакові, але цього разу була використана камера з різною фокусною відстанню.

Місяць Місяць Місяць Місяць Місяць Місяць

Неквадратні та нецентричні зразки з результатом 9988:

Місяць у неквадратичній рамці Місяць у неквадратичній рамці Місяць у неквадратичній рамці Місяць у неквадратичній рамці Місяць у неквадратичній рамці

О, у мене поки що немає еталонної реалізації, і я навіть не знаю, чи здатний я щось реалізувати. Але в моєму мозку є тверда віра, яка говорить мені, що вона повинна бути вирішена математично.

Правила

Це Code Golf. Найкоротший код на 2015-03-30 приймається.


9
У всіх прикладах центр Місяця, як видається, знаходиться в центрі зображення. Чи можна припустити, що Місяць завжди буде зосереджений?
Цифрова травма

1
ваша точність +/- 2% на площу відповідає +/- 1% по діаметру: приклад r = 100 пікселів, площа = 10000 * пі; r = 101 піксель, площа = 10201 * пі. Ваша менша картинка має r = 72, тому d = 144, тому це просто повинно бути можливим. Щодо зображень нижче d = 100, я думаю, що точність досягти не вдалося.
Річка Рівня Св.

@DigitalTrauma: центр не повинен бути посередині.
Томас Веллер

@ MartinBüttner: мінімальний видимий відсоток становить 5% місяця або 1,25% зображення.
Томас Веллер

@ MartinBüttner: гаразд, я оновив питання, оновив файл суміші для отримання неквадратичних нецентричних зображень за замовчуванням. Ви можете завантажити всі зображення тут (* .png.zip) . Оновлений лічильник пікселів: виводить ще трохи інформації та перевіряє правило 1,25%.
Томас Веллер

Відповіді:


10

Mathematica 126 119 109 байт

Mathematica може вимірювати подовження компонента в зображенні. Повний місяць, будучи ідеально симетричним, має подовження 0, за шкалою від 0 до 1.

Зменшується місяць стає все більш витягнутим, максимум приблизно до 0,8.

0.998 -0.788 x-0.578 x^2 була емпірично визначена модель (заснована на великих фотографіях) для `передбачення повноти Місяця (за площею), враховуючи його подовження.

Я відкоригував модель 1- 0.788 x -0.578 x^2так, що з точно нульовим подовженням (повний місяць) модель поверне 1 для коефіцієнта масштабу пікселя. Він економить 4 байти і все ще залишається в межах точності.

Ця модель використовується для зображень будь-якого розміру. Зображення місяця не потрібно зосереджувати. Також не потрібно висвітлювати фіксовану частку фотографії.

Тут представлені точки даних (подовження, відображеніMoonPixels / fullMoonPixels) для великих зображень та параболічна модель, яка була створена для відповідності даним. Лінійні моделі підходять нормально, але квадратична модель похила, в межах (див. Нижче).

Тут дані з великих зображень. Так само і модель

великі півмісяці


Нижче дані (червоні точки) - із невеликих картинок. Модель (синя крива) - це та, яка генерується великими картинками, та сама, що відображена вище.

Найменший півмісяць має 7,5% площі повного місяця. (Найменший півмісяць серед великих фотографій - це 19% повного місяця.) Якби квадратична модель базувалася на невеликих фотографіях, розміщення внизу було б краще, лише тому, що воно вмістило малий півмісяць. Надійна модель, яка стояла б при широкому діапазоні умов, включаючи дуже маленькі півмісяці, краще було б зробити з великого різноманіття картин.

Близькість прилягання показує, що модель не була чітко кодована для даних фотографій. Ми можемо бути впевнені, що подовження місяця не залежить від розміру фотографії, як можна було б очікувати.

невеликі півмісяці

fприймає зображення, iяк вхід і виводить передбачуваний розмір повного місяця, у пікселях. Він працює для кадрів поза центром.

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

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

На фотографії може з’явитися більше одного компонента зображення. Навіть один піксель, відокремлений від інших, буде вважатися окремим компонентом. З цієї причини необхідно здійснити пошук "всіх" компонентів, щоб знайти той, який має більшу кількість пікселів. (Одна з невеликих фотографій містить більше одного компонента зображення.)

Великі малюнки

Прогнози розміру місяця, зроблені на великих фотографіях, були однаково точними.

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

{"передбачувані розміри повного місяця", {16422., 16270.9, 16420.6, 16585.5, 16126.5, 16151.6}}

{"точність", {1.00037, 0.991161, 1.00028, 1.01033, 0.982367, 0.983891}}


Невеликі малюнки

Прогнози розміру місяця, зроблені з невеликих фотографій, були рівномірно, за одним великим винятком, підсумковою картиною. Я підозрюю, що питання пов'язане з тим, що півмісяць дуже вузький.

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

{"передбачувані розміри повного місяця", {10247.3, 10161., 10265.6, 10391., 10058.9, 7045.91}}
{"точність", {1.00061, 0.992192, 1.0024, 1.01465, 0.982221, 0.68801}}


Здається, я повинен вивчити Mathematica одного дня. Скільки часу вам знадобилося вирішити це без гольфу?
Томас Веллер

1
@Thomas W Минуло 2-3 години, експериментуючи з різними функціями обробки зображень та іншими (лінійними) моделями, поки я не отримав графік, який ви бачите у розміщенні. Кодування було не дуже складно. І майже немає гольфу, крім об'єднання окремих функцій в одну функцію.
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")
Мартін Ендер

З незрозумілих причин #2&@@@пропозиція не працює
DavidC

Ага, я розгляну це пізніше. Інший спосіб скоротити cцеc=Max@ComponentMeasurements[##][[All,2]]&
Мартін Ендер

5

J, 227 207 байт (максимальна помилка 1,9%)

Моя основна ідея полягає в тому, що якщо ми зможемо знайти 3 точки по контуру Місяця, які знаходяться і по контуру повного Місяця, ми можемо обчислити окружність цих точок. Це окружність буде до повного місяця.

Якщо ми знайдемо дві білі точки з максимальною відстані, вони завжди будуть такими точками, оскільки вони будуть або справжньою діагоналлю в повний місяць, або кінцевими точками півмісяця. Ми можемо знайти пару точок з найбільшою відстані в будь-якому графіку, вибравши крайню точку від будь-якої заданої початкової точки, а потім вибравши крайню точку з обраної.

Ми знаходимо третю точку з максимальним значенням добутків відстаней від попередніх точок. Це завжди буде по контуру і на зовнішній стороні півмісяця або на більшій стороні гіблу.

Діаметр обрізу обчислюється як довжина однієї сторони, поділена на синус протилежного кута.

Часова складність цього способу лінійна за розміром вхідного зображення.

Код

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
)

Функція очікує назви вхідного файлу у вигляді рядка.

(Для (трохи) більш читаної версії перевірити історію версій.)

Пояснення коду

  • p - список координат білого пікселя (називаються точки в майбутньому)
  • функція d обчислює відстані між елементами p і заданою точкою
  • друга частина визначення s створює 3-точковий список:

    • A - це найдальша точка від першої точки списку
    • B - найдальша точка від А
    • C - точка з максимальним значенням відстані у формі A, відстань від B
  • s - бічні довжини трикутника ABC

  • останній рядок обчислює площу навколо окружності ABC, яка є повним місяцем

Результати

Найбільша помилка - 1,9%.

Зображення в тому ж порядку, як у запитанні.

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 за участь та згадування підходу. Вибачте, що я не вказав, що центр не повинен бути посередині. Випадково образові зображення зосереджені по центру. Це моя вина.
Томас Веллер

@ThomasW. Тимчасово видалив свою відповідь, поки я не виправлю її.
randomra

2

Matlab 162 156 (не зовсім в поточній межі помилок)

Перш за все: точність становить менше 2% для всіх, крім одного зображення у кожній із двох серій, де вона більша (приблизно 5% та 14%). Мій підхід був пошук двох пікселів Місяця, які розташовані найдалі один від одного, а потім використання цього в якості оцінки діаметра.

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

Це результати точності (відштовхувальне відхилення 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

Це рішення працює не для всіх зображень, оскільки на одному із зображень нахил (m) стає нескінченним.

Принцип згадувався раніше:

  1. Знайдіть два бали з максимальною відстані (червоний)
  2. Уявіть лінію між ними (червона)
  3. Уявіть лінію з прямокутним кутом посередині (зелений)
  4. Знайдіть білі точки на зеленій лінії
  5. Використовуйте таку, яка має максимальну відстань від інших точок (зелена)
  6. Обчисліть площу кола з трьох точок

Пояснення

Проблемним випадком є ​​цей, де ухил - нескінченність. Вирішити це можливо, обертаючи зображення на 90 ° або в коді, перекидайте yвісь замість осі x.

Проблемний місяць

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

Мінімальна точність

  • + 1,89% для 256-піксельних зображень
  • -0,55% на зображення 177 пікселів
  • -1,66% для не квадратних зображень
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.