Bagaimana Gaussian Blur Diimplementasikan?

42

Saya pernah membaca bahwa blur dilakukan dalam grafik waktu nyata dengan melakukannya pada satu sumbu dan kemudian pada yang lain.

Saya telah melakukan sedikit konvolusi dalam 1D di masa lalu, tetapi saya tidak terlalu nyaman dengan itu, juga tidak tahu harus berbelit-belit dalam hal ini.

Adakah yang bisa menjelaskan dengan jelas bagaimana 2D Gaussian Blur dari suatu gambar dilakukan?

Saya juga mendengar bahwa jari-jari Blur dapat memengaruhi kinerja. Apakah itu karena harus melakukan konvolusi yang lebih besar?

Alan Wolfe
sumber

Jawaban:

48

Dalam konvolusi, dua fungsi matematika digabungkan untuk menghasilkan fungsi ketiga. Dalam fungsi pemrosesan gambar biasanya disebut kernel. Kernel tidak lebih dari array (persegi) piksel (gambar kecil untuk berbicara). Biasanya, nilai-nilai dalam kernel ditambahkan hingga satu. Ini untuk memastikan tidak ada energi yang ditambahkan atau dihapus dari gambar setelah operasi.

Secara khusus, sebuah kernel Gaussian (digunakan untuk Gaussian blur) adalah array persegi piksel di mana nilai-nilai piksel sesuai dengan nilai-nilai kurva Gaussian (dalam 2D).

Gambar ditautkan dari http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm

Setiap piksel dalam gambar dikalikan dengan kernel Gaussian. Ini dilakukan dengan menempatkan piksel tengah kernel pada piksel gambar dan mengalikan nilai dalam gambar asli dengan piksel pada kernel yang tumpang tindih. Nilai yang dihasilkan dari perkalian ini ditambahkan dan hasil itu digunakan untuk nilai pada piksel tujuan. Melihat gambar, Anda akan mengalikan nilai pada (0,0) dalam array input dengan nilai pada (i) dalam array kernel, nilai pada (1,0) dalam array input dengan nilai pada (h) ) dalam array kernel, dan sebagainya. dan kemudian tambahkan semua nilai ini untuk mendapatkan nilai untuk (1,1) pada gambar output.

Gambar ditautkan dari http://www.songho.ca/dsp/convolution/convolution.html

Untuk menjawab pertanyaan kedua Anda terlebih dahulu, semakin besar kernel, semakin mahal operasinya. Jadi, semakin besar radius blur, semakin lama operasi akan berlangsung.

Untuk menjawab pertanyaan pertama Anda, seperti yang dijelaskan di atas, konvolusi dapat dilakukan dengan mengalikan setiap piksel input dengan seluruh kernel. Namun, jika kernel simetris (yang merupakan kernel Gaussian), Anda juga dapat mengalikan setiap sumbu (x dan y) secara mandiri, yang akan mengurangi jumlah total perkalian. Dalam istilah matematika yang tepat, jika sebuah matriks dapat dipisahkan, ia dapat didekomposisi menjadi matriks (M × 1) dan (1 × N). Untuk kernel Gaussian di atas ini berarti Anda juga dapat menggunakan kernel berikut:

1256[1464141624164624362464162416414641]=1256[14641][14641]

Sekarang Anda akan mengalikan setiap piksel dalam gambar input dengan kedua kernel dan menambahkan nilai yang dihasilkan untuk mendapatkan nilai untuk piksel keluaran.

Untuk informasi lebih lanjut tentang cara melihat apakah kernel dapat dipisahkan, ikuti tautan ini .

Sunting: dua kernel yang ditunjukkan di atas menggunakan nilai yang sedikit berbeda. Ini karena parameter (sigma) yang digunakan untuk kurva Gaussian untuk membuat kernel ini sedikit berbeda dalam kedua kasus. Untuk penjelasan tentang parameter mana yang mempengaruhi bentuk kurva Gaussian dan dengan demikian nilai-nilai dalam kernel mengikuti tautan ini

Sunting: pada gambar kedua di atas dikatakan bahwa kernel yang digunakan terbalik. Ini tentu saja hanya membuat perbedaan jika kernel yang Anda gunakan tidak simetris. Alasan mengapa Anda perlu membalik kernel berkaitan dengan sifat matematika dari operasi konvolusi (lihat tautan untuk penjelasan lebih mendalam tentang konvolusi). Sederhananya: jika Anda tidak mau membalik kernel, hasil operasi konvolusi akan terbalik. Dengan membalik kernel, Anda mendapatkan hasil yang benar.

Bert
sumber
1
Bisakah Anda menambahkan catatan singkat untuk menjelaskan mengapa kedua kernel 5 dengan 5 kernel memiliki angka yang sedikit berbeda (satu penjumlahan ke 273, yang lain menjumlahkan ke 256)? Sepertinya ada potensi kebingungan bagi seseorang yang baru dalam hal ini.
trichoplax
Demikian pula, dapatkah Anda menjelaskan mengapa kernel membalik dalam diagram kedua Anda? Saya tidak berpikir itu relevan dengan penjelasan, tetapi fakta bahwa itu merupakan langkah ekstra yang jelas dapat menghalangi pemahaman kepada seseorang yang tidak tahu bahwa itu tidak perlu.
trichoplax
jangan lupa bekerja di ruang warna linier untuk hasil yang benar.
v.oddou
16

