6.18. ภาพและ ndarrays¶
คลาส Image เป็นพื้นผิวที่รวดเร็วสำหรับการทำงานกับพิกเซลในรูปแบบดั้งเดิมของกล้อง: ทุกเมธอดบนนั้นทำงานโดยตรงบนบัฟเฟอร์เฟรมในรูปแบบพิกเซลดั้งเดิมของกล้อง numpy คือพื้นผิวตัวเลขทั่วไปสำหรับทุกอย่างอื่น มีสองเมธอดที่เชื่อมต่อกัน:
image.Image.to_ndarray()-- คัดลอกพิกเซลของภาพไปยังndarrayตัวสร้าง
image.Image-- สร้างภาพใหม่จากndarray
เมื่อใช้ร่วมกัน ทั้งสองทำให้แอปพลิเคชันสามารถถ่ายสแนปช็อตเฟรม ส่งต่อไปยัง numpy เพื่อแปลงแบบกำหนดเอง แล้วนำผลลัพธ์กลับมาเป็นภาพเพื่อแสดง บันทึก หรือส่งกลับไปยังไลบรารีภาพที่เหลือ
6.18.1. Image เป็น ndarray¶
to_ndarray() จัดสรร ndarray ใหม่และคัดลอกข้อมูลพิกเซลของภาพเข้าไป (ด้วยการแมป dtype ที่แสดงด้านล่าง) ไม่ใช่มุมมองของบัฟเฟอร์เฟรมของภาพ -- อาร์เรย์ numpy เป็นเจ้าของไบต์ของตัวเองเสมอ ลายเซ็นคือ to_ndarray(dtype, *, buffer=None) และรูปร่างของผลลัพธ์ขึ้นอยู่กับรูปแบบภาพ:
GRAYSCALE -- อาร์เรย์ 2 มิติ รูปร่าง
(height, width)RGB565 -- อาร์เรย์ 3 มิติ รูปร่าง
(height, width, 3)ระนาบตามลำดับ R/G/B
อาร์กิวเมนต์ dtype ควบคุมการแมปของค่าพิกเซล 8 บิตแต่ละค่า v:
|
องค์ประกอบ |
การแมปสำหรับค่าพิกเซล 8 บิต |
|---|---|---|
|
|
|
|
|
|
|
|
|
ตัวอย่าง -- ดูเฟรม grayscale เป็นเมทริกซ์ uint8
import csi
from ulab import numpy as np
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize(csi.QVGA)
img = csi0.snapshot()
a = img.to_ndarray('B') # shape (240, 320), dtype=uint8
print(a.shape, a.dtype)
print("mean brightness:", np.mean(a))
คีย์เวิร์ด buffer= ช่วยให้แอปพลิเคชันนำ bytearray ที่จัดสรรไว้แล้วมาใช้ซ้ำ เพื่อให้กล้องไม่ต้องจัดสรรใหม่ทุกเฟรม:
buf = bytearray(320 * 240)
while True:
img = csi0.snapshot()
a = img.to_ndarray('B', buffer=buf)
# ... process a ...
6.18.2. ndarray เป็น image¶
ในทางตรงกันข้าม ส่ง ndarray เป็นอาร์กิวเมนต์แรกให้กับ image.Image ตัวสร้างจะจัดสรรบัฟเฟอร์ภาพใหม่และคัดลอกค่าของอาร์เรย์เข้าไป โดยตัดและปัดเศษให้อยู่ในช่วง 0..255
image.Image(arr, *, buffer=None, copy_to_fb=False)
ตัวสร้างจะอนุมานรูปทรงเรขาคณิตและรูปแบบพิกเซลจากรูปร่างของอาร์เรย์:
รูปร่าง
(h, w)-- ภาพGRAYSCALEรูปร่าง
(h, w, 3)-- ภาพRGB565
ndarray ต้องมี dtype เป็น float ตัวสร้างรองรับเฉพาะกรณีนั้นในปัจจุบัน ค่าจะถูกปัดเศษและตัดให้อยู่ในช่วง 0..255
buffer= ช่วยให้แอปพลิเคชันระบุ bytearray ที่จัดสรรไว้แล้วสำหรับภาพผลลัพธ์ copy_to_fb=True เขียนผลลัพธ์ลงในบัฟเฟอร์เฟรมของกล้อง ซึ่งเป็นตัวเลือกที่ถูกต้องเมื่อผลลัพธ์ควรปรากฏในการแสดงตัวอย่างใน IDE
6.18.3. การส่งข้อมูลรอบทริป¶
import csi
import image
from ulab import numpy as np
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize(csi.QVGA)
img = csi0.snapshot()
a = img.to_ndarray('f') # work in float space
a = 255.0 * (a / 255.0) ** 0.5 # gamma correction
out = image.Image(a, copy_to_fb=True) # back to an image
6.18.4. เมื่อไหร่ควรใช้การเชื่อมต่อ¶
การเชื่อมต่อนี้คือคำตอบที่ถูกต้องเมื่อแอปพลิเคชันต้องการการดำเนินการตัวเลข ทั่วไป ที่เมธอด image ในตัวไม่มีให้ -- ฟิลเตอร์แบบกำหนดเอง การผสมแบบกำหนดเอง ความไม่เป็นเชิงเส้นที่ผิดปกติ -- หรือเมื่อข้อมูลพิกเซลต้องรวมกับข้อมูลที่ไม่ใช่ภาพ (แกน IMU ตัวอย่างเสียง) ในการคำนวณเดียว
มัน ไม่ใช่ คำตอบที่ถูกต้องสำหรับการประมวลผลพิกเซลปริมาณงานสูงที่คลาส Image ครอบคลุมอยู่แล้ว เมธอดในตัวทำงานโดยตรงบนบัฟเฟอร์เฟรมในรูปแบบพิกเซลดั้งเดิมของกล้องและเร็วกว่านิพจน์ numpy ที่เทียบเท่ามาก ใช้การเชื่อมต่อสำหรับการดำเนินการที่ไลบรารีภาพยังไม่มีอยู่