Xây dựng ma trận Gaussian


12

Gaussian Blur là một phương pháp được sử dụng để làm mờ hình ảnh một cách mượt mà. Nó liên quan đến việc tạo ra một ma trận sẽ được sử dụng bằng cách kết hợp nó với các pixel của hình ảnh. Trong thử thách này, nhiệm vụ của bạn là xây dựng ma trận được sử dụng trong mờ Gaussian. Bạn sẽ mất một đầu vào r mà sẽ là bán kính mờ và một đầu vào σ đó sẽ là độ lệch chuẩn để xây dựng một ma trận với kích thước (2 r + 1 × 2 r + 1). Mỗi giá trị trong ma trận đó sẽ có giá trị ( x , y ) phụ thuộc vào khoảng cách tuyệt đối của nó theo từng hướng từ tâm và sẽ được sử dụng để tính G ( x , y ) trong đó công thứcG

công thức

Ví dụ: nếu r = 2, chúng tôi muốn tạo ma trận 5 x 5. Đầu tiên, ma trận của các giá trị ( x , y ) là

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

Sau đó, chúng ta hãy σ = 1,5 và áp dụng G với nhau ( 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

Thông thường trong làm mờ hình ảnh, ma trận này sẽ được chuẩn hóa bằng cách lấy tổng của tất cả các giá trị trong ma trận đó và chia cho nó. Đối với thử thách này, điều đó là không cần thiết và các giá trị thô được tính theo công thức là đầu ra phải là gì.

Quy tắc

  • Đây là nên mã ngắn nhất sẽ thắng.
  • Đầu vào r sẽ là số nguyên không âm và σ sẽ là số thực dương.
  • Đầu ra phải đại diện cho một ma trận. Nó có thể được định dạng như một mảng 2d, một chuỗi đại diện cho một mảng 2d hoặc một cái gì đó tương tự.
  • Không chính xác điểm nổi sẽ không được tính vào bạn.

Các trường hợp thử nghiệm

(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

Làm thế nào chính xác để chúng ta cần pi và e để được?
xnor

@xnor Câu hỏi hay. Nếu ngôn ngữ của bạn cho phép, bạn có thể cho rằng những giá trị đó đã được lưu trữ trong một biến hoặc một cái gì đó tương tự. Nếu không, bạn có thể sử dụng các giá trị đến hai vị trí thập phân làm cho pi = 3.14 và e = 2.72 trong đó bạn có thể đếm từng giá trị đó dưới dạng một byte. Tất nhiên, sự không chính xác trong câu trả lời cuối cùng sẽ không được tính vào bạn một lần nữa.
dặm

Là đầu ra phải là một số thập phân, hoặc nó có thể là số chính xác với hằng số trong đó?
JungHwan Min

@JungHwanMin Những con số chính xác, chẳng hạn như những con số trong Mathematica, đều ổn.
dặm

1
@miles Tôi nghĩ sẽ dễ dàng hơn nếu bạn chỉ cần một độ chính xác nhất định (ví dụ 3 chữ số thập phân).
orlp

Câu trả lời:


7

Toán học, 60 54 50 byte

Cảm ơn @GregMartin vì 4 byte!

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

Lấy r và sigma làm đầu vào, trả về ma trận (số chính xác).

Phiên bản tích hợp (58 byte)

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

Tất nhiên, Mathicala cũng tích hợp sẵn cho việc này, nhưng nó quá dài.


4
Bạn có thể thay thế -lbằng -#ở cuối ( Arraysẽ phân luồng trên cả hai chiều cho bạn); mà không cần phải xác định l, tiết kiệm 4 byte.
Greg Martin

5

MATL , 20 byte

_G&:U&+iUE/_Ze5MYP*/

Hãy thử trực tuyến!

Giải trình

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

Sử dụng quy tắc trong đó bạn có thể mã hóa cứng 3.14 và 2.72 với giá 1 byte mỗi cái.


1

Perl 6 , 71 byte

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

Về mặt kỹ thuật, đây có thể là hơn 71 byte nếu được mã hóa và lưu vào một tệp, nhưng tôi không thể cưỡng lại việc đặt tên đầu vào "sigma" bằng một sigma thực tế của Hy Lạp. Nó có thể được đổi tên thành bất kỳ chữ ASCII đơn giản nào nếu muốn.


1

Ngôn ngữ Macro SAS, 296 byte

Có lẽ là một cách hiệu quả hơn nhiều để làm điều này nhưng nó hoạt động :)

Mã này in ra tập dữ liệu kết quả.

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

Ví dụ sử dụng:

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

Một giải pháp rất đơn giản:

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)

Hãy thử nó ở đây !

Ung dung:

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, có thật không?
orlp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.