Побудуйте матрицю Гаусса


12

Гауссова розмитість - метод, що використовується для плавного розмивання зображень. Він передбачає створення матриці, яка буде використовуватися шляхом згортання її з пікселями зображення. У цьому завданні ваше завдання полягає в тому, щоб побудувати ту матрицю, яку використовують у розмитті Гаусса. Ви візьмете вхід r, який буде радіусом розмиття, і вхід σ, який буде стандартним відхиленням для побудови матриці з розмірами (2 r + 1 × 2 r + 1). Кожне значення в цій матриці матиме значення ( x , y ), яке залежить від його абсолютної відстані в кожному напрямку від центру і буде використовуватися для обчислення G ( x , y ), де формулаГ є

формула

Наприклад, якщо r = 2, ми хочемо генерувати матрицю 5 x 5. По-перше, матриця значень ( x , y ) є

(2, 2) (1, 2) (0, 2) (1, 2) (2, 2)
(2, 1) (1, 1) (0, 1) (1, 1) (2, 1)
(2, 0) (1, 0) (0, 0) (1, 0) (2, 0)
(2, 1) (1, 1) (0, 1) (1, 1) (2, 1)
(2, 2) (1, 2) (0, 2) (1, 2) (2, 2)

Тоді нехай σ = 1,5 і застосуємо G до кожного ( x , y )

0.0119552 0.0232856 0.0290802 0.0232856 0.0119552
0.0232856 0.0453542 0.0566406 0.0453542 0.0232856
0.0290802 0.0566406 0.0707355 0.0566406 0.0290802
0.0232856 0.0453542 0.0566406 0.0453542 0.0232856
0.0119552 0.0232856 0.0290802 0.0232856 0.0119552

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

Правила

  • Це тому найкоротший код виграє.
  • Вхід r буде невід’ємним цілим числом, а σ - додатним дійсним числом.
  • Вихід повинен представляти матрицю. Він може бути відформатований як 2d масив, рядок, що представляє 2d масив, або щось подібне.
  • Неточності з плаваючою комою не будуть зараховані проти вас.

Випробування

(r, σ) = (0, 0.25)
2.54648

(1, 7)
0.00318244 0.00321509 0.00318244
0.00321509 0.00324806 0.00321509
0.00318244 0.00321509 0.00318244

(3, 2.5)
0.00603332 0.00900065 0.0114421  0.012395 0.0114421 0.00900065 0.00603332
0.00900065  0.0134274 0.0170696 0.0184912 0.0170696  0.0134274 0.00900065
 0.0114421  0.0170696 0.0216997  0.023507 0.0216997  0.0170696  0.0114421
  0.012395  0.0184912  0.023507 0.0254648  0.023507  0.0184912   0.012395
 0.0114421  0.0170696 0.0216997  0.023507 0.0216997  0.0170696  0.0114421
0.00900065  0.0134274 0.0170696 0.0184912 0.0170696  0.0134274 0.00900065
0.00603332 0.00900065 0.0114421  0.012395 0.0114421 0.00900065 0.00603332

(4, 3.33)
0.00339074 0.00464913 0.00582484 0.00666854 0.00697611 0.00666854 0.00582484 0.00464913 0.00339074
0.00464913 0.00637454 0.00798657  0.0091434 0.00956511  0.0091434 0.00798657 0.00637454 0.00464913
0.00582484 0.00798657  0.0100063  0.0114556   0.011984  0.0114556  0.0100063 0.00798657 0.00582484
0.00666854  0.0091434  0.0114556   0.013115  0.0137198   0.013115  0.0114556  0.0091434 0.00666854
0.00697611 0.00956511   0.011984  0.0137198  0.0143526  0.0137198   0.011984 0.00956511 0.00697611
0.00666854  0.0091434  0.0114556   0.013115  0.0137198   0.013115  0.0114556  0.0091434 0.00666854
0.00582484 0.00798657  0.0100063  0.0114556   0.011984  0.0114556  0.0100063 0.00798657 0.00582484
0.00464913 0.00637454 0.00798657  0.0091434 0.00956511  0.0091434 0.00798657 0.00637454 0.00464913
0.00339074 0.00464913 0.00582484 0.00666854 0.00697611 0.00666854 0.00582484 0.00464913 0.00339074

Наскільки точними нам потрібні пі та е?
xnor

