Zbuduj macierz Gaussa

12

Rozmycie gaussowskie to metoda stosowana do płynnego rozmycia zdjęć. Polega na stworzeniu matrycy, która będzie używana przez splotowanie jej z pikselami obrazu. W tym wyzwaniu Twoim zadaniem jest zbudowanie matrycy stosowanej w rozmyciu gaussowskim. Weźmiesz wejściowy r, który będzie promieniem rozmycia, i wejściowy σ, który będzie standardowym odchyleniem, aby skonstruować macierz o wymiarach (2 r + 1 × 2 r + 1). Każda wartość w tej macierzy będzie miała wartość ( x , y ), która zależy od jej bezwzględnej odległości w każdym kierunku od środka i będzie używana do obliczenia G ( x , y ), gdzie wzórG jest

formuła

Na przykład, jeśli r = 2, chcemy wygenerować macierz 5 x 5. Po pierwsze, macierz wartości ( x , y ) to

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

Następnie pozwól σ = 1,5 i zastosuj G do każdego ( 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

Zwykle w przypadku rozmycia obrazu matrycę normalizuje się, biorąc sumę wszystkich wartości w tej macierzy i dzieląc ją. W przypadku tego wyzwania nie jest to konieczne, a surowe wartości obliczone na podstawie formuły są tym, czym powinny być dane wyjściowe.

Zasady

  • To jest więc wygrywa najkrótszy kod.
  • Wejście r będzie nieujemną liczbą całkowitą, a σ będzie dodatnią liczbą rzeczywistą.
  • Dane wyjściowe muszą reprezentować macierz. Może być sformatowany jako tablica 2d, ciąg znaków reprezentujący tablicę 2d lub coś podobnego.
  • Niedokładności zmiennoprzecinkowe nie będą liczone przeciwko tobie.

Przypadki testowe

(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
mile
źródło
Jak dokładny jest nam wskaźnik pi i e?
xnor
@ xnor Dobre pytanie. Jeśli twój język na to pozwala, możesz założyć, że te wartości są już przechowywane w zmiennej lub w podobnym celu. Jeśli nie, możesz użyć wartości z dokładnością do dwóch miejsc po przecinku, co daje pi = 3,14 i e = 2,72, gdzie możesz policzyć każdą z tych wartości jako pojedynczy bajt. Oczywiście, niedokładności w ostatecznej odpowiedzi nie będą ponownie liczone przeciwko tobie.
mil
Czy wynik musi być liczbą dziesiętną, czy może to być dokładne liczby ze stałymi w nich?
JungHwan Min.
@JungHwanMin Dokładne liczby, takie jak te w Mathematica, są w porządku.
mil
1
@miles Myślę, że byłoby łatwiej, gdybyś po prostu wprowadził określoną dokładność (np. 3 miejsca po przecinku).
lub

Odpowiedzi:

7

Mathematica, 60 54 50 bajtów

Dzięki @GregMartin za 4 bajty!

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

Pobiera r i sigma jako dane wejściowe, zwraca macierz (dokładne liczby).

Wersja wbudowana (58 bajtów)

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

Oczywiście Mathematica ma też do tego wbudowaną funkcję, ale jest za długa.

JungHwan Min
źródło
4
Można zastąpić -lprzez -#na końcu ( Arraybędzie wątek, który w ciągu dwóch wymiarach dla ciebie); eliminuje potrzebę definiowania l, oszczędzając 4 bajty.
Greg Martin
5

MATL , 20 bajtów

_G&:U&+iUE/_Ze5MYP*/

Wypróbuj online!

Wyjaśnienie

_     % 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
Luis Mendo
źródło
5

Oktawa, 45 bajtów

@(r,s)exp((x=-(-r:r).^2/2/s^2)+x')/2/s^2/pi
Rainer P.
źródło
4

Oktawa, 49 bajtów

@(r,q)1./((Q=2*q^2)*pi*e.^(((x=(-r:r).^2)+x')/Q))

Wypróbuj online!

rahnema1
źródło
4

Python, 88 bajtów

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

Korzysta z reguły, w której możesz kodować na stałe 3,14 i 2,72 po 1 bajcie kosztu.

orlp
źródło
1

Perl 6 , 71 bajtów

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

Technicznie może to być więcej niż 71 bajtów, jeśli jest zakodowane i zapisane w pliku, ale nie mogłem się oprzeć nazwaniu wejścia „sigma” rzeczywistą sigmą grecką. Można go zmienić na dowolną literę ASCII, jeśli ktoś chce.

Sean
źródło
1

SAS Macro Language, 296 bajtów

Prawdopodobnie o wiele bardziej wydajny sposób, ale działa :)

Ten kod drukuje wynikowy zestaw danych.

%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;
J_Lard
źródło
1

Haskell, 59 bajtów

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

Przykład użycia:

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]]
nimi
źródło
0

Python 2.7, 167 bajtów

Bardzo proste rozwiązanie:

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)

Wypróbuj tutaj !

Nie golfowany:

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)
Calconym
źródło
5
from __future__ import divisionnaprawdę?
lub