Sesekali sebuah proyek datang bersama dengan kekuatan magis untuk mengkonsumsi waktu dan perhatian Anda selama beberapa bulan. Ketika Anda akhirnya menyelesaikannya, Anda merasa kasihan bahwa Anda tidak perlu melakukan apa-apa lagi.

Apa yang istimewa dari Bingo Ball Reader ini? Ini mungkin tampak seperti proyek OCR biasa pada pandangan pertama; Kamera video menangkap perangkat lunak gambar dan OCR mengenali nomor tersebut. Mudah itu. Dan itu bekerja tanpa masalah, seperti setiap gadget mudah.

Tapi sekali lagi, mungkin itu tidak sesederhana itu. Angka tersebar di seluruh bola, sehingga mereka harus ditempatkan terlebih dahulu, dan kandidat pembacaan terbaik harus dipilih. Kemudian, angka dicat pada bola daripada permukaan datar, dalam beberapa kasus membuat mereka cacat pada titik di mana bentuknya harus dipulihkan terlebih dahulu. Juga, sudut bacaan tidak diperbaiki tetapi di suatu tempat pada skala 360 °. Dan kemudian kita memiliki masalah silau untuk boot, karena Bingo Balls begitu mengkilap sehingga setiap sumber cahaya mencerminkan sebagai titik terang jenuh.

Jadi, apakah itu semua? Hampir saja. Tugas ini diharapkan akan dilakukan oleh mikrokontroler tertanam, dengan kecepatan dan memori terbatas, namun proses pengakuan untuk satu bola harus cepat – 500 ms paling buruk. Tapi itu hanya satu bagian dari prosesnya. Proyek ini mencakup mekanisme pipelined yang menerima bola, mengangkutnya untuk dipindai oleh OCR dan kemudian ditembak oleh kamera video broadcast publik sebelum dibuang. Dan akhirnya, jika bacaannya tidak cukup dapat diandalkan, bola harus diputar secara halus sehingga jumlahnya akan diposisikan ulang untuk upaya membaca lain.

Meskipun tantangan ini saya berhasil membangun sistem ini. Ini cepat dan dapat diandalkan, dan saya menemukan beberapa trik yang sangat menarik di sepanjang jalan. Lihatlah video demo cepat di bawah ini untuk merasakan kecepatan, dan apa sistem “melihat”. Kemudian bergabunglah dengan saya setelah istirahat untuk menyelam ke detail dari Build Embedded yang menarik ini.

Awalnya, saya pikir saya harus mempekerjakan jaringan saraf untuk proses pengakuan, tetapi ternyata pengakuan sebenarnya adalah bagian paling sederhana dari proyek, dan bahwa akan jauh lebih sederhana dan lebih cepat untuk melakukannya secara algoritmik. Bagian yang sulit adalah mengidentifikasi apa yang ada pada seluruh gambar, menemukan angka terbaik, garis di bawahnya, dan mengukur seberapa besar harus diputar. Dimulai dengan tidak lebih dari gambar bitmap, prosesor harus melakukan banyak matematika bahkan sebelum itu dapat memastikan jika jumlahnya terdiri dari satu atau dua digit.

Skema Sederhana Bagian OCR
VGA selama pengembangan

Untuk membuat pengembangan, pemeliharaan, dan penyesuaian lebih mudah, MCU yang sama digunakan untuk pembuatan sinyal VGA selain pengambilan gambar dan pemrosesan. Itu tidak hanya menampilkan gambar yang dipindai, tetapi juga mencakup beberapa parameter saat ini dan konten RAM. Papan pengontrol memiliki konektor VGA, tetapi tidak boleh digunakan selama operasi normal unit. VGA Monitor tidak memiliki kesamaan dengan monitor siaran di Bingo Hall, karena ada dua kamera independen dan sistem pencahayaan.

Generasi sinyal VGA mengkonsumsi banyak waktu prosesor, sehingga dimatikan selama pengambilan gambar dan pemrosesan, yaitu sekitar 500 ms selama setiap siklus membaca bola. Sinyal sinkronisasi secara transparan dihasilkan oleh periferal PWM internal dan mereka aktif setiap saat, sehingga pemulihan gambar setelah sinyal RGB yang ditetapkan cepat.

Dalam hal ini, mikrokontroler 16-bit PIC24EP512GP806 digunakan, dengan 586/52 k memori program / data dan 60 kecepatan eksekusi MIPS.

