Click here to Skip to main content
15,860,859 members
Articles / Internet of Things / Raspberry-Pi

Raspberry Pi HD Surveillance Camera with Motion, Night Settings and a Website

Rate me:
Please Sign up or sign in to vote.
4.85/5 (28 votes)
12 May 2015CPOL9 min read 235K   71   56
Tutorial to create sharp 720P pictures by day and night and has a website that shows the last 10 pictures

Introduction

I'm currently working on an updated version of this PiCam sc which will be easier to install and gives you the possibility to receive updates and new features. You can find this project on GitHub: https://github.com/dofl/PiCam

This article will show you the best settings to use for your normal Raspberry Pi camera (not the NoIR) as a HD surveillance camera. In the end, you will have a crisp 720P image, with a pretty good quality at night and a webbrowser that shows the last 10 images.

Optionally, there is a tutorial on how to use an external storage like a NAS to copy images to. It uses an in-memory filesystem (TMPFS) as a buffer to store images while the slow Pi Wifi copies the images to the NAS.

Image 1

Background

There are many good tutorials on how to implement the Raspberry Pi and the camera as a low-cost surveillance camera. I've used these articles as a base and I'll try to reference the sources as much as I still remember.

As everything is already described by others, I'm more interested in getting the best quality in image sharpness and settings at night when using the normal camera (not the NoIR) camera.

Getting Started

It's wise to read ahead a couple of lines before you dive in. I don't always use all code from another article.

It's a good idea to start where I did. He is also the one that made me use codeproject.com as I didn't want to setup another blog that would go down again in a couple of months because I want to use my Pi for another project. :-)

Raspberry Pi as low-cost HD surveillance camera by Christoph Buenger.

Things to do:

  • Buy the hardware he describes
  • Install Raspbian
  • Setup networking

Things NOT to do (although experiment at will!):

  • Install the motion detection software
  • Read the rest of the article as it's based on other motion detection / image capture software

Why?

I never got the image sharpness and resolution that I now got and I think is because of Motion (the software package). I'd rather use the original software provided by the Raspberry Pi foundation as it uses less CPU, just as accurate with motion and creates very sharp pictures.

Casing

Offtopic: I also bought a dummy cam, but that was before I've seen 'PICE', a metal waterproof Raspberry Pi casing.

Image 2

Installing picam.py

The people from MakeTechEasier also wrote an article about using the rPi as a surveillance camera.
They use a Python script that is written by community members that constantly takes small pictures (in memory), compares it with the previous one for changed pixels and when 'enough' changed pixels are found, it takes a high-res picture. Well written, lots of config and uses only the original Rpi provided software.

Install as followed:

sudo apt-get install python-imaging-tk 
wget -c http://pastebin.com/raw.php?i=yH7JHz9w -O picam.py 
chmod +x picam.py   

The script will use a folder called 'picam' for storing all of the images. Create it before starting the script

mkdir ~/picam 

Start picam.py at boot

The picam.py script needs to be started at boot. This is required later on when the Raspberry will reboot into night and day settings.

wget http://pastebin.com/raw.php?i=AfqbjQrb -O picam_init 

The script needs to be moved to the init.d folder in order to boot:

sudo mv ~/picam_init /etc/init.d/picam 
sudo chmod +x /etc/init.d/picam  

Tell the system the picam 'service' has arrived:

sudo update-rc.d picam defaults 

View the Latest Pictures Through a Website

After a while, the SD card will fill up, which is nice as an archive. But I also wanted to see the latest image through my browser. Therefore I installed the lightweight webserver Lighttpd and PHP.

sudo apt-get -y install lighttpd
sudo apt-get -y install php5-common php5-cgi php5
sudo lighty-enable-mod fastcgi-php
sudo service lighttpd force-reload 

After this, you can view the demo website at the http://ip-address-of-your-raspberry-pi
Lighttpd is installed under /var/www/. The picam.py script writes its images under /home/pi/picam/.
I used a symboblic link to make the images of the picam available in the directory of the webserver:

sudo ln -s /home/pi/picam /var/www/picam  

This creates a 'folder' (link) in /var/www/picam that refers to /home/pi/picam.

I borrowed and adapted a piece of PHP code that shows the latest 6 images from the picam/ folder.

sudo nano /var/www/index.php  

Insert the following code:

PHP
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');

print '<meta http-equiv="refresh" content="15">';

//get all images
$images = glob('picam/*.jpg', GLOB_BRACE); //formats to look for
$num_of_files = 10; //number of images to display

//stats
echo "Images: ". count($images). " | ";

