5.23. Koreksi perspektif¶
Peringatan
Matriks transform 3-kali-3 yang sewenang-wenang hanya didukung pada OpenMV Cam N6 -- kata kunci ini diabaikan secara diam-diam di semua board lainnya. Aplikasi yang perlu berjalan di tempat lain harus menggunakan metode rotation_corr() yang sudah ada (dengan bentuk corners=-nya) atau menghitung citra yang telah dikoreksi di luar board.
Metode rotation_corr() yang sudah ada membungkus keluarga warp perspektif tertentu di balik kumpulan parameter kecil, dan berjalan di setiap board yang didukung. Beberapa aplikasi membutuhkan warp yang tidak sesuai dengan bentuk tersebut: remap proyektif sewenang-wenang dari satu segiempat ke segiempat lainnya, koreksi terkalibrasi untuk pemasangan yang diketahui yang telah dikerjakan secara luring, matriks warp yang diserahkan siap pakai oleh algoritma hulu. Untuk itu, draw_image() -- bersama dengan copy(), crop(), dan scale() -- menerima kata kunci transform yang mengambil matriks 3-kali-3 yang dibuat secara manual yang menjelaskan warp secara langsung.
5.23.1. Transformasi affine dan proyektif¶
Warp geometris diekspresikan dalam koordinat homogen: posisi piksel (x, y) dengan 1 ditambahkan, dikalikan dengan matriks 3-kali-3.
Bentuk affine adalah tempat untuk memulai. Baris bawahnya ditetapkan pada \((0, 0, 1)\):
Ditulis secara lengkap, setiap koordinat keluaran adalah kombinasi linear dari koordinat masukan ditambah konstanta:
yang mencakup penskalaan, rotasi, geseran, dan translasi dalam kombinasi apa pun -- dan di bawah semuanya, garis-garis sejajar tetap sejajar.
Bentuk proyektif (perspektif) membebaskan baris bawah:
Ditulis secara lengkap:
Pembagian dengan \(w' = g x + h y + 1\) adalah yang membuat transformasi bersifat proyektif daripada sekadar affine. Ketika \(g\) dan \(h\) keduanya nol, \(w'\) tetap di satu dan pembagian tidak melakukan apa-apa -- kembali ke bentuk affine. Ketika salah satunya bukan nol, \(w'\) bervariasi dengan posisi masukan dan piksel di posisi yang berbeda dipersingkat dengan jumlah yang berbeda, yang tidak lagi mempertahankan kesejajarannya -- ini persis efek keystone dari melihat bidang datar dari sudut miring. Transformasi proyektif adalah warp geometris paling umum yang mengubah garis lurus menjadi garis lurus; penskalaan, pembalikan, transposisi, rotasi, dan koreksi rotasi empat sudut semuanya adalah kasus khusus dari satu transformasi.
Transformasi bernama langsung berasal dari bentuk affine. Transformasi identitas adalah matriks identitas, dan:
Untuk sebagian besar transformasi yang dibuat secara manual, aplikasi mulai dengan salah satu dari ini sebagai dasar dan mengalikan matriks lebih lanjut untuk setiap operasi tambahan, berakhir dengan satu matriks 3-kali-3 yang menjelaskan warp komposit. Matriks diterapkan dari kanan ke kiri: \(M = T R S\) menjalankan skala terlebih dahulu, lalu rotasi, lalu translasi. Komposit yang pada akhirnya semua orang butuhkan adalah rotasi di sekitar pusat citra -- matriks rotasi biasa memutar citra di sekitar piksel asal di sudut kiri atas, sehingga versi yang berpusat memindahkan pusat \((c_x, c_y)\) ke titik asal, memutar, dan memindahkannya kembali:
5.23.2. Kata kunci transform¶
Matriks dimasukkan melalui kata kunci transform, yang diberikan sebagai ulab.numpy.ndarray berukuran 3-kali-3. Metode yang perlu dipanggil adalah draw_image(), yang mewarpkan sumber melalui matriks saat menggambarnya ke tujuan -- hasilnya mendarat di buffer yang dikontrol oleh aplikasi, dan warp tersebut tergabung dengan semua hal lain pada panggilan: penskalaan, pencampuran alpha, dan masking.
import ulab.numpy as np
M = np.array([[1.2, 0.0, -20.0],
[0.0, 1.2, -15.0],
[0.0, 0.0, 1.0]])
canvas.draw_image(img, transform=M)
Contoh tersebut mewarpkan img ke canvas yang diskalakan sebesar 1.2 di setiap arah dan digeser ke kiri dan atas sebesar 20 dan 15 piksel -- warp affine yang dibangun langsung dari entri matriks yang dijelaskan di atas. Kata kunci yang sama pada copy(), crop(), dan scale() menerapkan warp ke citra itu sendiri.