Mengambil gambar

Kamera video “Cube” analog murah digunakan pada fase pertama pengembangan, tetapi kemudian diganti dengan kamera cube digital. Keduanya mirip dalam harga dan kinerja, tetapi yang terakhir datang dengan lensa yang memiliki panjang fokus yang lebih tinggi, sehingga jarak bisa lebih tinggi dan kamera video dapat melihat area bola yang lebih besar.

Untuk benda kecil seperti itu, sumber cahaya terbaik seharusnya menjadi LED putih, tetapi silaunya cukup buruk dengan permukaan bola mengkilap. Saya melakukan beberapa eksperimen dengan diffusers, tetapi tanpa keberuntungan. Layanan akhirnya berasal dari pendekatan yang cukup berbeda: refleksi yang sangat cerah dan tajam, tetapi dengan paparan ganda yang menggunakan sumber cahaya yang berbeda. Selama proses pengambilan gambar kedua, MCU memilih nilai yang lebih rendah untuk setiap piksel.

Karena hotspot tidak pernah cocok, mereka akan dibatalkan dan gambar yang dihasilkan (foto ketiga dari kiri) diterangi secara merata dan bebas silau. Sebagai bonus tambahan, refleksi cahaya latar belakang dibatalkan dalam proses juga.

Harap dicatat bahwa sistem disematkan, tanpa fungsi tangkapan layar, sehingga gambar berasal dari monitor VGA yang ditembak dengan kamera.

Sumber cahaya terdiri dari 16 LED putih, sehingga delapan LED aktif pada suatu waktu. Gambar di sisi kanan kanan mewakili pengaturan LED dari sudut pandang kamera. LED berwarna merah dan biru di sini untuk membantu membedakan antarakelompok untuk paparan pertama dan kedua.

Ini membuat proses secara signifikan lebih lambat, karena sekarang kita tidak hanya memiliki dua eksposur, tetapi juga waktu bingkai dummy antara dua eksposur, untuk memungkinkan pemulihan dan akomodasi sensor CMOS setelah perubahan pencahayaan. Itu sebabnya seluruh proses pencitraan memerlukan 100 ms.

Resolusi gambar yang dipindai adalah 220 × 220 piksel, dengan kedalaman piksel 8-bit. Gambar grayscale analog hanya terdiri dari enam bit, dengan dua bit yang tersisa digunakan untuk representasi warna biru dan merah pada monitor, karena skala abu-abu sebenarnya adalah greenscale. Piksel ekstra tersebut digunakan sebagai piksel bendera khusus antara langkah-langkah pemrosesan, terlihat dalam mode langkah tunggal, seperti area biru dan merah. Ini [ternyata] sangat membantu selama pengembangan program dan debugging.

Seluruh proses dibagi menjadi 17 langkah, yang juga dapat dilakukan dalam mode langkah tunggal untuk keperluan pengembangan dan debugging. Nomor langkah ditampilkan di sudut kiri atas layar (lihat di bawah), dan keadaan stopwatch saat ini dengan resolusi 1 ms di kanan atas. Dengan cara ini mudah untuk mengikuti waktu eksekusi dan mengoptimalkan setiap langkah.

Lokasi Bola dan Peregangan

Untuk menemukan bola secara tepat, x, y koordinat untuk centroid (pusat geometrik) dihitung, menggunakan formula cx = σcixai / σAI dan CY = σciyai / σAI, di mana CX, CY adalah x, y koordinat dan A adalah nilai setiap piksel. Karena latar belakang sebagian besar hitam sebelum langkah ini, CX, CY akan kira-kira di tengah bola. Kemudian seluruh buffer buffer dipindahkan sebagai blok 2D, sehingga centroid pada koordinat x = 110, y = 110, yang berada di tengah bingkai. Pusat ini ditandai dengan 2 × 2 piksel merah (bit 7) hanya untuk kenyamanan pengembang, karena firmware pemrosesan dalam banyak kasus mengabaikan bit 6 dan 7.

Selanjutnya, diameter bola diukur, menghitung nilai piksel rata-rata pada perimeter untuk diameter yang berbeda. Kemudian, latar belakang (setiap piksel yang berada di luar diameter) diatur ke “putih” atau, jauh lebih spesifik, hijau (nilai 0x3f), untuk menjamin isolasi yang lebih baik dari area hitam. Latar belakang akan diatur ke putih atau hitam beberapa kali lebih banyak selama pemrosesan, setiap kali pemilihan area hitam (tinta) atau putih (kertas) diperlukan.

