<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="sodnpoo.xsl" type="text/xsl"?>
<xml page="/?t=birdcam"><a href="http://sodnpoo.com/?x=html">HTML version</a><post>
  <tag value="birdcam"/>
  <tag value="rpi"/>
  <title>picam motion detection and overlaying timestamps</title>
  <date>4 May 2014</date>
  <p>
  I wanted to add timestamps to the video that's captured while using <a href="/posts.xml/raspberrypi_camera_with_opencv_motion_detection_and_recording.xml">my picam, opencv-based motion detection</a> application. The easiest way would probably be to read and modify every frame in userspace on the Pi, before letting the GPU encode it to h264, however I'd like to keep frame rates as high as possible - so would rather the Pi did the minimum amount of work it needs to do. I only really need the frame number and a timestamp and some way to merge them with the video.
  </p>
  <p>
  The MMAL API for the Pi's camera has a bunch of flags in the 'buffer header' objects that get passed around as the image data flows from component to component. By counting the instances of one of these - MMAL_BUFFER_HEADER_FLAG_FRAME_END - you can track frame numbers. I've modified the code to emit the frame number and an epoch timestamp when motion is detected. To prevent it from producing hundreds of these events, it only emits when another flag: MMAL_BUFFER_HEADER_FLAG_KEYFRAME - is set at the start of a keyframe. This pegs the rate a the keyframe rate; every two seconds. An example keyframe event looks like this in the logs:
  </p>
  <pre>
  KEYFRAME (1397291533:1)
  </pre>
  <p>
  The logs are written to stderr and the h264 video stream is written to stdout. To record them both, the app is run like this:
  </p>
  <pre>
  ./mmal_opencv_modect &gt; video.h264 2&gt; video.log
  </pre>  
  <p>
  As it turns out the h264 file it spits out is less than perfect, some things play it at a high frame rate and some things don't play it at all. To clean it up I've been pushing it through ffmpeg to create a nice avi:
  </p>
  <pre>
  ./ffmpeg -r 30 -i video.h264 -q:v 1 -r 30 video.avi
  </pre>
  <p>
  This step doesn't need to happen on the pi, and can be offloaded to faster machine - and while we're post processing we may as well be adding timestamp overlays too :) Initially I tried to use ffmpeg's 'drawtext' filter and to start with it looked promising; it has expressions so that text strings can be positioned across exact frame ranges. Unfortunately each of these are specified individually on the command line and more than a thousand exceeds the maximum command line length - at least here on my machine.
  </p>
  <p>
  Instead I've written a <a href="https://github.com/sodnpoo/rpi-mmal-opencv-modetect/blob/master/scripts/modect2sub.py">python script</a> that can take the log output from mmal_opencv_modect and convert it into a MicroDVD subtitle file. The MicroDVD format uses frame numbers, so is easy to translate from the keyframe events in the logs. The epoch timestamp is also converted to something a little more human friendly. The script is run like this:
  </p>
  <pre>
  ./scripts/modect2sub.py video.log &gt; video.sub
  </pre>
  <p>
  Now we have the subtitle file it just needs to be merged with the h264 stream. Using ffmpeg, compiled with libass support:
  </p>
  <pre>
  ./ffmpeg -r 30 -i video.h264  -vf "subtitles=video.sub" -q:v 1 -r 30 video.avi
  </pre>
  <p>
  Github repo can be found <a href="https://github.com/sodnpoo/rpi-mmal-opencv-modetect">here</a>.
  </p>
</post><post>
  <tag value="birdcam"/>
  <tag value="rpi"/>
  <title>raspberrypi camera with opencv motion detection and recording</title>
  <date>2 Apr 2014</date>
  <p>
  I've just <a href="https://github.com/sodnpoo/rpi-mmal-opencv-modetect">pushed some code</a> for the raspberry pi and it's camera - based on <a href="http://www.raspberrypi.org/forums/viewtopic.php?f=43&amp;t=44982">tasanakorn's work</a> - up to github that uses some very simple <a href="http://opencv.org/">OpenCV</a> to do background subtraction and then detect movement. When it detects motion, the camera image data is sent on to the h264 encoder in the VideoCore and the h264 stream is written to stdout. The detection and encoding happen in different threads, so that even though we can't do motion detection at full frame rate, that doesn't affect the recording frame rate. Here's some frame rates and CPU utilisation numbers taken at various camera modes (incl. the new 640x480 at 90 FPS!):
  </p>
  <pre>
 720p30 : OpenCV = 15.05, Video = 30.51, ~60% CPU
1080p30 : OpenCV = 14.90, Video = 30.02, ~75% CPU
 VGAp90 : OpenCV = 21.57, Video = 91.12, ~90% CPU
  </pre>
  <p>
  To build, follow the README instructions in the github repo. Once it's built you can run it like this:
  </p>
  <pre>
  ./mmal_opencv_modect &gt; video.h264
  </pre>
  <p>
  I'm hoping to use some more raspberry pi's (and camera modules) to replace the analogue system we're currently using for <a href="/birdcam/">birdcam</a>. The resolution is much higher and the 90 FPS mode should show the very fast movement of some of the smaller birds. The pi based system should be more distributed and scalable than the current system too.
  </p>
</post><post>
  <tag value="birdcam"/>
  <title>first birdhouse visitor</title>
  <date>27 Jul 2013</date>  
  <p>
  We finally had our first visitor to the birdhouse :)
  </p>
  <image src="/posts.assets/firstbirdhousevisitor.jpg"/>
  <p>
  Believed to be a great tit - video clips can be found <a href="http://www.talesoftheinnermonkey.co.uk/2013/07/great-tit-in-bird-house-eeeeeeeeeeeeeep.html">here</a>. Live images can be found <a href="/birdcam/">here</a>.
  </p>
</post><post>
  <tag value="birdcam"/>
  <title>real time birdcam</title>
  <date>3 Mar 2013</date>
  <p>
  <a href="/birdcam/">Live images</a> taken from the cameras I recently installed watching our bird feeders. Jpegs are pulled via a cron'd script from the <a href="http://www.zoneminder.com">zoneminder</a> server and dropped onto the public web server. A tiny bit of jquery updates the images in the browser - both run once a minute.
  </p>
  <p>
  See <a href="/posts.xml/guerrilla_bird_cam.xml">here</a>, <a href="http://www.talesoftheinnermonkey.co.uk/2013/02/bird-cam.html">here</a> and <a href="http://www.talesoftheinnermonkey.co.uk/2013/03/more-birdies.html">here</a> for more information. Live images can be found <a href="/birdcam/">here</a>.
  </p>
</post><post>
  <tag value="birdcam"/>
  <title>guerrilla bird cam</title>
  <date>17 Feb 2013</date>
  <image src="/posts.assets/guerrilla_bird_cam1a.jpg"/>
  <p>
  Very quick and dirty outdoor bird cam. Pin hole camera/transmitter and a 9v battery in freezer bag and some gaffer tape. Lets see how long the battery lasts. 
  </p>
  <image src="/posts.assets/guerrilla_bird_cam1b.jpg"/>
  <p>
  Here's the image displayed on the bedroom TV.
  </p>
  <p>
  Update: battery only lasted a couple of hours so I've run a cable carrying 8v from a wall wart in the shed.
  </p>
</post></xml>
