【问题标题】:Increasing camera capture resolution in OpenCV提高 OpenCV 中的相机捕获分辨率
【发布时间】:2010-09-06 01:41:12
【问题描述】:

在我的 C/C++ 程序中,我使用 OpenCV 从我的网络摄像头捕获图像。相机 (Logitech QuickCam IM) 可以以 320x240640x4801280x960 的分辨率进行拍摄。但是,出于某种奇怪的原因,OpenCV 只给了我320x240 分辨率的图像。使用 cvSetCaptureProperty() 和其他分辨率值来更改分辨率的调用不起作用。如何使用我的网络摄像头捕捉其他分辨率的图像?

【问题讨论】:

  • 注意:术语“分辨率”的常见误用是指图像中的像素数。这不是各种标准的描述方式。分辨率与像素的大小而不是它们的数量密切相关。您可以拥有分辨率较差的 10MP 图像或高分辨率的 1MP。即使是足够幸运的 OpenCV 文档也不会犯这个错误。事实上,如果您例如转到 docs.opencv.org/modules/superres/doc/super_resolution.html 并查看底部的参考资料,您会发现图像分辨率与像素数明显不同。

标签: c image opencv webcam resolutions


【解决方案1】:

我在windows下使用openCV 1.1pre1(windows下这个版本的openCv默认使用videoinput库)。

通过这些说明,我可以设置相机分辨率。请注意,我调用旧的 cvCreateCameraCapture 而不是 cvCaptureFromCam。

capture = cvCreateCameraCapture(cameraIndex);

cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 640 );

cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 480 );


videoFrame = cvQueryFrame(capture);

我已经使用罗技、Trust 和飞利浦网络摄像头对其进行了测试

【讨论】:

  • 在 OpenCV 1.1 上也适用于我,我建议将其作为公认的答案。
  • 是的,我确认这也适用于我。当前公认的解决方案是不必要的。
  • 文档说这不受支持,但它甚至可以在高清分辨率下工作。但是,如果相机无法提供请求的分辨率,它会静默地回退到默认分辨率。当前公认的解决方案是不必要的。
  • 检查 cvSetCapture 属性的返回值 并非所有相机都会接受指令
【解决方案2】:

似乎没有解决办法。使用 lifebelt77 共享的this hack 可以将分辨率增加到 640x480。以下是转载的细节:

添加到 highgui.h

#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

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 如下:

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

【讨论】:

  • 此方法的分辨率上限为 640x480?
【解决方案3】:

我之前在 linux 中进行过图像处理,并跳过了 OpenCV 的内置摄像头功能,因为它(正如您所发现的)不完整。

根据您的操作系统,与通过 openCV 相比,您可能更幸运地通过正常渠道直接访问硬件。如果您使用的是 Linux,video4linux 或 video4linux2 应该可以让您相对轻松地访问 USB 网络摄像头,并且您可以使用 libavc1394 进行火线。根据您所遵循的示例代码的设备和质量,您应该能够在一两个小时内以您想要的参数运行设备。

编辑添加:如果它的 Windows,你是你自己的。我想这并不难,但我从来没有做过。

