Построить гауссову матрицу


12

Размытие по Гауссу - это метод, используемый для плавного размытия изображений. Это включает в себя создание матрицы, которая будет использоваться путем свертки ее с пикселями изображения. В этой задаче ваша задача - построить матрицу, используемую в размытии по Гауссу. Вы возьмете вход r, который будет радиусом размытия, и вход σ, который будет стандартным отклонением, чтобы построить матрицу с размерами (2 r + 1 × 2 r + 1). Каждое значение в этой матрице будет иметь значение ( x , y ), которое зависит от его абсолютного расстояния в каждом направлении от центра и будет использоваться для вычисления G ( x , y ), где формулаG это

формула

Например, если r = 2, мы хотим сгенерировать матрицу 5 x 5. Во-первых, матрица значений ( 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)

Тогда пусть σ = 1,5 и применим G к каждому ( 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

Обычно при размытии изображения эта матрица нормализуется путем взятия суммы всех значений в этой матрице и деления на нее. Для этой задачи это не нужно, и необработанные значения, рассчитанные по формуле, - это то, каким должен быть результат.

правила

  • Это поэтому выигрывает самый короткий код.
  • Входное значение r будет неотрицательным целым числом, а σ будет положительным действительным числом.
  • Выходные данные должны представлять матрицу. Он может быть отформатирован как 2d массив, строка, представляющая 2d массив, или что-то подобное.
  • Неточности с плавающей точкой не будут засчитаны против вас.

Тестовые случаи

(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

Насколько точно нам нужно пи и е, чтобы быть?
xnor

@xnor Хороший вопрос. Если ваш язык позволяет, вы можете предположить, что эти значения уже хранятся в переменной или что-то подобное. Если нет, вы можете использовать значения с двумя десятичными разрядами, делая pi = 3,14 и e = 2,72, где вы можете считать каждое из этих значений как один байт. Конечно, неточности в окончательном ответе больше не будут засчитываться против вас.
миль

Должен ли вывод быть десятичным числом или это могут быть точные числа с константами в них?
JungHwan Мин

@JungHwanMin Точные цифры, такие как в Mathematica, в порядке.
миль

1
@ Мили Я думаю, было бы проще, если бы вы просто указали определенную точность (например, 3 знака после запятой).
orlp

Ответы:


7

Mathematica, 60 54 50 байт

Спасибо @GregMartin за 4 байта!

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

Принимает r и sigma в качестве входных данных, возвращает матрицу (точные числа).

Встроенная версия (58 байт)

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

Конечно, в Mathematica тоже есть встроенный модуль, но он слишком длинный.


4
Вы можете заменить -lна -#конце ( Arrayбудет нить , что по обоим размерам для вас); это устраняет необходимость определения l, сохраняя 4 байта.
Грег Мартин

5

MATL , 20 байтов

_G&:U&+iUE/_Ze5MYP*/

Попробуйте онлайн!

объяснение

_     % 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 байт

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

Использует правило, в котором вы можете жестко закодировать 3.14 и 2.72 по цене 1 байт каждая.


1

Perl 6 , 71 байт

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

Технически это может быть больше 71 байта, если закодировано и сохранено в файл, но я не смог удержаться от того, чтобы назвать вход «сигма» действительной греческой сигмой. При желании его можно переименовать в любое простое ASCII-письмо.


1

Язык макросов SAS, 296 байт

Вероятно, гораздо более эффективный способ сделать это, но это работает :)

Этот код распечатывает результирующий набор данных.

%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 байт

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

Пример использования:

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 байт

Очень простое решение:

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)

Попробуй это здесь !

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, действительно?
orlp
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.