在我的C / C ++程序中,我正在使用OpenCV从网络摄像头捕获图像。 摄像机(Logitech QuickCam IM)可以以320x240、640x480和1280x960的分辨率捕获。 但是,出于某些奇怪的原因,OpenCV仅给我提供分辨率为320x240的图像。 使用cvSetCaptureProperty()和其他分辨率值来更改分辨率的调用根本不起作用。 如何使用网络摄像头以其他分辨率捕获图像?
我在Windows下使用openCV 1.1pre1(默认情况下,在Windows下此版本的openCv使用videoinput库)。
通过这些说明,我可以设置相机分辨率。请注意,我称旧的cvCreateCameraCapture而不是cvCaptureFromCam。
1 2 3 4 5 6 7 8
| capture = cvCreateCameraCapture(cameraIndex);
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 640 );
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 480 );
videoFrame = cvQueryFrame(capture); |
我已经使用Logitech,Trust和Philips网络摄像头对其进行了测试
似乎没有解决办法。使用lifebelt77共享的此技巧,可以将分辨率提高到640x480。以下是转载的详细信息:
添加到highgui.h:
1 2 3 4 5
| #define CV_CAP_PROP_DIALOG_DISPLAY 8
#define CV_CAP_PROP_DIALOG_FORMAT 9
#define CV_CAP_PROP_DIALOG_SOURCE 10
#define CV_CAP_PROP_DIALOG_COMPRESSION 11
#define CV_CAP_PROP_FRAME_WIDTH_HEIGHT 12 |
将函数icvSetPropertyCAM_VFW添加到cvcap.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| static int icvSetPropertyCAM_VFW( CvCaptureCAM_VFW* capture, int property_id, double value )
{
int result = -1;
CAPSTATUS capstat;
CAPTUREPARMS capparam;
BITMAPINFO btmp;
switch( property_id )
{
case CV_CAP_PROP_DIALOG_DISPLAY:
result = capDlgVideoDisplay(capture->capWnd);
//SendMessage(capture->capWnd,WM_CAP_DLG_VIDEODISPLAY,0,0);
break;
case CV_CAP_PROP_DIALOG_FORMAT:
result = capDlgVideoFormat(capture->capWnd);
//SendMessage(capture->capWnd,WM_CAP_DLG_VIDEOFORMAT,0,0);
break;
case CV_CAP_PROP_DIALOG_SOURCE:
result = capDlgVideoSource(capture->capWnd);
//SendMessage(capture->capWnd,WM_CAP_DLG_VIDEOSOURCE,0,0);
break;
case CV_CAP_PROP_DIALOG_COMPRESSION:
result = capDlgVideoCompression(capture->capWnd);
break;
case CV_CAP_PROP_FRAME_WIDTH_HEIGHT:
capGetVideoFormat(capture->capWnd, &btmp, sizeof(BITMAPINFO));
btmp.bmiHeader.biWidth = floor(value/1000);
btmp.bmiHeader.biHeight = value-floor(value/1000)*1000;
btmp.bmiHeader.biSizeImage = btmp.bmiHeader.biHeight *
btmp.bmiHeader.biWidth * btmp.bmiHeader.biPlanes *
btmp.bmiHeader.biBitCount / 8;
capSetVideoFormat(capture->capWnd, &btmp, sizeof(BITMAPINFO));
break;
default:
break;
}
return result;
} |
并按如下所示编辑captureCAM_VFW_vtable:
1 2 3 4 5 6 7 8 9 10
| static CvCaptureVTable captureCAM_VFW_vtable =
{
6,
(CvCaptureCloseFunc)icvCloseCAM_VFW,
(CvCaptureGrabFrameFunc)icvGrabFrameCAM_VFW,
(CvCaptureRetrieveFrameFunc)icvRetrieveFrameCAM_VFW,
(CvCaptureGetPropertyFunc)icvGetPropertyCAM_VFW,
(CvCaptureSetPropertyFunc)icvSetPropertyCAM_VFW, // was NULL
(CvCaptureGetDescriptionFunc)0
}; |
现在重建了highgui.dll。
一旦Aaron Haun指出我需要在使用set函数之前定义它们的代码,我终于可以在Python中工作了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| #Camera_Get_Set.py
#By Forrest L. Erickson of VRX Company Inc. 8-31-12.
#Opens the camera and reads and reports the settings.
#Then tries to set for higher resolution.
#Workes with Logitech C525 for resolutions 960 by 720 and 1600 by 896
import cv2.cv as cv
import numpy
CV_CAP_PROP_POS_MSEC = 0
CV_CAP_PROP_POS_FRAMES = 1
CV_CAP_PROP_POS_AVI_RATIO = 2
CV_CAP_PROP_FRAME_WIDTH = 3
CV_CAP_PROP_FRAME_HEIGHT = 4
CV_CAP_PROP_FPS = 5
CV_CAP_PROP_POS_FOURCC = 6
CV_CAP_PROP_POS_FRAME_COUNT = 7
CV_CAP_PROP_BRIGHTNESS = 8
CV_CAP_PROP_CONTRAST = 9
CV_CAP_PROP_SATURATION = 10
CV_CAP_PROP_HUE = 11
CV_CAPTURE_PROPERTIES = tuple({
CV_CAP_PROP_POS_MSEC,
CV_CAP_PROP_POS_FRAMES,
CV_CAP_PROP_POS_AVI_RATIO,
CV_CAP_PROP_FRAME_WIDTH,
CV_CAP_PROP_FRAME_HEIGHT,
CV_CAP_PROP_FPS,
CV_CAP_PROP_POS_FOURCC,
CV_CAP_PROP_POS_FRAME_COUNT,
CV_CAP_PROP_BRIGHTNESS,
CV_CAP_PROP_CONTRAST,
CV_CAP_PROP_SATURATION,
CV_CAP_PROP_HUE})
CV_CAPTURE_PROPERTIES_NAMES = [
"CV_CAP_PROP_POS_MSEC",
"CV_CAP_PROP_POS_FRAMES",
"CV_CAP_PROP_POS_AVI_RATIO",
"CV_CAP_PROP_FRAME_WIDTH",
"CV_CAP_PROP_FRAME_HEIGHT",
"CV_CAP_PROP_FPS",
"CV_CAP_PROP_POS_FOURCC",
"CV_CAP_PROP_POS_FRAME_COUNT",
"CV_CAP_PROP_BRIGHTNESS",
"CV_CAP_PROP_CONTRAST",
"CV_CAP_PROP_SATURATION",
"CV_CAP_PROP_HUE"]
capture = cv.CaptureFromCAM(0)
print ("\
Camera properties before query of frame.")
for i in range(len(CV_CAPTURE_PROPERTIES_NAMES)):
# camera_valeus =[CV_CAPTURE_PROPERTIES_NAMES, foo]
foo = cv.GetCaptureProperty(capture, CV_CAPTURE_PROPERTIES[i])
camera_values =[CV_CAPTURE_PROPERTIES_NAMES[i], foo]
# print str(camera_values)
print str(CV_CAPTURE_PROPERTIES_NAMES[i]) +":" + str(foo)
print ("\
Open a window for display of image")
cv.NamedWindow("Camera", 1)
while True:
img = cv.QueryFrame(capture)
cv.ShowImage("Camera", img)
if cv.WaitKey(10) == 27:
break
cv.DestroyWindow("Camera")
#cv.SetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 1024)
#cv.SetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 768)
cv.SetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 1600)
cv.SetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 896)
print ("\
Camera properties after query and display of frame.")
for i in range(len(CV_CAPTURE_PROPERTIES_NAMES)):
# camera_valeus =[CV_CAPTURE_PROPERTIES_NAMES, foo]
foo = cv.GetCaptureProperty(capture, CV_CAPTURE_PROPERTIES[i])
camera_values =[CV_CAPTURE_PROPERTIES_NAMES[i], foo]
# print str(camera_values)
print str(CV_CAPTURE_PROPERTIES_NAMES[i]) +":" + str(foo)
print ("/nOpen a window for display of image")
cv.NamedWindow("Camera", 1)
while True:
img = cv.QueryFrame(capture)
cv.ShowImage("Camera", img)
if cv.WaitKey(10) == 27:
break
cv.DestroyWindow("Camera") |
检查这张票:
https://code.ros.org/trac/opencv/ticket/376
"解决方案是使用较新的基于libv4l的包装器。
安装libv4l-dev(这是在Ubuntu中的调用方式)
重新运行cmake,您将看到" V4L / V4L2:使用libv4l"
重新运行。现在可以更改分辨率。在MBP上使用内置isight进行了测试。"
这可以使用Ubuntu为我修复,也可以为您工作。
我强烈建议使用VideoInput lib,它支持任何DirectShow设备(甚至可以同时使用多个设备),并且更具可配置性。您将花费五分钟使其与OpenCV一起播放。
我以前在linux中完成过图像处理,并跳过了OpenCV的内置摄像头功能,因为它(如您所发现的)不完整。
根据您的操作系统,您可能会更幸运地通过常规渠道而不是通过openCV直接进入硬件。如果您使用的是Linux,video4linux或video4linux2应该可以让您相对轻松地访问USB网络摄像头,并且可以将libavc1394用于火线。根据设备和所遵循示例代码的质量,您应该能够在一两个小时内使设备运行所需的参数。
编辑添加:如果您使用的是Windows,则自己运行。我想这并不困难,但我从未做到过。
我正在使用debian和ubuntu,我遇到了同样的问题,我无法使用CV_CAP_PROP_FRAME_WIDTH和CV_CAP_PROP_FRAME_HEIGHT更改视频输入的分辨率
我发现原因是缺少库。
我通过突触安装了lib4l-dev,重建了OpenCV,问题已解决!
我发布此消息是为了确保没有其他人在此setproperty函数上浪费时间。我花了两天的时间,似乎没有任何反应。因此,我挖出了代码(我是第一次安装该库)。这就是实际发生的情况-cvSetCaptureProperty,在CvCapture类内调用setProperty,而setProperty则不执行任何操作。它只是返回false。
相反,我将使用另一个库来为OpenCV提供捕获的视频/图像。我正在使用OpenCV 2.2
对于难以更改默认捕获分辨率(640 x 480)的人们来说,只有一种可能有价值的信息!我用opencv 2.4.x和一台Logitech相机对自己进行了实验,发现了一个解决方法!
我检测到的行为是,在开始摄像头捕获(cvCreateCameraCapture)时,默认格式设置为初始参数,并且所有请求更改高度或宽度:
1
| cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, ... |
要么
1
| cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, ... |
之后是不可能的!实际上,我发现通过添加ioctl函数的返回错误,V4l2驱动程序正在为该请求返回EBUSY!
因此,一种解决方法是直接在highgui / cap_v4l.cpp中更改默认值:
1 2 3
| *#define DEFAULT_V4L_WIDTH 1280 // Originally 640*
*#define DEFAULT_V4L_HEIGHT 720 // Originally 480* |
之后,我只是重新编译了opencv ...并毫无疑问地获得了1280 x 720的分辨率!当然,更好的解决方法应该是停止采集,更改参数并在之后重新启动流,但是我对opencv不够了解!
希望会有所帮助。
米歇尔·贝吉
如果您在Windows平台上,请尝试DirectShow(IAMStreamConfig)。
http://msdn.microsoft.com/zh-cn/library/dd319784%28v=vs.85%29.aspx
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, WIDTH );
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, HEIGHT);
cvQueryFrame(capture);
那不适用于OpenCV 2.2,但是如果您使用OpenCV 2.1,它将可以正常工作!
在Windows下,尝试使用VideoInput库:
http://robocraft.ru/blog/computervision/420.html
我发现在Windows(从Win98到WinXP SP3)中,OpenCV通常会使用Microsoft的VFW库来进行摄像机访问。问题在于它通常非常慢(例如最多捕获15 FPS帧)和越野车(因此cvSetCaptureProperty为什么通常不起作用)。幸运的是,您通常可以在其他软件(特别是" AMCAP",这是一个易于使用的演示程序)中更改分辨率,这将影响OpenCV使用的分辨率。例如,您可以运行AMCAP将分辨率设置为640x480,然后OpenCV从那时起默认使用该分辨率!
但是,如果可以使用其他Windows摄像机访问库,例如" videoInput"库http://muonics.net/school/spring05/videoInput/,则可以使用非常高效的DirectShow(DirectX的一部分)访问摄像机。或者,如果您拥有专业质量的相机,则通常会附带一个自定义API,该API可让您访问相机,并且可以使用它来快速访问并具有更改分辨率和许多其他功能的能力。
试试这个:
1 2 3 4
| capture = cvCreateCameraCapture(-1);
//set resolution
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, frameWidth);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, frameHeight); |
1 2 3 4 5 6 7
| cvQueryFrame(capture);
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, any_supported_size );
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, any_supported_size);
cvQueryFrame(capture); |
应该足够了!