Bagaimana seseorang menerapkan FFT dengan benar dalam denoising gambar

8

Saya sedang menulis program (Qt widgets / c ++) untuk menghilangkan noise dari gambar. Sebagai metode denoising, saya memilih metode non lokal berarti . Metode ini memiliki kualitas luar biasa dari gambar yang dipulihkan (itu sebabnya itu satu-satunya metode denoising di OpenCV), tetapi memiliki biaya perhitungan yang besar , jadi saya membuat banyak varian modifikasi dari metode ini (beberapa dengan multithreading, beberapa algoritmik). Tapi, saya mengalami masalah dengan yang satu, melibatkan FFT

Saya mengikuti semua langkah artikel ini (hanya satu halaman, 1430) dan semua berfungsi dengan baik, kecuali untuk bagian FFT, hanya ada 2 baris tentang hal itu di koran dan saya tidak bisa mengerti, BAGAIMANA harus menggunakan fft

Masalah ini telah mengganggu saya selama berbulan-bulan, bantuan atau wawasan apa pun akan sangat appriciated.

Versi pertanyaan yang singkat: Bagaimana saya bisa mendapatkan perbedaan kuadrat terangkum dari dua array pada gambar (satu di atas dan satu di tengah, nilai adalah warna) dengan cepat? (O (n ^ 2) adalah biaya besar, ada banyak jenis operasi ini, kertas di atas menyatakan, bahwa hal itu dapat dilakukan melalui FFT dengan O (n * log n) (mengatakan bahwa 2 array ini entah bagaimana membentuk lilitan melingkar melingkar) )

masukkan deskripsi gambar di sini

Shf
sumber
Apa yang akhirnya Anda lakukan untuk menghitung FFT? Bahkan jika FFT didahului, perkalian titik-bijaksana dan penambahan semua elemen tambalan membutuhkan waktu di manaadalah ukuran tambalan. Bagaimana Anda mengatasi ini? O(|P|)|P|
curryage

Jawaban:

5

Trik di dalam kertas adalah sebagai berikut:

  1. Apa yang ingin Anda hitung adalah , di mana adalah gambar, dan dua piksel berisik dan adalah offset 2D digunakan untuk mendefinisikan suatu tambalan.iW|I(x+i)I(y+i)|2Ixyi
  2. Memperluas ekspresi yang dihasilkan: .iI2(x+i)+iI2(y+i)2iI(x+i)I(y+i)=A+B2C
  3. A dan dihitung menggunakan gambar integral kuadrat, yaitu, gambar integral dari gambar asli kuadrat.B
  4. C adalah konvolusi antara dua tambalan yang berpusat pada dan . Dengan demikian, itu dapat dihitung dalam domain Fourier, di mana ia menjadi perkalian. Anda mendapatkan nilai dengan menghitung transformasi Fourier dari tambalan di sekitar , tambalan di sekitar , mengalikan hasil ini secara pointwise dan mengambil transformasi Fourier terbalik dari hasil multplikasi.xyCxy

Transformasi Fourier jelas merupakan transformasi 2D karena Anda bekerja dengan data 2D. Apa yang Anda peroleh untuk tambalan tertentu adalah array 2D nilai-nilai kompleks.

Catatan tambahan

Menurut pendapat saya, artikel ini bukan strategi speedup NL-means terbaik. Eksperimen yang saya lakukan pada 2007/2008 menunjukkan bahwa pra-pemilihan tambalan lebih baik (baik dari segi kecepatan dan kualitas hasil). Saya sudah mulai menulis blog tentang ini di sini , tetapi sayangnya saya mencari waktu untuk menyelesaikan posting.

Makalah NL-means asli menyebutkan implementasi blockwise yang bisa menarik. Ada 2 cara mendasar dalam mengimplementasikan NL-means:

  1. menulis lingkaran denoising untuk setiap piksel dalam gambar
  2. menulis lingkaran denoising untuk setiap patch, kemudian memproyeksikan kembali patch untuk membentuk gambar.

Impolementasi pertama adalah pendekatan asli, karena pada tahun 2005 memori dan CPU multicore mahal. Saya memilih di sisi lain nomor 2 pada perangkat keras terbaru dalam 2 tahun terakhir. Itu tergantung pada ukuran gambar khas Anda dan jika Anda ingin dapat menghitung transformasi domain seperti DFT / DCT (seperti dalam makalah yang diusulkan dan dalam BM3D).

sansuiso
sumber
Terima kasih banyak atas jawaban Anda, itulah yang saya butuhkan, semua sudah siap dan berfungsi sejak lama, kecuali untuk item ke-4 dalam daftar itu, tetapi sekarang jauh lebih jelas. Meskipun ada satu pertanyaan lagi, jika Anda tidak keberatan: apa yang akan mengembalikan transformasi Fourier dari patch x atau y? Array, vektor, atau nilai tunggal? Dan apa yang dibutuhkan untuk menggunakan transformasi terbalik? Karena saya berpikir tentang precomputing fft untuk setiap pixel (patch berpusat di sekitarnya) dan menulis hasilnya ke array 2d sebelum denoising dan kemudian gunakan matriks tersebut untuk mendapatkan invers fft, tetapi saya tidak tahu apakah ini akan cukup untuk invers fft
Shf
oh, dan haruskah saya menggunakan 2d fft, atau menerjemahkan patch ke array 1d? Ngomong-ngomong, saya berencana untuk menulis setelah implementasi patchwise ini, terima kasih atas sarannya :) sesuatu yang mirip dengan ini juga sudah lama sekali- ipol.im/pub/art/2011/bcm_nlm
Shf
Saya sudah memperbarui jawabannya.
sansuiso
ok, jadi saya bisa melakukan precompute FFT untuk patch, berpusat di sekitar setiap pixel sebelum membuat donoising meskipun akan membutuhkan banyak memori (m n size_of_patch size_of_patch sizeof (double)), tetapi ketika saya akan menghitung bobot, saya masih perlu mengalikan 2 array kompleks dan setelah itu lakukan invers fft pada array 2d yang diterima, bahkan lebih dari O (n ^ 2) jika saya tidak salah
Shf
2
Jawaban yang bagus, tetapi bagaimana menurut Anda bahwa adalah konvolusi? Cara ditulisnya itu adalah produk elemen demi elemen yang bijak. Di mana konvolusi? C
TheGrapeBeyond