waveform80 / picamera

A pure Python interface to the Raspberry Pi camera module
https://picamera.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
1.57k stars 357 forks source link

camera.capture() blocks #649

Open dneunkirch opened 4 years ago

dneunkirch commented 4 years ago

I've a problem and I don't know why. I use:

If I capture the small image the script hangs up and isn't anymore responding.

Simplified example:

import io
import numpy
import picamera
from PIL import Image
import datetime
from threading import Condition

class StreamingOutput(object):
    def __init__(self):
        self.last_frame = datetime.datetime.now()
        self.condition = Condition()
        self.screen = bytes()

    def write(self, frame):
        now = datetime.datetime.now()
        time_diff = (now - self.last_frame).microseconds
        if time_diff < 500000:
            return
        self.last_frame = now
        size = str(len(frame)).encode('utf-8')
        self.screen = b'Content-Type: image/jpeg\r\n' \
                      b'Content-Length: ' + size + b'\r\n\r\n' \
                      + frame + b'\r\n'
        self.condition.acquire()
        self.condition.notifyAll()
        self.condition.release()

motion_port = 1
streaming_port = 2
preview_port = 3

camera = picamera.PiCamera(framerate=15, sensor_mode=2, resolution=(1920,1080))
stream = picamera.PiCameraCircularIO(camera, seconds=20, splitter_port=motion_port)
output = StreamingOutput()

camera.start_recording(stream, format='h264', splitter_port=motion_port)
camera.start_recording(output, format='mjpeg', splitter_port=streaming_port)

prev_temp_img = None

def capture_preview_image():
    stream = io.BytesIO()
    # here the script blocks
    camera.capture(stream, format='jpeg', resize=(192,108), splitter_port=preview_port, use_video_port=True)
    stream.seek(0)
    image = Image.open(stream)
    image_array = numpy.asarray(image)
    return image_array[::, ::, 1]

def motion_detected():
    global prev_temp_img
    current_temp_img = capture_preview_image()
    diff = (numpy.absolute(prev_temp_img.astype(numpy.int) - current_temp_img.astype(numpy.int)) > 22).sum()
    prev_temp_img = current_temp_img
    motion = diff >= 25
    return motion

try:
    while True:
        camera.wait_recording(1)
        prev_temp_img = capture_preview_image()
        if motion_detected():
            camera.split_recording('after.h264')
            stream.copy_to('before.h264')
            camera.wait_recording(3)      
            while motion_detected():
                camera.wait_recording(5)        
            camera.split_recording(stream, splitter_port=motion_port)              
finally:
    camera.stop_recording()
dneunkirch commented 4 years ago

This Issue is duplicated. See https://github.com/waveform80/picamera/issues/546

flomine commented 3 years ago

Hi, I tried your script and have same problem. Nevertheless, if I change resolution behavior is different: resolution=(1920,1080) -> works for few seconds then hangs resolution=(1640,1232) -> works for few seconds then hangs resolution=(1080,720) -> works (for at least more than 10 minutes) Seems related to a buffer overflow. I check memory usage (cpu and gpu) but it is far from being full.