$lastImage = new DateTime(date('Y-m-d h:i', filemtime(end($images))));
$firstImage =  new DateTime(date('Y-m-d h:i', filemtime($images[0])));

$interval = $lastImage->diff($firstImage);
echo $interval->format('Timespan between first and last image: %a days, %h hours, %i minutes</br>');

krsort($images);

//show photos
foreach($images as $image)
    {
         $num_of_files--;

         if($num_of_files > -1) //this made me laugh when I wrote it
           echo "<b>".$image."</b> | 
           Created on ".date('D, d M y H:i:s', filemtime($image)) ."<br><img src="."'".$image."'"."><br><br>" ; //display images
         else
           break;
    }
?> 

You now have a very simple website running that always shows the latest 6 images. It refreshes itself every 15 seconds.

Optional: webserver security

When you make the camera website public to the rest of the internet, I'll be wise to secure it. We'll do this by username/password protecting the root folder of the Lighttpd webserver:

Create a username/password file:

sudo nano /etc/lighttpd/.htpasswd 

Insert your username:password combination in this file. Nothing more.

MyUsername:MyPassword  

Next, add a few lines of code to the Lighttpd configuration file:

sudo nano /etc/lighttpd/lighttpd.conf

In 'server.modules =', add the line:

"mod_auth" 

Place the following code (for example) after 'server.port = 80':

PHP
auth.backend = "plain"
auth.backend.plain.userfile = "/etc/lighttpd/.htpasswd"
auth.debug = 1

$HTTP["url"] == "/" {
        auth.require = ( "" =>
        (
        "method" => "basic",
        "realm" => "Authorization",
        "require" => "valid-user"
        ) )
} 

Save and restart Lighttpd by typing:

sudo service lighttpd restart  

Optimal Settings for Night Photos

Normal surveillance cameras have some sort of infrared to lit up the environment at night in order to take a decent picture. As I also wanted good pictures by day, I decided to go with the normal camera and use longer exposure times for the camera. Fast moving objects will blur, but it's the best there is under low-light conditions.

First of all, install the camera in place. Wait for dark and run the excellent Python camera test script written by raspberrypi-spy.co.uk.

cd ~
mkdir test_camera
cd test_camera

wget http://www.raspberrypi-spy.co.uk/archive/python/pi_camera_options.py 

Edit the pi_camera_options.py file:

nano pi_camera_options.py

Set it up so that it takes pictures under all different circumstances.

list_ex  = ['off','auto','night','backlight','spotlight','fireworks']
list_awb = ['off','auto','sun','cloud','shade','tungsten','fluorescent','incandescent','flash','horizon']  

After this, you can run it. It will take pictures under all kinds of different camera settings. It's up to you to compare them to see which picture gives you the best results for what you want to achieve. Remember the 'ex' and 'awb' setting that worked best for the next step.

sudo python pi_camera_options.py 

CRON: Changing Between Day and Night Settings

I am switching between a day and night setting on my rPi. I want to scare away burglars with the blinking red light at night, but I don't want to freak out the neighbors with it by day. At the same time, I want pictures by night to use specific camera settings that worked best in the previous step as well as a longer exposure time. In order to do this, I created 2 scripts that are run by CRON at set times.

First, create the 2 scripts that CRON will run. One to rule by day, one by night.

sudo nano /opt/picam_night.sh   

Insert the following code:

#! /bin/sh

sed -i 's/disable_camera_led=1/disable_camera_led=0/' /boot/config.txt
sed -i 's/cameraSettings = ""/cameraSettings = "-ex night -awb auto"/' /home/pi/picam.py
sed -i 's/-t 200/-t 500/' /home/pi/picam.py 
sed -i 's/threshold = 30/threshold = 10/' /home/pi/picam.py
sed -i 's/sensitivity = 30/sensitivity = 20/' /home/pi/picam.py
/sbin/reboot 

And the one by day:

sudo nano /opt/picam_day.sh 
#! /bin/sh

sed -i 's/disable_camera_led=0/disable_camera_led=1/' /boot/config.txt
sed -i 's/cameraSettings = "-ex night -awb auto"/cameraSettings = ""/' /home/pi/picam.py
sed -i 's/-t 500/-t 200/' /home/pi/picam.py
sed -i 's/threshold = 10/threshold = 30/' /home/pi/picam.py
sed -i 's/sensitivity = 20/sensitivity = 30/' /home/pi/picam.py

/sbin/reboot 

