5.30. การจับคู่เทมเพลต

ตัวตรวจจับที่ผ่านมาตอบคำถามเกี่ยวกับ เนื้อหา ของเฟรมเดียว: บลอบอยู่ที่ไหน เส้นวิ่งไปทางใด โค้ดที่พิมพ์บอกว่าอะไร คำถามประเภทหนึ่งที่แตกต่างออกไปคือการเปรียบเทียบภาพหนึ่งกับอีกภาพหนึ่ง บริเวณที่จับภาพได้นี้มีลักษณะเหมือนกับแผ่นอ้างอิงที่บันทึกไว้ตอนปรับเทียบหรือไม่? วิธีการจับคู่ตอบคำถามนั้น

การวิเคราะห์ด้านโทนสีและสถิติได้แนะนำ get_similarity() สำหรับคำถามที่เกี่ยวข้อง -- สองภาพที่มีขนาดเท่ากันนี้เหมือนกันโดยรวมแค่ไหน? -- โดยใช้ SSIM เป็นตัวชี้วัดพื้นฐาน คำถามการจับคู่ที่เหลืออยู่คือคำถามเรื่อง การระบุตำแหน่ง: ไม่ใช่ "สองภาพนี้เหมือนกันแค่ไหน" แต่เป็น "แผ่นย่อยขนาดเล็กนั้นปรากฏอยู่ที่ไหนภายในภาพขนาดใหญ่นี้?" เครื่องมือที่เหมาะสมสำหรับคำถามเรื่องการระบุตำแหน่งคือ การจับคู่เทมเพลต

5.30.1. การเรียกใช้งานพื้นฐาน

find_template() ค้นหาตำแหน่งแรกที่ภาพ เทมเพลต ขนาดเล็กปรากฏในเฟรมที่จับได้ การใช้งานใช้ การสหสัมพันธ์ไขว้แบบปรับมาตรฐาน (NCC): เทมเพลตเลื่อนผ่านเฟรม คำนวณคะแนนการจับคู่ต่อตำแหน่งจากความสหสัมพันธ์ระหว่างพิกเซลของเทมเพลตและพิกเซลเฟรมที่อยู่ด้านล่าง (ปรับมาตรฐานตามค่าเฉลี่ยและความแปรปรวนในพื้นที่ เพื่อไม่ให้การเปลี่ยนแปลงค่าเกนทำให้การจับคู่ผิดพลาด) และตำแหน่งแรกที่คะแนนผ่าน threshold จะถูกส่งคืนในรูปแบบกรอบล้อมรอบ:

template = image.Image("/sdcard/template.bmp", copy_to_fb=False)
template.to_grayscale()

match = img.find_template(template, threshold=0.7,
                           search=image.SEARCH_DS)

if match is not None:
    img.draw_rectangle(match, color=(255, 0, 0))

เมธอดนี้ ทำงานได้เฉพาะกับภาพระดับสีเทาเท่านั้น จับภาพในโหมดระดับสีเทา (ตัวเลือกที่เป็นธรรมชาติสำหรับกล้องใดๆ ที่ไม่มีเซนเซอร์สี) หรือแปลงในที่เดิมผ่าน to_grayscale() ก่อนเรียกใช้ เช่นเดียวกันกับเทมเพลตที่โหลดจากดิสก์: เทมเพลตสีถูกแปลงด้วยเมธอดเดียวกัน และผลลัพธ์คือสิ่งที่ตัวจับคู่คาดหวัง

threshold เป็นค่า float ตั้งแต่ 0.0 ถึง 1.0 ค่า 1.0 ต้องการการจับคู่พิกเซลต่อพิกเซลที่สมบูรณ์แบบ (ซึ่งไม่เคยเกิดขึ้นกับภาพที่จับได้จริง) 0.0 ยอมรับทุกอย่าง และค่าระหว่าง 0.6 ถึง 0.8 ครอบคลุมกรณีทั่วไปที่เทมเพลตถูกจับภาพในสภาพแสงที่คล้ายกันและฉากไม่ได้เปลี่ยนแปลงอย่างมาก เพิ่มค่าขีดแบ่งเพื่อลดผลบวกลวง ลดค่าเพื่อยอมรับการจับคู่ที่มีสัญญาณรบกวนมากขึ้นโดยแลกกับผลลัพธ์ที่เป็นเท็จมากขึ้น

5.30.2. กลยุทธ์การค้นหา

