OpenCV and Python
The next best bet looked to be the open source library OpenCV (originally Intel’s Open Source Computer Vision library), which has a choice of Python interfaces. At the time of writing, the current release is OpenCV 2.3.1 (August 2011), prior to that v2.3.0 (July 2011), and v2.2.0 (December 2010). That seems pretty current - so how can I call it from Python?
It turns out there are several (defunct) interfaces for OpenCV from Python. One of the older ones was ctype-opencv which used Python's ctypes library to give access to (some of) OpenCV. Looking at their source repository, the last commit was in 2009, so the library seems dead.
Later project PyOpenCV tried to address weaknesses in wrapping OpenCV's C++ seen in swig or ctypes-based approaches, and instead uses Boost.Python for interoperability between C++ and Python. However, the latest release is from September 2008, PyOpenCV v1.2.0 for OpenCV v2.1.0 (which is now quite out of date). There is an open issue for updating PyOpenCV to work with OpenCV v2.2.x, where a year ago (Jan 2011) developer Minh Tri talks about the alternative Python bindings being provided with OpenCV itself, and waiting to see how things pan out. It looks like PyOpenCV is also dead.
All is not lost though. Looking over the OpenCV release notes, it seems they have their own Python interfaces - an older one called cv, and a more recent C++ style one called cv2. Since this is part of OpenCV, it seems like my best bet. Specifically their VideoCapture class.
Installing OpenCV on Mac OS X
First the source code OpenCV-2.3.1a.tar.bz2 doesn't come with an INSTALL text file, they point you at the website - I found the OpenCV install instructions here which linked to another page with Mac specific guidelines (confusingly full of historical information for out dated OpenCV releases).
The first hurdle was installing CMake 2.6 or later, which thankfully comes with Mac binaries - so that was easy. Now unzip the tar ball and change to that directory, then:
$ cd OpenCV-2.3.1That worked smoothly on Mac OS X 10.7 "Lion", and the Apple provided Python 2.6.
$ mkdir build
$ cd build
$ cmake -G "Unix Makefiles" ..
$ sudo make install
Using OpenCV in Python
If everything went smoothly with the OpenCV install, and you have a camera installed, then this should work in Python:
>>> import cv2So far so good... that turned on my built in FaceTime camera (green LED on), grabbed a single image, and then turned it off (LED off), and saved the image to disk. When I have a USB camera plugged in as well, using device 0 or 1 seems to work, and I've captured test images from both.
>>> vidcap = cv2.VideoCapture()
>>> retval, image = vidcap.retrieve()
Cleaned up camera.
>>> cv2.imwrite("test.png", image)
As a bonus, the images are the right way round - using Apple's Photo Booth application gives me mirror images with left/right swapped.
I haven't worked out how the device numbers get assigned yet - device zero may depend on what was last used? I think there should be away to get the device name associated with this index. From experiment using 0 to 99 seemed to work differently from 100 or more. Reading the source code file
modules/highgui/src/cap.cppthere is a comment that you can add multiples of 100 to the camera index to select an API (if the camera supports more than one). Looking deeper, on the Mac it looks like they use the QuickTime API via
modules/highgui/src/cap_qt.cppand this has some debug code which looks at the device name - but does not seem to provide the device name to the calling code.
The API style of the cv2 library isn't very Pythonic. Calling function methods and getting return codes rather than a Python exception is much more C or C++ style. Also the library seems to print lots of messages to screen (probably to stderr, I haven't checked) where using Python's warning library would be more elegant. But it works, and ought to be cross platform too (Mac OS X, Linux and Windows).
For this to be useful for astrophotography, I'm going to need to work out how to control things like the automatic exposure control and the gain, and how to capture save images at a good frame rate.
The bad news is that under Mac OS X, OpenCV doesn't seem to support accessing or setting things like brightness, contrast, saturation, hue, gain, or exposure. There is a comment to this effect in
modules/highgui/src/cap_qt.cpp, capture properties currently unimplemented for QuickTime camera interface, which clinches it. This harks back to the QTKit capture API limitations I mentioned on my last post. It looks like for a Mac solution with full control over the camera settings, we either have to wait for Apple to fix their QTKit API, or do it via the UVC interface (which isn't so straightforward).