I'm using openCV 1.1pre1 under Windows (videoinput library is used by default by this version of openCv under windows).
With these instructions I can set camera resolution. Note that I call the old cvCreateCameraCapture instead of cvCaptureFromCam.
capture = cvCreateCameraCapture(cameraIndex);
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 640 );
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 480 );
videoFrame = cvQueryFrame(capture);
I've tested it with Logitech, Trust and Philips webcams
That was actually interesting question that I had myself.
The results I managed to obtain suggest slightly different reasons for performance loss than 'fixed' statement itself.
You can see the tests I run and the results below but there are following observations I draw from those:
- the performance of using 'fixed' with pure pointers (x*), without IntPtr, is as good as in managed code; in Release Mode, it is even way better if fixed is not used too often - that's the most performent way of accessing multiple array values
- in Debug Mode, using 'fixed' (inside a loop) has big negative performance impact but in Release Mode, it works almost as good as normal array access (method FixedAccess);
- using 'ref' on a reference-type parameter value (float[]) was consistently more or equally performant (both modes)
- Debug Mode has significant performance drop vs Release Mode when using IntPtr arithmetic (IntPtrAccess) but for both modes the performance was worse than normal array access
- if using using offset not aligned to the array's values' offset, the performance is terrible, regardless of the mode (it actually takes the same amount of time to for both modes). That holds true for 'float' but has no impact for 'int'
Running the tests multiple times, gives slightly different but broadly consistent results. Probably I should have ran many series of tests and take the average times - but had no time for that :)
The test class first:
class Test {
public static void NormalAccess (float[] array, int index) {
array[index] = array[index] + 2;
}
public static void NormalRefAccess (ref float[] array, int index) {
array[index] = array[index] + 2;
}
public static void IntPtrAccess (IntPtr arrayPtr, int index) {
unsafe {
var array = (float*) IntPtr.Add (arrayPtr, index << 2);
(*array) = (*array) + 2;
}
}
public static void IntPtrMisalignedAccess (IntPtr arrayPtr, int index) {
unsafe {
var array = (float*) IntPtr.Add (arrayPtr, index); // getting bits of a float
(*array) = (*array) + 2;
}
}
public static void FixedAccess (float[] array, int index) {
unsafe {
fixed (float* ptr = &array[index])
(*ptr) = (*ptr) + 2;
}
}
public unsafe static void PtrAccess (float* ptr) {
(*ptr) = (*ptr) + 2;
}
}
And the tests themselves:
static int runs = 1000*1000*100;
public static void Print (string name, Stopwatch sw) {
Console.WriteLine ("{0}, items/sec = {1:N} \t {2}", sw.Elapsed, (runs / sw.ElapsedMilliseconds) * 1000, name);
}
static void Main (string[] args) {
var buffer = new float[1024*1024*100];
var len = buffer.Length;
var sw = new Stopwatch();
for (int i = 0; i < 1000; i++) {
Test.FixedAccess (buffer, 55);
Test.NormalAccess (buffer, 66);
}
Console.WriteLine ("Starting {0:N0} items", runs);
sw.Restart ();
for (int i = 0; i < runs; i++)
Test.NormalAccess (buffer, i % len);
sw.Stop ();
Print ("Normal access", sw);
sw.Restart ();
for (int i = 0; i < runs; i++)
Test.NormalRefAccess (ref buffer, i % len);
sw.Stop ();
Print ("Normal Ref access", sw);
sw.Restart ();
unsafe {
fixed (float* ptr = &buffer[0])
for (int i = 0; i < runs; i++) {
Test.IntPtrAccess ((IntPtr) ptr, i % len);
}
}
sw.Stop ();
Print ("IntPtr access (fixed outside loop)", sw);
sw.Restart ();
unsafe {
fixed (float* ptr = &buffer[0])
for (int i = 0; i < runs; i++) {
Test.IntPtrMisalignedAccess ((IntPtr) ptr, i % len);
}
}
sw.Stop ();
Print ("IntPtr Misaligned access (fixed outside loop)", sw);
sw.Restart ();
for (int i = 0; i < runs; i++)
Test.FixedAccess (buffer, i % len);
sw.Stop ();
Print ("Fixed access (fixed inside loop)", sw);
sw.Restart ();
unsafe {
fixed (float* ptr = &buffer[0]) {
for (int i = 0; i < runs; i++) {
Test.PtrAccess (ptr + (i % len));
}
}
}
sw.Stop ();
Print ("float* access (fixed outside loop)", sw);
sw.Restart ();
unsafe {
for (int i = 0; i < runs; i++) {
fixed (float* ptr = &buffer[i % len]) {
Test.PtrAccess (ptr);
}
}
}
sw.Stop ();
Print ("float* access (fixed in loop)", sw);
and finally the results:
Debug mode
Starting 100,000,000 items
00:00:01.0373583, items/sec = 96,432,000.00 Normal access
00:00:00.8582307, items/sec = 116,550,000.00 Normal Ref access
00:00:01.8822085, items/sec = 53,134,000.00 IntPtr access (fixed outside loop)
00:00:10.5356369, items/sec = 9,492,000.00 IntPtr Misaligned access (fixed outside loop)
00:00:01.6860701, items/sec = 59,311,000.00 Fixed access (fixed inside loop)
00:00:00.7577868, items/sec = 132,100,000.00 float* access (fixed outside loop)
00:00:01.0387792, items/sec = 96,339,000.00 float* access (fixed in loop)
Release mode
Starting 100,000,000 items
00:00:00.7454832, items/sec = 134,228,000.00 Normal access
00:00:00.6619090, items/sec = 151,285,000.00 Normal Ref access
00:00:00.9859089, items/sec = 101,522,000.00 IntPtr access (fixed outside loop)
00:00:10.1289018, items/sec = 9,873,000.00 IntPtr Misaligned access (fixed outside loop)
00:00:00.7899355, items/sec = 126,742,000.00 Fixed access (fixed inside loop)
00:00:00.5718507, items/sec = 175,131,000.00 float* access (fixed outside loop)
00:00:00.6842333, items/sec = 146,198,000.00 float* access (fixed in loop)
Best Answer
This is a bug in the v4l "version" (build) of OpenCV 2.4 (including 2.4.12), but the bug is not in the libv4l version. For OpenCV 3.1.0, neither the v4l nor the libv4l version has the bug.
(Your error error message
HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP
indicates that you have the v4l version; the message is in cap_v4l.cpp, see code, but not in cap_libv4l.cpp.)A workaround to get the v4l version of OpenCV 2.4 to work at a fixed resolution other than 640x480 is changing the values for
DEFAULT_V4L_WIDTH
andDEFAULT_V4L_HEIGHT
in modules/highgui/src/cap_v4l.cpp and re-building OpenCV, kudos to this answer.If you want to build the libv4l version instead, all you likely need to do is install
libv4l-dev
and rebuild OpenCV;WITH_LIBV4L
was enabled by default for me. If it is not, your cmake command should containThe cmake output (or version_string.tmp) for a libv4l build contains something like
(For a v4l build, it is just
V4L/V4L2: NO/YES
.)