Hãy bắt đầu bằng cách nhìn vào các mô-đun máy ảnh. Mô-đun máy ảnh v1 có khả năng tạo khung 2x2 và 4x4 (xem bảng chế độ máy ảnh ); Tôi cũng đã nghe nói có chế độ tạo thùng 8 x 8 nhưng các nhà phát triển phần sụn không thể làm cho nó hoạt động. Đây là lý do tại sao mô-đun v1 có thể đạt được trường quan sát (foV) đầy đủ trong hầu hết các chế độ.
Thật không may, mô-đun máy ảnh v2 được so sánh, chỉ có khả năng tạo khung 2x2, điều này giải thích tại sao nhiều chế độ của nó có một phần foV (Tôi nghĩ rằng mô-đun v2 cũng có thể bỏ qua dòng, nhưng tôi không nghĩ rằng đó là máy ảnh của Pi sử dụng phần sụn). Tuy nhiên, đây không phải là toàn bộ câu chuyện. Đây chỉ là sự khởi đầu của đường ống xử lý hình ảnh. Nói cách khác, đây chỉ là những gì cảm biến tự chuyển đến khối ISP trong GPU xử lý phần còn lại của quá trình xử lý, bao gồm mọi thay đổi kích thước. Trong khi máy ảnh có một số chế độ riêng biệt (được liệt kê trong bảng đó), nó có thể hoạt động hiệu quả trong mọi chế độđộ phân giải lên đến mức tối đa được liệt kê. Nếu bạn đọc thêm một chút từ các bảng đó trong tài liệu, bạn sẽ tìm thấy mô tả về heuristic được sử dụng để chọn chế độ cảm biến theo độ phân giải và tốc độ khung hình được yêu cầu.
Miễn là bạn kết nối hoặc buộc sử dụng chế độ cảm biến toàn khung hình, bạn sẽ chụp từ tất cả các pixel trên cảm biến. Đối với những lo ngại về việc sử dụng CPU: đừng lo lắng. CPU không được sử dụng cho bất kỳ phần nào trong đường dẫn hình ảnh của máy ảnh, nó gần như hoàn toàn dựa trên GPU (ngoại trừ bước tạo thùng đầu tiên được thực hiện bởi ISP cảm biến). Lần duy nhất CPU tham gia là khi nó nhận được đầu ra cuối cùng và phải làm gì đó với nó.
Nếu bạn đang tìm kiếm mức sử dụng CPU tối thiểu, đây là điểm cộng lớn của mô-đun máy ảnh so với webcam USB, vì bus USB được CPU thăm dò, hãy sử dụng thời gian CPU đáng kể (USB3 sử dụng ngắt thay vì bỏ phiếu nhưng chúng tôi nói về Pis ở đây chỉ có USB2 và bên cạnh đó: hầu hết các webcam USB không sử dụng USB3 tại thời điểm viết).
Lên các yêu cầu cụ thể của bạn. Bạn muốn:
- để tạo ra hình ảnh 120x90
- với góc nhìn đầy đủ
- màu đen và trắng (tôi sẽ hiểu điều này chỉ có nghĩa là luma là tốt)
- đến một mảng numpy Python
- nhanh nhất có thể
Vừa đủ dễ. Chúng tôi sẽ sử dụng chế độ cảm biến 4 cung cấp trường quan sát đầy đủ và sử dụng cảm biến để thực hiện chế độ tạo 2x2 ban đầu. Chúng tôi sẽ đặt độ phân giải đầu ra của máy ảnh thành 120x90 (điều này đơn giản có nghĩa là khối thay đổi kích thước của GPU sẽ lấy dữ liệu cảm biến có khung hình 2x2 toàn khung hình và giảm kích thước xuống 120x90). Cuối cùng, chúng ta sẽ chụp thẳng vào một mảng gọn gàng nhưng chúng ta sẽ chỉ làm cho nó đủ lớn cho mặt phẳng Y (độ chói) của dữ liệu; nó sẽ gây ra lỗi vì mảng không đủ lớn cho tất cả dữ liệu, nhưng không sao - chúng ta có thể bỏ qua điều đó và nó vẫn sẽ ghi dữ liệu Y ra:
import time
import picamera
import numpy as np
with picamera.PiCamera(
sensor_mode=4,
resolution='120x90',
framerate=40) as camera:
time.sleep(2) # let the camera warm up and set gain/white balance
y_data = np.empty((96, 128), dtype=np.uint8)
try:
camera.capture(y_data, 'yuv')
except IOError:
pass
y_data = y_data[:120, :90]
# y_data now contains the Y-plane only
print(y_data.max())
Điều này ít nhiều được sao chép trực tiếp từ công thức chụp ảnh chưa được mã hóa (YUV) cũng giải thích lý do tại sao chúng tôi thực sự chụp 128x96 ở đây (máy ảnh hoạt động trong các khối 32x16).
Điều gì về chụp liên tục nhanh chóng? Tôi cho rằng bạn quan tâm đến điều này đơn giản chỉ vì bạn muốn điều này càng nhanh càng tốt (điều này thường có nghĩa là bạn muốn càng nhiều càng tốt). Trong trường hợp này, tốt nhất là sử dụng đầu ra tùy chỉnh với bản ghi YUV (sẽ nhận một cuộc gọi write () trên mỗi khung hình), sau đó sử dụng frombuffer
phương pháp rất tiện dụng của numpy để xếp một mảng numpy lên trên mặt trước của dữ liệu đã chụp (lưu ý: việc này cực kỳ nhanh vì chúng tôi không phân bổ mảng numpy hoặc sao chép dữ liệu, chúng tôi chỉ nói "tạo một mảng gọn gàng trên khối bộ nhớ hiện có này "):
import time
import picamera
import numpy as np
class MyOutput(object):
def write(self, buf):
# write will be called once for each frame of output. buf is a bytes
# object containing the frame data in YUV420 format; we can construct a
# numpy array on top of the Y plane of this data quite easily:
y_data = np.frombuffer(
buf, dtype=np.uint8, count=128*96).reshape((96, 128))
# do whatever you want with the frame data here... I'm just going to
# print the maximum pixel brightness:
print(y_data[:90, :120].max())
def flush(self):
# this will be called at the end of the recording; do whatever you want
# here
pass
with picamera.PiCamera(
sensor_mode=4,
resolution='120x90',
framerate=40) as camera:
time.sleep(2) # let the camera warm up and set gain/white balance
output = MyOutput()
camera.start_recording(output, 'yuv')
camera.wait_recording(10) # record 10 seconds worth of data
camera.stop_recording()
Mặc dù tạo ra 40 khung hình mỗi giây của dữ liệu hình ảnh trong các mảng khó hiểu, việc sử dụng CPU của tập lệnh này là tối thiểu. Nhận xét câu lệnh in, thực sự khá nặng về CPU, để xem mức độ sử dụng CPU tổng thể: đó là khoảng 2% trên Pi3 của tôi vì vậy còn dư lại cho bất kỳ xử lý hình ảnh nào bạn muốn làm.
v4l2-ctl
để đặt mọi thứ trên máy ảnh mà sau đó bạn có thể sử dụng/dev/video
thiết bị trực tiếp. Tôi sẽ thử điều đó và xem làm thế nào bạn nhận được trên. Nếu bạn gặp khó khăn liên hệ với tác giả về bất kỳ vấn đề hoặc câu hỏi thực sự. Anh ấy là một chàng trai rất tốt, thích giúp đỡ với những vấn đề thực sự. Chúc may mắn và hãy trả lời với cách bạn giải quyết vấn đề của bạn.