OpenCV:无法设置视频捕获的分辨率

12

我正在使用OpenCV 2.4.5在Ubuntu 12.04 64位上。我想要能够设置我的Logitech C310网络摄像头的输入分辨率。该相机支持最高1280x960,30fps的视频,并且我可以在guvcview中以这种分辨率查看视频。但是OpenCV始终只获取640x480的视频。

在创建VideoCapture cap之后立即使用cap.set(CV_CAP_PROP_FRAME_WIDTH,1280)和cap.set(CV_CAP_PROP_FRAME_HEIGHT,960)尝试更改分辨率没有效果;在获取每个帧之前立即设置它们会导致程序立即崩溃。我也无法用此方法缩小分辨率。我还遇到了“HIGHGUI ERROR:V4L/V4L2:VIDIOC_S_CROP”的错误。我认为这可能与问题有关,因为它在创建VideoCapture时一次出现,在我尝试设置宽度和高度时再次出现(但奇怪的是,如果我只尝试设置其中一个,则不会出现)。

我知道我不是第一个遇到这个问题的人,但经过大量搜索Google、SO和其他互联网资源(我已经尝试过许多事情),我仍然没有找到解决方案(其中包括这个StackOverflow问题的答案:Increasing camera capture resolution in OpenCV)。这是OpenCV中的一个bug吗?如果是,那就太明显了。

下面给出了一个展示该问题的代码示例(仅是OpenCV视频显示代码的修改版):

#include <cv.h>
#include <highgui.h>
using namespace cv;

int main(int argc, char** argv)
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
            return -1;

    cap.set(CV_CAP_PROP_FRAME_WIDTH, 160);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 120);

    Mat image;
    namedWindow("Video", CV_WINDOW_AUTOSIZE);

    while(1)
    {
            // cap.set(CV_CAP_PROP_FRAME_WIDTH, 160);
            // cap.set(CV_CAP_PROP_FRAME_HEIGHT, 120);
            cap >> image;

            imshow("Video", image);

            if(waitKey(10) == 99 ) break;
    }
    return 
}

目前情况是,我得到了两个" HIGHGUI ERROR "的错误提示,如上所述,并且输出为640x480。 我知道160x120是我的相机支持的一种分辨率,可以通过运行v4l2-ctl --list-formats-ext来确认。如果我取消while循环中被注释掉的两行代码的注释,程序会立即崩溃。

以下链接可能与此相关或具有可能的解决方案:http://answers.opencv.org/question/11427/decreasing-capture-resolution-of-webcam/, http://answers.opencv.org/question/30062/error-setting-resolution-of-video-capture-device/


请发布您的代码。如果有什么问题,很可能是您的代码出了问题,所以没有您的代码我们无法帮助您。我没有使用过C310,但是我在使用C920时没有遇到任何设置分辨率的问题。 - Tae-Sung Shin
发布成功!该问题可以通过一个简单修改过的OpenCV VideoCapture示例来展示。 - erobertc
我现在已经尝试使用C920,它产生了完全相同的结果。 - erobertc
1
您正在遇到“highgui错误”。这可能意味着您在设置图像大小方面没有任何问题,但是您的代码无法处理图像抓取的速度。在获取图像后,您的代码会累积延迟。我怀疑这是错误的原因。通常,您应该有一个单独的线程用于抓取和另一个线程用于显示获取的图像。您的代码没有这两个线程。我刚刚尝试了我的代码,并没有在设置分辨率方面遇到任何问题。 - Tae-Sung Shin
@Tae-SungShin,我怀疑你之所以能够正常工作是因为你使用了OpenCV的libv4l版本,请参见我的答案 - Ulrich Stern
4个回答

5
这是OpenCV 2.4中版本(包括2.4.12)的一个错误,但该错误不在版本中。对于OpenCV 3.1.0,无论是v4l还是libv4l版本都没有此错误。您的错误信息HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP表明您使用的是v4l版本;该信息位于cap_v4l.cpp中,请参见code,但不在cap_libv4l.cpp中。
一个解决方案,使OpenCV 2.4的v4l版本能够在固定分辨率(非640x480)下工作是更改modules/highgui/src/cap_v4l.cpp中的DEFAULT_V4L_WIDTH和DEFAULT_V4L_HEIGHT值并重新构建OpenCV,感谢此答案的作者
如果您想要构建libv4l版本,您可能只需要安装libv4l-dev并重新构建OpenCV;对于我来说,默认情况下启用了WITH_LIBV4L。如果没有启用,请确保您的cmake命令包含它。
-D WITH_LIBV4L=ON

一个libv4l构建的cmake输出(或version_string.tmp)包含以下内容:

  Video I/O:
    ...
    V4L/V4L2:   Using libv4l1 (ver 0.8.6) / libv4l2 (ver 0.8.6)

(对于v4l构建,它只是V4L/V4L2: NO/YES。)

你是怎么让Python绑定与OpenCV3.1一起工作的? - user592419
@user592419,我在构建过程中没有做任何特殊处理(使用了这个 cmake)。通常我会跳过make install,直接执行sudo cp lib/cv2.so /usr/local/lib/python2.7/dist-packages/ - Ulrich Stern
我好像没有lib/cv2.so这个文件。我有很多lib/libopencv_*.so文件和一个lib/python3/cv2.cpython-34m.so文件,但没有你指定的那个。 - user592419
@SAMPro,如果你还没有尝试过,可以试试OpenCV 3.1的v4l版本。如果这不起作用,查看OpenCV源代码可能是最好的选择... - Ulrich Stern
感谢您在这篇文章中提供了大量的好建议。WITH_LIBV4L起到了关键作用,以下是我在为Java构建时使用的make选项: - Austin
显示剩余9条评论

0

我想在基于Ulrich全面回答OpenCV 3.2.0的树莓派3上添加我的CMAKE选项以构建Java。在与OpenCV CMakeList.txt相同的文件夹中创建/build文件夹,并为新的/build文件夹执行此脚本:

sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D WITH_OPENCL=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_SHARED_LIBS=OFF -D JAVA_INCLUDE_PATH=$JAVA_HOME/include -D JAVA_AWT_LIBRARY=$JAVA_HOME/jre/lib/arm/libawt.so -D JAVA_JVM_LIBRARY=$JAVA_HOME/jre/lib/arm/server/libjvm.so -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_TESTS=OFF -D WITH_MATLAB=OFF -D WITH_CUFFT=OFF -D WITH_CUDA=OFF -D WITH_CUBLAS=OFF -D WITH_GTK=OFF -D WITH_WEBP=OFF -D BUILD_opencv_apps=OFF -D BUILD_PACKAGE=OFF -D WITH_LIBV4L=ON ..


-1

您可以使用v4l2-ctl来设置捕获视频的帧大小,如下所示。

v4l2-ctl --set-fmt-video=width=1920,height=1080,pixelformat=1

您可以在此链接找到更多信息。


这将更改由v4l2-ctl记录的捕获视频的分辨率,对您的C++程序没有影响。 - SAMPro

-2

也许你可以尝试这个,但我不确定这是否是你想要的:

#include <X11/Xlib.h>

Display* disp = XOpenDisplay(NULL);
Screen*  scrn = DefaultScreenOfDisplay(disp);
int height = scrn->height;
int width  = scrn->width;

//Create window for the ip cam video
cv::namedWindow("Front", CV_WINDOW_NORMAL);

cvSetWindowProperty( "Front", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN );

//Position of the screen where the video is shows
cvMoveWindow("Front", 0, 0);
cvResizeWindow( "Front", width, height );

这样你就可以在任何屏幕上获得全屏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接