Tanpa cacat mengubah bola ke permukaan datar tidak mungkin, tetapi bentuknya dapat ditingkatkan jika gambar tidak berbentuk linear, seperti pada gambar Langkah 3. Mikrokontroler 16-bit kecil tidak memiliki coprocessor aritmatika, dan menggunakan pustaka trigonometri standar akan mengkonsumsi terlalu banyak waktu prosesor. Itu sebabnya tabel pencarian trigonometri digunakan, dan Anda dapat melihat pada stopwatch (digit biru terbaik) yang, dalam hal ini, waktu eksekusi untuk prosedur peregangan hanya 11 ms. Anda juga dapat melihat bahwa bagian tengah bola sebagian besar tidak berubah, dan ujung-ujungnya tidak diregangkan secara linear sehingga deformasi bola diminimalkan.

Pada langkah 4, sama dengan fungsi masker Unsharp di Photoshop, gambar baru yang kabur dibuat. Karena tidak ada cukup ruang RAM untuk buffer frame penuh lainnya, itu dilakukan pada gambar bantu yang ditingkatkan ke resolusi 44 × 44. Fungsi topeng Unsharp sangat penting, karena menjamin pemilihan yang lebih baik dari “tinta” piksel relatif terhadap piksel “kertas”. Memilih menyiratkan “pengaturan bit 7”, yang akan menghasilkan area merah pada layar VGA.

Sekarang ada dua gambar dalam buffer buffer yang sama, grayscale one (bit 0-5) dan biner satu (bit 7). Yang terakhir digunakan dalam langkah preprocessing 6, di mana lubang kecil dan goresan dihilangkan. Gambar yang dipilih pertama kali diperluas dan dikontrak, dan kemudian proses diulangi dengan pembelian operasi terbalik – yang menghasilkan tepi yang dibulatkan dengan lancar dan bebas sampah.

Manipulasi komponen

Setelah beberapa langkah preprocessing, jauh lebih banyak operasi besar terjadi. Yang pertama dikenal sebagai “komponen yang terhubung”, di mana area terisolasi dipilih dan parameter untuk masing-masing diperoleh. Ini termasuk dimensi X dan Y, koordinat pusat X dan Y, jumlah piksel yang dipilih, dan jarak Euclid dari tengah bingkai. Ini akan membantu mengurutkan setiap komponen sebagai digit, lingkaran besar, garis bawah atau latar belakang. Pada tahap ini, juga menjadi jelas jika jumlahnya mencakup satu atau dua digit.

Langkah ini membutuhkan banyak waktu pemrosesan, sekitar 200 ms. Masalah lain adalah bahwa algoritma standar untuk komponen yang terhubung membutuhkan buffer bingkai bantu dengan ukuran yang sama, jadi saya harus membuat algoritma baru yang memanfaatkan buffer buffer yang sama, ditambah tabel kecil untuk koordinat jangka pendek.

Pada titik ini, mudah bagi prosesor untuk memilih kandidat terbaik untuk pengakuan – itu adalah lingkaran dengan jarak Euclid terkecil dari pusat bola. Komponen yang terhubung di dalam lingkaran ini diperhitungkan, dan yang lainnya dihapuskan.

Bola yang dimaksud adalah bola OCR khusus dengan angka yang digarisbawahi, so bahwa sudut rotasi dapat diukur. Sekarang, pusat lingkaran diketahui, program ini memutar formulir “T” virtual, yang sesuai dengan bentuk garis bawah, dalam 512 langkah di sekitar lingkaran 360 °, menghitung berapa banyak piksel “tinta” yang dikandungnya. Hitungan peringkat tertinggi menentukan sudut rotasi, maka blok 2D bingkai buffer dipindahkan ke bawah sudut terbaik gambar (langkah 12 pada gambar paling kiri), dan rotasi dilakukan, memindahkan bitmap ke sudut yang berlawanan buffer bingkai. Berkat tabel pencarian logaritmik, grup operasi ini hanya membutuhkan 50 ms.

