Photographing Incidences of Gregarious Eating by Ornithological Neighbors
I know the acronym is a stretch, but I already had the project name before figuring out what it stood for. My wife gets the credit for coming up with it.
The PIGEON is a bird feeder that can detect when birds land and automatically trigger a camera to take a picture. The basic components are shown in the diagram below:
PIGEON system
The original plan for this project was to use a mechanical switch to detect when a bird landed on the feeder. That version is described in the section MechaPIGEON. This design worked well, but I ran into problems after only a few days of having the feeder installed in the wild. The bird's voracious eating threw seed shells and poo all over the feeder. Often something would get under the switch and prevent it from working. Also some of the parts were not holding up well to being exposed to the elements. So I came up with version 2 OptoPIGEON which uses frame differencing to detect the presence of a bird.
Version 1: MechaPIGEON
The feeder has a pivoting perch. When a bird lands on the perch it drops down slightly to bring a magnet close to a reed switch. The magnet closes the reed switch which is read by the Raspberry Pi as a signal to turn on a web camera. The images from the web camera are displayed on a monitor.
The perches pivot on a hinge. They are counter weighted so that they are normally up when no bird is landed on them.
The top slides off. Bird seed is poured into the cylinder and comes out of two holes at the bottom.
The pieces in green are the switch mechanism. The top part is a magnet, the bottom part is where the reed switch is mounted.
I have written a simple program that runs on the Raspberry Pi to monitor the GPIO pin that the switch is connected to. When the pin value goes low the web camera is started using OpenCV. The images that come in are displayed on the screen. Eventually I would like to improve the program so that it can also work as a digital picture frame when there are no birds on the feeder. In this mode it would make a slideshow of previous bird images that would be displayed between bird events.
The most difficult part of this project was finding a way to trigger a switch when a bird lands on the feeder. We have many chickadees around our apartment and they weigh only about 10 grams (the weight of 2 quarter coins). So there is not enough force to trigger a normal switch. Also the feeder will be outdoors so any switches with exposed contacts would rust or corrode. The reed switches seem to be a good solution because they are sealed. However, they can be a little sensitive if the magnet is not in just the right position.
Feeder in window. The shiny thing is the camera that takes the bird images.
Closer view of feeder
Code:
The code for MechaPIGEON is available in the attachments section at the bottom of this page. It was written in C++ and compiled on the Raspberry Pi(Raspbian distribution). It was in an early stage of development. You will need to have OpenCV installed to use it. The GPIO pin state is read using the C library for Broadcom BCM2835 by Mike McCauley.
Version 2: OptoPIGEON
For this version, I built a simple feeder out of styrene sheets from HobbyTown. The only special feature is the backdrop. I added a white sheet of plastic to the back of the feeder for three reasons: 1. It forces the birds to land on the front or side of the feeder so they are visible in the image, 2. It creates a good background to contrast the birds in the images, 3. It makes the frame differencing easier.
Front view
Animation (Click on the image to open)
The feeder is designed to hang from a window. This is the only way to guarantee the squirrels can't get to it. Version 1 of the feeder was mounted to our windowsill. It took a while, but eventually a squirrel figured out how to scale the building up to the second floor and get to the nuts. The camera is mounted just inside the window. I upgraded to the Microsoft LifeCam Studio and it has much better image quality than my old VGA webcam.
I wrote some code in C++ using OpenCV to access the camera. The program has multiple modes:
1. Calibration mode: The camera is streamed live on the monitor. The user can define "bird zones" in the image using the mouse. The bird zones are the regions that the code will look in for the presence of birds.
2. Normal mode: The incoming frames are processed by comparing the current frame to the previous frame. If there is a difference in intensity(color) in the bird zone between the frames, then that means something has moved in the bird zone. This is called a bird event. During a bird event, the incoming frames are displayed on the screen. The frames are also stored in a circular buffer of 50 frames. So after 50 bird images they will be overwritten.
3. Review mode: If you see a good bird image that you want to save, pressing 'R' key will enter review mode. The 50 images in the buffer can be reviewed and saved permanently.
4. Slideshow mode: If there are no birds out, you can enter slideshow mode and all the previously saved bird images will be shown in a slideshow.
Bird detection using frame differencing
Bird detection is accomplished by comparing consecutive frames(images) from the camera. The color image is converted to a grayscale or intensity image. This is done to simplify some of the image processing steps. Then for each new image frame:
1. Smooth the image by replacing each pixel value with the average of all pixel values in a 7x7 window around the current pixel. See the diagram below for an example of averaging an image using a 3x3 window. It helps to remember that a digital image is made up of pixels which represent the light intensity of the image at that point. You will notice that the final average image is much "smoother" than the input image meaning there are less abrupt changes in values between neighboring pixels. Also notice that the single black pixel surrounded by white pixels has become a light gray after averaging. This is where averaging will help when we do our frame differencing.
2. Subtract the previous frame from the current frame. This means that we take the intensity value of each pixel in the previous frame and subtract it from the corresponding pixel in the current frame. So we are getting the "difference" in intensity from the previous frame and the current frame. If the camera has not moved, then a difference in intensity between frames indicates that something(such as a bird) has moved in the scene.
3. Compare the difference values within the bird zone to a threshold. There will always be some change in intensity between frames even if there is no motion in the scene. This is caused by flickering fluorescent lights, camera auto exposure adjustments, etc. Smoothing the image using averaging helps to reduce these factors. The threshold is set to a value that is just above the average difference value with no motion in the scene. When the frame difference value at a pixel is greater than the threshold, then we consider that pixel to represent something moving or something new in the scene.
4. If the difference value is greater than the threshold then the image is saved as a bird image.
Bird Detection Flowchart
Example of using averaging to smooth an image
Code:
The code that runs OptoPIGEON can be downloaded from the attachments section at the bottom of the page. The code was written in C++ and compiled on the Raspberry Pi (Raspbian distribution). You will need OpenCV installed to run it.
The commands to build it are:
cmake .
make
sudo ./pigeonBS
Note: I was experimenting with turning off and on the HDMI port automatically when there was no bird activity. So you may want to take that part of the code out before trying it.