2

I am very new to R Pi, but I know my Python.

I am working on a project where I have an always running camera, that is kept in dark. What I need to do is to capture an image when there is light. (lets say the pi cam is in a dark box and when somebody opens the box it takes an image about them)

So far I using the code from the basic getting started tutorial.

camera.start_preview()
sleep(5)
camera.capture('/home/pi/Desktop/image.jpg')
camera.stop_preview()

And it works fine. I have camera feed and it takes an image. I will write around this script.

I know how to make it run forever, also how to start it on turning on the Pi. The only thing I missing: How to know from the camera feed if there is light?

1 Answer 1

2

I: Photodetector

Use an additional photodetector, e.g. a fototransistor, attached to a GPIO pin and detect when there is light.

A simple circuit could look like this (source). With Vcc=3.3 V and Vout tied to a GPIO input pin of the Pi. According to the source the resistor would be 100 Ohms, I would think it should be higher (Adafruit is in the range of 1k to 10k Ohms). Major drawback of this circuit is its analogue signal that is feed into the digital input and might be somewhat less repeatable.

enter image description here

An improved circuit would use a Schmitt-Trigger, either integrated, e.g. the 74HC14, or a circuit like this (source):

enter image description here

Needs additional hardware.

II: Raspicam

Wait, a camera is essentially a photodetector, why use another one? Simply have the Raspicam taking pictures all the time in an appropriate frame rate. Read the picture, calculate the sum of all pixels. If this value is above a certain threshold assume it's "light" and keep the picture, otherwise discard of it. You will need to figure out that threshold for your particular setup - a dark image will not be zero due to hot pixels and noise.

As an example using numpy/scipy (just because I use those all the time - one could also use any other package that imports images).

import numpy as np
import scipy.misc as spmisc

img = spmisc.imread(filename, flatten=True)
lumi = np.sum(img)
if lumi > threshold:
    # do something

Improvement to that would be to not save all the unneeded images to the SD card. Instead use picamera.capture() to capture the image to a file-like object (an io.BytesIO stream) or even better (thanks to Dave Jones) directly to a numpy array. Calculate your result from that object and save only if necessary.

An example from here shows how to do it and gives important notes to the resolution.

import time
import picamera
import numpy as np

with picamera.PiCamera() as camera:
    camera.resolution = (320, 240)
    camera.framerate = 24
    time.sleep(2)
    output = np.empty((240, 320, 3), dtype=np.uint8)
    camera.capture(output, 'rgb')

It is also important to note that when outputting to unencoded formats, the camera rounds the requested resolution. The horizontal resolution is rounded up to the nearest multiple of 32 pixels, while the vertical resolution is rounded up to the nearest multiple of 16 pixels.

See:

3
  • OK this is a very good answer. The second one works just like I want it to be. Commented Sep 23, 2017 at 16:26
  • 2
    One minor addition to an otherwise excellent answer: a few versions ago I added the ability to capture directly to an array which is easier than capturing to a BytesIO first for this purpose
    – Dave Jones
    Commented Sep 24, 2017 at 14:19
  • @DaveJones, thanks, that's a very good hint, I should have read the whole documentation ;)
    – Ghanima
    Commented Sep 24, 2017 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.