Saya sedang melakukan proyek yang menyenangkan: Memecahkan Sudoku dari gambar input menggunakan OpenCV (seperti di Google goggles dll). Dan saya telah menyelesaikan tugas, tetapi pada akhirnya saya menemukan sedikit masalah di mana saya datang ke sini.
Saya melakukan pemrograman menggunakan Python API dari OpenCV 2.3.1.
Di bawah ini yang saya lakukan:
- Baca gambarnya
- Temukan kontur
- Pilih satu dengan luas maksimum, (dan juga agak setara dengan kuadrat).
Temukan titik sudut.
misalnya diberikan di bawah ini:
( Perhatikan di sini bahwa garis hijau bertepatan dengan benar dengan batas sejati Sudoku, sehingga Sudoku dapat dibengkokkan dengan benar . Periksa gambar berikutnya)
warp gambar ke kotak yang sempurna
misalnya gambar:
Lakukan OCR (yang saya gunakan metode yang saya berikan dalam Simple Digit Recognition OCR di OpenCV-Python )
Dan metodenya bekerja dengan baik.
Masalah:
Lihat gambar ini.
Melakukan langkah 4 pada gambar ini memberikan hasil di bawah ini:
Garis merah yang digambar adalah kontur asli yang merupakan garis besar batas sudoku yang sebenarnya.
Garis hijau yang ditarik adalah kontur yang diperkirakan yang akan menjadi garis besar gambar melengkung.
Yang tentu saja, ada perbedaan antara garis hijau dan garis merah di tepi atas sudoku. Jadi saat warping, saya tidak mendapatkan batas asli dari Sudoku.
Pertanyaan saya :
Bagaimana saya bisa melengkungkan gambar pada batas Sudoku yang benar, yaitu garis merah ATAU bagaimana saya bisa menghapus perbedaan antara garis merah dan garis hijau? Apakah ada metode untuk ini di OpenCV?
sumber
Jawaban:
Saya punya solusi yang berfungsi, tetapi Anda harus menerjemahkannya sendiri ke OpenCV. Itu ditulis dalam Mathematica.
Langkah pertama adalah menyesuaikan kecerahan pada gambar, dengan membagi setiap piksel dengan hasil operasi penutupan:
Langkah selanjutnya adalah menemukan area sudoku, jadi saya bisa mengabaikan (menutupi) latar belakang. Untuk itu, saya menggunakan analisis komponen terhubung, dan pilih komponen yang punya area cembung terbesar:
Dengan mengisi gambar ini, saya mendapatkan topeng untuk kisi sudoku:
Sekarang, saya dapat menggunakan filter turunan urutan ke-2 untuk menemukan garis vertikal dan horizontal dalam dua gambar terpisah:
Saya menggunakan analisis komponen terhubung lagi untuk mengekstrak garis grid dari gambar-gambar ini. Garis kisi jauh lebih panjang daripada angka, jadi saya bisa menggunakan panjang caliper untuk memilih hanya komponen yang terhubung garis kisi. Mengurutkan mereka berdasarkan posisi, saya mendapatkan gambar topeng 2x10 untuk setiap garis kisi vertikal / horizontal pada gambar:
Selanjutnya saya mengambil setiap pasangan garis grid vertikal / horizontal, melebarkannya, menghitung persimpangan pixel-demi-pixel, dan menghitung pusat hasilnya. Titik-titik ini adalah persimpangan garis kisi:
Langkah terakhir adalah mendefinisikan dua fungsi interpolasi untuk pemetaan X / Y melalui titik-titik ini, dan mengubah gambar menggunakan fungsi-fungsi ini:
Semua operasi adalah fungsi pemrosesan gambar dasar, jadi ini juga harus dimungkinkan di OpenCV. Transformasi gambar berbasis spline mungkin lebih sulit, tetapi saya tidak berpikir Anda benar-benar membutuhkannya. Mungkin menggunakan transformasi perspektif yang Anda gunakan sekarang pada setiap sel individu akan memberikan hasil yang cukup baik.
sumber
Jawaban Nikie memecahkan masalah saya, tetapi jawabannya ada di Mathematica. Jadi saya pikir saya harus memberikan adaptasi OpenCV di sini. Tetapi setelah mengimplementasikan saya bisa melihat bahwa kode OpenCV jauh lebih besar dari kode natici Mathematica. Dan juga, saya tidak bisa menemukan metode interpolasi yang dilakukan oleh nikie di OpenCV (walaupun itu bisa dilakukan dengan menggunakan scipy, saya akan memberi tahu kapan saatnya tiba.)
1. Image PreProcessing (operasi penutupan)
Hasil:
2. Menemukan Sudoku Square dan Membuat Gambar Topeng
Hasil:
3. Menemukan garis vertikal
Hasil:
4. Menemukan Garis Horizontal
Hasil:
Tentu saja, yang ini tidak begitu baik.
5. Menemukan Poin Grid
Hasil:
6. Memperbaiki cacat
Di sini, nikie melakukan semacam interpolasi, tentang yang aku tidak punya banyak pengetahuan. Dan saya tidak dapat menemukan fungsi yang sesuai untuk OpenCV ini. (mungkin ada di sana, saya tidak tahu).
Lihatlah SOF ini yang menjelaskan bagaimana melakukan ini menggunakan SciPy, yang saya tidak ingin gunakan: Transformasi gambar di OpenCV
Jadi, di sini saya mengambil 4 sudut dari masing-masing sub-square dan menerapkan warp Perspektif untuk masing-masing.
Untuk itu, pertama kita temukan centroid.
Tetapi centroid yang dihasilkan tidak akan disortir. Lihat gambar di bawah ini untuk melihat pesanan mereka:
Jadi kami mengurutkannya dari kiri ke kanan, atas ke bawah.
Sekarang lihat di bawah pesanan mereka:
Akhirnya kami menerapkan transformasi dan membuat gambar baru berukuran 450x450.
Hasil:
Hasilnya hampir sama dengan nikie, tetapi panjang kode besar. Mungkin, metode yang lebih baik tersedia di luar sana, tetapi sampai saat itu, ini berfungsi dengan baik.
Salam ARK.
sumber
Anda dapat mencoba menggunakan beberapa jenis pemodelan berbasis grid dari Anda sembarang warping. Dan karena sudoku sudah berupa kisi, itu seharusnya tidak terlalu sulit.
Jadi, Anda bisa mencoba mendeteksi batas setiap subkawasan 3x3 dan kemudian membengkokkan masing-masing wilayah secara terpisah. Jika deteksi berhasil, itu akan memberi Anda perkiraan yang lebih baik.
sumber
Saya ingin menambahkan bahwa metode di atas hanya berfungsi ketika papan sudoku berdiri tegak, jika tidak, uji rasio tinggi / lebar (atau sebaliknya) kemungkinan besar akan gagal dan Anda tidak akan dapat mendeteksi tepi sudoku. (Saya juga ingin menambahkan bahwa jika garis yang tidak tegak lurus terhadap batas gambar, operasi sobel (dx dan dy) akan tetap berfungsi karena garis masih akan memiliki tepi sehubungan dengan kedua sumbu.)
Untuk dapat mendeteksi garis lurus, Anda harus mengerjakan analisis kontur atau piksel-bijaksana seperti contourArea / boundingRectArea, titik kiri atas dan kanan bawah ...
Sunting: Saya berhasil memeriksa apakah satu set kontur membentuk garis atau tidak dengan menerapkan regresi linier dan memeriksa kesalahan. Namun regresi linier berkinerja buruk ketika kemiringan garis terlalu besar (yaitu> 1000) atau sangat dekat dengan 0. Oleh karena itu menerapkan uji rasio di atas (dalam sebagian besar jawaban tervvotasikan) sebelum regresi linier logis dan berhasil bagi saya.
sumber
Untuk menghapus sudut yang tidak terlindungi, saya menerapkan koreksi gamma dengan nilai gamma 0,8.
Lingkaran merah digambar untuk menunjukkan sudut yang hilang.
Kode tersebut adalah:
Ini sebagai tambahan atas jawaban Abid Rahman jika beberapa titik sudut hilang.
sumber
Saya pikir ini adalah pos yang bagus, dan solusi yang bagus oleh ARK; ditata dengan sangat baik dan dijelaskan.
Saya sedang mengerjakan masalah yang sama, dan membangun semuanya. Ada beberapa perubahan (yaitu xrange to range, argumen di cv2.findContours), tetapi ini harus bekerja di luar kotak (Python 3.5, Anaconda).
Ini adalah kompilasi dari elemen-elemen di atas, dengan beberapa kode yang hilang ditambahkan (yaitu, pelabelan poin).
sumber