5.20. การถดถอยและความคล้ายคลึง¶
การวัดอีกสองรายการในคลาส Image สรุปภาพในรูปแบบที่ต่างจากการกระจายค่าพิกเซล การถดถอยเชิงเส้นของพิกเซลที่ผ่านค่าขีดแบ่งให้ เส้น แก่แอปพลิเคชันเพื่อดำเนินการ ซึ่งเป็นข้อมูลนำเข้าแบบดั้งเดิมสำหรับหุ่นยนต์ที่ติดตามเส้น การวัดความคล้ายคลึงให้ตัวเลขเดียวแก่แอปพลิเคชันที่อธิบายว่าสองภาพคล้ายกันเพียงใด ซึ่งเป็นข้อมูลนำเข้าที่เหมาะสมสำหรับการทดสอบ regression แบบ golden-image หรือตัวตรวจจับการเปลี่ยนแปลงขนาดใหญ่
5.20.1. การถดถอยเชิงเส้น¶
เมื่อพิกเซลพื้นหน้าของภาพเกิดขึ้นเป็น เส้น ตัดผ่านเฟรม เช่น เทปบนรางที่หุ่นยนต์กำลังติดตาม เส้นขอบฟ้า ขอบถนนหรือทางเดิน แอปพลิเคชันมักไม่ต้องการพิกเซลพื้นหน้าแต่ละตัว แต่ต้องการ เส้นที่ fit ได้ดีที่สุด ผ่านพิกเซลทั้งหมด โดยกำหนดพารามิเตอร์เพื่อให้สามารถตัดสินใจได้ว่าเส้นมีทิศทางอย่างไรและตัดเฟรมที่ตำแหน่งใด
get_regression() ทำการ fit นั้น โดยรับรูปแบบ tuple ค่าขีดแบ่งเดียวกับที่ binary() และ find_blobs() ใช้ ระบุพิกเซลทุกตัวที่ตรงกับค่าขีดแบ่ง และส่งคืนผลลัพธ์ line เพียงรายการเดียวที่อธิบายเส้นที่ fit ได้ดีที่สุดผ่านพิกเซลเหล่านั้น:
line = img.get_regression([(0, 60)])
if line:
img.draw_line((line.x1(), line.y1(),
line.x2(), line.y2()),
color=(255, 0, 0))
การ fit ใช้การถดถอยเชิงเส้น Theil-Sen ซึ่งเป็นวิธีการที่แข็งแกร่งที่ทนต่อค่าผิดปกติได้ดีกว่าการ fit กำลังสองน้อยที่สุดที่คุ้นเคยมากกว่า พิกเซลจำนวนน้อยที่อยู่ห่างจากเส้นจริงไม่บิดเบือนผลลัพธ์ในแบบที่จะเกิดกับกำลังสองน้อยที่สุด ซึ่งตรงกับความเป็นจริงของพิกเซลพื้นหน้าที่มีสัญญาณรบกวนจากผลลัพธ์ค่าขีดแบ่งจริง
ผลลัพธ์ line มีจุดสิ้นสุดที่ถูก clip ไว้ในสี่เหลี่ยมผืนผ้าของภาพ (x1, y1, x2, y2) ความยาวและขนาดของเส้น (length, magnitude) และคำอธิบายเชิงเรขาคณิตของเส้นในรูปแบบ polar (theta, rho) ซึ่งเป็นมุมของเส้นจากแนวนอนและระยะห่างตั้งฉากจากจุดกำเนิด รูปแบบ polar คือสิ่งที่ control loop มักต้องการ: theta บอกหุ่นยนต์ว่าเส้นเอียงไปทางไหน rho บอกว่าเส้นตัดผ่านภาพที่ตำแหน่งใด และ feedback loop บนทั้งสองค่าช่วยให้หุ่นยนต์อยู่ตรงกลางของเส้น
อาร์กิวเมนต์คีย์เวิร์ดบางตัวปรับความแข็งแกร่งและต้นทุน x_stride และ y_stride ข้ามพิกเซลระหว่างการ fit ซึ่ง stride ที่ใหญ่กว่าทำให้การถดถอยถูกกว่าแต่ fit พิกเซลน้อยลง area_threshold และ pixels_threshold ปฏิเสธเส้นที่ไม่มีพิกเซลที่ตรงกันเพียงพอ target_size ปรับขนาดข้อมูลนำเข้าให้เล็กลงก่อน fit ซึ่งการถดถอยทำงานได้เร็วกว่าบนตัวแทนขนาด 80x60 ของภาพโดยไม่สูญเสียความแม่นยำทิศทางเส้นมากนัก
หากไม่สามารถ fit เส้นที่ยอมรับได้ เช่น ค่าขีดแบ่งไม่ตรงกับพิกเซลใดเลย หรือตรงกับรูปแบบที่ไม่ดูเหมือนเส้น เมธอดจะส่งคืน None โค้ดติดตามเส้นจริงจะตรวจสอบ None ทุกการเรียก get_regression() ก่อนที่จะเข้าถึงแอตทริบิวต์ของเส้น
5.20.2. ความคล้ายคลึงของภาพ¶
การวัดประเภทต่างกัน: แทนที่จะถามว่า "ภาพมีอะไรอยู่?" ให้ถามว่า "สองภาพนี้คล้ายกันเพียงใด?" การดำเนินการที่ควรใช้คือ get_similarity() ซึ่งคำนวณ Structural Similarity Index (SSIM) ระหว่างภาพต้นทางและภาพอ้างอิง
s = img.get_similarity(reference)
print(s.mean, s.stdev)
SSIM เป็นเมตริกความคล้ายคลึงของภาพมาตรฐานที่ใช้ในการประมวลผลภาพเพราะทำงานในแบบที่สัญชาตญาณของมนุษย์เกี่ยวกับความคล้ายคลึงทำงาน การเลื่อนเล็กน้อยหรือการเปลี่ยนแปลงความสว่างเล็กน้อยลดคะแนนเล็กน้อย ในขณะที่การเปลี่ยนแปลงโครงสร้างขนาดใหญ่ (วัตถุหายไป ฉากต่างกัน) ลดคะแนนอย่างมาก คะแนนอยู่ในช่วง -1 ถึง +1 โดย +1 หมายความว่าสองภาพเหมือนกัน 0 หมายความว่าไม่เกี่ยวข้องกัน และ -1 หมายความว่าตรงข้ามกันในเชิงโครงสร้าง วัตถุ similarity ที่ส่งคืนเปิดเผยค่าเฉลี่ย SSIM ตลอดทั้งภาพ บวกกับส่วนเบี่ยงเบนมาตรฐาน min และ max ของคะแนนต่อ tile
สำหรับการเปรียบเทียบที่ ตัวเลขน้อย ดีกว่าตัวเลขมาก เช่น การทดสอบ regression ที่ควรรายงานศูนย์เมื่อ "ไม่มีอะไรเปลี่ยน" และเพิ่มขึ้นเมื่อการเปลี่ยนแปลงสะสม ค่าสถานะ dssim=True จะส่งคืนความไม่คล้ายกันในเชิงโครงสร้าง: ค่าเฉลี่ย SSIM ลบออกจาก 1 ดังนั้นค่าที่ส่งคืนจะเป็น 0.0 สำหรับภาพที่เหมือนกันและเพิ่มขึ้นเมื่อแตกต่างกัน
5.20.3. กรณีการใช้งาน SSIM¶
สองแอปพลิเคชันที่พบบ่อย:
การทดสอบ regression แบบ Golden-image กรอบการทดสอบจับภาพเฟรมอ้างอิงภายใต้เงื่อนไขที่ทราบว่าดีและเก็บเป็นภาพ golden การทดสอบรันถัดไปจับภาพในเงื่อนไขเดียวกันและเปรียบเทียบกับภาพ golden ด้วย SSIM คะแนนที่สูงกว่าค่าขีดแบ่งบางค่า (0.95 หรือ 0.98 ขึ้นอยู่กับความคลาดเคลื่อน) ถือว่าผ่าน ต่ำกว่าถือว่าล้มเหลว กรอบการทดสอบไม่จำเป็นต้องรู้ว่า อะไร เปลี่ยน คะแนน SSIM คือสัญญาณ
การตรวจจับการเปลี่ยนแปลงขนาดใหญ่ แอปพลิเคชันที่ต้องการเวอร์ชันหยาบกว่าของการ differencing เฟรม ซึ่งไม่สนใจการเปลี่ยนแปลงความสว่างเล็กน้อยแต่ตอบสนองต่อการเปลี่ยนแปลงโครงสร้างขนาดใหญ่ สามารถใช้ SSIM กับเฟรมอ้างอิงแทน difference() ต่อพิกเซลตามด้วยค่าขีดแบ่ง SSIM มีความไวต่อการเปลี่ยนแปลงแสงน้อยกว่าการ differencing ต่อพิกเซล ซึ่งทำให้เป็นตัวเลือกที่ดีกว่าเมื่อเป้าหมายคือการตรวจจับว่า "ฉากดูแตกต่างอย่างมีสาระสำคัญ" มากกว่า "พิกเซลแต่ละตัวเปลี่ยนแปลง"
ทั้งสองแอปพลิเคชันใช้การเรียกเดียวกัน นั่นคือ img.get_similarity(reference) และทริกเกอร์ที่ค่าขีดแบ่งของคะแนนที่ส่งคืน ความแตกต่างคือเพียงว่าค่าขีดแบ่งสูง (การทดสอบ regression ที่มองหาความตรงกันใกล้เคียงกัน) หรือต่ำ (การตรวจจับการเปลี่ยนแปลง ที่มองหาการเปลี่ยนแปลงโครงสร้างขนาดใหญ่ใดๆ)
5.20.4. รูปแบบการแปลงแล้วเปรียบเทียบ¶
รายละเอียดที่เป็นประโยชน์: get_similarity() รับพารามิเตอร์ x, y, x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint และ transform เดียวกับ draw_image() ภาพอ้างอิงถูกจัดตำแหน่ง ปรับขนาด และแปลงด้วยพารามิเตอร์เหล่านั้น ก่อน การเปรียบเทียบ SSIM จะรัน
นั่นหมายความว่าแอปพลิเคชันสามารถถามว่า "ฉากนี้คล้ายกับเฟรมอ้างอิง หลังจาก การเลื่อนตำแหน่ง/การหมุน/การปรับขนาดที่ทราบเพียงใด" โดยไม่ต้องเตรียมภาพอ้างอิงที่แปลงไว้ล่วงหน้า นี่คือวิธีราคาถูกในการสร้างตัวติดตามที่ค้นหาพื้นที่พารามิเตอร์และรายงานว่าการแปลงใดของอ้างอิงที่ตรงกับเฟรมปัจจุบันได้ดีที่สุด