Construir una matriz gaussiana

12

El desenfoque gaussiano es un método utilizado para desenfocar imágenes suavemente. Se trata de crear una matriz que se utilizará convolucionarla con los píxeles de una imagen. En este desafío, su tarea es construir esa matriz utilizada en el desenfoque gaussiano. Tomará una entrada r que será el radio del desenfoque y una entrada σ que será la desviación estándar para construir una matriz con dimensiones (2 r + 1 × 2 r + 1). Cada valor en esa matriz tendrá un valor ( x , y ) que depende de su distancia absoluta en cada dirección desde el centro y se usará para calcular G ( x , y ) donde la fórmulaG es

fórmula

Por ejemplo, si r = 2, queremos generar una matriz de 5 x 5. Primero, la matriz de valores ( x , y ) es

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

Luego, deje σ = 1.5 y aplique G a cada uno ( 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 en el desenfoque de la imagen, esta matriz se normalizaría tomando la suma de todos los valores en esa matriz y dividiéndola por ella. Para este desafío, eso no es necesario y los valores brutos calculados por la fórmula es lo que debería ser la salida.

Reglas

  • Este es el por lo que gana el código más corto.
  • La entrada r será un número entero no negativo y σ será un número real positivo.
  • La salida debe representar una matriz. Se puede formatear como una matriz 2d, una cadena que representa una matriz 2d, o algo similar.
  • Las imprecisiones de punto flotante no se contarán en su contra.

Casos de prueba

(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
millas
fuente
¿Cuán precisos necesitamos que sean pi y e?
xnor
@xnor Buena pregunta. Si su idioma lo permite, puede suponer que esos valores ya están almacenados en una variable o algo similar. De lo contrario, puede usar valores con dos decimales, haciendo pi = 3.14 y e = 2.72, donde puede contar cada uno de esos valores como un solo byte. Por supuesto, las inexactitudes en la respuesta final no se contarán en su contra nuevamente.
millas
¿La salida tiene que ser un número decimal, o podrían ser números exactos con constantes?
JungHwan Min
@JungHwanMin Los números exactos, como los de Mathematica, están bien.
millas
1
@miles Creo que sería más fácil si solo exigiera una cierta precisión (por ejemplo, 3 decimales).
orlp

Respuestas:

7

Mathematica, 60 54 50 bytes

¡Gracias @GregMartin por 4 bytes!

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

Toma r y sigma como entrada, devuelve la matriz (números exactos).

Versión incorporada (58 bytes)

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

Por supuesto, Mathematica también tiene una función incorporada para esto, pero es demasiado larga.

JungHwan Min
fuente
44
Puede reemplazar -lpor -#al final ( Arraylo enhebrará en ambas dimensiones por usted); eso elimina la necesidad de definir l, ahorrando 4 bytes.
Greg Martin
5

MATL , 20 bytes

_G&:U&+iUE/_Ze5MYP*/

Pruébalo en línea!

Explicación

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

Octava, 45 bytes

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

Python, 88 bytes

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

Utiliza la regla donde puede codificar 3.14 y 2.72 a 1 byte cada uno.

orlp
fuente
1

Perl 6 , 71 bytes

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

Técnicamente, esto puede tener más de 71 bytes si está codificado y guardado en un archivo, pero no pude resistir nombrar la entrada "sigma" con una sigma griega real. Se podría cambiar el nombre a cualquier letra ASCII simple si se quisiera.

Sean
fuente
1

Lenguaje de macros SAS, 296 bytes

Probablemente sea una forma mucho más eficiente de hacer esto, pero funciona :)

Este código imprime el conjunto de datos resultante.

%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
fuente
1

Haskell, 59 bytes

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

Ejemplo de uso:

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
fuente
0

Python 2.7, 167 bytes

Una solución muy 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)

Pruébalo aquí !

Sin 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
fuente
55
from __future__ import division, ¿De Verdad?
orlp