Chụp ảnh trong một thời gian ngắn bằng mô-đun máy ảnh Raspberry Pi


13

Tôi đang làm việc trong một dự án mà tôi cần chụp khoảng 30 hình ảnh mỗi giây (không có phim) bằng mô-đun máy ảnh Raspberry Pi.

Tôi đang sử dụng thư viện Picamera ( http://picamera.readthedocs.org/en/latest/api.html ) cho vấn đề đó nhưng vấn đề là, việc chụp ảnh mất khoảng 0,2 - 0,4 giây kéo dài. Tôi đã thiết lập use_video_porttài sản True, giúp một chút, nhưng thời gian vẫn còn dài.

Có ai trong số các bạn biết cách chụp ảnh trong một thời gian ngắn (khoảng 0,025 giây) bằng mô-đun máy ảnh Python và Raspberry Pi không?

Câu trả lời:


18

Để chụp ảnh trong 0,025 giây với picamera, bạn sẽ cần tốc độ khung hình lớn hơn hoặc bằng 80 khung hình / giây. Lý do yêu cầu 80 chứ không phải 40 khung hình / giây (với tỷ lệ 1 / 0,025 = 40) là hiện tại có một số vấn đề khiến mọi khung hình khác bị bỏ qua trong bộ mã hóa đa hình ảnh để tốc độ chụp hiệu quả tăng lên bằng một nửa tốc độ khung hình của máy ảnh.

Mô-đun máy ảnh của Pi có khả năng 80fps trong các phần cứng sau này (xem các chế độ camera trong tài liệu picamera), nhưng chỉ ở độ phân giải VGA (yêu cầu độ phân giải cao hơn với tốc độ khung hình> 30fps sẽ dẫn đến việc nâng cấp từ VGA sang độ phân giải được yêu cầu, vì vậy đây là một giới hạn mà bạn phải đối mặt ngay cả ở tốc độ 40fps). Vấn đề khác bạn có thể gặp phải là giới hạn tốc độ thẻ SD. Nói cách khác, có lẽ bạn sẽ cần phải chụp đến một cái gì đó nhanh hơn như cổng mạng hoặc luồng trong bộ nhớ (giả sử tất cả hình ảnh bạn cần chụp sẽ phù hợp với RAM).

Kịch bản sau đây cho tôi tốc độ chụp ~ 38 khung hình / giây (tức là chỉ trên 0,025 giây trên mỗi ảnh) trên một Pi với mức ép xung được đặt thành 900Mhz:

import io
import time
import picamera

with picamera.PiCamera() as camera:
    # Set the camera's resolution to VGA @40fps and give it a couple
    # of seconds to measure exposure etc.
    camera.resolution = (640, 480)
    camera.framerate = 80
    time.sleep(2)
    # Set up 40 in-memory streams
    outputs = [io.BytesIO() for i in range(40)]
    start = time.time()
    camera.capture_sequence(outputs, 'jpeg', use_video_port=True)
    finish = time.time()
    # How fast were we?
    print('Captured 40 images at %.2ffps' % (40 / (finish - start)))

Nếu bạn muốn làm một cái gì đó ở giữa mỗi khung, điều này có thể ngay cả với capture_sequenceviệc cung cấp chức năng tạo thay vì danh sách đầu ra:

import io
import time
import picamera
#from PIL import Image

def outputs():
    stream = io.BytesIO()
    for i in range(40):
        # This returns the stream for the camera to capture to
        yield stream
        # Once the capture is complete, the loop continues here
        # (read up on generator functions in Python to understand
        # the yield statement). Here you could do some processing
        # on the image...
        #stream.seek(0)
        #img = Image.open(stream)
        # Finally, reset the stream for the next capture
        stream.seek(0)
        stream.truncate()

with picamera.PiCamera() as camera:
    camera.resolution = (640, 480)
    camera.framerate = 80
    time.sleep(2)
    start = time.time()
    camera.capture_sequence(outputs(), 'jpeg', use_video_port=True)
    finish = time.time()
    print('Captured 40 images at %.2ffps' % (40 / (finish - start)))

Hãy nhớ rằng trong ví dụ trên, quá trình xử lý đang diễn ra nghiêm ngặt trước lần chụp tiếp theo (tức là bất kỳ quá trình xử lý nào bạn thực hiện sẽ nhất thiết phải trì hoãn lần chụp tiếp theo). Có thể giảm độ trễ này bằng các thủ thuật xâu chuỗi nhưng làm như vậy liên quan đến một mức độ phức tạp nhất định.

Bạn cũng có thể muốn xem xét các ảnh chụp chưa được mã hóa để xử lý (loại bỏ phần trên của mã hóa và sau đó giải mã JPEG). Tuy nhiên, hãy nhớ rằng CPU của Pi rất nhỏ (đặc biệt là so với GPU VideoCore). Mặc dù bạn có thể chụp ở tốc độ 40 khung hình / giây, nhưng không có cách nào bạn có thể thực hiện bất kỳ xử lý nghiêm trọng nào đối với các khung hình đó ở tốc độ 40 khung hình / giây ngay cả với tất cả các thủ thuật được đề cập ở trên. Cách thực tế duy nhất để thực hiện xử lý khung hình ở tốc độ đó là chuyển các khung qua mạng đến một máy nhanh hơn hoặc thực hiện xử lý trên GPU.


Cảm ơn bạn đã trả lời nhanh chóng! Nhưng trong chương trình của bạn, tôi sẽ không thể xử lý các ảnh riêng lẻ trong khi .capture_ resultence chạy, phải không? Có cách nào để làm việc này không? Bởi vì tôi cần phải làm việc với mọi hình ảnh riêng lẻ trước khi tiếp theo là mã thông báo.
Timo Denk

1
Sửa đổi câu trả lời để bao gồm một phương pháp thực hiện xử lý giữa các khung với chức năng tạo.
Dave Jones

.capture_ resultence xuất hiện để bỏ qua KeyboardInterrupts. Bạn có biết làm thế nào để làm việc xung quanh này?
Cerin

@Cerin tiêu thụ năng lượng cho một cái gì đó như thế này là gì?
Ted Taylor của cuộc sống

Các khung hình / giây là nhanh cho giải pháp này nhưng làm thế nào để lưu hình ảnh vào các tập tin từ luồng?
bakalolo

4

Theo câu trả lời StackOverflow này, bạn có thể sử dụng guxer và lệnh sau để thực hiện những gì bạn muốn:

raspivid -n -t 1000000 -vf -b 2000000 -fps 25 -o - | gst-launch-1.0 fdsrc ! video/x-h264,framerate=25/1,stream-format=byte-stream ! decodebin ! videorate ! video/x-raw,framerate=10/1 ! videoconvert ! jpegenc ! multifilesink location=img_%04d.jpg

Lệnh này xuất hiện để lấy đầu ra video của raspivid để tạo luồng video với 25 khung hình mỗi giây và sau đó sử dụng bộ chuyển đổi video để chuyển đổi video thành hình ảnh jpeg riêng lẻ.

Bài viết này cung cấp hướng dẫn về cách cài đặt gstreamer1.0 từ kho lưu trữ thay thế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.