0

I need to take a video under low light conditions using a NoIR Pi camera, so I followed the suggestions given in this post. But I still get completely black frames. I have attached the code here.

# -*- coding: utf-8 -*-
from  __future__ import unicode_literals

import io
import picamera
import time

class PtsOutput(object):
    def __init__(self, camera, video_filename, pts_filename):
        self.camera = camera
        self.video_output = io.open(video_filename, 'wb')
        self.pts_output = io.open(pts_filename, 'w') #For recording timestamps of the frames
        self.start_time = None

    def write(self, buf): 
        self.video_output.write(buf)
        if self.camera.frame.complete and self.camera.frame.timestamp:
            if self.start_time is None:
                self.start_time = self.camera.frame.timestamp
                    self.pts_output.write('# timecode format v2\n')
                    self.pts_output.write('%f\n' % ((self.camera.frame.timestamp - self.start_time) / 1000.0))

    def flush(self):    
        self.video_output.flush()
        self.pts_output.flush()

    def close(self):
        self.video_output.close()
        self.pts_output.close() 


with picamera.PiCamera() as camera:
    camera.resolution = (640,480)
    time.sleep(30)
    camera.exposure_mode = 'off'
    camera.framerate = 30
    camera.start_recording(PtsOutput(camera, '640480_30fps.h264','yuv_pts_640480_30fps.txt'), format='h264')
    camera.start_preview()
    camera.wait_recording(60)
    camera.stop_recording()

What am I doing wrong?

NTE12
  • 41
  • 1
  • 6

1 Answers1

2

The problem (and I've just noticed this is also a problem in the other post, which I missed in my reply to that one) is that you're setting framerate after setting exposure_mode. Here's what's going on under the covers:

  1. You initialize the camera with the PiCamera() line. This activates the sensor, sets the initial resolution to the display's resolution, and the framerate to 30fps. Immediately after this point the camera's gains will be 0 (which would result in black frames), but the AGC will start adjusting them upwards according to the scene.

  2. You set resolution to 640x480 - this causes the sensor to reset, which sets the gains back to their default (0) and AGC once again starts adjusting them.

  3. You wait 30 seconds - this will give the AGC plenty of time to adjust the gains to reasonable values.

  4. You set exposure_mode to off which disables the AGC. From this point on the camera's gains will be fixed.

  5. You set framerate to 30. Firstly this is unnecessary (it's already 30). But a side effect of this is that setting the framerate (or the resolution) resets the sensor, and once again the gains are back to 0. Unfortunately, the AGC is now disabled so they won't float back up and you'll just get black frames.

  6. The rest of the script continues from here...

So, the simple solution is to get rid of the line setting the framerate. Alternatively, if you want to ensure the framerate is explicitly set, I generally recommend setting it next to the resolution so that all the sensor resetting gets done together.

If you don't like the idea of all that sensor resetting (which is quite slow - although that's generally not a problem if it's a one-off thing at script start-up), you can override the initial resolution and framerate in the PiCamera() initializer:

import picamera

with picamera.PiCamera(resolution=(640, 480), framerate=24) as camera:
    # Do stuff with the camera
Dave Jones
  • 3,978
  • 15
  • 22