5.23. การแก้ไขมุมมอง¶
Warning
เมทริกซ์ transform ขนาด 3x3 ตามอำเภอใจนั้น รองรับเฉพาะบน OpenMV Cam N6 เท่านั้น คีย์เวิร์ดนี้จะถูกละเว้นอย่างเงียบๆ บนบอร์ดอื่นทุกตัว แอปพลิเคชันที่ต้องการรันในที่อื่นต้องใช้เมธอด rotation_corr() ที่เตรียมไว้ (ในรูปแบบ corners=) หรือคำนวณภาพที่แก้ไขแล้วนอกบอร์ด
เมธอด rotation_corr() ที่เตรียมไว้จะรวมกลุ่มการบิดเบือนมุมมองเฉพาะประเภทหนึ่งไว้เบื้องหลังชุดพารามิเตอร์ขนาดเล็ก และรันบนทุกบอร์ดที่รองรับ แอปพลิเคชันบางตัวต้องการการบิดเบือนที่ไม่ตรงกับรูปแบบนั้น เช่น การรีแมปแบบฉายภาพตามอำเภอใจจากรูปสี่เหลี่ยมด้านไม่เท่าหนึ่งไปอีกรูปหนึ่ง การแก้ไขที่ได้รับการสอบเทียบสำหรับการติดตั้งที่ทราบซึ่งได้คำนวณออฟไลน์แล้ว หรือเมทริกซ์การบิดเบือนที่อัลกอริทึมอัปสตรีมส่งมาพร้อมใช้ สำหรับกรณีเหล่านั้น draw_image() พร้อมกับ copy(), crop() และ scale() จะรับคีย์เวิร์ด transform ที่รับเมทริกซ์ 3x3 ที่สร้างด้วยตนเองซึ่งอธิบายการบิดเบือนโดยตรง
5.23.1. การแปลงแบบ Affine และ Projective¶
การบิดเบือนเชิงเรขาคณิตแสดงออกในรูปแบบ พิกัดเนื้อเดียวกัน: ตำแหน่งพิกเซล (x, y) ที่ต่อท้ายด้วย 1 คูณด้วยเมทริกซ์ขนาด 3x3
รูปแบบ affine คือจุดเริ่มต้น แถวล่างของมันถูกกำหนดไว้ที่ \((0, 0, 1)\):
เมื่อเขียนออกมา พิกัดเอาต์พุตแต่ละพิกัดคือการรวมเชิงเส้นของพิกัดอินพุตบวกค่าคงที่:
ซึ่งครอบคลุมการปรับขนาด การหมุน การเฉือน และการเลื่อนตำแหน่งในทุกการผสมผสาน และภายใต้ทุกอย่างนั้น เส้นขนานยังคงขนาน
รูปแบบ projective (perspective) จะปลดปล่อยแถวล่าง:
เมื่อเขียนออกมา:
การหารด้วย \(w' = g x + h y + 1\) คือสิ่งที่ทำให้การแปลงเป็น projective ไม่ใช่เพียง affine เมื่อ \(g\) และ \(h\) ทั้งคู่เป็นศูนย์ \(w'\) จะอยู่ที่หนึ่งและการหารไม่มีผล กลายเป็นรูปแบบ affine อีกครั้ง เมื่อค่าใดค่าหนึ่งไม่ใช่ศูนย์ \(w'\) จะแปรผันตามตำแหน่งอินพุตและพิกเซลที่ตำแหน่งต่างกันจะถูกยืดย่อในปริมาณที่แตกต่างกัน ซึ่งไม่รักษาความขนานของเส้นอีกต่อไป นั่นคือปรากฏการณ์ keystone ของการมองระนาบแบนจากมุมเฉียงนั่นเอง การแปลงแบบ projective คือการบิดเบือนเชิงเรขาคณิตที่ทั่วไปที่สุดที่ยังคงทำให้เส้นตรงไปเป็นเส้นตรง การปรับขนาด การกลับด้าน การสับเปลี่ยน การหมุน และการแก้ไขการหมุนสี่มุมล้วนเป็นกรณีพิเศษของการแปลงนี้
การแปลงที่มีชื่อเรียกจะออกมาจากรูปแบบ affine โดยตรง การแปลงเอกลักษณ์คือเมทริกซ์เอกลักษณ์ และ:
สำหรับการแปลงที่สร้างด้วยตนเองส่วนใหญ่ แอปพลิเคชันจะเริ่มต้นด้วยหนึ่งในนี้เป็นฐานและคูณเมทริกซ์เพิ่มเติมสำหรับการดำเนินการเพิ่มเติมแต่ละอย่าง ลงท้ายด้วยเมทริกซ์ 3x3 เดียวที่อธิบายการบิดเบือนผสม เมทริกซ์ใช้จากขวาไปซ้าย: \(M = T R S\) จะรันการปรับขนาดก่อน จากนั้นการหมุน แล้วการเลื่อนตำแหน่ง การผสมที่ทุกคนต้องการในที่สุดคือการหมุนรอบศูนย์กลางภาพ เมทริกซ์การหมุนเปล่าๆ จะหมุนภาพรอบจุดกำเนิดพิกเซลที่มุมซ้ายบน ดังนั้นรุ่นที่อยู่ตรงกลางจะย้ายจุดกลาง \((c_x, c_y)\) ไปที่จุดกำเนิด หมุน แล้วย้ายกลับ:
5.23.2. คีย์เวิร์ด transform¶
เมทริกซ์จะถูกส่งผ่านคีย์เวิร์ด transform โดยให้เป็น ulab.numpy.ndarray ขนาด 3x3 เมธอดที่ควรใช้คือ draw_image() ซึ่งจะบิดเบือนแหล่งที่มาผ่านเมทริกซ์ขณะที่วาดลงบนปลายทาง ผลลัพธ์จะอยู่ในบัฟเฟอร์ที่แอปพลิเคชันควบคุม และการบิดเบือนจะผสมกับทุกอย่างอื่นในการเรียก ไม่ว่าจะเป็นการปรับขนาด การผสมอัลฟ่า และการสวมหน้ากาก
import ulab.numpy as np
M = np.array([[1.2, 0.0, -20.0],
[0.0, 1.2, -15.0],
[0.0, 0.0, 1.0]])
canvas.draw_image(img, transform=M)
ตัวอย่างจะบิดเบือน img ไปยัง canvas โดยปรับขนาด 1.2 ในแต่ละทิศทางและเลื่อนไปทางซ้ายและขึ้นด้านบน 20 และ 15 พิกเซลตามลำดับ ซึ่งเป็นการบิดเบือนแบบ affine ที่สร้างโดยตรงจากรายการเมทริกซ์ที่อธิบายไว้ข้างต้น คีย์เวิร์ดเดียวกันบน copy(), crop() และ scale() จะใช้การบิดเบือนกับภาพเอง