Construire une matrice gaussienne

12

Le flou gaussien est une méthode utilisée pour flouter les images en douceur. Il s'agit de créer une matrice qui sera utilisée en la convoluant avec les pixels d'une image. Dans ce défi, votre tâche consiste à construire la matrice utilisée dans le flou gaussien. Vous prendrez une entrée r qui sera le rayon du flou et une entrée σ qui sera l'écart type afin de construire une matrice de dimensions (2 r + 1 × 2 r + 1). Chaque valeur de cette matrice aura une valeur ( x , y ) qui dépend de sa distance absolue dans chaque direction par rapport au centre et sera utilisée pour calculer G ( x , y ) où la formuleG est

formule

Par exemple, si r = 2, nous voulons générer une matrice 5 x 5. Premièrement, la matrice des valeurs ( x , y ) est

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

Soit ensuite σ = 1,5 et applique G à chacun ( 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

Normalement, dans le flou de l'image, cette matrice serait normalisée en prenant la somme de toutes les valeurs de cette matrice et en la divisant. Pour ce défi, cela n'est pas nécessaire et les valeurs brutes calculées par la formule sont ce que la sortie devrait être.

Règles

  • C'est le donc le code le plus court l'emporte.
  • L'entrée r sera un entier non négatif et σ sera un nombre réel positif.
  • La sortie doit représenter une matrice. Il peut être formaté comme un tableau 2D, une chaîne représentant un tableau 2D ou quelque chose de similaire.
  • Les inexactitudes en virgule flottante ne seront pas prises en compte pour vous.

Cas de 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
miles
la source
Quelle précision avons-nous besoin de pi et e pour être?
xnor
@xnor Bonne question. Si votre langue le permet, vous pouvez supposer que ces valeurs sont déjà stockées dans une variable ou quelque chose de similaire. Sinon, vous pouvez utiliser des valeurs à deux décimales faisant pi = 3,14 et e = 2,72 où vous pouvez compter chacune de ces valeurs comme un seul octet. Bien sûr, les inexactitudes dans la réponse finale ne seront pas à nouveau prises en compte.
miles
La sortie doit-elle être un nombre décimal ou pourrait-il s'agir de nombres exacts avec des constantes?
JungHwan Min
@JungHwanMin Les nombres exacts, comme ceux de Mathematica, sont corrects.
miles
1
@miles Je pense que ce serait plus facile si vous exigiez juste une certaine précision (par exemple 3 décimales).
orlp

Réponses:

7

Mathematica, 60 54 50 octets

Merci @GregMartin pour 4 octets!

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

Prend r et sigma en entrée, retourne la matrice (nombres exacts).

Version intégrée (58 octets)

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

Bien sûr, Mathematica a également une fonction intégrée pour cela, mais c'est trop long.

JungHwan Min
la source
4
Vous pouvez remplacer -lpar -#à la fin ( Arrayenfilez cela sur les deux dimensions pour vous); cela enlève le besoin de définir l, en économisant 4 octets.
Greg Martin
5

MATL , 20 octets

_G&:U&+iUE/_Ze5MYP*/

Essayez-le en ligne!

Explication

_     % 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
la source
5

Octave, 45 octets

@(r,s)exp((x=-(-r:r).^2/2/s^2)+x')/2/s^2/pi
Rainer P.
la source
4

Octave, 49 octets

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

Essayez-le en ligne!

rahnema1
la source
4

Python, 88 octets

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

Utilise la règle selon laquelle vous pouvez coder en dur 3.14 et 2.72 à un coût de 1 octet chacun.

orlp
la source
1

Perl 6 , 71 octets

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

Techniquement, cela peut être plus de 71 octets s'il est codé et enregistré dans un fichier, mais je n'ai pas pu résister à nommer l'entrée "sigma" avec un sigma grec réel. Il pourrait être renommé en n'importe quelle lettre ASCII si vous le souhaitez.

Sean
la source
1

SAS Macro Language, 296 octets

Probablement un moyen beaucoup plus efficace de le faire, mais cela fonctionne :)

Ce code imprime l'ensemble de données résultant.

%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
la source
1

Haskell, 59 octets

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

Exemple d'utilisation:

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
la source
0

Python 2.7, 167 octets

Une solution très simple:

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)

Essayez-le ici !

Non golfé:

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
la source
5
from __future__ import division, vraiment?
orlp