All Sky Camera software

All sky camera software enables the user to sample the sky at periodic intervals, analyze the images for motion, and transfer the images and data to a web service. It may useful to weather watchers, amateur astronomers, and others who have an interest in observing the sky and objects as it provides and excellent way to check sky conditions at local or remote locations. The all software utilizes the OpenCV computer vision and machine learning library to capture, process, and analyze video from an all sky camera.

Details on how to install the OpenCV software are provided for recent versions of the Ubuntu® and Microsoft Windows® operating systems.

The allsky camera software will be presented in a series of examples. The first example, called "VidRecord", captures live video from an all sky camera and periodically saves the images or records to a video file. The second example, "Motion detection example" will be available shortly...

OpenCV installation notes

The following are installation notes on how to install OpenCV library on the platforms indicated.

OpenCV 2.4.2 installation for Microsoft Windows®

Installation instructions for OpenCV 2.X software for Microsoft Windows® by Bernát Gábor on the OpenCV website are very good. Just click on the "OpenCV for Windows" link at the OpenCV downloads page http://opencv.org/downloads.html If you decide to compile the source code yourself, theOpenCV2.4.2 you should use the VC++ 2010 compiler under Windows. If you are using the Visual Studio 2012 IDE do not select the option to convert the project solution to the newer version. The VC++ 2011 compiler will generate lots of errors if you do.

OpenCV installation for Ubuntu 12.04

To install OpenCV 2.4.2 or 2.4.3 on the Ubuntu 12.04 operating system, first install a developer environment to build OpenCV.

    sudo apt-get -y install build-essential cmake pkg-config

Install Image I/O libraries

    sudo apt-get -y install libjpeg62-dev 
    sudo apt-get -y install libtiff4-dev libjasper-dev

Install the GTK dev library

    sudo apt-get -y install  libgtk2.0-dev

Install Video I/O libraries

    sudo apt-get -y install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev

Optional - install support for Firewire video cameras

 sudo apt-get -y install libdc1394-22-dev

Optional - install video streaming libraries

 sudo apt-get -y install libxine-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev 

Optional - install the Python development environment and the Python Numerical library

    sudo apt-get -y install python-dev python-numpy
 

Optional - install the parallel code processing library (the Intel tbb library)

    sudo apt-get -y install libtbb-dev

Optional - install the Qt dev library

    sudo apt-get -y install libqt4-dev

Now download OpenCV 2.4 to wherever you want to compile the source.

    mkdir xxx
    cd xxx 
    wget http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.4.2/Op...
or 
   wget http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.4.3/Op...
    tar -xvf OpenCV-2.4.*.tar.bz2

Create and build directory and onfigure OpenCV with cmake. Don't forget the .. part at the end of cmake cmd !!

    cd OpenCV-2.4.*
    mkdir build
    cd build
    cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local
    -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON 
    -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON 
    -D BUILD_EXAMPLES=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..

Now compile it

    make

And finally install OpenCV

    sudo make install

OpenCV installation with Python

Python with Ubuntu

To use Python OpenCV scripts with Ubuntu be sure to install NumPy before the "cmake" phase when compiling the OpenCV source code. Ubuntu distribution includes Python so you shouldn't need to install it. See article OpenCV Installation for Ubuntu 12.04, and follow instructions in the Python section.

Python with MS Windows

To use Python with OpenCV 2.4.2 pre-compiled binaries you need to install Python version 2.7.X and NumPy version 1.6. Download Python 2.7 from http://www.python.org website and then right click on the ".exe" file and select "install as administrator". You'll also need to install the NumPy tools from http://numpy.scipy.org/ The downloads link will take you to the Numerical Python project on sourceforge.net. Be sure to download the NumPy 1.6 version for Python 2.7.

Tell your scripts where to find Python

You'll need to tell your Python scripts where to find the OpenCV. You can do that by setting the PYTHONPATH environment variable or including it in your scripts.
For Windows 7
Select menus Control Panel -> System and Security -> System and then click on the "Advanced system settings" link. Click on the "Environment variables" button near the bottom of the menu. Click the "New.." button under System for all users or User variables (for your account only) For "Variable name" enter: "PYTHONPATH" and set the "Variable value": " to where you installed OpenCV and then add "build\python\2.7"; this will be something like "C:\opencv\build\python\2.7".
For Ubuntu
Edit your .bashrc file and add  the line export PYTHONPATH=/usr/local/lib/python2.7

