Kami merekatkan beberapa foto menjadi satu foto panjang menggunakan computer vision

Artikel sebelumnya menjelaskan metode enam poin untuk membuka bungkus label dan cara kami melatih jaringan saraf . Artikel ini menjelaskan cara merekatkan fragmen yang dibuat dari sudut berbeda menjadi satu gambar panjang.





Label sudah tersegmentasi sebelumnya dan diterapkan oleh jaringan saraf yang dijelaskan di artikel sebelumnya.







Bagaimana cara kerja perekatan secara umum? Anda perlu mengambil dua gambar yang tumpang tindih, menghitung pergeseran timbal balik dan menempatkan satu di atas yang lain. Kedengarannya sangat sederhana, tetapi mari kita bahas setiap langkahnya.



Untuk menghitung pergeseran timbal balik, Anda perlu menemukan beberapa objek yang ada di kedua gambar dan menghitung transformasi titik dari satu gambar ke gambar lainnya. Pergeseran ini dapat diwakili oleh matriks transformasi, di mana elemen-elemen matriks mengkodekan beberapa transformasi sekaligus - penskalaan, terjemahan, dan rotasi.



Ada tabel bagus di wikipedia yang menunjukkan bagaimana dan elemen mana yang mempengaruhi transformasi.



Seperti yang Anda lihat pada gambar di bawah, ada cukup banyak objek umum:







Tetapi ada masalah dengan objek yang dipilih - objek tersebut sulit dideteksi secara algoritme. Sebaliknya, biasanya mencari objek yang lebih sederhana - yang disebut "corners", mereka juga merupakan deskriptor ("deskriptor", "fitur").



Ada artikel bagus dalam dokumentasi OpenCV tentang mengapa sudut - singkatnya, menentukan garis itu mudah, tetapi hanya memberi Anda satu koordinat. Oleh karena itu, perlu juga untuk mendeteksi garis kedua (bukan paralel). Jika mereka bertemu pada suatu titik, maka tempat ini ideal untuk menemukan deskriptor, ini juga merupakan sudut (meskipun deskriptor sebenarnya bukanlah sudut dalam arti geometris dari kata tersebut).



Salah satu algoritma untuk menemukan deskriptor adalah SIFT (Scale-Invariant Feature Transform). Terlepas dari kenyataan bahwa itu ditemukan pada tahun 1999, itu cukup populer karena kesederhanaan dan keandalannya. Algoritme ini telah dipatenkan, tetapi patennya berakhir musim semi ini (2020). Namun, mereka tidak berhasil mentransfernya ke build OpenCV utama, jadi Anda perlu menggunakan build non-free khusus.



Jadi, mari temukan sudut serupa di kedua gambar:



sift = cv2.xfeatures2d.SIFT_create()
features_left = sift.detectAndCompute(left_image, None)






features_right = sift.detectAndCompute(left_image, None)






Mari kita gunakan Pencocok Flann - ini memiliki kinerja yang baik meskipun jumlah deskriptornya banyak.



KNN = 2
LOWE = 0.7
TREES = 5
CHECKS = 50

matcher = cv2.FlannBasedMatcher({'algorithm': 0, 'trees': TREES}, {'checks': CHECKS})
matches = matcher.knnMatch(left_descriptors, right_descriptors, k=KNN)

logging.debug("filtering matches with lowe test")

positive = []
for left_match, right_match in matches:
    if left_match.distance < LOWE * right_match.distance:
        positive.append(left_match)


Garis kuning menunjukkan bagaimana matcher menemukan kecocokan.







Seperti yang bisa Anda lihat dengan jelas, hanya ada sekitar setengah dari pertandingan yang benar. Namun, jika kecocokan yang benar selalu memberikan transformasi yang sama, maka kecocokan yang salah menunjukkan arah baru yang kacau. Itu. secara teoritis, mereka entah bagaimana dapat dipisahkan satu sama lain:







Salah satu algoritma untuk menemukan transformasi yang benar adalah RANSAC. Algoritme ini berfungsi dengan baik saat Anda ingin memisahkan nilai yang baik dari noise - inilah masalahnya.



Untungnya, OpenCV sudah memiliki fungsi yang akan menemukan matriks transformasi dengan kecocokan menggunakan RANSAC, yaitu. sebenarnya, Anda tidak perlu menulis apa pun.



Mari gunakan fungsi estimAffineP Partial2D yang mencari transformasi berikut: rotasi, penskalaan, dan terjemahan (4 derajat kebebasan).



H, _ = cv2.estimateAffinePartial2D(right_matches, left_matches, False)


Setelah matriks transformasi ditemukan, kita dapat mengubah gambar yang tepat untuk perekatan.



Fragmen Kiri: Fragmen





Kanan:







Pertama, mari kita gunakan cara paling sederhana untuk merekatkan fragmen bersama-sama, saat setiap piksel dari perpotongannya dihitung sebagai rata-rata. Sayangnya, hasilnya biasa saja - gambar terlihat berlipat ganda, terutama di dekat garis perekatan.







Dalam animasi, perbedaan antara dua bingkai lebih terlihat jelas:







Ini tidak mengherankan - foto diambil dari sudut yang berbeda, jaringan saraf juga mengubahnya sedikit berbeda, dan akibatnya, ada sedikit perbedaan.



Untuk perekatan yang mulus, perlu mengkompensasi distorsi non-linier. Distorsi dapat direpresentasikan sebagai bidang vektor dengan resolusi yang sama dengan gambar asli, hanya saja alih-alih warna, pergeseran akan dikodekan di setiap piksel. Bidang vektor ini disebut "aliran optik".



Secara umum, ada beberapa metode berbeda untuk menghitung aliran optik - beberapa di antaranya dibuat langsung ke OpenCV, dan ada juga jaringan saraf khusus.



Dalam kasus kami, saya akan menghilangkan teknik spesifik, tetapi saya akan mempublikasikan hasilnya:







Tetapi kompensasi harus dilakukan secara proporsional untuk kedua fragmen. Untuk melakukan ini, kami membaginya menjadi dua matriks:







Fragmen kiri akan dikompensasikan dari kiri ke kanan dengan cara yang meningkat, sedangkan yang kanan - sebaliknya.



Sekarang kedua fragmen saling tumpang tindih hampir sempurna:







Sekarang overlay secara geometris benar, tetapi kita melihat lompatan yang sangat mencolok dalam kecerahan pada jahitannya:







Masalah ini dapat dengan mudah diperbaiki jika alih-alih nilai rata-rata, mereka dilapisi dengan gradien:







Dengan pendekatan ini, jahitan tidak terlihat sama sekali:







Pada prinsipnya, ada juga teknik perekatan lainnya, misalnya , pencampuran multiband, yang digunakan untuk menggabungkan panorama, tetapi tidak berfungsi baik dengan teks - hanya kompensasi aliran optik yang dapat sepenuhnya menghilangkan ghosting pada teks.



Sekarang kami merekatkan gambar lengkap:







Versi final:







Peningkatan lebih lanjut dapat berupa kompensasi untuk efek bayangan (sisi kanan gambar), atau bahkan lebih banyak pemrosesan warna dan kontras pasca. Anda juga dapat melihat bahwa geometri global telah sedikit rusak - garis di sebelah kanan telah sedikit naik. Secara teoritis, masalah ini juga dapat diperbaiki dengan menambahkan koreksi penskalaan global, tetapi ini juga bukan tugas yang sepenuhnya sepele.



Kami memeriksa cara kerja perekatan, solusi siap pakai tersedia di sini dalam bentuk REST API, saya juga merekomendasikan untuk melihat tautan berikut:






All Articles