The SED command will find specific pieces of text inside a file and replace it with another piece of text. What the lines do:

  1. Change the LED of the camera in the rPi boot sequence. On by night, off by day.
  2. Set the specific nighttime camera setting (the 'ex' and 'awb' settings).
  3. Change the exposure time of the camera for day and night. Longer by night, shorter by day.
  4. Set the threshold lower at night (more chance of shooting pictures at night).
  5. Set the sensitivity lower at night, also to get more pictures at night. Raise this if the Pi takes too much pictures at night, as it will be because of image noise.

The raspberry Pi will reboot after changing these settings. This is required for changing the blinking LED on the camera. It's set by boot options (/boot/config.txt).

In order to let it run by the CRON daemon:

sudo crontab -e

And add these two lines at the bottom:

00 23  *   *   *   sh /opt/picam_night.sh
00 06  *   *   *   sh /opt/picam_day.sh

This will run the 'night' script at 23.00 hours and the 'day' script at 06.00 hours.

That's it. I'll generate some pretty decent images and use specific settings at night.

Transferring Images to your NAS over WIFI with a Temporary RAM Buffer: TMPFS

I've fitted the Raspberry PI with a WIFI dongle from Edimax. Bought it on Ebay for a couple of euros. It's cheap but it also has a very limited in range and speed, especially when it's not in a direct line of site of the access point.

Therefore, I wanted my Raspberry PI images to be transferred to my NAS. It's on 24/7 and I'm afraid that the SD card in the Raspberry PI will die very soon if 1000 images of 300 KB (around 300 MB) are written to it, every day.

To make sure that copying images over a slow WIFI network does not interfere with the speed at which the picam can take images, I'll be using a temporary buffer to store images in the RAM memory with TMPFS.

By using TMPFS, the picam can keep shooting images as quickly as it can into the fast TMPFS file system, without having to wait on the slower WIFI network to finish copying the image to the NAS. The process of copying the images to the NAS will be taken care by a simple BASH script.

The approach:

  1. We'll setup the mount to the NAS share.
  2. Setup a TMPFS file system share of 10 MB as a buffer for images.
  3. Create a bash script that will copy all the photos from TMPFS buffer to the NAS, but:
    Only if the image is created more than 5 seconds ago (to make sure it doesn't copy images that are being created by raspistill at the exact same moment.
  4. Set the picam.py script to the right folder.

Step 1 and 2: Mount your NAS and create the TMPFS filesystem

Create the folders that will hold the mount to the NAS and the TMPFS file system.

sudo mkdir /mnt/Name_Of_Your_NAS_Share
sudo mkdir /mnt/picam_tmpfs   

Mount the NAS share and TMPFS at boot. This can be done in the fstab file:

sudo nano /etc/fstab  

Add the following two lines:
Line 1: This example below works for a Samba / CIFS / 'Windows' share that can login as guest.

//IP.ADDRESS.OF.SERVER/SHARENAME   /mnt/Name_Of_Your_NAS_Share   cifs    guest 0 01 

Line 2: This creates the 10MB tmpfs filesystem at the folder /mnt/picam_tmpfs folder that you just created.

tmpfs  /mnt/picam_tmpfs  tmpfs   defaults,noatime,size=10M,mode=0777 0 0    

The noatime parameter skips settings the last accessed time for a file. This should give us a I/O performance boost, although I hardly doubt we will notice it on a file system in the RAM memory.

3. Create the BASH script that copies the images from TMPFS to the NAS

sudo nano /opt/tmpfsToNAS.sh 

This script checks the TMPFS folder every two seconds (sleep 2) and moves (-exec mv) all files (-type f) that are created at least 5 seconds ago (-mmin +0.05). Insert the following code:

#! /bin/sh

while :
do
        find /mnt/picam_tmpfs -type f -mmin +0.05 -exec mv "{}" /mnt/Name_Of_Your_NAS_Share/ \;
        sleep 2
done 

Let's make sure this script boots up when the Raspberry boots. This works the same as how picam.py boots at startup:

sudo nano /etc/init.d/tmpfsToNAS  

Insert the following code. I 've set this up with the help of an article at stuffaboutcode.com.

PHP
 #! /bin/sh
# /etc/init.d/tmpfsToNAS

### BEGIN INIT INFO
# Provides:          Copies images from the picam tmpfs to a NAS
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Simple script to start a program at boot
# Description:       Copies images from the picam tmpfs to a NAS
### END INIT INFO

# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Starting copy tmpfs to NAS"
    sh /opt/tmpfsToNAS.sh 2>&1 &
    ;;
  stop)
    echo "Stopping copy tmpfs to serv"
    tmpfsPID=`ps auxwww | grep tmpfsToNAS.sh | head -1 | awk '{print $2}'`
    kill -9 $tmpfsPID
    ;;
  *)
    echo "Usage: /etc/init.d/tmpfsToNAS {start|stop}"
    exit 1
    ;;
