5.2. Koordinat dan wilayah¶
Pemrosesan citra bekerja pada piksel, dan untuk bekerja pada sebuah piksel, sebuah algoritma harus mengalamatkannya dengan koordinat. Untuk bekerja pada sekumpulan piksel berbentuk persegi panjang, hal yang sama berlaku -- persegi panjang tersebut harus dideskripsikan dengan cara yang disepakati oleh algoritma dan kode aplikasi. Konvensi yang digunakan modul image untuk koordinat dan persegi panjang bersifat lugas, dengan satu detail yang sering mengejutkan pembaca yang terbiasa dengan konvensi matematika daripada konvensi grafis komputer, dan hal itu perlu dijelaskan secara eksplisit sejak awal.
5.2.1. Grid piksel¶
Piksel (0, 0) adalah sudut kiri-atas dari sebuah citra. Sumbu x berjalan ke kanan, sehingga nilai x yang lebih besar berarti lebih jauh ke kanan. Sumbu y berjalan ke bawah, sehingga nilai y yang lebih besar berarti lebih jauh ke bawah pada citra. Sebuah citra berukuran lebar-kali-tinggi memiliki piksel pada koordinat integer dari (0, 0) hingga (width - 1, height - 1); tidak ada piksel pada (width, 0) atau (0, height) -- posisi-posisi tersebut adalah tepi kanan dan bawah, satu langkah melewati piksel aktual terakhir di setiap arah.
Sumbu y yang mengarah ke bawah adalah detail yang disebutkan di atas. Pembaca yang terbiasa dengan geometri kertas grafik mengharapkan nilai y yang lebih besar berarti lebih tinggi ke atas; di sini intuisi tersebut terbalik sepenuhnya. Alasan pembalikan ini adalah karena sensor digital dan layar digital keduanya bekerja dari sudut kiri-atas dan berjalan ke kanan melalui setiap baris, dari atas ke bawah, dan menempatkan piksel dalam memori dengan urutan yang sama membuat hubungan antara "posisi i dalam buffer" dan "baris r, kolom c dari citra" menjadi aritmatika sesederhana mungkin -- posisi i dari piksel (x, y) hanyalah y * width + x. Setiap pustaka pencitraan telah menyepakati pengaturan tersebut beberapa dekade lalu dengan alasan yang sama, dan biayanya hanyalah satu penyesuaian mental kecil saat pertama kali bekerja dengan citra.
Sistem koordinat citra: titik asal di kiri-atas, x berjalan ke kanan, y berjalan ke bawah. Wilayah persegi panjang di dalam citra dinamai berdasarkan sudut kiri-atasnya (x, y) dan dimensinya (w, h).¶
5.2.2. Persegi panjang¶
Sebagian besar operasi pada citra lebih peduli pada persegi panjang piksel daripada satu piksel saja -- area untuk dicari, wilayah yang akan disalin, bingkai dalam bingkai untuk menghitung statistik. Bentuk penamaan persegi panjang mengambil perluasan paling sederhana dari konvensi piksel tunggal: berikan koordinat sudut kiri-atas, diikuti dengan dimensi persegi panjang, dikemas dalam tupel empat elemen (x, y, w, h). Piksel di dalam persegi panjang berada pada kolom x hingga x + w - 1 dan baris y hingga y + h - 1.
Detail yang perlu dijelaskan secara eksplisit di sini adalah bahwa w dan h adalah ukuran, bukan koordinat sudut kanan-bawah. Persegi panjang (10, 20, 4, 3) mencakup kolom 10, 11, 12, 13 dan baris 20, 21, 22 -- dua belas piksel secara total -- bukan wilayah yang membentang dari (10, 20) ke (4, 3). Konvensi ini seragam di seluruh modul, sehingga begitu sudah terinternalisasi maka kesalahan akan berhenti, tetapi memang sering mengejutkan orang pertama kali.
Bentuk (x, y, w, h) muncul di tiga tempat yang tampak berbeda tetapi berbagi konvensi yang sama. Pertama adalah ketika sebuah citra mendeskripsikan cakupannya sendiri: persegi panjang yang mencakup seluruh citra adalah (0, 0, width, height). Kedua adalah ketika metode deteksi mengembalikan hasil dengan kotak pembatas -- sebuah blob, sebuah rect, sebuah apriltag -- dan kotak tersebut dilaporkan kembali sebagai (x, y, w, h). Ketiga adalah ketika sebuah metode harus diperintahkan untuk bekerja pada sub-wilayah citra daripada seluruh bingkai; argumen kata kunci roi yang membatasi operasi mengambil tupel empat elemen yang sama.
Mengambil kotak pembatas dari satu metode dan menempatkannya ke argumen roi metode berikutnya adalah salah satu pola paling umum dalam pemrosesan citra. Kotak pembatas dari deteksi kasar pertama mempersempit area pencarian untuk deteksi kedua yang lebih halus, dan kosakata seragam antara hasil deteksi dan argumen metode inilah yang membuat pola tersebut semudah itu -- satu bentuk tupel, digunakan dengan cara yang sama di kedua sisi serah-terima.
5.2.3. Alamat integer, centroid fraksional¶
Alamat piksel itu sendiri adalah integer. Sebuah piksel ada atau tidak ada pada kolom dan baris integer tertentu, dan menanyakan apa yang ada di koordinat (40.5, 30.7) bukanlah pertanyaan yang terbentuk dengan baik -- tidak ada piksel yang duduk tepat di posisi tersebut. Namun, sejumlah kecil besaran yang diturunkan oleh modul image dari posisi piksel bersifat fraksional, dan penting untuk memahami mengapa agar perbedaan tersebut tidak mengejutkan aplikasi di kemudian hari.
Kasus paling umum adalah centroid -- pusat massa dari sebuah wilayah. Untuk wilayah piksel yang terhubung, centroid dalam bentuk floating-point adalah rata-rata posisi piksel anggotanya, tertimbang berdasarkan densitasnya. Sebuah wilayah yang pikselnya melintasi dua kolom akan memiliki centroid x sebesar, katakanlah, 41.6 -- posisi nyata yang oleh mata akan dideskripsikan sebagai "tengah wilayah itu" meskipun tidak ada piksel aktual yang berada tepat di x tersebut. Objek hasil deteksi membawa kedua bentuk sebagai properti hanya-baca: pasangan integer (cx / cy, berguna saat mengumpankan posisi kembali ke sesuatu yang menginginkan koordinat piksel integer) dan pasangan floating-point (cxf / cyf, berguna saat posisi akan masuk ke loop kontrol yang mendapat manfaat dari resolusi sub-piksel).
Kasus lainnya adalah pergeseran antara dua bingkai yang diukur dalam domain frekuensi. Teknik yang menganalisis konten spektral sebuah citra daripada pikselnya secara langsung dapat menyelesaikan pergeseran yang lebih halus dari satu piksel, dan melaporkan pergeseran tersebut sebagai nilai floating-point (dx, dy).
Aturan praktisnya: alamat piksel adalah integer; posisi dan pergeseran yang keluar dari sebuah algoritma bisa berupa float. Metode gambar menerima kedua bentuk dan membulatkan float ke bawah ke piksel integer terdekat saat hasilnya harus mendarat di grid.
5.2.4. Kartesian dan polar¶
Sistem yang dijelaskan sejauh ini bersifat Kartesian: setiap piksel dinamai berdasarkan offset horizontal dan vertikalnya dari titik asal. Itulah sistem tempat byte disimpan -- piksel i dalam buffer sesuai dengan piksel di kolom i % width dan baris i // width, menelusuri baris dari atas -- dan itulah sistem yang dioperasikan setiap metode secara default.
Representasi kedua perlu diketahui karena beberapa algoritma bekerja jauh lebih baik di dalamnya. Koordinat polar menamai setiap piksel berdasarkan jaraknya dari titik pusat yang dipilih dan sudut antara piksel tersebut dan arah referensi. Piksel-piksel citra belum berpindah -- byte masih ada di buffer row-major yang sama -- tetapi skema pengalamatan telah beralih dari "seberapa jauh ke kanan dan seberapa jauh ke bawah" menjadi "seberapa jauh dari pusat dan pada sudut berapa di sekelilingnya."
Titik P yang sama, dinamai dengan dua cara: Kartesian (x, y) dari asal kiri-atas, polar (r, theta) dari pusat yang dipilih.¶
Mengapa repot-repot beralih? Karena dua identitas yang mengubah pencarian sulit menjadi mudah.
Dalam koordinat polar, memutar citra terhadap pusat yang dipilih adalah operasi yang sama dengan mentranslasikan pikselnya sepanjang sumbu sudut -- arah x dalam citra yang diproyeksikan ulang. Salinan yang diputar adalah asli yang digeser ke kiri atau kanan dalam bentuk polar.
Dalam varian log-polar -- sumbu jarak menggunakan skala logaritmik, sumbu sudut tetap linier -- menskalakan citra terhadap pusat yang dipilih adalah operasi yang sama dengan mentranslasikan pikselnya sepanjang sumbu jarak -- arah y. Salinan yang diskalakan adalah asli yang digeser ke atas atau ke bawah dalam bentuk log-polar.
Jadi algoritma yang harus mengenali pola yang diketahui di bawah rotasi atau skala dapat melakukan pencariannya dalam ruang polar, di mana kedua transformasi berubah menjadi translasi biasa. Translasi jauh lebih murah untuk dicari daripada rotasi dan skala, dan proyeksi ulang polar inilah yang membuat substitusi tersebut tersedia.
Koordinat polar tidak menggantikan Kartesian untuk menyimpan piksel; byte selalu berada di grid Kartesian. Modul ini menyediakan sepasang metode yang memproyeksikan ulang sebuah citra dari bentuk Kartesian ke bentuk polar sesuai permintaan, algoritma yang membutuhkan koordinat polar melakukan pekerjaannya, dan hasilnya baik diproyeksikan kembali atau pengukuran dalam ruang polar digunakan secara langsung. Mekanisme tersebut adalah satu-satunya alasan koordinat polar muncul di mana pun dalam antarmuka modul.
Dengan koordinat Kartesian untuk menamai piksel individual, tupel empat elemen (x, y, w, h) untuk menamai persegi panjangnya, dan koordinat polar yang tersedia saat sebuah algoritma membutuhkannya, sebuah aplikasi memiliki kosakata lengkap untuk menamai di mana dalam sebuah citra sesuatu berada. Apa yang sebenarnya tersimpan di salah satu posisi tersebut adalah lapisan dasar berikutnya.