5.31. การจับคู่การเคลื่อนที่

การจับคู่แม่แบบตอบคำถาม ตำแหน่งของแพตช์นี้ในเฟรมอยู่ที่ไหน; การให้คะแนนความคล้ายคลึงตอบคำถาม สองภาพนี้คล้ายกันโดยรวมมากน้อยเพียงใด คำถามอื่นอยู่ระหว่างกลาง: สองเฟรมแสดงฉากเดียวกัน แต่กล้อง (หรือฉาก) เคลื่อนที่ระหว่างสองเฟรม -- เคลื่อนที่ไปเท่าใด? นั่นคือปัญหา การเคลื่อนที่ และโมดูล image แก้ปัญหานี้ด้วยวิธีการสหสัมพันธ์เฟสเพียงวิธีเดียว

5.31.1. การเคลื่อนที่ด้วยสหสัมพันธ์เฟส

find_displacement() ประเมินการจัดวางแบบแข็งระหว่างสองภาพที่มีขนาดเท่ากันโดยใช้ สหสัมพันธ์เฟส -- วิธีการในโดเมนความถี่ที่รันการแปลงฟูเรียร์อย่างเร็ว (FFT) บนแต่ละภาพ สหสัมพันธ์เฟสของทั้งสอง และหาตำแหน่งยอดสูงสุดในผลลัพธ์ ตำแหน่งยอดสูงสุดคือการเลื่อนที่จัดวางสองภาพให้ตรงกัน:

d = img.find_displacement(template)

print("shift:", d.x_translation, d.y_translation,
      " response:", d.response)

ออบเจ็กต์ Displacement ที่คืนค่ามามี x_translation และ y_translation -- การเลื่อนพิกเซลในแต่ละแกน -- บวกกับ response ซึ่งเป็นคะแนนความเชื่อมั่นจาก 0.0 ถึง 1.0 โดย 1.0 คือยอดสูงสุดที่สมบูรณ์แบบ การกรองการตรวจจับออกต่ำกว่า response > 0.3 จะทิ้งผลลัพธ์ที่ไม่แน่นอนซึ่งสหสัมพันธ์เฟสไม่พบยอดสูงสุดที่ชัดเจน

ทั้ง rotation และ scale เป็น 0.0 และ 1.0 ตามลำดับในโหมดเริ่มต้น; จะมีค่าจริงเฉพาะเมื่อ logpolar=True (ดูด้านล่าง)

เมธอดนี้มีข้อจำกัดในทางปฏิบัติสองประการ ประการแรกคือ มิติที่เป็นเลขยกกำลังสอง: FFT ที่เป็นแกนหลักของสหสัมพันธ์เฟสทำงานเร็วที่สุด -- และบนกล้อง มีการรองรับอย่างสมบูรณ์ -- ที่ขนาดเช่น 32x32, 64x64 และ 128x128 การตั้งค่าที่สะอาดที่สุดคือการจับภาพที่ขนาดเหล่านั้นโดยตรง โดยส่งความละเอียดไปยัง framesize() เป็น tuple:

csi0.framesize((64, 64))

แอปพลิเคชันที่ต้องการการเคลื่อนที่จากเฟรมที่ใหญ่กว่าจะครอปแพตช์ที่มีขนาดเป็นเลขยกกำลังสองออกจากบริเวณที่สนใจและรันตัวจับคู่บนแพตช์นั้น

ประการที่สองคือ อินพุตต้องมีขนาดเท่ากัน: roi และ template_roi ต้องเลือกความกว้างและความสูงที่เหมือนกัน มิฉะนั้นตัวจับคู่จะปฏิเสธการเรียก ภาพที่จับสองภาพจากกล้องเดียวกันที่การตั้งค่าเดียวกันตรงตามเงื่อนไขนี้โดยอัตโนมัติ; เฟรมที่จับภาพเปรียบเทียบกับข้อมูลอ้างอิงที่โหลดมาต้องครอปทั้งสองให้เป็นแพตช์เลขยกกำลังสองที่ตรงกันก่อน

5.31.2. การหมุนและการปรับขนาดผ่าน log-polar

โหมดเริ่มต้นหา เฉพาะการเลื่อน เมื่อสองเฟรมยังต่างกันใน การหมุน รอบจุดศูนย์กลางที่เลือกหรือใน การปรับขนาด รอบจุดศูนย์กลางเดียวกัน การรันสหสัมพันธ์เฟสบนการฉาย log-polar ซ้ำของแต่ละภาพจะเปลี่ยนพารามิเตอร์เหล่านั้นเป็นการเลื่อนในระบบพิกัด log-polar -- ซึ่งตัวจับคู่สหสัมพันธ์เฟสเดิมสามารถกู้คืนได้:

