Although installing OpenCV on the Raspberry Pi was made very easy by Arch Linux (see previous blog post), persuading OpenCV to capture images from my webcam was substantially harder. But, eventually I managed to get it working. Here's how.
My first attempt followed a sample program found on Stack Overflow. But what I found was that I was repeatedly receiving
select timeout errors on the
cv.QueryFrame(...) call. I also received 3
VIDIOC_QUERYMENU: Invalid argument errors every time I called
Xlib: extension "RANDR" missing on display "localhost:10.0" the first time that I called
cv.NamedWindow(...). Following those errors, the captured frame was displaying as a black screen, so I assumed that one of them was fatal.
It turns out that 2 of the 3 errors are simply warnings, and can be ignored. Those are the
RANDR ones. The interesting error is
select timeout, which it turns out is intermittent - if you wave the camera around, occasionally a frame grab is successful and is captured. Eventually, I realised (having had problems with really slow captures in other webcam apps on the Pi, at full resolution) that maybe the error was accurate, and it was just being too slow.
Sure enough, when I reconfigured my OpenCV capture to use a lower resolution (320x240), I got perfect captures and no more select timeouts. The Python2 code that I used to achieve this is shown below. Just displaying the captured frames, I get approximately 4 frames per second in good light, with the Pi running close to 100% CPU. The picture at the start of this post is a self-portrait of the Pi, taken via this code. When running with the full processing (greyscale, blur and edge detection) I get an average of 1.5 FPS.