Berikut ini adalah artikel terbaik yang pernah saya baca tentang topik: Efisien Gaussian blur dengan pengambilan sampel linier . Ini menjawab semua pertanyaan Anda dan benar-benar dapat diakses.

Bagi orang awam penjelasan yang sangat singkat: Gaussian adalah fungsi dengan sifat bagus dipisahkan, yang berarti bahwa fungsi Gaussian 2D dapat dihitung dengan menggabungkan dua fungsi Gaussian 1D.

n×nHAI(n2)2×nHAI(n) ), itu adalah berita baik: lebih sedikit keran lebih murah karena mengambil tekstur memiliki biaya.

nn

Julien Guertault
sumber
13

Secara umum, konvolusi dilakukan dengan mengambil integral dari produk dari dua fungsi di jendela geser, tetapi jika Anda bukan dari latar belakang matematika, itu bukan penjelasan yang sangat membantu, dan tentu saja tidak akan memberi Anda intuisi yang berguna untuk itu. Lebih intuitif, konvolusi memungkinkan banyak titik dalam sinyal input untuk mempengaruhi satu titik pada sinyal output.

Karena Anda tidak terlalu nyaman dengan konvolusi, pertama mari kita tinjau apa arti konvolusi dalam konteks diskrit seperti ini, dan kemudian lanjutkan dengan blur yang lebih sederhana.

Dalam konteks diskrit kami, kami dapat mengalikan dua sinyal kami dengan hanya mengalikan masing-masing sampel yang sesuai. Integral juga mudah dilakukan secara terpisah, kami hanya menjumlahkan setiap sampel dalam interval yang kami integrasikan. Satu konvolusi diskrit sederhana adalah menghitung rata-rata bergerak. Jika Anda ingin mengambil rata-rata bergerak 10 sampel, ini dapat dianggap sebagai melilit sinyal Anda dengan distribusi 10 sampel panjang dan 0,1 tinggi, masing-masing sampel di jendela pertama kali dikalikan dengan 0,1, maka semua 10 ditambahkan bersama-sama untuk menghasilkan rata-rata. Ini juga mengungkapkan perbedaan yang menarik dan penting, ketika Anda kabur dengan konvolusi, distribusi yang Anda gunakan harus berjumlah 1,0 pada semua sampelnya, jika tidak maka akan menambah atau mengurangi kecerahan keseluruhan gambar ketika Anda menerapkannya.

Sekarang kita telah melihat konvolusi, kita bisa beralih menjadi kabur. Gaussian blur diimplementasikan dengan menggabungkan gambar dengan distribusi Gaussian. Pengaburan lainnya umumnya diterapkan dengan menggabungkan gambar dengan distribusi lain. Kabur paling sederhana adalah kotak kabur, dan menggunakan distribusi yang sama seperti yang kami jelaskan di atas, kotak dengan satuan luas. Jika kita ingin mengaburkan area 10x10, maka kita mengalikan setiap sampel dalam kotak dengan 0,01, dan kemudian menjumlahkan semuanya untuk menghasilkan piksel tengah. Kita masih perlu memastikan bahwa jumlah total semua sampel dalam distribusi blur kami adalah 1,0 untuk memastikan gambar tidak menjadi lebih terang atau lebih gelap.

r

e-x2/22π

HAI(n2)HAI(n).

porglezomp
sumber
1
Melihat jawaban Anda yang lain, sepertinya latar belakang matematika Anda lebih baik daripada yang saya kerjakan, tapi saya harap itu masih cukup detail untuk membantu. Saya ingin ini bermanfaat bagi orang-orang dari berbagai latar belakang yang datang ke sini.
porglezomp
1
Jika Anda berbicara kepada saya, tidak sama sekali. Jawaban Anda dan Bert sangat mencerahkan. Terima kasih banyak! Harus mencerna info sedikit sekarang (:
Alan Wolfe
11

HAI(n2)HAI(n)

Tetapi ada dua trik lagi yang mungkin ingin Anda pertimbangkan dalam implementasi aktual:

Filter memiliki jari-jari tertentu dan karena itu, di batas yang paling, Anda harus menghitung dengan piksel yang berada di luar gambar. Dalam kasus seperti itu, Anda dapat mencoba salah satu dari yang berikut: untuk piksel luar, Anda cukup mengambil nilai terakhir yang mungkin (yaitu piksel di batas paling bawah, seperti pada max(x, 0). Atau Anda dapat "mencerminkan" gambar ke arah luar (seperti pada x < 0 ? -x : x). Atau Anda bisa berhenti di perbatasan tetapi kemudian Anda perlu menyesuaikan penyebut dalam filter konvolusi sehingga jumlahnya menjadi 1. Sebagai contoh:

jumlah1256[1464141624164624362464162416414641]=jumlah1225[0000001624160024361600162416000000]=1.
     1
    1 1
   1 2 1
  1 3 3 1
[1 4 6 4 1]
Ecir Hana
sumber