Costruisci una matrice gaussiana


12

La sfocatura gaussiana è un metodo usato per sfocare le immagini senza problemi. Implica la creazione di una matrice che verrà utilizzata contorcendola con i pixel di un'immagine. In questa sfida, il tuo compito è costruire quella matrice usata nella sfocatura gaussiana. Prenderai un input r che sarà il raggio della sfocatura e un input σ che sarà la deviazione standard per costruire una matrice con dimensioni (2 r + 1 × 2 r + 1). Ogni valore in quella matrice avrà un valore ( x , y ) che dipende dalla sua distanza assoluta in ciascuna direzione dal centro e sarà usato per calcolare G ( x , y ) dove la formulaG è

formula

Ad esempio, se r = 2, vogliamo generare una matrice 5 x 5. Innanzitutto, la matrice dei valori ( 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)

Quindi, lascia σ = 1.5 e applica G a ciascuno ( 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

Normalmente nella sfocatura delle immagini, questa matrice sarebbe normalizzata prendendo la somma di tutti i valori in quella matrice e dividendola per essa. Per questa sfida, ciò non è necessario e i valori grezzi calcolati dalla formula sono quelli che dovrebbero essere i risultati.

Regole

  • Questo è quindi vince il codice più corto.
  • L'ingresso r sarà un numero intero non negativo e σ sarà un numero reale positivo.
  • L'output deve rappresentare una matrice. Può essere formattato come un array 2d, una stringa che rappresenta un array 2d o qualcosa di simile.
  • Le imprecisioni in virgola mobile non verranno conteggiate nei tuoi confronti.

Casi test

(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

Quanto precisi abbiamo bisogno di pi ed e per essere?
xnor

@xnor Buona domanda. Se la tua lingua lo consente, puoi presumere che tali valori siano già memorizzati in una variabile o qualcosa di simile. In caso contrario, è possibile utilizzare i valori con due cifre decimali facendo pi = 3.14 ed e = 2.72 in cui è possibile contare ciascuno di quei valori come un singolo byte. Naturalmente, le inesattezze nella risposta finale non verranno conteggiate nuovamente contro di te.
miglia

L'output deve essere un numero decimale o potrebbero essere numeri esatti con costanti in essi?
JungHwan Min

@JungHwanMin I numeri esatti, come quelli di Mathematica, vanno bene.
miglia

1
@miles Penso che sarebbe più semplice se si imponesse una certa precisione (ad es. 3 cifre decimali).
orlp

Risposte:


7

Mathematica, 60 54 50 byte

Grazie @GregMartin per 4 byte!

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

Prende r e sigma come input, restituisce la matrice (numeri esatti).

Versione integrata (58 byte)

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

Certo, anche Mathematica ha un built-in per questo, ma è troppo lungo.


4
Puoi sostituirlo -lcon -#alla fine ( Arrayinserirai il thread su entrambe le dimensioni); che elimina la necessità di definire l, salvando 4 byte.
Greg Martin,

5

MATL , 20 byte

_G&:U&+iUE/_Ze5MYP*/

Provalo online!

Spiegazione

_     % 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

5

Ottava, 45 byte

@(r,s)exp((x=-(-r:r).^2/2/s^2)+x')/2/s^2/pi


4

Python, 88 byte

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

Utilizza la regola in cui è possibile codificare 3.14 e 2.72 al costo di 1 byte ciascuno.


1

Perl 6 , 71 byte

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

Tecnicamente questo può essere più di 71 byte se codificato e salvato in un file, ma non ho resistito a nominare l'input "sigma" con un vero sigma greco. Potrebbe essere rinominato in qualsiasi lettera ASCII semplice se si desidera.


1

SAS Macro Language, 296 byte

Probabilmente un modo molto più efficiente per farlo ma funziona :)

Questo codice stampa il set di dati risultante.

%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 byte

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

Esempio di utilizzo:

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 byte

Una soluzione molto semplice:

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)

Provalo qui !

Ungolfed:

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, veramente?
orlp
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.