【讨论】:

    【解决方案4】:

    我强烈建议使用VideoInput lib,它支持任何 DirectShow 设备(甚至同时支持多个设备)并且更易于配置。您将花 5 分钟时间使用 OpenCV。

    【讨论】:

      【解决方案5】:

      查看这张票: https://code.ros.org/trac/opencv/ticket/376

      “解决方案是使用较新的基于 libv4l 的包装器。

      1. 安装 libv4l-dev(在 Ubuntu 中是这样调用的)

      2. 重新运行cmake,你会看到“V4L/V4L2: Using libv4l”

      3. 重新运行 make。现在可以更改分辨率。在 MBP 上使用内置 isight 进行测试。”

      这为我使用 Ubuntu 修复了它,也可能对你有用。

      【讨论】:

      【解决方案6】:

      当 Aaron Haun 指出我需要在使用 set 函数的参数之前定义它们时,我终于在 Python 中工作了。

      #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 ("\nCamera 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 ("\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")
      
      
      #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 ("\nCamera 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")
      

      【讨论】:

        【解决方案7】:

        我正在使用 debian 和 ubuntu,我遇到了同样的问题,我无法使用 CV_CAP_PROP_FRAME_WIDTHCV_CAP_PROP_FRAME_HEIGHT

        更改视频输入的分辨率

        我发现原因是缺少库。 我通过突触安装了 lib4l-dev重建 OpenCV,问题已解决!

        【讨论】:

          【解决方案8】:

          我发布这个是为了确保没有其他人在这个 setproperty 函数上浪费时间。我花了 2 天的时间来查看似乎没有任何效果。所以我挖出了代码(我第一次安装了这个库)。这就是实际发生的情况 - cvSetCaptureProperty,在 CvCapture 类中调用 setProperty,你看 setProperty 什么也没做。它只是返回假。 相反,我将使用另一个库来为 OpenCV 提供捕获视频/图像。我正在使用 OpenCV 2.2

          【讨论】:

            【解决方案9】:

            cvSetCaptureProperty(捕获, CV_CAP_PROP_FRAME_WIDTH, WIDTH);

            cvSetCaptureProperty(捕获, CV_CAP_PROP_FRAME_HEIGHT, HEIGHT);

            cvQueryFrame(捕获);

            这不适用于 OpenCV 2.2,但如果您使用 OpenCV 2.1,它将正常工作!

            【讨论】:

              【解决方案10】:

              如果您在 windows 平台上,请尝试 DirectShow (IAMStreamConfig)。

              http://msdn.microsoft.com/en-us/library/dd319784%28v=vs.85%29.aspx

              【讨论】:

                【解决方案11】:

                在 Windows 下尝试使用 VideoInput 库: http://robocraft.ru/blog/computervision/420.html

                【讨论】:

                • VideoInput 是否可以捕捉多重曝光图像?
                【解决方案12】:

                我发现在 Windows(从 Win98 到 WinXP SP3)中,OpenCV 经常会使用微软的 VFW 库来访问摄像头。这样做的问题是它通常非常慢(比如最多 15 FPS 帧捕获)和错误(因此 cvSetCaptureProperty 经常不起作用)。幸运的是,您通常可以在其他软件中更改分辨率(特别是“AMCAP”,这是一个易于使用的演示程序),它将影响 OpenCV 将使用的分辨率。例如,您可以运行 AMCAP 将分辨率设置为 640x480,然后 OpenCV 将从那时起默认使用该分辨率!

                但是,如果您可以使用不同的 Windows 摄像头访问库,例如“videoInput”库http://muonics.net/school/spring05/videoInput/,它使用非常高效的 DirectShow(DirectX 的一部分)访问摄像头。或者,如果您拥有专业品质的相机,那么它通常会附带一个自定义 API,让您可以访问相机,您可以使用它来快速访问,并能够更改分辨率和许多其他功能。

                【讨论】:

                  【解决方案13】:

                  对于难以更改默认捕获分辨率 (640 x 480) 的人来说,这只是一个有价值的信息!我用 opencv 2.4.x 和一台罗技相机对自己进行了这样的实验......并找到了一种解决方法!

                  我检测到的行为是默认格式设置为相机捕获开始时的初始参数(cvCreateCameraCapture),并且所有更改高度或宽度的请求:

                  cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, ... 
                  

                  cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, ...
                  

                  以后不可能了!实际上,通过添加 ioctl 函数的返回错误,我发现 V4l2 驱动程序正在为请求返回 EBUSY ! 因此,一种解决方法应该是直接在 highgui/cap_v4l.cpp 中更改默认值:

                  *#define DEFAULT_V4L_WIDTH  1280    // Originally 640* 
                  
                  *#define DEFAULT_V4L_HEIGHT 720     // Originally 480*
                  

                  在那之后,我只是重新编译了 opencv ... 并没有任何问题地得到 1280 x 720 !当然,更好的解决方法应该是停止采集,更改参数,然后重新启动流,但我对 opencv 还不够熟悉!

                  希望它会有所帮助。

                  米歇尔·贝吉

                  【讨论】:

                    【解决方案14】:

                    试试这个:

                    capture = cvCreateCameraCapture(-1);
                    //set resolution
                    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, frameWidth);
                    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, frameHeight);
                    

                    【讨论】:

                    • 那么您建议将初始参数设置为-1,然后呢?这有什么作用?
                    • cvCreateCameraCapture 的初始参数 -1 将选择第一个可用的设备/相机。
                    【解决方案15】:
                    cvQueryFrame(capture);
                    
                    cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, any_supported_size );
                    
                    cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, any_supported_size);
                    
                    cvQueryFrame(capture);
                    

                    应该够了!

                    【讨论】:

                    • 也许您可以尝试更多地解释您的代码。由于您已经回答了一个非常古老的问题,原来的提问者可能不会回来,但可能会帮助其他人。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-09-12
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-01-30
                    • 1970-01-01
                    • 2012-08-21
                    相关资源
                    最近更新 更多