some camera advice/findings
Posted: Thu Sep 24, 2015 11:26 pm
Hi, I've been working a lot with camera setups lately and thought I would share a bit.
I've been accessing the cameras directly using libUVC and this has taught me a few important things:
1. Each camera decides what matrix of { resolution , compression, framerate } it supports. The matrix may be sparse!
2. Low-quality cameras support only uncompressed frames, which quickly eat up the USB bus bandwidth, even at 480Mbit/sec since apparently the host controller doesn't allow the entire 480mbit/sec to be isochronously allocated. Right now I can easily run four cameras (three at 640x480, one at 1600x1200, all at 30fps if desired) over a single USB 2.0 cable through the dragchain, so long as all of them use MJPEG compression. But every single camera must support MJPEG; if even one of them forces uncompressed frames then it will lock all the others out of the bus (on linux: usb_submit_urb returned -28). The numbers say this shouldn't happen, so I think the low-quality cameras (see next point) are buggy and allocate way more bandwidth than they need.
3. Low-quality cameras support only one framerate, usually 30fps, which can be a real waste of USB bandwidth or CPU power (USB puts a very heavy burden on the host CPU).
4. Lower framerates give longer exposure times and therefore better image quality using a given amount of light. In particular, you want very low framerates on the downcam.
5. You definitely need to lock out the camera's auto-exposure and auto-framerate mechanisms to get consistent images; libUVC lets you do this, not sure if other APIs do.
As I've mentioned before, my favorite camera by far is still the Andonstar originally recommended by @thereza. It does 1600x1200 with MJPEG compression and has a very high-quality focus knob mechanism. It seems to cost around $80-$100 in the US. Be careful, though, there are a LOT of cheap knockoffs! I bought one for $25 and found out it only supported uncompressed video at 30fps! This is totally useless since it basically hogs the entire USB bus to itself.
My second-favorite camera is the Logitech HD Webcam C270, which is not quite as good as the Andonstar, but it is insanely cheap at only $22 in the US. I bought four of them! If you unscrew the plastic cover you'll find that it actually has a focus lens inside that the user can't normally access! After adjusting this it's possible to get a very wide focus range, and the camera is very flat (after you rip off the plastic housing) so it makes a fantastic up-looking camera. You do need to disable the annoying green LED though, otherwise you'll see it in reflections on shiny parts (see upper-right quadrant in image below for an example). Having a good upcam matters for fine-pitch parts: you need a camera with pixel resolution much higher than the mechanical resolution of the XYZ axes to get <0.5 degree rotational correctness.
And it does 1280x720 with MJPEG compression at 30fps -- definitely the least expensive camera that can do that, by a very wide margin. I apologize if somebody else mentioned this camera here first; I definitely remember first hearing about it on a PNP forum but I don't think it was this one (I could be wrong!). Finally, each camera has a unique USB iSerial number, so the software can robustly know which camera is which, even across reboots or hub topology changes.
Now I have a four-camera setup, shown below.
The two standard cameras are:
- downcam: high-resolution Andonstar downcam (lower-right)
- upcam: Logitech C270 (upper-right)
To this I have added two other cameras:
- plancam: Logitech C270 (upper-left)
- needlecam: Logitech C270 (lower-left)
The needlecam is strictly for debugging and checking component placement; no vision operations ever happen through this camera. It's very very helpful for debugging placement problems, and in the future I may decide to snap a photo of every placement to see if misalignments are the result of misplacement or rather from shifting during reflow.
The plancam is mounted to the gantry head, on the very short piece of extrusion that runs between the front and back plates of the gantry head. It's as high up as possible giving it the widest possible field of vision. On startup my software homes the device and then quickly "scans" the head across the build area to collect a single huge stitched image of the entire workspace. This stitched image is then updated incrementally; whenever the head passes over a region, whatever part of it the plancam can see is updated. This giant stitched image is then displayed in the UI, and the user can pick and select various things (components, tapes, solderball reservoirs, etc) by zooming and clicking on parts of the gigantic stitched image without having to move the head.
The three head-mounted cameras (downcam, plancam, and needlecam) all run to a USB hub strapped to the back of the placement head, and through this they share a single USB 2.0 cable running down the dragchain.
The images you see are rendered live at full framerate using DirectFB. At 30fps on all four cameras using MJPEG it takes almost 40% of one core of a very powerful 2.4ghz Intel Xeon to just get the images off the cameras, decompressed, and onto the screen (although I can run the downcam at 1600x1200@30fps, in practice I use 5fps to get a longer exposure time). This is why I eventually gave up on having the CPU near the placer... now I use an eight-core rackmount server with an OpenCL GPGPU for image processing, but it's so loud and noisy I have to put it in another room. Fortunately USB 2.0 (for control) and HDMI (for the image display to the user) can run pretty long distances using digital repeaters, although threading those wires through the walls was a real hassle. So now the liteplacer, screen, and trackball sit next to the user in one room, and all the wires run through the wall to the machine that actually does all the thinking.
I'm pretty happy with it. My only disappointment is that I have been totally unable to find any software that supports the USB UVC "take snapshot" command (VS_STILL_IMAGE_TRIGGER_CONTROL). Linux's V4L and libuvc definitely don't support it. Most libraries/applications instead turn on video streaming, grab one frame, then turn streaming off. The problem is that in streaming mode the camera is continuously sampling the pixels as they are read out in scan-order, so if the head is moving you'll get a warped image. The camera does this to maximize the exposure time per pixel: each pixel is exposed for a full frame-time, but the exposure times are staggered according to the scan-out. This makes sense for video, where maximum exposure time means best image quality for a given illumination level. But if the camera or scene is in rapid motion and you want a still image this is the wrong strategy, which is why the "snapshot" command exists. The "snapshot" command tells the camera to capture all pixels simultaneously, then read out the captured pixels. So you can get non-warped images from a moving head this way. But there doesn't seem to be any software that supports it, just lots of software that claims to but really uses the streaming commands behind your back Also the Logitech camera purportedly can take snapshots at 3x higher resolution than its video capture.
I've been accessing the cameras directly using libUVC and this has taught me a few important things:
1. Each camera decides what matrix of { resolution , compression, framerate } it supports. The matrix may be sparse!
2. Low-quality cameras support only uncompressed frames, which quickly eat up the USB bus bandwidth, even at 480Mbit/sec since apparently the host controller doesn't allow the entire 480mbit/sec to be isochronously allocated. Right now I can easily run four cameras (three at 640x480, one at 1600x1200, all at 30fps if desired) over a single USB 2.0 cable through the dragchain, so long as all of them use MJPEG compression. But every single camera must support MJPEG; if even one of them forces uncompressed frames then it will lock all the others out of the bus (on linux: usb_submit_urb returned -28). The numbers say this shouldn't happen, so I think the low-quality cameras (see next point) are buggy and allocate way more bandwidth than they need.
3. Low-quality cameras support only one framerate, usually 30fps, which can be a real waste of USB bandwidth or CPU power (USB puts a very heavy burden on the host CPU).
4. Lower framerates give longer exposure times and therefore better image quality using a given amount of light. In particular, you want very low framerates on the downcam.
5. You definitely need to lock out the camera's auto-exposure and auto-framerate mechanisms to get consistent images; libUVC lets you do this, not sure if other APIs do.
As I've mentioned before, my favorite camera by far is still the Andonstar originally recommended by @thereza. It does 1600x1200 with MJPEG compression and has a very high-quality focus knob mechanism. It seems to cost around $80-$100 in the US. Be careful, though, there are a LOT of cheap knockoffs! I bought one for $25 and found out it only supported uncompressed video at 30fps! This is totally useless since it basically hogs the entire USB bus to itself.
My second-favorite camera is the Logitech HD Webcam C270, which is not quite as good as the Andonstar, but it is insanely cheap at only $22 in the US. I bought four of them! If you unscrew the plastic cover you'll find that it actually has a focus lens inside that the user can't normally access! After adjusting this it's possible to get a very wide focus range, and the camera is very flat (after you rip off the plastic housing) so it makes a fantastic up-looking camera. You do need to disable the annoying green LED though, otherwise you'll see it in reflections on shiny parts (see upper-right quadrant in image below for an example). Having a good upcam matters for fine-pitch parts: you need a camera with pixel resolution much higher than the mechanical resolution of the XYZ axes to get <0.5 degree rotational correctness.
And it does 1280x720 with MJPEG compression at 30fps -- definitely the least expensive camera that can do that, by a very wide margin. I apologize if somebody else mentioned this camera here first; I definitely remember first hearing about it on a PNP forum but I don't think it was this one (I could be wrong!). Finally, each camera has a unique USB iSerial number, so the software can robustly know which camera is which, even across reboots or hub topology changes.
Now I have a four-camera setup, shown below.
The two standard cameras are:
- downcam: high-resolution Andonstar downcam (lower-right)
- upcam: Logitech C270 (upper-right)
To this I have added two other cameras:
- plancam: Logitech C270 (upper-left)
- needlecam: Logitech C270 (lower-left)
The needlecam is strictly for debugging and checking component placement; no vision operations ever happen through this camera. It's very very helpful for debugging placement problems, and in the future I may decide to snap a photo of every placement to see if misalignments are the result of misplacement or rather from shifting during reflow.
The plancam is mounted to the gantry head, on the very short piece of extrusion that runs between the front and back plates of the gantry head. It's as high up as possible giving it the widest possible field of vision. On startup my software homes the device and then quickly "scans" the head across the build area to collect a single huge stitched image of the entire workspace. This stitched image is then updated incrementally; whenever the head passes over a region, whatever part of it the plancam can see is updated. This giant stitched image is then displayed in the UI, and the user can pick and select various things (components, tapes, solderball reservoirs, etc) by zooming and clicking on parts of the gigantic stitched image without having to move the head.
The three head-mounted cameras (downcam, plancam, and needlecam) all run to a USB hub strapped to the back of the placement head, and through this they share a single USB 2.0 cable running down the dragchain.
The images you see are rendered live at full framerate using DirectFB. At 30fps on all four cameras using MJPEG it takes almost 40% of one core of a very powerful 2.4ghz Intel Xeon to just get the images off the cameras, decompressed, and onto the screen (although I can run the downcam at 1600x1200@30fps, in practice I use 5fps to get a longer exposure time). This is why I eventually gave up on having the CPU near the placer... now I use an eight-core rackmount server with an OpenCL GPGPU for image processing, but it's so loud and noisy I have to put it in another room. Fortunately USB 2.0 (for control) and HDMI (for the image display to the user) can run pretty long distances using digital repeaters, although threading those wires through the walls was a real hassle. So now the liteplacer, screen, and trackball sit next to the user in one room, and all the wires run through the wall to the machine that actually does all the thinking.
I'm pretty happy with it. My only disappointment is that I have been totally unable to find any software that supports the USB UVC "take snapshot" command (VS_STILL_IMAGE_TRIGGER_CONTROL). Linux's V4L and libuvc definitely don't support it. Most libraries/applications instead turn on video streaming, grab one frame, then turn streaming off. The problem is that in streaming mode the camera is continuously sampling the pixels as they are read out in scan-order, so if the head is moving you'll get a warped image. The camera does this to maximize the exposure time per pixel: each pixel is exposed for a full frame-time, but the exposure times are staggered according to the scan-out. This makes sense for video, where maximum exposure time means best image quality for a given illumination level. But if the camera or scene is in rapid motion and you want a still image this is the wrong strategy, which is why the "snapshot" command exists. The "snapshot" command tells the camera to capture all pixels simultaneously, then read out the captured pixels. So you can get non-warped images from a moving head this way. But there doesn't seem to be any software that supports it, just lots of software that claims to but really uses the streaming commands behind your back Also the Logitech camera purportedly can take snapshots at 3x higher resolution than its video capture.