search เลือกระหว่างสองกลยุทธ์ image.SEARCH_EX คือการค้นหา แบบสมบูรณ์: เทมเพลตเลื่อนผ่านทุกตำแหน่งแบบ step พิกเซลในเฟรมและส่งคืนผลตรงแรกที่เกินค่าขีดแบ่ง image.SEARCH_DS คือ การค้นหาแบบเพชร: ตัวจับคู่สุ่มตัวอย่างแบบหยาบก่อน จากนั้นปรับแต่งรอบคะแนนที่ดีที่สุด ซึ่งเร็วกว่ามากแต่อาจพลาดการจับคู่ที่แท้จริงหากการผ่านแบบหยาบลงเอยใกล้ค่าสูงสุดเฉพาะที่ที่ชนะค่าทั่วโลก สำหรับไปป์ไลน์แบบเรียลไทม์ที่เทมเพลตถูกกำหนดชัดเจนและไม่น่าสับสน SEARCH_DS คือค่าเริ่มต้นที่เหมาะสม สำหรับการปรับเทียบแบบครั้งเดียวที่ค่าใช้จ่ายของการพลาดสูงกว่าค่าใช้จ่ายของการสแกนที่ช้ากว่า SEARCH_EX จะปลอดภัยกว่า

step ควบคุมการข้ามพิกเซลระหว่างการผ่านแบบสมบูรณ์ (การค้นหาแบบเพชรจัดการขั้นตอนของตัวเอง) ค่า step ที่ใหญ่ขึ้นจะเร่งการสแกนแต่แลกกับความแม่นยำระดับต่ำกว่าพิกเซล roi จำกัดการค้นหาไปยังบริเวณที่สนใจ (ROI) ของเฟรม ทั้งการจำกัดสิ่งที่ตัวจับคู่พิจารณาและการลดงาน

ค่าที่ส่งคืนคือ tuple กรอบล้อมรอบ (x, y, w, h) ที่ระบุการจับคู่ที่ดีที่สุด หรือ None หากไม่มีตำแหน่งใดผ่านค่าขีดแบ่ง กรอบล้อมรอบนี้ส่งต่อไปยัง draw_rectangle() หรือ crop() โดยตรงสำหรับขั้นตอนการประมวลผลถัดไป

5.30.3. กับดักของสเกลและการหมุน

ข้อผิดพลาดคลาสสิกของการจับคู่เทมเพลตคือ ความไวต่อสเกลและการหมุน ตัวจับคู่เปรียบเทียบเทมเพลตกับเฟรมพิกเซลต่อพิกเซล เทมเพลตที่จับภาพที่ระยะหนึ่งไม่ตรงกับวัตถุเดียวกันที่จับภาพที่ระยะอื่น และเทมเพลตที่จับภาพตรงๆ ไม่ตรงกับวัตถุเดียวกันที่มองจากมุมเฉียง ค่าขีดแบ่งจะลดลงอย่างเงียบๆ ต่ำกว่าระดับการจับคู่แม้ว่าวัตถุจะมองเห็นได้ชัดเจนด้วยตาของมนุษย์ และเมธอดจะส่งคืน None

มีวิธีแก้ปัญหาบางอย่างสำหรับกรณีง่ายๆ แอปพลิเคชันสามารถจับภาพเทมเพลตหลายแบบที่สเกลต่างกันและเรียก find_template() สำหรับแต่ละแบบตามลำดับ ยอมรับแบบแรกที่ผ่านค่าขีดแบ่ง ค่าใช้จ่ายจะเพิ่มขึ้นตามจำนวนเทมเพลต แอปพลิเคชันสามารถประมวลผลล่วงหน้าเฟรมด้วย rotation_corr() หรือการแปลงเชิงขั้ว (การแปลงทางเรขาคณิต) เพื่อลบการหมุนที่ก่อให้เกิดปัญหาก่อนที่การจับคู่จะทำงาน เทมเพลตที่จับคู่ยังคงต้องตรงกับเรขาคณิตที่แก้ไขแล้ว

สำนวนที่มีประโยชน์สำหรับไปป์ไลน์การตรวจสอบ QA จับคู่ตัวจับเทมเพลตกับตัวให้คะแนนความคล้ายคลึงที่การวิเคราะห์ด้านโทนสีและสถิติแนะนำ: find_template() ระบุตำแหน่งชิ้นส่วนในเฟรมที่จับได้และกรอบล้อมรอบที่ส่งคืนถูกตัดออกและส่งต่อไปยัง get_similarity() เทียบกับแผ่นอ้างอิง ขั้นตอนการจับเทมเพลตตัดสิน ว่าชิ้นส่วนอยู่ที่ไหน; ขั้นตอนคะแนนความคล้ายคลึงตัดสิน ว่าชิ้นส่วนนั้นยอมรับได้หรือไม่ ทั้งสองขั้นตอนทำงานทุกเฟรม ค่าขีดแบ่งบน mean คือประตูผ่าน/ไม่ผ่าน และกรอบล้อมรอบที่จับคู่ได้วาดกลับเข้าไปในเฟรมเป็นตัวอย่างของ IDE ที่ผู้ปฏิบัติงานคอยดู