Raspberry Pi 카메라 모듈을 사용하여 짧은 시간에 이미지 촬영


13

Raspberry Pi 카메라 모듈을 사용하여 초당 약 30 개의 이미지 (동영상 없음)를 촬영해야하는 프로젝트를 진행하고 있습니다.

필자는 Picamera 라이브러리 ( http://picamera.readthedocs.org/en/latest/api.html )를 사용하고 있지만 문제는 사진을 찍는 데 약 0.2-0.4 초가 걸리는 것입니다. 나는 이미 use_video_port속성을로 설정 True했는데 약간 도움이되었지만 시간이 여전히 길다.

Python과 Raspberry Pi 카메라 모듈을 사용하여 짧은 시간 (약 0.025 초)에 사진을 찍는 방법을 아는 사람이 있습니까?

답변:


18

picamera로 0.025 초 안에 사진을 찍으려면 80fps 이상의 프레임 속도가 필요합니다. 80fps가 아닌 40fps (1 / 0.025 = 40)가 필요한 이유는 현재 여러 이미지 인코더에서 다른 모든 프레임을 건너 뛰게하여 유효 캡처 속도가 카메라 프레임 속도의 절반으로 줄어드는 문제가 있기 때문입니다.

Pi의 카메라 모듈은 이후 펌웨어에서 80fps가 가능 하지만 (picamera 문서의 카메라 모드 참조 ) VGA 해상도에서만 (프레임 속도가 30fps보다 높은 해상도를 요청하면 VGA에서 요청 된 해상도로 업 스케일링 됨) 40fps에서도 직면하는 한계). 발생할 수있는 다른 문제는 SD 카드 속도 제한입니다. 다시 말해, 네트워크 포트 나 메모리 스트림과 같은 빠른 속도로 캡처해야 할 수도 있습니다 (캡쳐해야하는 모든 이미지가 RAM에 적합하다고 가정).

다음 스크립트는 오버 클럭킹이 900Mhz로 설정된 Pi에서 ~ 38fps (그림 당 0.025 초 이상)의 캡처 속도를 보여줍니다.

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)))

각 프레임 사이에 무언가를 원한다면 capture_sequence출력 목록 대신 생성기 기능을 제공하여 가능 합니다.

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)))

위의 예에서 처리는 다음 캡처 이전에 연속적으로 발생합니다 (즉, 처리하는 경우 반드시 다음 캡처가 지연됨). 스레딩 트릭으로 이러한 대기 시간을 줄일 수 있지만 그렇게하려면 일정량의 복잡성이 수반됩니다.

처리를 위해 인코딩되지 않은 캡처를 살펴볼 수도 있습니다 (이는 인코딩 오버 헤드를 제거한 다음 JPEG 디코딩). 그러나 Pi의 CPU는 작습니다 (특히 VideoCore GPU와 비교). 40fps 로 캡처 할 수는 있지만 위에서 언급 한 모든 트릭을 사용하더라도 40fps에서 해당 프레임을 심각하게 처리 할 수있는 방법은 없습니다. 이 속도로 프레임 처리를 수행하는 유일한 현실적인 방법은 네트워크를 통해 프레임을 더 빠른 컴퓨터로 보내거나 GPU에서 처리를 수행하는 것입니다.


빠른 답변 감사합니다! 그러나 귀하의 프로그램에서 .capture_sequence가 실행되는 동안 개별 그림을 처리 할 수 ​​없습니다. 이것을 할 수있는 방법이 있습니까? 다음은 토큰 전에 모든 개별 사진으로 작업해야하기 때문입니다.
Timo Denk

1
생성기 기능을 사용하여 프레임 간 처리를 수행하는 방법을 포함하도록 답변을 수정했습니다.
Dave Jones

.capture_sequence는 KeyboardInterrupts를 무시하는 것으로 보입니다. 이 문제를 해결하는 방법을 알고 있습니까?
Cerin

@Cerin 이와 같은 전력 소비는 무엇입니까?
생명의 테드 테일러

fps는이 솔루션에 빠르지 만 스트림에서 파일로 이미지를 저장하는 방법은 무엇입니까?
bakalolo 2016 년

4

이 StackOverflow 답변 에 따르면 gstreamer 및 다음 명령을 사용하여 원하는 것을 수행 할 수 있습니다.

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

이 명령은 raspivid의 비디오 출력을 초당 25 프레임의 비디오 스트림을 생성 한 다음 gstreamer를 사용하여 비디오를 개별 JPEG 이미지로 변환하는 것으로 보입니다.

이 기사 는 대체 저장소에서 gstreamer1.0을 설치하는 방법에 대한 지시 사항을 제공합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.