UVC Camera Control for Mac OS X
For a recent computer vision project I needed to pull images out of a Logitech QuickCam 9000 and track some markers with the help of the ARToolKitPlus library. I connected the camera to my Mac and was quite surprised to see that it just works. There was no need to install any drivers. As I learned later, that's because the QuickCam 9000 is a UVC webcam for which Mac OS X 10.4.9 already provides a driver. I was able to get to the raw camera images through the QTKit Framework in no time.
However, the QuickCam 9000 has its auto exposure enabled by default, which is absolutely deadly for stable tracking results. I thought I could just turn the auto exposure off and set it to a fixed value through some QTKit API – but no, there's no way to change the exposure of a UVC camera with QTKit. In fact, there's no way to change any parameters of your camera. No exposure values, no white balance, no gain, nothing. Apple just implemented the bare minimum in its UVC driver and the QTkit Framework.
Well, maybe I could get to these parameters through the older Sequence Grabber Framework then? After all, there's a
VDIIDCSetFeatures function and a
vdIIDCFeatureExposure key! But nope, as the name implies, this stuff only works for IIDC cameras. What's an IIDC camera? Wil Shipley asked the same questions almost 3 years ago - even back then, IIDC cameras were pretty much deprecated. Still, these cameras are the only devices that Apple provides an API for, if you want to change some esoteric parameters no one would ever need to change, like oh, the exposure time or white balance temperature for instance.
Apple is aware of the problem but hasn't done anything to solve it. And Logitech apparently doesn't see the need to provide a Mac driver for their cameras, since Mac OS X already ships with one. Great.
But wait, UVC is a standard, right? USB.org provides a documentation for all device classes, and the Video Class is no exception. So, I poked around in the documentation for a while, read some Linux UVC driver sourcecode and used Apple's USB Prober to see what's going on. After some more hours of playing around with the Kernel Framework's USB API, I was finally able to control some of the QuickCam's settings!
I've now cleaned up the source a bit and organized everything in a UVCCameraControl class. You can use it like this:
UVCCameraControl * cameraControl = [[UVCCameraControl alloc] initWithVendorID:0x046d productID:0x0990]; [cameraControl setAutoExposure:NO]; [cameraControl setExposure:0.9]; [cameraControl release];
All the input values are normalized. Before setting a value the UVCCameraControl class asks the device for the
max value for that setting and maps the input value accordingly. So exposure, gain, brightness, contrast, saturation, sharpness and white balance all accept values from 0.0 to 1.0.
In this example, VendorID and ProductID are the ones of the Logitech QuickCam 9000. You can use the USB Prober to find the values of your camera. In theory, the UVCCameraControl class should work with all UVC compatible cameras. However, I wasn't able to control the built-in iSight of my MacBook Air at all and I don't have any other cameras to test this with. So all I know at this moment, is that it works with the QuickCam. I've also only implemented those controls that are supported by the QuickCam – other cameras might not support all of these, or might support additional ones.
Note that you only have access to the camera if it is not in use by another process. This means you can't change the camera's settings while using it in iChat or other applications. My understanding is that if you'd want to do that, you'd have to write a Kernel Extension. The UVCCameraControl class is only useful for you, if you use the camera in your own application. So if you're doing blob tracking or marker detection or any other computer vision stuff, this probably is what you're looking for.
I also built a simple demo application that makes use of the UVCCameraControl class. This demo uses QTKit to open a connection to the first (default) video device and simply displays the images in a QTCaptureView. There's no system setting to select the default video device, however the device you selected to use in iChat will be the default (you have to quit iChat after selecting your camera, otherwise it will be locked for all other applications).
The controls currently supported by the UVCCameraControl class are:
- (BOOL)setAutoExposure:(BOOL)enabled; - (BOOL)getAutoExposure; - (BOOL)setExposure:(float)value; - (float)getExposure; - (BOOL)setGain:(float)value; - (float)getGain; - (BOOL)setBrightness:(float)value; - (float)getBrightness; - (BOOL)setContrast:(float)value; - (float)getContrast; - (BOOL)setSaturation:(float)value; - (float)getSaturation; - (BOOL)setSharpness:(float)value; - (float)getSharpness; - (BOOL)setAutoWhiteBalance:(BOOL)enabled; - (BOOL)getAutoWhiteBalance; - (BOOL)setWhiteBalance:(float)value; - (float)getWhiteBalance;
Consider this as public domain. Do whatever you want with it. I'm not responsible if your camera explodes or for any other damages this software might cause!