4.14. Dasar-dasar CSI¶
Modul csi adalah cara kode Python mengendalikan sensor kamera. Setiap skrip yang menangkap bingkai mengikuti bentuk tiga bagian yang sama: impor di bagian atas, konfigurasi satu kali di tengah, dan loop while True di bagian bawah yang mengambil bingkai dari kamera satu per satu.
4.14.1. Loop yang umum¶
import csi, image, time
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
# process img here
print(clock.fps())
4.14.2. Apa yang dilakukan setiap panggilan¶
import csi, image, timeMembawa tiga modul.
csimengontrol sensor,imagemendefinisikan kelasImageyang dikembalikan olehsnapshot(), dantimemenyediakan helpertime.clock()yang digunakan untuk mengukur bingkai per detik.csi.CSI()Membangun instansi
CSIyang membungkus satu sensor kamera fisik. Konstruktor mengklaim periferal kamera dan merekam konfigurasi per-sensor. Kamera dengan satu sensor memiliki satu instansiCSI; kamera dengan dua sensor (warna plus termal, warna plus peristiwa) memiliki dua, masing-masing dipilih oleh argumencidpada konstruktor.csi0.reset()Memberi daya dan mengonfigurasi sensor. Secara default, ia menyentakkan pin reset sensor, lalu menulis register I2C sensor ke kondisi awal yang diketahui. Panggilan konfigurasi berikutnya --
pixformat,framesize, knob kontrol otomatis -- mendorong penulisan register lebih lanjut melalui bus kontrol I2C yang sama.csi0.pixformat(csi.RGB565)Menulis register sensor yang memilih format piksel keluaran. Pilihan yang tersedia adalah format yang diperkenalkan halaman format piksel:
RGB565,GRAYSCALE,BAYER,YUV422, danJPEGpada sensor yang mendukungnya.csi0.framesize(csi.QVGA)Menulis register yang memilih resolusi keluaran.
QVGAadalah 320 × 240; ukuran bernama berjalan hinggaWQXGA2(2592 × 1944, sekitar 5 MP) pada sensor yang mendukungnya. Tuple(width, height)kustom juga dapat digunakan, selama sesuai dengan kemampuan keluaran sensor.clock = time.clock()Membuat helper clock. Setiap panggilan ke
clock.tick()di dalam loop merekam waktu mulai iterasi;time.clock.fps()melaporkan laju loop terkini dalam bingkai per detik.img = csi0.snapshot()Menangkap satu bingkai dari sensor dan mengembalikannya sebagai
Image. Mekanika bagaimana bingkai tersebut berakhir di memori layak dilihat lebih dekat.
4.14.3. Bagaimana snapshot mengisi memori¶
Sensor mengirimkan piksel pada bus data piksel yang dijelaskan di bus sensor pada kecepatan ratusan megabyte per detik -- jauh terlalu cepat untuk disalin CPU piksel per piksel dalam perangkat lunak.
Sebagai gantinya, MCU mendelegasikan transfer ke Direct Memory Access (DMA) -- mesin perangkat keras terpisah dari CPU yang menyalin byte dari satu tempat ke tempat lain di dalam MCU tanpa melibatkan CPU sama sekali. Periferal masukan kamera menangkap setiap byte piksel masuk ke dalam FIFO kecil di dalam chip; tahap ISP mana pun yang berjalan di sisi MCU memproses data saat melewatinya; dan mesin DMA menulis piksel yang sudah selesai ke dalam framebuffer di RAM pada offset piksel yang sesuai. Tidak ada yang dalam rantai tersebut memerlukan CPU setelah saluran DMA diprogram.
Saat snapshot() dipanggil:
Driver CSI memprogram mesin DMA dengan alamat framebuffer, panjang transfer (sejumlah piksel satu bingkai), dan callback untuk interupsi DMA-done.
Driver mengaktifkan periferal masukan kamera dan menunggu sensor memberi sinyal awal bingkai berikutnya.
Saat sensor mengalirkan bingkai keluar, periferal meneruskan setiap byte piksel melalui ISP dan ke mesin DMA, yang menulis hasilnya ke RAM pada offset framebuffer berikutnya. CPU bebas menjalankan kode lain selama transfer.
Saat piksel terakhir bingkai tiba, DMA mengaktifkan interupsi done-nya, driver membungkus framebuffer dalam
Image, dansnapshot()mengembalikannya ke kode pengguna.
Image yang dikembalikan tidak memiliki salinan data piksel -- ia menunjuk ke salah satu framebuffer kamera di RAM. Berapa banyak framebuffer yang disimpan kamera, dan bagaimana mereka diserahkan antara DMA dan kode pengguna pada setiap panggilan ke snapshot(), bergantung pada mode buffering yang dipilih aplikasi melalui framebuffers().