Video recorder example

The first example, called "VidRecord", may be used to capture live video from an all sky camera and periodically save an image or record to a video file. This relatively simple example is developed for GNU C++ on Ubuntu, Visual C++ on Microsoft Windows, and Python which will run on both MS Windows and Ubuntu. On my machine the Python example records video at 15 fps. The C++ versions running on Ubuntu and MS Windows records at 30 fps.

File names of the recorded video or images are created using current date/time in GMT when file is created.

Command line arguments:

-dis=[True|False] : Whether or not to display video frame from device on your computer screen (default is True)
-viddev=n : Select video device (default is 0, usually 0, 1, or 2)
-viddir=XXX: Set directory to store videos (default is the Videos directory in the user's home directory $HOME/Videos )
-vidint=n : Length of a video in seconds (default is 60)
-vidnum=n : Number of videos to be recorded (default is 0)
-codec=XXXX : Video codec to use when recording (default is DIVX)
-imgint=n : Interval for saving image a file in seconds (default is 60)
-imgfmt=[jpg,png,tif] : Image format to save interval image (default is jpg)
-imgdir=XXX: Set directory to store images ( defalt is Pictures direcotry in the user's home directory, $HOME/Pictures)
-imgnum=n : Number of images to be recorded (default is 0)

The user may view current video frames by adding -dis=True to the command line. Video recording is started by clicking on the display frame and pressing the 'r' key. To stop recording press 'r' again. To capture an image press the 'i' key and 'i' again to stop image capture.

Command line examples:
Record videos from video device 1 without a display, each 20 seconds long for 2 hours
VidRecord -dis=False -viddev=1 -vidint=20 vidnum=360

Capture a picure every 30 seconds from video device 2 for 1 hour
VidRecord -viddev=2 imgint=30 imglen=120

Above params may also be set in a config file called ".vidrecordrc" located in you home directory.
One parameter setting per line in the form NAME=VALUE, you may add comments by starting a line with '#'
For example...

# ----------
# Disable display of video frames on the screen
dis=False
# Capture 20 images
imgnum=20
# Capture an image each 30 second time interval
imgint=30
# Save the image in the PNG format
imgfmt=png
# ----------

Command line arguments override those loaded from the config file.

VidRecord example in C++

You may download the source code for this example. The VidRecord example software is released under terms of the Open Source Initiative BSD 2 - Clause license. Copy of the license for this software is at http://www.raben.com/sites/default/files/allsky/software/license.txt . If you have not already done so, download and install OpenCV on your local machine, see the installation notes. Unzip the VidRecordCpp.zip file somewhere in your local directory. It will create a directory called "VidRecord" containing the source files and license.

To compile on Ubuntu 12.04

unzip VidRecordCpp.zip
cd VidRecord
mkdir build
cd build
cmake ..
make
make install

To compile on MS Windows Vista or Windows 7

  • Download and install CMake from http://www.cmake.org
  • Start up CMake and set the source directory to the VidRecord directory you previously unzipped. Set the binaries directory to be just below the source in a directory called say "build", something like WHATEVER\VidRecord\build
  • Click on the "Configure" button.
  • Click on the "Build" button
  • Use Visual Studio 2010, 2011, 2012 edition if you already have it. If not, download and install MS Windows Visual Studio Express 2011 or 2012 from www.microsoft.com (Currently the free Express edition is at http://www.microsoft.com/visualstudio/eng/downloads#d-2012-express ).
  • Now run Visual Studio and then click on the "Project" button at the top and select the VidRecord\build directory and click on the project solution file.
  • Click the "Compile" button
  • Answer yes to popup to build additonal projects, ie, build-all and install
  • Note that OpenCV 2.4.2 is compatible with the VS 2010 compiler. If you are using the 2012 edition of VS, answer to "No" to dialog asking to convert project to 2012 (unless you like seeing lots of error messages)

VidRecord C++ source notes

The required includes for OpenCV are just "core" and "highgui".

#include < opencv2/core/core.hpp >
#include < opencv2/highgui/highgui.hpp >

Remainder of the includes are just standard cpp libraries for iostream, some string manipulations and time routines.

Included is simplistic class called "Config.cpp" for retrieving configuration parameters from the command line arguments or from a configuration file called (no surprise) ".vidrecordrc". It has a number overloaded function "getters" for retrieving various parameter types, int, double, bool, and string.

/**
  * Get configuration value for a parameter
  * @param name Name of the parameter
  * @param default Default value for the parameter if not set
  * @return the parameter's value as an integer
  */
int Config::getVal(string name, int defaultVal) {
	int retVal = defaultVal;

	if (vals.count(name) > 0) {
		istringstream iss(vals[name]);
		iss >> retVal;
	}

	return retVal;
}

We use get parameters previously set from command line arguments or previously loaded from a config file. For example, the configuration parameters for image writing are retrieved as follows:

    imgDir = config.getVal("imgdir", imgDir);
    imgFmt = config.getVal("imgfmt", imgFmt);
    imgInterval = config.getVal("imgint", imgInterval);
    imgNum = config.getVal("imgnum", imgNum);

We open the video device connected to our allsky camera as follows:

    // Open video device, set video frame width and height as driver often does not
    VideoCapture cap = VideoCapture(vidDevice);

    if (cap.isOpened()) {
        cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
        cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    } else {
    	cerr << "Error: Could not open video device "<< vidDevice << endl;
        return 1;   
    } 

Frames from the video device are moved to our image frame

    // Frame capture loop
    while(isEnabled) {
        cap >> frame;
        ....

We then write the frame to the video file, calculate the time interval passed and based on whether or not to create a new file:

        if (isRecordingEnabled) {
            writer.write(frame);
            vidDelta = sec - vidTime;
            cout << "vidDelta "<= "<= vidInterval) {
                isRecording = false;
                vidTotal = vidTotal + 1;
                ....
        if ((isRecordingEnabled) && (!isRecording)) {
            int width = (int)cap.get(CV_CAP_PROP_FRAME_WIDTH);
            int height = (int)cap.get(CV_CAP_PROP_FRAME_HEIGHT);
            writer = createVideoFile(vidDir, width, height, vidFps, fourcc, sec);
            vidTime = sec;
            isRecording = true;
            frameNum = 0;
        }

The "createVideoFile function creates a new VideoWriter object that starts writing passing it a file name with current time stamp.

VideoWriter createVideoFile(String vidDir, int width, int height, int fps, int fourcc, time_t sec) {

    string timeStr = currentTimeString(&sec);
    string fileName = vidDir + timeStr + ".avi";
	cout << "Video file name = " << fileName << endl;
	Size frameSize = Size(width, height);
    VideoWriter vidWriter = VideoWriter(fileName, fourcc, fps,
        frameSize);
	return vidWriter;
}

The "currentTimeString" function uses the current time in seconds and uses the gmtime function to return the current time.

string currentTimeString(time_t *sec) {
    struct tm *ptm = gmtime (sec);
    ostringstream ostr;
    ostr<tm_year + 1900)<< "-" << setw(2)<< (ptm->tm_mon+1)
            << "-" << setw(2)<tm_mday << "T"<tm_hour
            << "h" <tm_min << "m" << setw(2) << ptm->tm_sec;
    return ostr.str();
}

The writeImageFile uses the cuirrentTimeString as well to create new png, jpg, tiff, etc image files at periodic intervals. Logic as to when to write them is very similar to how its done for video. See source code referenced above for details.

VidRecord example in Python

You may download the source code for this example. Software is released under terms of the Open Source Initiative BSD 2 - Clause license. Copy of the license for this software is at http://www.raben.com/sites/default/files/allsky/software/license.txt .

Required imports are:

import argparse
import os
import time
from cv2 import *

You need to define the following properties to record video as they seem to be
missing in the OpenCV 2.4.2 python module.

CV_CAP_PROP_FRAME_WIDTH = 3
CV_CAP_PROP_FRAME_HEIGHT = 4

Also the CV_FOURCC function is not defined in the OpenCV 2.4.2 python module.

def CV_FOURCC(c1, c2, c3, c4) :
    return (c1 & 255) + ((c2 & 255) << 8) + ((c3 & 255) << 16) + ((c4 & 255) << 24)

Here is a function to create a video file named with the time stamp of when its created

def createVideoFile(path, width, height, fps ,fourcc,tsec):
    filename = time.strftime("%Y-%m-%dT%Hh%Mm%Ss", time.gmtime(tsec))
    pathname = os.path.join(path,filename) + ".avi"
    print "Create video file "+pathname
    writer = VideoWriter(pathname, fourcc, fps,(width,height))
    return writer;

And a function to write an image file

def writeImageFile(path, tsec, frame):
    filename = time.strftime("%Y-%m-%dT%Hh%Mm%Ss", time.gmtime(tsec))
    pathname = os.path.join(path,filename) + "." + imageFmt
    print "Create image file "+pathname
    imwrite(pathname, frame)

To get started we set the default video and image directories to store videos and images. These may be overridden by command line arguments.

videoDir = os.path.join(os.getenv("HOME","."),"Videos")
imageDir = os.path.join(os.getenv("HOME","."),"Pictures")

We can use Python's nifty ArgumentParser class to set up defaults and parse the command line.

parser = argparse.ArgumentParser()
parser.add_argument("-dis","--dis", help="Display video frame (set DIS to True or False)",default=True)
parser.add_argument("-viddir","--viddir",help="Set directory to save videos", default=videoDir)
parser.add_argument("-viddev","--viddev",help="Select video device number (usually 0 or 1, defailt is 0)",type=int,default = 0) 
parser.add_argument("-vidint","--vidint",help="recording interval in sec (default=0)",type=int,default=60)
parser.add_argument("-vidnum","--vidnum",help="number of videos to record default is 1",type=int,default=0)
parser.add_argument("-codec","--codec",help="Set recording codec MJPG,PIM1,MP42,U263,I263,FLV1 default is DIVX (mpeg4)",default="DIVX")
parser.add_argument("-vidfps", "--vidfps", help="Set recording fps", type=int, default=30)
parser.add_argument("-imgfmt","--imgfmt",help="Set video image format [jpg, png, tiff]",default="jpg")
parser.add_argument("-imgint","--imgint",help="Set interval between images (sec)", type=int,default=60)
parser.add_argument("-imgdir", "--imgdir", help="Set directory to save images",default=imageDir)
parser.add_argument("-imgnum", "--imgnum", help="Number of images to take", type=int, default=0)
args = parser.parse_args()

The argument values can be accessed through the "args" variable returned by the parser, for example args.dis, args.vidfps, etc. We use these to initialize some variables.

Now calculate the fourcc value from codec specified.; by default the codec is "DIVX"

codecArr = list(args.codec)
fourcc = CV_FOURCC(ord(codecArr[0]),ord(codecArr[1]),ord(codecArr[2]),ord(codecArr[3]))

Then open the video device to which the camera is connected. Its necessary to set width and height as some device drivers default to a only a frame which is only a few pixels in width and height.

cap = VideoCapture(videoDevice)
if cap.isOpened():
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 640)
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480)
else:
    exit    

A video frame is transferred to a image matrix by simply:

cap >> frame;

Frames are transferred from the VideoCapture class to an image matrix called "frame" on each pass through the loop.

To control everything the current time in seconds since 1970 is obtained by the following call.

sec = time.time()

The createVideoFile or writeImageFile functions are called at the proper intervals by checking the difference between current time and last time the file was written. Here is some of the code inside the loop for calling the writeImageFile function.

    if isImageEnabled:
        imageDelta = sec - imageTime
        
        if (imageDelta >= imageInterval):
            writeImageFile(imageDir, sec, frame)
            imageTime = sec
            imageTotal = imageTotal + 1
            if (imageTotal >= imageNum):
                isImageEnabled = False

The code for creating the image file is similar. See source code file referenced above for more details.

Motion detection example (not yet available)

Coming soon, please check back in a few days.

Motion analysis example (not yet available)

Future article, not yet available.

All sky camera calibration example (not yet available)

Not yet available

Image and data upload example (not yet available)

Coming soon ??