Itu terus membaik dengan setiap langkah. Digit dipilih dengan warna yang berbeda, maka satu digit dipindahkan ke jarak aman, dan kemudian setiap digit diskalakan ke resolusi 30 × 46 yang diketahui.

Pengakuan

Karena pembaca ini adalah proyek OCR pertama saya, saya dengan naif berpikir proses pengakuan akan menjadi bagian terberat untuk dipecahkan. Setelah setiap langkah dibebani sepenuhnya dan diperiksa satu per satu, saya mencapai langkah ke-17 dan terakhir. Seperti yang sudah saya tunjukkan, rencana awal saya adalah memilih untuk jaringan saraf, tetapi kemudian saya mencoba algoritma yang mudah dan bermain-main dengannya. Saya mengevaluasi dengan beberapa bola dan Anda tidak dapat membayangkan betapa kagetnya saya ketika saya melihatnya bekerja dengan sempurna! Akhirnya bitmap dirender dengan benar ke dua nomor ASCII.

Algoritma ini cukup sederhana. Bitmap untuk setiap digit praktis dibagi dalam tiga bagian, pertama secara horizontal, dan kemudian secara vertikal. Kemudian piksel aktif dihitung di setiap kolom atau baris, dan histogram dibuat. Ada juga histogram ke-7 yang ditambahkan, yang miring untuk membantu mendeteksi garis crosscut yang lebih baik pada digit 4 dan 7.

Hanya butuh 3 ms untuk membangun tujuh histogram untuk setiap digit dan membandingkannya dengan tabel yang direkam, menghitung jumlah kesalahan kuadrat yang disiratkan dan mengurutkan hasilnya. Untuk membuat pengembangan dan debugging lebih mudah, semua histogram diplot ke layar.

Setelah hasil perbandingan diurutkan, kami mendapatkan pemenang untuk setiap digit (dalam hal ini 8 dan 5), tetapi pekerjaan kami tidak dilakukan sampai satu hal lagi terjadi. Kualitas bacaan harus diberi peringkat, sehingga pengontrol dapat memperkirakan jika hasilnya cukup dapat diandalkan.

Jika nomor pada bola hanya memiliki satu digit, tabel kesalahan untuk setiap digit (0 … 9) diurutkan dan “pemenang” dibandingkan dengan yang kedua (hampir-pemenang). Jika rasionya tinggi, itu menyiratkan bahwa pengakuan berhasil. Dalam kasus kami, itu adalah 147%, yang menyiratkan bahwa kandidat peringkat kedua memiliki kesalahan 147% lebih banyak daripada yang terbaik. Misalnya, yang pertama memiliki 100 “unit kesalahan” dan yang kedua memiliki 247. Ini adalah peringkat yang baik, meskipun banyak peringkat berada di utara 300%. Secara umum, peringkat lebih tinggi dari 80% harus dianggap cukup aman.

Tetapi bagaimana jika ada dua digit? Rantai hanya sekuat tautan terlemahnya, sehingga program akan mengabaikan digit yang jauh lebih berhasil diakui (yang satu dengan rasio yang lebih tinggi) dan menggunakan yang lebih lemah untuk membuat keputusan akhir tentang kesuksesan.

Pengontrol memiliki dua mode dasar operasi. Dalam mode cepat, hanya ada satu bacaan, yang diulang (setelah rotasi bola) hanya jika bacaan pertama tidak dinilai dengan cukup baik. Dalam mode yang lebih lambat (“aman”), ada dua bacaan yang hasilnya harus cocok.

Pembaca dievaluasi di Beograd, di perusahaan Eleks-M, yang memproduksi peralatan kasino. Tes ini dilakukan dengan satu kamera video tambahan tambahan yang secara otomatis merekam setiap bacaan bola, kemudian gambar (dengan nama file yang tidak mengandung apa-apa selain nomor bola yang dikenali) diurutkan secara alfabet dan pemeriksaan akhir dilakukan secara manual.

Seluruh tes berlangsung selama 240 jam, yang akan membantu stres – menguji daya tahan bingo blower selain pembaca. Setelah 10 hari dan 115.000 bola membaca, hanya ada satu bacaan yang salah (Ball 37 dibaca sebagai 7), dengan pembaca diatur ke mode cepat. Pengujian dalam mode aman akan tidak ada artinya, karena kesalahan mungkin tidak akan pernah terjadi.

Konsep mekanis.

Jalur fisik untuk bola bingo adalah c