5.3. Format piksel¶
Sebuah algoritma yang mendeteksi tepi mengharapkan setiap piksel menyimpan nilai kecerahan. Sebuah algoritma yang melacak objek berwarna mengharapkan setiap piksel membawa informasi warna. Sebuah algoritma yang menjalankan penutupan morfologis mengharapkan setiap piksel bernilai on atau off. Format piksel yang dibawa oleh sebuah Image -- salah satu dari katalog yang dienumerasi oleh Vision Sensors -- adalah yang membuat ekspektasi tersebut dapat diperiksa di awal: format tersebut menyatakan, sejak awal, bentuk piksel yang ada, dan algoritma mana yang dapat berjalan di atasnya tanpa langkah konversi.
Halaman ini membahas bagaimana batasan tersebut berlaku dalam praktik. Format mana yang tepat bergantung pada apa yang akan dilakukan oleh pipeline, dan metode konversi antar format adalah cara pipeline yang membutuhkan lebih dari satu format menyambung tahap-tahap tersebut.
Lima format piksel tidak terkompresi dan cara byte-nya dikemas. JPEG dan PNG tidak digambar di sini karena keduanya adalah aliran terkompresi dengan panjang variabel, bukan kisi piksel berukuran tetap.¶
5.3.1. Andalan skala abu-abu¶
Sebagian besar visi mesin klasik bermuara pada bekerja dengan nilai kecerahan. Deteksi tepi, pencocokan template, dekoding AprilTag, estimasi aliran optik, operator morfologis, analisis blob -- semuanya, pada level algoritma beroperasi, melihat seberapa terang setiap piksel dan bagaimana kecerahan itu dibandingkan dengan kecerahan piksel di sekitarnya. Warna adegan seringkali berguna bagi aplikasi yang memanggilnya, tetapi algoritma itu sendiri tidak membutuhkannya.
Format skala abu-abu memberikan hal tersebut secara langsung kepada algoritma, tanpa overhead. Satu byte per piksel menyimpan nilai kecerahan dari 0 (hitam) hingga 255 (putih). Format ini setengah ukuran dari RGB565 dan YUV422 serta sepertiga ukuran dari RGB888, sehingga setiap operasi memproses lebih sedikit data -- lebih cepat sekaligus dengan tekanan buffer yang lebih kecil. Pada kamera yang lebih kecil, di mana buffer bingkai bersaing dengan sisa skrip untuk RAM, perbedaan ukuran tersebut bisa menjadi penentu apakah sebuah pipeline muat sama sekali. Jika warna bukan petunjuk yang dibutuhkan algoritma, skala abu-abu adalah jawaban yang tepat.
5.3.2. Warna melalui RGB565¶
Ketika warna adalah petunjuknya -- melacak penanda berwarna, membedakan apel merah dari yang hijau, menemukan elemen UI berdasarkan rona warnanya -- dua byte per piksel memberikan cukup warna untuk jenis klasifikasi yang dilakukan algoritma. RGB565 adalah format warna bawaan pada kamera, dan yang diharapkan oleh metode-metode berkorelasi warna.
Merender bingkai beranotasi -- menggambar kotak deteksi, menulis teks diagnostik, menampilkan bingkai ke layar atau mengirimnya ke penampil jarak jauh -- juga secara alami membutuhkan RGB565. Pratinjau IDE, kontroler layar onboard, dan sebagian besar tujuan jaringan baik mengkonsumsi format ini secara langsung atau melakukan konversi dari format ini dengan murah.
5.3.3. Bayer sebagai format penyimpanan¶
Citra Bayer adalah output sensor mentah, sebelum ISP melakukan debayer menjadi representasi warna yang sudah jadi. Setiap piksel adalah satu byte yang menyimpan satu saluran warna -- yang diloloskan oleh filter warna pada posisi tersebut dalam mosaik. Hal ini membuat citra Bayer berukuran sama dengan citra skala abu-abu dan sepertiga ukuran RGB888, yang sesuai dengan kegunaan Bayer yang sesungguhnya: menyimpan banyak bingkai sekaligus ketika RAM adalah batasan utama.
Kendalanya adalah bahwa algoritma dalam modul image tidak beroperasi langsung pada citra Bayer. Tanpa debayering, tidak ada piksel yang membawa cukup informasi untuk membuat penilaian warna sendiri, dan pola yang dicari algoritma -- tepi, sudut, blob -- akan terdistorsi oleh mosaik. Satu-satunya cara untuk membaca atau memodifikasi citra Bayer adalah get_pixel() dan set_pixel(); semua lainnya mengharapkan representasi yang sudah jadi.
Pola yang muncul adalah menyimpan bingkai sebagai Bayer selama bingkai tersebut perlu menunggu dalam antrean dan mengonversi masing-masing ke skala abu-abu atau RGB565 pada saat pemrosesannya benar-benar dimulai. Konversi ini membutuhkan siklus CPU tetapi menghemat RAM yang seharusnya terikat untuk menyimpan bingkai yang sudah jadi sepanjang masa hidup aplikasi.
Catatan
Satu-satunya operasi modul image pada piksel Bayer secara langsung adalah get_pixel(), set_pixel(), dan jalur enkoding JPEG yang memberi makan pratinjau IDE atau penampil jarak jauh. Menggambar, analisis, dan pemfilteran semuanya memerlukan konversi ke skala abu-abu, RGB565, atau binary terlebih dahulu.
5.3.4. YUV422 untuk pipeline yang membutuhkan keduanya¶
YUV422 memisahkan informasi setiap piksel menjadi saluran luminansi (Y) dan dua saluran krominansi (U dan V), serta melakukan subsampel krominansi sehingga pasangan piksel yang berdekatan berbagi satu U dan satu V. Rata-rata byte per piksel adalah dua -- sama dengan RGB565 -- tetapi disusun sedemikian rupa sehingga saluran Y sudah merupakan citra skala abu-abu 8-bit kontinu yang berada pada offset yang diketahui dalam buffer.
Tata letak itulah yang diinginkan pipeline ketika beberapa tahapnya adalah pekerjaan skala abu-abu dan sebagian lainnya membutuhkan warna. Membaca nilai Y secara langsung untuk tahap skala abu-abu melewati biaya konversi eksplisit; saluran U dan V tersedia ketika tahap selanjutnya benar-benar membutuhkan warna. Di luar pola spesifik tersebut, RGB565 biasanya merupakan pilihan yang lebih sederhana untuk warna dan skala abu-abu merupakan pilihan yang lebih sederhana untuk pekerjaan berbasis kecerahan saja -- nilai YUV422 berasal dari kemampuannya melakukan keduanya secara bersamaan.
Catatan
Modul image beroperasi pada YUV422 dengan cara yang lebih terbatas dibandingkan pada skala abu-abu, RGB565, atau binary -- pembacaan saluran Y langsung untuk pekerjaan skala abu-abu dan jalur enkoding JPEG yang memberi makan pratinjau IDE atau penampil jarak jauh. Metode yang menyadari warna mengharapkan RGB565; bingkai YUV422 membutuhkan konversi eksplisit sebelum analisis warna atau penggambaran.
5.3.5. Binary, mask, dan output hasil threshold¶
Citra binary adalah satu bit per piksel: setiap piksel bernilai 0 atau 1. Format ini jarang muncul sebagai hasil tangkapan sensor; sebaliknya ia muncul sebagai keluaran alami dari thresholding (di mana pengujian warna atau kecerahan mengklasifikasikan setiap piksel menjadi "ya, cocok" atau "tidak, tidak cocok") dan sebagai masukan alami untuk operasi morfologis serta argumen mask yang diterima banyak metode.
Keunggulan praktis format ini adalah ukurannya. Sebuah citra binary adalah seperdelapan ukuran citra skala abu-abu, sehingga membawa mask yang besar -- pilihan per piksel tentang posisi mana yang harus disentuh oleh operasi hilir -- adalah hal yang murah. Fakta bahwa banyak operasi menerima citra binary sebagai argumen kata kunci mask= adalah sisi lain dari poin yang sama: formatnya kecil, dan merantai keluaran binary dari satu tahap ke masukan mask tahap lain adalah pola pipeline yang umum.
5.3.6. JPEG dan PNG di batas¶
Objek Image JPEG dan PNG berbeda dari yang lain dalam katalog. Keduanya bukan kisi piksel; keduanya adalah aliran byte terkompresi yang mengkodekan data piksel dalam bentuk yang tidak dapat dibaca oleh operasi tingkat piksel. Memanggil get_pixel() pada JPEG tidak mengembalikan piksel pada suatu posisi; piksel tersebut tidak tersimpan dalam keadaan tidak terkemas di mana pun dalam buffer agar dapat diambil oleh metode tersebut.
JPEG dan PNG muncul di batas pemrosesan citra, di mana data piksel meninggalkan atau memasuki kamera dalam bentuk terkompresi. Menyimpan bingkai ke disk sebagai JPEG membuat file tetap kecil; mengirim bingkai melalui jaringan sebagai JPEG membuat transmisi tetap murah; memuat bingkai referensi dari file JPEG memungkinkannya tersimpan di disk dalam bentuk yang jauh lebih kecil daripada piksel mentah. Untuk semua kasus penggunaan tersebut representasi terkompresi adalah jawaban yang tepat. Namun untuk melakukan pemrosesan aktual pada JPEG, aplikasi terlebih dahulu mengonversinya ke format yang dapat digunakan -- dan konversi itulah di mana byte terkompresi diperluas menjadi piksel dan di mana balon buffer terjadi (sebuah JPEG 30 KB dapat menjadi 600 KB RGB565).
5.3.7. Konversi antar format¶
Jalur konversi adalah yang menghubungkan berbagai format menjadi satu pipeline. Lima metode pada kelas Image mengambil citra yang ada dan mengembalikan citra baru dalam format yang berbeda:
to_grayscale()menghasilkan citra satu-byte-per-piksel, format yang diinginkan oleh algoritma klasik.to_rgb565()menghasilkan format warna dua-byte-per-piksel yang digunakan oleh metode berkorelasi warna maupun pratinjau IDE.to_bitmap()menghasilkan citra binary satu-bit, format yang diterima oleh morfologi dan argumenmask.to_jpeg()menghasilkan citra terkompresi JPEG yang sesuai untuk penyimpanan atau transmisi.to_png()menghasilkan citra terkompresi PNG ketika pengkodean tanpa kerugian lebih disukai daripada file yang lebih kecil dari JPEG.
Setiap konversi berjalan di tempat secara default: buffer citra sumber ditimpa dengan hasil yang telah dikonversi, dan piksel asli sumber hilang setelah pemanggilan selesai. Ini adalah opsi paling murah baik untuk CPU maupun memori, dan ini adalah jawaban yang tepat ketika bingkai sumber tidak akan dibutuhkan untuk hal lain.
Ketika sumber masih dibutuhkan -- ketika tahap pipeline berikutnya harus melihat bingkai asli -- dua argumen kata kunci mengganti default di-tempat. copy=True mengalokasikan buffer terpisah untuk citra yang telah dikonversi di heap Python dan membiarkan sumber tetap utuh. copy_to_fb=True melakukan alokasi yang sama tetapi menempatkannya di buffer bingkai daripada di heap -- yang digunakan aplikasi ketika citra yang telah dikonversi perlu masuk ke pratinjau IDE, karena IDE membaca dari buffer bingkai.
Dua metode lebih lanjut menghasilkan citra RGB565 yang diwarnai melalui sebuah palet daripada melalui konversi langsung. to_rainbow() memetakan setiap nilai masukan saluran tunggal ke warna sepanjang gradien halus yang melewati spektrum tampak. to_ironbow() memetakan setiap nilai masukan ke palet kamera termal non-linear yang berjalan dari hitam melalui merah gelap dan oranye hingga putih. Keduanya adalah alat visualisasi daripada alat pengukuran; tujuannya adalah untuk membuat citra saluran tunggal yang nilai mentahnya sebaliknya tidak terlihat oleh mata menjadi mudah dibaca sekilas.
5.3.8. Ukuran buffer¶
Satu detail terakhir tentang format yang perlu dijelaskan secara eksplisit. size() selalu melaporkan ukuran buffer byte, bukan jumlah piksel. Untuk format tidak terkompresi hal ini mengikuti langsung dari dimensi dan byte-per-piksel: width * height * bytes_per_pixel. Untuk JPEG dan PNG ini adalah ukuran aliran terkompresi, yang bervariasi dari bingkai ke bingkai tergantung pada isi adegan. Kode yang mengalokasikan buffer dari anggaran byte menggunakan size() untuk kasus sebelumnya; kode yang mengalirkan bingkai terkompresi keluar dari kamera membacanya setelah setiap kompresi untuk mengetahui berapa banyak byte yang sebenarnya dikandung aliran tersebut.