d = img.find_displacement(template, logpolar=True)

print("rotation rad:", d.rotation,
      " scale:", d.scale,
      " response:", d.response)

ด้วย logpolar=True เมธอดจะรันกระบวนการจับคู่เดิมกับภาพที่ฉาย log-polar แทนต้นฉบับ ฟิลด์ rotation และ scale ของผลลัพธ์จะถูกกรอกข้อมูล: rotation คือมุมเป็นเรเดียนระหว่างสองเฟรม scale คืออัตราส่วนขนาดระหว่างทั้งสอง x_translation และ y_translation ไม่มีความหมายในโหมดนี้ (การเลื่อนตามแกน log-polar ไม่สอดคล้องกับการเลื่อนเชิงเส้นในแหล่งข้อมูล)

คำสำคัญ fix_rotation_scale=True ครอบคลุมกรณีระหว่างกลาง: สองภาพต่างกันทั้ง การเลื่อน และ การหมุน/การปรับขนาด และแอปพลิเคชันต้องการ เฉพาะการเลื่อน หลังจากแก้ไขการหมุนและการปรับขนาดแล้ว ตัวจับคู่รัน log-polar pass ก่อนเพื่อกู้คืนการหมุนและการปรับขนาด ใช้ค่าผกผันกับภาพหนึ่ง จากนั้นรัน translation pass เพื่อกู้คืนการเลื่อนที่เหลือ แฟล็กนี้มีความหมายเฉพาะเมื่อ logpolar=False -- มันขอให้ตัวจับคู่โหมดการเลื่อนก่อนตัดการหมุน/การปรับขนาดออก

รูปแบบจากการแปลง Polar -- Cartesian → polar → match -- คือสิ่งที่ find_displacement() ด้วย logpolar=True ทำในการเรียกครั้งเดียว แอปพลิเคชันเก็บแพตช์ log-polar อ้างอิงไว้เมื่อเริ่มต้น จับภาพและแปลง log-polar สำหรับแต่ละเฟรมสด และเมธอดจะกู้คืนความแตกต่างของการหมุนและการปรับขนาดระหว่างกัน สำหรับแอปพลิเคชันที่ต้องการตัวติดตามที่ไม่ขึ้นกับการหมุนและการปรับขนาด -- หุ่นยนต์ท่าเรือที่กล้องเอียงและซูมขณะเข้าใกล้เป้าหมาย, กิมบัลที่มีระบบกันสั่นที่ต้องรู้ว่าภาพหมุนเทียบกับอ้างอิงอย่างไร -- นี่คือโครงสร้างมาตรฐาน

5.31.3. การใช้งานแบบคลาสสิก

การใช้งานทั่วไปที่สุดของ find_displacement() คือ การประมาณการเคลื่อนที่เฟรมต่อเฟรม ในกระบวนการที่ประมวลผลกล้องที่กำลังเคลื่อนที่ กล้องจับแพตช์เลขยกกำลังสองขนาดเล็กที่เฟรม N จับแพตช์ขนาดเดียวกันที่เฟรม N+1 รัน find_displacement() บนทั้งสอง และอ่านการเลื่อนพิกเซลระหว่างกัน การเลื่อนนี้เป็นการเคลื่อนที่โดยประมาณของกล้อง (หรือของฉาก ขึ้นอยู่กับกรอบอ้างอิงที่สำคัญ) ระหว่างการจับภาพสองครั้ง มีประโยชน์สำหรับ:

  • การรับรู้แบบ optical flow -- โดรนโฮเวอร์ที่มีกล้องหันลงใช้การเคลื่อนที่ต่อเฟรมเพื่อประมาณการเคลื่อนที่ด้านข้างและป้อนกลับเข้าสู่ตัวควบคุมการบิน

  • การทำให้ภาพมีเสถียรภาพ -- การเคลื่อนที่ระหว่างเฟรมต่อเนื่องถูกหักออกจากภาพที่จับก่อนบันทึกหรือส่ง ทำให้สตรีมวิดีโอราบรื่นขึ้น

  • การจัดวางการตรวจสอบ -- กล้องสแกนที่เคลื่อนที่ตามสายพานลำเลียงใช้การเคลื่อนที่ต่อเฟรมเพื่อลงทะเบียนแต่ละเฟรมกับเฟรมถัดไปและสร้างมุมมองที่เย็บต่อกันของชิ้นส่วนทั้งหมด

แต่ละแอปพลิเคชันเหล่านั้นมีรูปแบบเดียวกัน: จับภาพ, หาการเคลื่อนที่, สะสมในค่าประมาณที่ไหลต่อเนื่อง, จับภาพอีกครั้ง