Stephen Crampton wrote:
Mark,
A few additional questions:
The Windows driver supports compression, which allows for a much higher
frame rate. The Linux driver does too, but you'll need to get the latest
stable version (1.62) from http://alpha.dyndns.org/ov511/ . After
compiling the driver, you need to:
insmod ov511.o compress=1
insmod ov511_decomp.o
Then check dmesg. If the driver reports that your camera has an OV7620
sensor, you should be able to get 30 FPS at up to 352x288, and 10-15 FPS
at 640x480. If it says you have something else, the frame rate may be lower.
FYI, dmesg reports a USB OV511+ video device found, "Sensor is an OV7620."
When I use the compression as you suggest, there are faint, but noticeable
squares throughout the image. They look like artifacts of the compression
scheme.
Correct. The quantization that's done during compression causes those
artifacts. The blocks are 8x8 for the Y channel and 16x16 for the U/V
channels.
Are there options that affect how the compression is done? I
would be willing to trade frame rate for image quality.
There are some options in registers 0x70 - 0x77, but I'm not quite sure
what they do, if anything. Your best option is probably to upload a
different quantization table. This is defined in ov511.h. It's also
defined in the DeZigZag section of ov511_decomp.c, as crude bit-shifts.
In fact, rewriting the dequantization code as a loop that multiplies
image elements by their corresponding quantization table elements would
probably improve the image quality a bit, at the expense of
decompression speed.
Decreasing the quantization values will result in less image information
being lost.
If I could
achieve a consistent 15 fps with decent image quality, I would be
satisfied. Currently, I'm getting a highly variable frame rate that jumps
between about 20 to 37 fps (the rate is measured each frame so it reflects
the time between the current and previous frames).
Unfortunately, I don't think there's any way around that, other than by
dropping frames (either in the camera or in your app). Since the data
are compressed with a fixed quantization table, the compressor can't
auto-adjust the compression level to maintain a constant frame rate.
Even cameras that can do that don't do it all that well, since it takes
at least one frame for the change to take effect.
The newer drivers (2.01+) and the driver in the 2.5 kernel don't support
RGB/BGR any more. You might want to capture VIDEO_PALETTE_YUV420P images
instead, and use the conversion code that's in the 1.62 driver
(yuv420p_to_rgb()) to do the conversion in user-space. That will work
with the 1.xx drivers too.
Do you mean to say that the RGB format is supplied by the driver?
In 1.62, yes. In 2.xx, no. That functionality was intentionally removed.
I thought that was the native mode of the hardware.
The OV7620 can output the image data as GBR 4:2:0, but that's a pretty
awkward format to support. Neither V4L nor V4L2 (nor any existing app /
file format) supports it, so I use YUV 4:2:0 instead. Converting YUV to
RGB isn't difficult at all, especially in user-space, so this doesn't
cause much of a problem.
Also, I thought I heard
somewhere that there were video cameras that perform compression on the
CCD chip itself, in parallel, much more efficiently than in software.
I haven't heard of that. Not sure of how it would work, but sounds
interesting.
I'm doing research in computer vision, and I would prefer that technical
issues, such as acquisition of images, take as few resources as possible.
What I'm getting at is, What's the most efficient way of doing things that
would be forward compatible? Is YUV420P the native mode of the
chip? Given my requirements, would that be your recommendation?
YUV420P is the most forward-compatible, since it's the only
non-greyscale format that the driver in the 2.5 supports now. It's also
more convenient since your algorithm could drop the U/V data if it
noticed high system load or that it was getting too lagged.
Also, the image freezes briefly every so often. Do you have
recommendations for how to keep the frame rate more or less constant? I
have implemented the double-buffering you suggested. I tried implementing
a frame queue, but I think it adds a lot of overhead as well as a time
lag. Since I'm interesting in using video input to control the computer,
I would prefer to minimize the time lag.
I suspect the lag is caused by some process taking more than its fair
share of CPU time. The preemptive and low-latency kernel patches may
help, as well as increasing your process's priority.
One other point regarding compression and image quality. From my
standpoint, the important issue is consistency from frame to frame, so I
can, e.g., track objects. I use brightness (e.g., grayscale images) for
most of my routines, but sometimes I am interested in color (e.g., skin
color). If I could get much better performance, I might opt for grayscale
images from the camera. (This would be pointless, however, if the camera
always sends color and the driver merely converts the images to
grayscale.)
If your app selects VIDEO_PALETTE_GREY, the camera will be programmed to
send greyscale data only. This results in a noticable frame rate
improvment. Unfortunately that feature wasn't working with the OV7620
last time I checked, but I can try to fix it if you need it.
Like I said previously, I don't need 30fps, but 4 fps is a bit low.
Somewhere in the middle would be ideal.
I hate to say it, but for this type of application, a USB camera is
never going to work all that well. USB 1.1 simply doesn't have very much
bandwidth, nor do most CMOS-based USB cameras have very good image
quality. Your best bet might be to get a cheap PCI Bt8xx frame grabber
card and a decent CCD camera.
That said, I'm willing to help you get your current setup working as
best I can. Let me know if you have any further questions.
--
Mark McClelland
mark@xxxxxxxxxxxxxxxx