esac

exit 0  

Make the script executable:

sudo chmod 755 /etc/init.d/tmpfsToNAS 

Register the script to run at start-up:

sudo update-rc.d tmpfsToNAS defaults  

And finally edit the picam.py script. Let it write to our new TMPFS location:

sudo nano ~/picam.py 

Change the line:

filepath = "/mnt/picam_tmpfs" 

I would say reboot your Pi and check if everything goes well. You should see images being created at the TMPFS folder, but quickly be copied to the NAS share.

History

  • 21-04-2014: First release
  • 21-04-2014: Added webserver security
  • 08-05-2014: Added website statistics (image count and timespan) plus treshold and sensitivity change at night
  • 11-05-2014: Added a TMPFS solution for copying files over WIFI to a NAS

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSadly not working Pin
Member 112035543-Nov-14 9:45
Member 112035543-Nov-14 9:45 
AnswerRe: Sadly not working Pin
Member 112035543-Nov-14 10:22
Member 112035543-Nov-14 10:22 
GeneralRe: Sadly not working Pin
Member 1152065212-Mar-15 10:36
Member 1152065212-Mar-15 10:36 
QuestionUndefined variable Pin
Member 1119082929-Oct-14 9:57
Member 1119082929-Oct-14 9:57 
Questionscript doesn't start automatically Pin
Member 1114747817-Oct-14 15:22
Member 1114747817-Oct-14 15:22 
AnswerRe: script doesn't start automatically Pin
d0fl17-Oct-14 19:53
d0fl17-Oct-14 19:53 
GeneralRe: script doesn't start automatically Pin
Member 1114747818-Oct-14 2:17
Member 1114747818-Oct-14 2:17 
GeneralRe: script doesn't start automatically Pin
Matthew Beaven16-Feb-15 22:21
Matthew Beaven16-Feb-15 22:21 
There are windows carriage return characters present messing up the script and the init script. This thread at Linux Questions took care of it for me.
QuestionThanks so much for your documentation Pin
carefreeames22-Aug-14 3:58
carefreeames22-Aug-14 3:58 
SuggestionSSL? Pin
blassster16-Aug-14 10:45
blassster16-Aug-14 10:45 
SuggestionNice work, some remarks Pin
napulias13-Aug-14 22:38
napulias13-Aug-14 22:38 
GeneralRe: Nice work, some remarks Pin
carefreeames22-Aug-14 3:52
carefreeames22-Aug-14 3:52 
Buginsserv script : service already provided! Pin
jameswing10-Aug-14 14:29
jameswing10-Aug-14 14:29 
QuestionWrite to USB stick? Pin
bobtheboffin7-Aug-14 1:45
bobtheboffin7-Aug-14 1:45 
QuestionThanks, with a few comments Pin
Jeremy Hettenhouser26-Jul-14 11:09
Jeremy Hettenhouser26-Jul-14 11:09 
Questionpicam.py threshold and sensitivity settings Pin
Member 1092629925-Jul-14 0:43
Member 1092629925-Jul-14 0:43 
QuestionFood for Thought Pin
Member 1096675223-Jul-14 9:57
Member 1096675223-Jul-14 9:57 
AnswerRe: Food for Thought Pin
d0fl24-Jul-14 19:46
d0fl24-Jul-14 19:46 
GeneralRe: Food for Thought Pin
Member 1096675227-Jul-14 8:23
Member 1096675227-Jul-14 8:23 
QuestionHi Pin
Yepi108-Jul-14 0:18
Yepi108-Jul-14 0:18 
QuestionResize images to fit web page Pin
Member 109262997-Jul-14 23:44
Member 109262997-Jul-14 23:44 
AnswerRe: Resize images to fit web page Pin
d0fl24-Jul-14 19:48
d0fl24-Jul-14 19:48 
GeneralRe: Resize images to fit web page Pin
Member 1092629925-Jul-14 0:37
Member 1092629925-Jul-14 0:37 
QuestionUndefined offset: 0 in /var/www/index.php on line 15 Pin
Member 109262995-Jul-14 4:02
Member 109262995-Jul-14 4:02 
AnswerRe: Undefined offset: 0 in /var/www/index.php on line 15 Pin
Member 109306987-Jul-14 23:36
Member 109306987-Jul-14 23:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.