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

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.


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



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.


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.


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;

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

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)

5
from __future__ import divisionnaprawdę?
lub
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.