5.3. รูปแบบพิกเซล¶
อัลกอริทึมที่ตรวจจับขอบคาดหวังให้แต่ละพิกเซลเก็บค่าความสว่าง อัลกอริทึมที่ติดตามวัตถุที่มีสีคาดหวังให้แต่ละพิกเซลพกพาข้อมูลสี อัลกอริทึมที่ทำการปิด morphological คาดหวังให้แต่ละพิกเซลเป็นเพียงเปิดหรือปิด รูปแบบพิกเซลที่ Image ใช้ -- หนึ่งในรายการที่ Vision Sensors ระบุไว้ -- คือสิ่งที่ทำให้การตรวจสอบข้อกำหนดเหล่านั้นสามารถทำได้ล่วงหน้า: รูปแบบบอกไว้ล่วงหน้าว่าพิกเซลอยู่ในรูปแบบใด และอัลกอริทึมใดสามารถทำงานกับพิกเซลเหล่านั้นได้โดยไม่ต้องแปลงรูปแบบ
หน้านี้กล่าวถึงวิธีที่ข้อจำกัดนั้นส่งผลในทางปฏิบัติ การเลือกรูปแบบที่เหมาะสมขึ้นอยู่กับสิ่งที่ pipeline จะทำ และวิธีการแปลงระหว่างรูปแบบคือวิธีที่ pipeline ซึ่งต้องการมากกว่าหนึ่งรูปแบบเชื่อมต่อขั้นตอนต่าง ๆ เข้าด้วยกัน
รูปแบบพิกเซลห้ารูปแบบที่ไม่บีบอัดและวิธีที่ไบต์บรรจุ JPEG และ PNG ไม่ได้วาดไว้ที่นี่เพราะเป็นสตรีมที่บีบอัดและมีความยาวผันแปร ไม่ใช่กริดพิกเซลขนาดคงที่¶
5.3.1. แกนหลักสำหรับระดับสีเทา¶
การมองเห็นของเครื่องแบบคลาสสิกส่วนใหญ่ลงมาที่การทำงานกับค่าความสว่าง การตรวจจับขอบ การจับคู่แม่แบบ การถอดรหัส AprilTag การประมาณค่า optical-flow ตัวดำเนินการ morphological การวิเคราะห์บลอบ -- ทั้งหมดนี้ในระดับที่อัลกอริทึมทำงานอยู่กำลังดูว่าแต่ละพิกเซลสว่างแค่ไหนและความสว่างนั้นเปรียบเทียบกับความสว่างของพิกเซลใกล้เคียงอย่างไร สีของฉากมักมีประโยชน์ สำหรับ แอปพลิเคชันที่เรียกใช้ แต่ตัวอัลกอริทึมเองไม่ต้องการมัน
รูปแบบระดับสีเทาส่งมอบสิ่งที่อัลกอริทึมต้องการโดยตรง โดยไม่มีค่าใช้จ่ายเพิ่มเติม หนึ่งไบต์ต่อพิกเซลเก็บค่าความสว่างตั้งแต่ 0 (ดำ) ถึง 255 (ขาว) รูปแบบนี้มีขนาดครึ่งหนึ่งของ RGB565 และ YUV422 และหนึ่งในสามของ RGB888 ดังนั้นทุกการดำเนินการจึงผ่านข้อมูลน้อยลง -- ทั้งเร็วขึ้นและมีแรงกดดันจากบัฟเฟอร์น้อยลง สำหรับกล้องขนาดเล็กที่บัฟเฟอร์เฟรมแข่งขันกับส่วนที่เหลือของสคริปต์เพื่อหน่วยความจำ ความแตกต่างของขนาดนั้นอาจเป็นตัวตัดสินว่า pipeline จะพอดีหรือไม่ หากสีไม่ใช่สัญญาณที่อัลกอริทึมต้องการ ระดับสีเทาคือคำตอบที่ถูกต้อง
5.3.2. สีผ่าน RGB565¶
เมื่อสี คือ สัญญาณ -- ติดตามเครื่องหมายสี แยกแยะแอปเปิ้ลแดงจากแอปเปิ้ลเขียว เลือกองค์ประกอบ UI โดยเฉดสี -- สองไบต์ต่อพิกเซลให้สีเพียงพอสำหรับประเภทการจำแนกประเภทที่อัลกอริทึมดำเนินการ RGB565 เป็นรูปแบบสีเริ่มต้นบนกล้อง และเป็นรูปแบบที่วิธีการที่รับรู้สีบนพื้นผิวคาดหวัง
การแสดงผลเฟรมที่มีคำอธิบาย -- การวาดกรอบล้อมรอบสำหรับการตรวจจับ การเขียนข้อความวินิจฉัย การนำเฟรมไปแสดงบนหน้าจอหรือส่งไปยังผู้รับชมระยะไกล -- ยังเรียกร้อง RGB565 ตามธรรมชาติ การแสดงตัวอย่าง IDE ตัวควบคุมจอแสดงผลบนบอร์ด และปลายทางเครือข่ายส่วนใหญ่ไม่ว่าจะใช้รูปแบบนี้โดยตรงหรือแปลงจากมันได้อย่างถูก
5.3.3. Bayer เป็นรูปแบบการจัดเก็บ¶
ภาพ Bayer คือผลลัพธ์ raw จาก sensor ก่อนที่ ISP จะถอดรหัส Bayer ให้เป็นการนำเสนอสีที่สมบูรณ์ แต่ละพิกเซลเป็นหนึ่งไบต์ที่เก็บช่องสีเดียว -- ช่องที่ตัวกรองสีที่ตำแหน่งนั้นในโมเสกผ่านไป ทำให้ภาพ Bayer มีขนาดเท่ากับภาพระดับสีเทาและหนึ่งในสามของ RGB888 ซึ่งสอดคล้องกับสิ่งที่ Bayer มีประโยชน์จริง ๆ: การจัดเก็บหลายเฟรมพร้อมกันเมื่อ RAM เป็นข้อจำกัดหลัก
ข้อเสียคือ อัลกอริทึมใน image module ไม่ทำงานกับภาพ Bayer โดยตรง หากไม่มีการถอดรหัส Bayer ไม่มีพิกเซลใดที่มีข้อมูลเพียงพอในการตัดสินสีด้วยตัวเอง และรูปแบบที่อัลกอริทึมค้นหา -- ขอบ มุม บลอบ -- จะถูกบิดเบือนโดยโมเสก วิธีเดียวในการอ่านหรือแก้ไขภาพ Bayer คือ get_pixel() และ set_pixel(); ส่วนอื่น ๆ ทั้งหมดคาดหวังการนำเสนอที่สมบูรณ์
รูปแบบที่เกิดขึ้นคือการจัดเก็บเฟรมเป็น Bayer ตราบเท่าที่ต้องรออยู่ในคิว และแปลงแต่ละเฟรมเป็นระดับสีเทาหรือ RGB565 ณ เวลาที่การประมวลผลจริงเริ่มต้น การแปลงใช้รอบ CPU แต่ช่วยประหยัด RAM ที่มิฉะนั้นจะถูกผูกไว้กับการเก็บเฟรมที่สมบูรณ์ตลอดอายุการใช้งานของแอปพลิเคชัน
Note
การดำเนินการเดียวของ image module กับพิกเซล Bayer โดยตรงคือ get_pixel(), set_pixel(), และเส้นทางการเข้ารหัส JPEG ที่ป้อนการแสดงตัวอย่าง IDE หรือผู้รับชมระยะไกล การวาด การวิเคราะห์ และการกรองทั้งหมดต้องการการแปลงเป็นระดับสีเทา RGB565 หรือ binary ก่อน
5.3.4. YUV422 สำหรับ pipeline ที่ต้องการทั้งสอง¶
YUV422 แยกข้อมูลของแต่ละพิกเซลออกเป็นช่องความส่องสว่าง (Y) และช่องโครมิแนนซ์สองช่อง (U และ V) และลดการสุ่มตัวอย่างโครมิแนนซ์ให้คู่พิกเซลที่อยู่ติดกันใช้ U และ V เดียวกัน ค่าเฉลี่ยไบต์ต่อพิกเซลคือสอง -- เหมือนกับ RGB565 -- แต่วางเลย์เอาต์ในลักษณะที่ช่อง Y เป็นภาพระดับสีเทา 8 บิตต่อเนื่องอยู่ที่ออฟเซ็ตที่ทราบในบัฟเฟอร์แล้ว
เลย์เอาต์นั้นคือสิ่งที่ pipeline ต้องการเมื่อบางขั้นตอนเป็นงานระดับสีเทาและบางขั้นตอนต้องการสี การอ่านค่า Y โดยตรงสำหรับขั้นตอนระดับสีเทาข้ามต้นทุนของการแปลงที่ชัดเจน ช่อง U และ V จะอยู่ที่นั่นเมื่อขั้นตอนภายหลังต้องการสีจริง ๆ นอกจากรูปแบบเฉพาะนั้น RGB565 มักเป็นตัวเลือกที่ง่ายกว่าสำหรับสี และระดับสีเทาเป็นตัวเลือกที่ง่ายกว่าสำหรับงานที่ใช้เฉพาะความสว่าง -- ค่าของ YUV422 มาจากการเก็บดีทั้งสองอย่างในเวลาเดียวกัน
Note
image module ทำงานกับ YUV422 ในลักษณะที่จำกัดกว่าระดับสีเทา RGB565 หรือ binary -- การอ่านช่อง Y โดยตรงสำหรับงานระดับสีเทาและเส้นทางการเข้ารหัส JPEG ที่ป้อนการแสดงตัวอย่าง IDE หรือผู้รับชมระยะไกล วิธีการที่รับรู้สีคาดหวัง RGB565 เฟรม YUV422 ต้องการการแปลงอย่างชัดเจนก่อนการวิเคราะห์สีหรือการวาด
5.3.5. Binary หน้ากาก และผลลัพธ์ที่ผ่านการกำหนดค่าขีดแบ่ง¶
ภาพ binary คือหนึ่งบิตต่อพิกเซล: แต่ละพิกเซลเป็น 0 หรือ 1 รูปแบบนี้แทบไม่ปรากฏเป็นการจับภาพจาก sensor แต่ปรากฏเป็นผลลัพธ์ตามธรรมชาติของการกำหนดค่าขีดแบ่ง (ซึ่งการทดสอบสีหรือความสว่างจำแนกแต่ละพิกเซลเป็น "ใช่ ตรงกัน" หรือ "ไม่ ไม่ตรง") และเป็นข้อมูลนำเข้าตามธรรมชาติสำหรับการดำเนินการ morphological และสำหรับอาร์กิวเมนต์ mask ที่หลายวิธีรับ
ข้อได้เปรียบในทางปฏิบัติของรูปแบบนี้คือขนาด ภาพ binary มีพื้นที่หนึ่งในแปดของภาพระดับสีเทา ดังนั้นการพกพาหน้ากากขนาดใหญ่ -- การเลือกต่อพิกเซลว่าตำแหน่งใดที่การดำเนินการปลายทางควรสัมผัส -- มีราคาถูก ความจริงที่ว่าการดำเนินการหลายอย่างรับภาพ binary เป็นอาร์กิวเมนต์คำสำคัญ mask= คืออีกด้านหนึ่งของจุดเดียวกัน: รูปแบบมีขนาดเล็ก และการเชื่อมผลลัพธ์ binary ของขั้นตอนหนึ่งเข้ากับอินพุต mask ของขั้นตอนอื่นเป็นรูปแบบ pipeline ทั่วไป
5.3.6. JPEG และ PNG ที่ขอบเขต¶
ออบเจ็กต์ Image ของ JPEG และ PNG แตกต่างจากรูปแบบอื่น ๆ ในรายการ ไม่ใช่กริดพิกเซล แต่เป็นสตรีมไบต์ที่บีบอัดซึ่ง เข้ารหัส ข้อมูลพิกเซลในรูปแบบที่การดำเนินการระดับพิกเซลไม่สามารถอ่านได้ การเรียก get_pixel() บน JPEG ไม่ได้คืนค่าพิกเซลที่ตำแหน่ง เนื่องจากพิกเซลนั้นไม่ได้วางแบบแกะออกไว้ที่ใดในบัฟเฟอร์ให้วิธีการดึงข้อมูล
JPEG และ PNG ปรากฏที่ขอบเขตของการประมวลผลภาพ ซึ่งข้อมูลพิกเซลกำลังออกหรือเข้าสู่กล้องในรูปแบบบีบอัด การบันทึกเฟรมลงดิสก์เป็น JPEG ทำให้ไฟล์มีขนาดเล็ก การส่งเฟรมผ่านเครือข่ายเป็น JPEG ทำให้การส่งข้อมูลประหยัด การโหลดเฟรมอ้างอิงจากไฟล์ JPEG ทำให้นั่งอยู่บนดิสก์ในรูปแบบที่เล็กกว่าพิกเซล raw มาก สำหรับกรณีการใช้งานเหล่านั้น การนำเสนอแบบบีบอัดคือคำตอบที่ถูกต้อง แต่สำหรับการประมวลผลจริงบน JPEG แอปพลิเคชันจะแปลงเป็นรูปแบบที่ใช้งานได้ก่อน -- และการแปลงนั้นคือที่ที่ไบต์ที่บีบอัดได้รับการขยายเป็นพิกเซลและที่ที่บัฟเฟอร์พองตัวเกิดขึ้น (JPEG 30 KB อาจกลายเป็น RGB565 600 KB)
5.3.7. การแปลงระหว่างรูปแบบ¶
เส้นทางการแปลงคือสิ่งที่เชื่อมต่อรูปแบบต่างๆ เข้าสู่ pipeline เดียว วิธีการห้าวิธีบน Image class รับภาพที่มีอยู่และคืนค่าภาพใหม่ในรูปแบบอื่น:
to_grayscale()สร้างภาพหนึ่งไบต์ต่อพิกเซล ซึ่งเป็นรูปแบบที่อัลกอริทึมคลาสสิกต้องการto_rgb565()สร้างรูปแบบสีสองไบต์ต่อพิกเซลที่วิธีการที่รับรู้สีและการแสดงตัวอย่าง IDE ใช้ร่วมกันto_bitmap()สร้างภาพ binary หนึ่งบิต ซึ่งเป็นรูปแบบที่ morphology และอาร์กิวเมนต์maskรับto_jpeg()สร้างภาพที่บีบอัดด้วย JPEG ที่เหมาะสำหรับการบันทึกหรือการส่งto_png()สร้างภาพที่บีบอัดด้วย PNG เมื่อต้องการการเข้ารหัสแบบ lossless มากกว่าไฟล์ที่เล็กกว่าของ JPEG
การแปลงแต่ละครั้งทำงาน ในที่เดิม โดยค่าเริ่มต้น: บัฟเฟอร์ของภาพต้นฉบับถูกเขียนทับด้วยผลลัพธ์ที่แปลงแล้ว และพิกเซลดั้งเดิมของต้นฉบับหายไปหลังจากการเรียกคืน นั่นเป็นตัวเลือกที่ถูกที่สุดทั้งสำหรับ CPU และหน่วยความจำ และเป็นคำตอบที่ถูกต้องเมื่อเฟรมต้นฉบับไม่จำเป็นสำหรับสิ่งอื่น
เมื่อต้นฉบับ ยังจำเป็นอยู่ -- เมื่อขั้นตอนภายหลังของ pipeline ต้องเห็นเฟรมดั้งเดิม -- อาร์กิวเมนต์คำสำคัญสองตัวแทนที่ค่าเริ่มต้นในที่เดิม copy=True จัดสรรบัฟเฟอร์แยกต่างหากสำหรับภาพที่แปลงแล้วบน Python heap และปล่อยต้นฉบับไว้เหมือนเดิม copy_to_fb=True ทำการจัดสรรเดียวกันแต่วางไว้ในบัฟเฟอร์เฟรมแทน heap -- ซึ่งเป็นสิ่งที่แอปพลิเคชันเข้าถึงเมื่อภาพที่แปลงแล้วต้องลงในการแสดงตัวอย่าง IDE เนื่องจาก IDE อ่านจากบัฟเฟอร์เฟรม
วิธีการเพิ่มเติมสองวิธีสร้างภาพ RGB565 ที่มีสีผ่าน palette แทนที่จะเป็นการแปลงตรง ๆ to_rainbow() แมปค่าอินพุตช่องเดียวแต่ละค่าไปยังสีตามระดับสีที่ราบรื่นที่วิ่งผ่านสเปกตรัมที่มองเห็นได้ to_ironbow() แมปค่าอินพุตแต่ละค่าไปยัง palette ของเครื่องวัดอุณหภูมิแบบไม่เชิงเส้นที่วิ่งจากสีดำผ่านสีแดงเข้มและสีส้มไปยังสีขาว ทั้งสองเป็นเครื่องมือ การแสดงภาพ มากกว่าเครื่องมือวัด จุดประสงค์คือทำให้ภาพช่องเดียวที่ค่า raw ปกติจะมองไม่เห็นด้วยตาเปล่าสามารถอ่านได้อย่างรวดเร็ว
5.3.8. ขนาดบัฟเฟอร์¶
รายละเอียดสุดท้ายเกี่ยวกับรูปแบบที่ควรระบุอย่างชัดเจน size() รายงานขนาด บัฟเฟอร์ไบต์ เสมอ ไม่ใช่จำนวนพิกเซล สำหรับรูปแบบที่ไม่บีบอัด ขนาดนั้นตามมาจากมิติและไบต์ต่อพิกเซลโดยตรง: width * height * bytes_per_pixel สำหรับ JPEG และ PNG ขนาดนั้นคือขนาดของสตรีมที่บีบอัด ซึ่งผันแปรตามเฟรมขึ้นอยู่กับเนื้อหาของฉาก โค้ดที่จัดสรรบัฟเฟอร์จากงบประมาณไบต์ใช้ size() สำหรับกรณีแรก โค้ดที่สตรีมเฟรมที่บีบอัดออกจากกล้องอ่านค่านี้หลังจากการบีบอัดแต่ละครั้งเพื่อทราบว่าสตรีมมีกี่ไบต์จริง ๆ