5.28. QR codes และ AprilTags¶
ตัวตรวจจับที่ผ่านมา -- บลอบ, เส้น, วงกลม, สี่เหลี่ยม -- ค้นหาลักษณะเด่น เชิงเรขาคณิต: ตำแหน่งและโครงร่างที่ขั้นตอนถัดไปนำไปตีความ ส่วนตัวตรวจจับที่เหลือค้นหาลักษณะเด่น เชิงสัญลักษณ์: รูปแบบที่พิมพ์ออกมา ซึ่งโครงสร้างทางภาพมีขึ้นเพื่อเข้ารหัสข้อมูลโดยเฉพาะ กล้องระบุตำแหน่งสัญลักษณ์เหล่านี้ ตัวถอดรหัสอ่านบิต และสิ่งที่ได้กลับมาไม่ใช่ตำแหน่ง แต่เป็น สตริง (หรือ ID) ที่ผู้พิมพ์สัญลักษณ์เลือกมาโดยเจตนา
มีสองตระกูลหลักที่ครองตลาดในแอปพลิเคชันกล้องขนาดเล็ก QR codes บรรจุข้อความ URL นามบัตร หรือข้อมูลไบนารีตามต้องการ -- เป็นโค้ด 2D ที่ผู้บริโภครู้จักซึ่งปรากฏบนโปสเตอร์ บรรจุภัณฑ์ และบัตรที่นั่งเครื่องบิน AprilTags บรรจุ ID ตัวเลขเดียวจากชุดค่าคงที่ขนาดเล็ก ถอดรหัสได้รวดเร็วแม้อยู่ไกล และ (เมื่อระบุค่า intrinsics ของเลนส์) รายงาน pose แบบ 6-DoF ในระบบพิกัดกล้อง -- เป็นโค้ด 2D ที่ใช้ในงานหุ่นยนต์ ซึ่งใช้ทำเครื่องหมายโดรน เป้าสอบเทียบ และ fiducials ตัวตรวจจับทั้งสองคืนออบเจ็กต์ผลลัพธ์ที่ใช้คำศัพท์กรอบล้อมรอบเดียวกันกับตัวตรวจจับบลอบและสี่เหลี่ยม แต่ข้อมูล payload ทำให้มันแตกต่างจากทุกสิ่งที่กล่าวถึงมาก่อนอย่างแท้จริง
5.28.1. QR codes¶
find_qrcodes() สแกนเฟรมเพื่อค้นหา QR codes และคืนรายการออบเจ็กต์ผลลัพธ์ QRCode:
codes = img.find_qrcodes()
for c in codes:
img.draw_rectangle(c.rect, color=(0, 255, 0))
for corner in c.corners:
img.draw_circle((corner[0], corner[1], 4),
color=(0, 255, 0))
print(c.payload)
ตัวตรวจจับรับพารามิเตอร์ roi เสริมตัวเดียวเพื่อจำกัดขอบเขตการค้นหา ต้องการอินพุตระดับสีเทา -- เฟรมสีจะถูกแปลงภายในก่อนถอดรหัส
การตรวจจับแต่ละรายการมีกรอบล้อมรอบ (x, y, w, h, rect) มุมสี่จุดที่ตรวจจับได้ (corners ซึ่งเป็นสี่เหลี่ยมเปอร์สเปคทีฟที่รูปแบบ finder ของ QR code ติดตาม) และ payload ที่ถอดรหัสแล้วเป็นสตริง มุมทั้งสี่คือสิ่งที่ควรวาดเมื่อทำ annotation การตรวจจับ -- QR code ที่มองจากมุมเฉียงจะไม่ตรงแกน และกรอบล้อมรอบให้เพียงโครงร่างหลวม ๆ เท่านั้น
ข้อมูล metadata ของตัวถอดรหัสครอบคลุมทุกสิ่งที่ตัวถอดรหัส QR เรียนรู้มาตลอดทาง version คือเวอร์ชันของ QR code ตั้งแต่ 1 ถึง 40 ซึ่งกำหนดขนาดตาราง module (โค้ดเวอร์ชัน 1 กว้าง 21 module ส่วนเวอร์ชัน 40 กว้าง 177 module) ecc_level คือระดับการแก้ไขข้อผิดพลาด (0 -- 3 สำหรับ L / M / Q / H) ระดับที่สูงขึ้นสำรอง codewords ไว้สำหรับการแก้ไขข้อผิดพลาดมากขึ้นและทนต่อความเสียหายได้มากขึ้น แต่แลกมาด้วยพื้นที่ payload ที่น้อยลง mask คือรูปแบบ mask (0 -- 7) ที่ encoder เลือกเพื่อลดความสับสนของตัวถอดรหัส data_type คือการเข้ารหัสที่ตัวถอดรหัสรายงาน -- ตัวเลข ตัวอักษรและตัวเลข ไบนารี หรือ Kanji -- และ flag is_numeric / is_alphanumeric / is_binary / is_kanji แสดงค่าเดียวกันในรูปแบบบูลีนที่เป็นมิตรกว่า
eci คือค่า Extended Channel Interpretation ซึ่งระบุการเข้ารหัสข้อความที่ไบต์ใช้ (UTF-8, ISO-8859-1 เป็นต้น) QR code จากสื่อสิ่งพิมพ์ทั่วไปอาจไม่รับประกันว่าเป็น UTF-8 แอปพลิเคชันที่ต้องถอดรหัสไบต์อย่างถูกต้องจะตรวจสอบ eci และถอดรหัสตามนั้น กรณี Kanji โดยเฉพาะ: MicroPython ไม่แยกวิเคราะห์การเข้ารหัส Kanji ดังนั้น payload ที่มี is_kanji ต้องถือเป็น byte array และถอดรหัสโดยแอปพลิเคชัน
ตัวอย่างการใช้งานทั่วไป: กล้องอ่าน QR codes จากสายพานลำเลียงและรายงาน payload ที่ถอดรหัสแล้วไปยังโฮสต์ กล้องรัน find_qrcodes() หนึ่งครั้งต่อเฟรม วนซ้ำรายการที่ส่งกลับ เลือกโค้ดที่ data_type ตรงกับที่แอปพลิเคชันคาดหวัง และส่ง c.payload ผ่าน UART หรือ USB ข้อมูลกรอบล้อมรอบและมุมมีประโยชน์สำหรับการแสดงผลใน IDE แต่ไม่ใช่สิ่งที่โฮสต์สนใจ
5.28.2. AprilTags¶
find_apriltags() สแกนเฟรมเพื่อค้นหา AprilTags และคืนรายการออบเจ็กต์ผลลัพธ์ AprilTag:
tags = img.find_apriltags(families=image.TAG36H11)
for t in tags:
img.draw_rectangle(t.rect, color=(0, 255, 0))
img.draw_cross(t.cx, t.cy, color=(0, 255, 0))
print(t.id, t.decision_margin)
AprilTags แตกต่างจาก QR codes ในเป้าหมายการออกแบบ QR code ถูกสร้างมาเพื่อเข้ารหัส ข้อมูลตามต้องการ ในสัญลักษณ์หนาแน่นตัวเดียวที่ผู้ใช้อ่านครั้งเดียวในระยะใกล้ AprilTag ถูกสร้างมาเพื่อเข้ารหัส ID ขนาดเล็ก ในสัญลักษณ์เบาบางที่กล้องอ่านได้ต่อเนื่องจากระยะไกล โดยมีค่าความทนทานต่อข้อผิดพลาดเท่าที่ Hamming code ของตระกูลนั้นอนุญาต การแลกเปลี่ยนปรากฏให้เห็นในทั้งสองทิศทาง: QR code บรรจุได้หลายร้อยไบต์แต่ต้องอ่านจากระยะใกล้ ส่วน AprilTag บรรจุ ID ที่ไม่ซ้ำกันได้เพียงไม่กี่ร้อยรายการแต่อ่านได้น่าเชื่อถือจากระยะหลายเมตร
คีย์เวิร์ด families รับ bitmask ของตระกูล tag ที่จะถอดรหัส ตระกูลที่มีให้ใช้ได้แก่ image.TAG16H5, image.TAG25H9, image.TAG36H10, image.TAG36H11, image.TAGCIRCLE21H7, image.TAGCIRCLE49H12, image.TAGCUSTOM48H12, image.TAGSTANDARD41H12 และ image.TAGSTANDARD52H13 แต่ละตระกูลแลกเปลี่ยนระหว่างจำนวน ID กับความทนทาน ตัวเลข H ในชื่อคือระยะ Hamming ขั้นต่ำระหว่างโค้ดใด ๆ สองตัวในตระกูล -- จำนวนบิตที่ต้องเปลี่ยนกว่าโค้ดที่ถูกต้องตัวหนึ่งจะกลายเป็นอีกตัว -- TAG16H5 มี 30 ID ที่ระยะ 5, TAG25H9 มี 35 ID ที่ระยะ 9 และ TAG36H11 (ค่าเริ่มต้นและที่ใช้กันทั่วไปที่สุด) มี 587 ID ที่ระยะ 11 ตัวตรวจจับแก้ไขข้อผิดพลาดได้สูงสุดสองบิตโดยไม่คำนึงถึงตระกูล ดังนั้นระยะกำหนดว่าการแก้ไขนั้นเสี่ยงแค่ไหน: รูปแบบสุ่มในเฟรมที่มีสัญญาณรบกวนต้องอยู่ห่างจากโค้ดที่ถูกต้องแค่สองบิตเท่านั้นเพื่อถอดรหัสเป็นการตรวจจับเท็จ และตระกูลที่มีระยะสูงกว่าจะกระจายโค้ดอย่างเบาบางมากขึ้นจนการชนกันดังกล่าวเกิดขึ้นน้อย -- นั่นคือเหตุผลที่ TAG36H11 เป็นตัวเลือกที่แนะนำ เวลาในการตรวจจับเพิ่มขึ้นตามจำนวนตระกูลที่เปิดใช้งาน ดังนั้นแอปพลิเคชันจึงเปิดใช้งานเฉพาะสิ่งที่พิมพ์จริง bitmask คือ bitwise OR ของค่าคงที่ตระกูลเมื่อต้องการหลายตระกูลในการเรียกครั้งเดียว
การตรวจจับแต่ละรายการมีคำศัพท์กรอบล้อมรอบ -- x, y, w, h, rect, area, จุดกึ่งกลางแบบจำนวนเต็มและ sub-pixel (cx, cy, cxf, cyf) -- และมุมสี่จุดที่ตรวจจับได้ (corners) ช่องข้อมูลการระบุตัวตนตามมา: id คือ ID ตัวเลขภายในตระกูล (0 -- 586 สำหรับ TAG36H11), family คือค่าคงที่ตระกูลตัวเลข และ name คือชื่อตระกูลเป็นสตริง
ช่องข้อมูล match-quality คือสิ่งที่แอปพลิเคชันใช้กรองผลการตรวจจับ decision_margin คือคะแนนความเชื่อมั่นระหว่าง 0.0 ถึง 1.0 ยิ่งสูงยิ่งดี การกรองออกผลการตรวจจับที่ต่ำกว่า decision_margin > 0.1 จะลดการตรวจจับเท็จส่วนใหญ่โดยไม่มีค่าใช้จ่าย hamming นับข้อผิดพลาดบิตที่ตัวถอดรหัสยอมรับสำหรับ tag นี้ -- ยิ่งต่ำยิ่งดี โดย 0 หมายถึงการถอดรหัสที่สมบูรณ์แบบ goodness เป็น metric คุณภาพของภาพในอดีตที่ตัวถอดรหัสปัจจุบันไม่ได้คำนวณอีกต่อไป ค่าจะเป็น 0.0 เสมอและสามารถละเว้นได้
5.28.3. Pose จาก intrinsics¶
ลักษณะเด่นที่เปลี่ยนแปลงเกมของ find_apriltags() ซึ่งเป็นเหตุผลที่ AprilTags เป็น fiducial ในงานหุ่นยนต์ที่เลือกใช้ คือเมธอดสามารถกู้คืน pose 6-DoF ของ tag ในระบบพิกัดกล้อง โดยตรงจากมุมที่ตรวจจับได้และชุดค่า calibration intrinsics จำนวนเล็กน้อย intrinsics ได้แก่ ความยาวโฟกัส X และ Y ของกล้องเป็นพิกเซล (fx, fy) และจุดศูนย์กลางออปติคัลเป็นพิกเซล (cx, cy) ซึ่งทั้งสี่ค่านี้แอปพลิเคชันวัดครั้งเดียวด้วยขั้นตอน calibration และ hard-code ไว้ตลอดไป
เมื่อระบุ intrinsics แล้ว AprilTag ที่ส่งกลับจะเติมช่องข้อมูล x_translation, y_translation, z_translation ด้วยตำแหน่งของ tag เทียบกับกล้อง และ x_rotation, y_rotation, z_rotation (และ rotation ที่ซ้ำกันเพื่อความสมมาตร) ด้วยทิศทางของ tag หากไม่มี intrinsics ช่องข้อมูลทั้งหกจะเป็น 0.0 และแอปพลิเคชันต้องรับผิดชอบการประมาณ pose เองที่ต้องการ
ช่องข้อมูล translation รายงานเป็นหน่วยความกว้างของ tag: ตัวถอดรหัสถือว่า tag กว้าง 1 หน่วย ดังนั้นแอปพลิเคชันจึงคูณ translation แต่ละค่าด้วยความกว้างจริงของ tag ที่พิมพ์เพื่อได้ระยะทางเชิงเมตริก tag ที่พิมพ์ที่ความกว้าง 100 มม. และรายงาน z_translation = 8.3 อยู่ห่างจากกล้อง 830 มม. tag เดียวกันที่พิมพ์ที่ความกว้าง 50 มม. ในระยะเดียวกันจะรายงาน z_translation = 16.6 ช่องข้อมูล rotation อยู่ในหน่วยเรเดียนและไม่ต้องปรับขนาด
การประมาณ pose เป็นพื้นฐานสำหรับแอปพลิเคชันหุ่นยนต์หลากหลายประเภท: การนำหุ่นยนต์เข้าเทียบสถานีชาร์จที่ทำเครื่องหมายด้วย tag, การติดตามเส้นทาง waypoint ที่พิมพ์, การกู้คืน pose ของกล้องเองจาก tag ที่รู้จักหลายตัวในสภาพแวดล้อม กล้องที่รู้ intrinsics เห็น tag และมีตำแหน่งในโลกแห่งความเป็นจริงสำหรับ tag นั้น ก็มีตำแหน่งในโลกแห่งความเป็นจริงสำหรับตัวเองด้วยเช่นกันจากการคำนวณเดียวกัน
5.28.4. เลือกอันไหนเมื่อไร¶
QR codes และ AprilTags แก้ปัญหาที่แตกต่างกัน การเลือกระหว่างทั้งสองขึ้นอยู่กับ สิ่งที่สัญลักษณ์ที่พิมพ์บรรจุ
เมื่อแอปพลิเคชันต้องการส่ง ข้อมูลตามต้องการ ผ่านสัญลักษณ์ที่พิมพ์ -- URL, สตริงหมายเลขซีเรียล, ข้อมูลติดต่อ -- QR code คือตัวเลือกที่ถูกต้อง บรรจุได้หลายร้อยไบต์ในโค้ดขนาดพอเหมาะ การเข้ารหัสเป็นมาตรฐานสาธารณะและรองรับบนทุกสมาร์ทโฟน และตัวถอดรหัสรับมือกับการหมุน ความเสียหายปานกลาง และมุมเฉียงได้
เมื่อแอปพลิเคชันต้องการ ID ขนาดเล็กที่อ่านได้ต่อเนื่องจากระยะไกลพร้อม pose ทางเลือก -- fiducial บนหุ่นยนต์เคลื่อนที่, เป้า calibration ในห้อง, marker เทียบท่าบนสถานีชาร์จ -- AprilTag คือตัวเลือกที่ถูกต้อง ID หลายร้อยรายการเพียงพอสำหรับกรณีการใช้งาน Hamming code กู้คืนจากข้อผิดพลาดบิตที่จะทำให้ QR code ล้มเหลว และการประมาณ pose ฟรีเมื่อ calibrate intrinsics แล้ว
บางแอปพลิเคชันใช้ทั้งสอง: AprilTag ทำเครื่องหมายตำแหน่งที่รู้จัก และ QR code ที่เกี่ยวข้อง (พิมพ์ควบคู่กัน) บรรจุ metadata เกี่ยวกับสิ่งที่ตำแหน่งนั้น หมายถึง ตัวตรวจจับทั้งสองทำงานอิสระบนเฟรมเดียวกัน และแอปพลิเคชันเชื่อมโยงกรอบล้อมรอบเพื่อจับคู่แต่ละ tag กับโค้ดคู่กัน