5.9. Operasi aritmatika¶
Keluarga gambar pada bagian sebelumnya melukis ke dalam suatu citra. Keluarga aritmatika menggabungkan dua citra menjadi satu -- menjumlahkan nilai piksel keduanya, mengurangkan satu dari yang lain, mengambil minimum atau maksimum pada setiap posisi. Sekumpulan kecil operasi aritmatika per-piksel itulah yang menjadi fondasi diferensiasi bingkai, pengurangan latar belakang, penumpukan eksposur, dan beberapa pola klasik lainnya.
Keluarga aritmatika pada kelas Image cukup kecil untuk dienumerasi sekaligus:
add()--self + otherper-piksel, dipotong pada nilai maksimum format.sub()--self - otherper-piksel, dipotong pada0di bawah.rsub()--other - selfper-piksel, dipotong pada0(aritmatika yang sama dengansubdengan operan dibalik).min()-- nilai minimum dari dua nilai per-piksel.max()-- nilai maksimum per-piksel.difference()--|self - other|per-piksel, selisih absolut.
Ditambah dua operasi citra tunggal terkait:
invert()-- ganti setiap piksel dengan255 - pixel(atau maksimum yang setara untuk format tersebut).
Dua gradien sumber A dan B, dan hasil dari setiap operasi berpasangan yang diterapkan pada keduanya. Setiap operasi berjalan posisi demi posisi -- apa yang muncul dalam hasil di satu lokasi hanya bergantung pada dua piksel sumber di lokasi tersebut.¶
5.9.1. Dua bentuk operan¶
Masing-masing metode dua-citra menerima salah satu bentuk untuk operan keduanya:
Imagelain dengan dimensi yang sama. Aritmatika berjalan posisi demi posisi -- hasil pada(x, y)adalah operasi yang diterapkan pada piksel sumber pada(x, y)dari kedua citra.Nilai skalar -- integer untuk skala abu-abu, tuple
(r, g, b)untuk RGB565. Skalar yang sama berlaku di setiap posisi.
Bentuk skalar berguna ketika aplikasi ingin menggeser setiap piksel dengan jumlah yang konstan. img.add(40) mencerahkan seluruh citra sebesar 40; img.sub((20, 20, 20)) menggelapkan setiap piksel sebesar 20 per saluran; img.max(50) mengangkat piksel mana pun di bawah 50 menjadi 50 dan membiarkan sisanya -- jenis operasi yang mengubah lantai sensor yang hampir hitam menjadi abu-abu gelap rata untuk tahap berikutnya.
5.9.2. Pemotongan¶
Nilai piksel tetap berada dalam rentang format melalui setiap operasi. Untuk saluran 8-bit itu berarti 0 -- 255: apa pun yang akan meluap melewati 255 dipotong kembali ke 255, dan apa pun yang akan turun di bawah 0 dipotong naik ke 0. Tidak ada wrap-around.
Pilihan tersebut penting dalam praktiknya. Pencerahaan add piksel tidak pernah menghasilkan artefak penggelapan tiba-tiba di ujung terang di mana matematika seharusnya meluap; sub menggelapkan piksel tidak pernah menghasilkan artefak pencerahaan tiba-tiba di ujung gelap di mana seharusnya underflow. Hasilnya tetap bermakna secara visual dengan mengorbankan beberapa kehilangan informasi di ekstrem yang jenuh.
Pemotongan juga merupakan alasan mengapa sub dan rsub mengembalikan hasil yang berbeda satu sama lain. img_a.sub(img_b) memberikan bagian dari a yang lebih terang dari b dan nol di tempat lain; img_a.rsub(img_b) memberikan bagian dari b yang lebih terang dari a. Keduanya berguna untuk deteksi perubahan satu sisi -- jika aplikasi hanya peduli pada piksel yang menjadi lebih terang, atau hanya pada piksel yang menjadi lebih gelap -- tetapi keduanya tidak menangkap semua perubahan antara dua bingkai.
5.9.3. Operasi selisih¶
Untuk deteksi perubahan dua sisi, operasi yang tepat adalah difference(), yang menghitung |self - other| di setiap posisi -- selisih absolut, bebas tanda. Setiap piksel yang berubah dalam arah mana pun muncul sebagai nilai bukan-nol dalam hasilnya, dengan besarnya sebanding dengan seberapa banyak perubahan di posisi tersebut.
Properti tersebut -- bukan-nol tepat di mana dua citra tidak sepakat -- inilah yang menjadikan difference sebagai tulang punggung deteksi perubahan bingkai-demi-bingkai. Bingkai referensi yang disimpan saat startup dan tangkapan segar, dijalankan melalui difference, menghasilkan citra yang piksel bukan-nolnya menandai setiap posisi di mana sesuatu dalam pemandangan bergerak atau mengubah kecerahan.
5.9.4. Pembatasan dengan mask¶
Semua metode aritmatika menerima argumen kata kunci mask yang diperkenalkan pada halaman wilayah-dan-mask. Ketika mask diteruskan, operasi hanya berjalan pada posisi di mana mask bukan-nol; di semua tempat lain, citra tujuan dibiarkan.
Komposisi tersebut muncul dalam dua pola. Yang pertama adalah membatasi operasi pada area yang diketahui: menambahkan dua bingkai bersama hanya di dalam kotak pembatas marker yang terdeteksi, misalnya. Yang kedua adalah membangun bingkai komposit secara bertahap -- min di atas urutan bingkai di dalam mask latar depan, max di atas urutan yang sama di dalam mask pelengkap -- jenis pola seperti itu.
5.9.5. Di tempat, dan menjaga input¶
Metode aritmatika semuanya mengikuti konvensi operasi yang ditetapkan sebelumnya: masing-masing memodifikasi citra sumber di tempat dan mengembalikan citra yang sama untuk chaining. Piksel sumber hilang setelah pemanggilan -- digantikan dengan hasil operasi terhadap apa pun yang diteruskan sebagai operan kedua.
Ketika aplikasi perlu menjaga kedua input, pola yang aman adalah menyalin salah satunya terlebih dahulu:
diff = current.copy() # leaves current intact
diff.difference(reference) # diff now holds the absolute difference
Pola tersebut -- salin, lalu operasi -- adalah tulang punggung dari setiap pipeline diferensiasi bingkai, di mana bingkai referensi harus bertahan dari perbandingan sehingga dapat digunakan kembali pada bingkai yang diambil berikutnya.
Dengan enam operasi penggabungan, dua operasi citra tunggal, satu tulang punggung selisih absolut, dan kata kunci mask untuk pembatasan, toolkit aritmatika piksel mencakup kombinasi kecerahan-dan-saluran yang dibutuhkan visi mesin klasik. Alat yang tersisa mirip-aritmatika pada permukaannya bekerja bit demi bit, bukan nilai demi nilai.