@xnor Добре запитання. Якщо ваша мова дозволяє, ви можете припустити, що ці значення вже зберігаються в змінній або щось подібне. Якщо ні, то ви можете використовувати значення для двох знаків після коми, роблячи pi = 3,14 і e = 2,72, де ви можете рахувати кожне з цих значень як один байт. Звичайно, неточності в остаточній відповіді знову не будуть зараховані проти вас.
миль

Чи має виведення бути десятковим числом, чи це можуть бути точні числа із константами в них?
JungHwan Min

@JungHwanMin Точні цифри, наприклад, у Mathematica, є нормальними.
миль

1
@miles Я думаю, що було б простіше, якби ви просто доручили певну точність (наприклад, 3 знаки після коми).
orlp

Відповіді:


7

Математика, 60 54 50 байт

Дякую @GregMartin за 4 байти!

Array[s=2#2^2;E^(-{##}.{##}/s)/π/s&,1+2{#,#},-#]&

Бере r і sigma як вхід, повертає матрицю (точні числа).

Вбудована версія (58 байт)

GaussianMatrix[{##},Standardized->1<0,Method->"Gaussian"]&

Звичайно, в Mathematica є вбудований і для цього, але це занадто довго.


4
Ви можете замінити -lна -#кінці ( Arrayбуде нитка , що за обома розмірами для вас); що забирає необхідність визначення l, зберігаючи 4 байти.
Грег Мартін

5

MATL , 20 байт

_G&:U&+iUE/_Ze5MYP*/

Спробуйте в Інтернеті!

Пояснення

_     % Take input r implicitly. Negate
G     % Push r again
&:    % Binary range: [-r -r+1 ... r]
U     % Square, elementwise
&+    % Matrix of all pairwise additions
i     % Take input σ
U     % Square
E     % Multiply by 2. Gives 2σ^2
/     % Divide
_     % Negate
Ze    % Exponential
5M    % Push 2σ^2 again
YP    % Push pi
*     % Multiply
/     % Divide. Display implicitly



4

Пітон, 88 байт

lambda r,s:[[.5/3.14/s/s/2.72**((x*x+y*y)/2/s/s)for x in range(-r,r+1)]for y in range(-r,r+1)]

Використовується правило, коли ви можете жорстко кодувати 3,14 та 2,72 за 1 байт.


1

Perl 6 , 71 байт

->\r,\σ{map ->\y{map ->\x{exp((x*x+y*y)/-2/σ/σ)/2/pi/σ/σ},-r..r},-r..r}

Технічно це може бути більше, ніж 71 байт, якщо їх закодувати і зберегти у файл, але я не міг протистояти називанню входу "sigma" фактичною грецькою сигмою. Він може бути перейменований на будь-який звичайний лист ASCII, якщо хочете.


1

Мова макросів SAS, 296 байт

Можливо, набагато ефективніший спосіб це зробити, але це працює :)

Цей код друкує отриманий набір даних.

%macro G(r,s);%let l=%eval(2*&r+1);%let pi=%sysfunc(constant(pi));data w;array a[*] t1-t&l;%do i=-&r %to &r;%do j=-&r %to &r;%let t=%sysfunc(sum(&j,&r,1));a[&t]=%sysevalf(1/(2*&pi*&s**2)*%sysfunc(exp(-(%sysfunc(abs(&j))**2+%sysfunc(abs(&i))**2)/(2*&s**2))));%end;output;%end;proc print;run;%mend;

1

Haskell, 59 байт

r#s|i<-[-r..r]=[[exp(-(x*x+y*y)/2/s/s)/2/pi/s/s|x<-i]|y<-i]

Приклад використання:

1#7

[[3.1824449424224664e-3,3.2150851187016326e-3,3.1824449424224664e-3],
 [3.2150851187016326e-3,3.2480600630999047e-3,3.2150851187016326e-3],
 [3.1824449424224664e-3,3.2150851187016326e-3,3.1824449424224664e-3]]

0

Python 2.7, 167 байт

Дуже просте рішення:

from __future__ import division;from math import*;r,s=input();s*=2*s;R=range(-r,r+1);print"\n".join("\t".join(str(pow(e,-(x*x+y*y)/s)/(pi*s))[:9]for x in R)for y in R)

Спробуйте тут !

Безголівки:

from __future__ import division
from math import *
r,s = input()                         # Take input
s *= 2*s                              # Set s = 2*s^2; simplifies the expression
R = range(-r,r+1)                     # Range object; used twice

                                   # G(x,y)             # Stripped
print "\n".join("\t".join(str(pow(e,-(x*x + y*y)/s)/(pi*s))[:9] for x in R) for y in R)

5
from __future__ import division, справді?
orlp
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.