OpenCV抓取在网络摄像头什么都不做 [英] OpenCV grab does nothing on webcam

查看:179
本文介绍了OpenCV抓取在网络摄像头什么都不做的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试同时从两个不同的相机抓取帧,但无论多少次我调用VideoCapture :: grab(),似乎没有效果。使用VideoCapture :: retrieve()检索的帧总是从最后一个VideoCapture :: retrieve()捕获的第一帧。



我已经在OpenCV 2.4



例如:

  VideoCapture vCapture; 
Mat imgResult;
vCapture.open(0); //此时,相机前面有一个绿色的表
Sleep(100000); //用红色表更改绿色表
vCapture.grab(); // returns true
vCapture.retrieve(imgResult); // image with green sheet was retrieved
Sleep(100000); // change blue sheet with blue sheet
vCapture.retrieve(imgResult); // red sheet is retrieved

我也尝试过:

  for(int i = 0; i <1000; i ++){
vCapture.grab
} //几乎没有处理时间,就像
的空白vCapture.retrieve(imgResult); //与之前相同

Retrieve始终返回true并检索框架,即使没有调用grab打开vCapture。



我当前的解决方案已经检索了帧两次(多线程),以确保最新的帧,但它不够可靠,无法同步两个摄像头。任何人都可以了解如何强制相机抓取当前帧?



谢谢!





为了清楚起见,第一个示例的变体:

  VideoCapture vCapture; 
Mat imgResult;
vCapture.open(0); //在这一点上,相机前面有一个绿色的工作表
vCapture.retrieve(imgResult); // image with green sheet was retrieved
Sleep(100000); //用红色表更改绿色表
vCapture.grab(); // returns true
vCapture.retrieve(imgResult); //检索绿色表
vCapture.retrieve(imgResult); // red sheet was retrieved
Sleep(100000); // change blue sheet with blue sheet
vCapture.retrieve(imgResult); // red sheet is retrieved
vCapture.retrieve(imgResult); // blue sheet was retrieved

预期行为:

  VideoCapture vCapture; 
Mat imgResult;
vCapture.open(0); //在这一点上,相机前面有一个绿色的工作表
vCapture.retrieve(imgResult); //错误或图像与绿色表检索
睡眠(100000); //用红色表更改绿色表
vCapture.grab(); // returns true
vCapture.retrieve(imgResult); //检索红色表

Per OpenCV文档:



VideoCapture :: grab :方法/函数从视频文件或摄像机抓取下一帧,并在成功的情况下返回true(非零)。 / p>

VideoCapture :: retrieve :方法/函数解码并返回刚刚抓取的帧。如果没有抓取任何帧(相机已断开连接,或视频文件中没有更多帧),则方法返回false,函数将返回NULL指针。

解决方案

请在启动程序之前和期间尝试使用以下说明执行此代码:


  1. ,在相机前面握住红色的纸。


  2. 一旦你看到黑色的窗口弹出来,删除红色的表格,拿着一张蓝色的表格或其他东西(红色或绿色片除外)。然后按键盘琴键'q'。


  3. 现在您有5秒钟时间来重新更改场景。握住相机前面的绿色薄片并等待。黑色窗口将切换到您的一个相机图片。

      int main(int argc,char * argv [])
    {
    cv :: Mat input = cv :: Mat(512,512,CV_8UC1,cv :: Scalar(0));

    cv :: VideoCapture cap(0);


    while(cv :: waitKey(10)!='q')
    {
    cap.grab();
    cv :: imshow(input,input);
    }
    cv :: waitKey(5000);
    cap.retrieve(input);

    cv :: imshow(input,input);
    cv :: waitKey(0);
    return 0;
    }



  1. 您会看到红色表格:这意味着第一个抓图被调用并修复了图片,直到调用了检索。


  2. 您看到蓝色表格:这意味着每个.grab调用删除一个图像,相机将在下次调用.grab时捕获一个新图像


  3. 您会看到绿色工作表:这表示您的.retrieve根本不需要.grab,只会自动抓取图片。

    >

对我来说,结果1出现,所以你不能抓住和抓住,只是恢复最后的图像。






测试2:控制一切:




  • 看起来你是对的,在我的机器上,无论什么时候或多久我调用抓,下一个图像将是当我调用以前的 .retrieve 并且 .grab 的调用似乎不影响捕获的时间位置。



对于不同的(所有)类型的相机和操作系统是否会出现相同的行为会非常有趣。



我已经在内部摄像头的T450s和Windows 7。

  int main(int argc,char * argv [])
{
cv :: Mat input = cv :: Mat(512,512,CV_8UC1,cv :: Scalar(0));

cv :: VideoCapture cap(0);

bool grabbed;
bool retrieve;

while(true)
{
char w = cv :: waitKey(0);
switch(w)
{
case'q':return 0;
case 27:return 0;
case'':retrieved = cap.retrieve(input);打破;
case'p':grabbed = cap.grab();打破;
}

cv :: imshow(input,input);
}

return 0;
}






代码似乎关闭了1帧为我的相机(因此可能有一个2的缓冲区):

  while )
{
cap>>输入;

cv :: imshow(input,input);
cv :: waitKey(0);
}


I've been trying to simultaneously grab frames from two different cameras, but no matter how many times I call VideoCapture::grab(), there seems to be no effect. The frame retrieved using VideoCapture::retrieve() is always the first frame captured from the last VideoCapture::retrieve().

I've tested it on both OpenCV 2.4 and 3.1, with a Logitech C920 camera on windows.

Example:

VideoCapture vCapture;
Mat imgResult;
vCapture.open(0); //at this point, there is a green sheet in front of the camera
Sleep(100000); //change green sheet with red sheet
vCapture.grab(); //returns true
vCapture.retrieve(imgResult); //image with green sheet is retrieved
Sleep(100000); //change red sheet with blue sheet
vCapture.retrieve(imgResult); //red sheet is retrieved

I've also tried:

for(int i = 0; i < 1000; i++){
    vCapture.grab();
} //takes almost no processing time, like an empty for
vCapture.retrieve(imgResult); //same as before

Retrieve always returns true and retrieves a frame, even if no grab was called since opening vCapture.

My current solution has been retrieving the frame twice (multi-threaded) to ensure the latest frame, but it isn't reliable enough to sync both cameras. Can anyone shed some light on how to force the camera to grab the current frame?

Thanks!

Edit:

A variation of the first example, for clarity:

VideoCapture vCapture;
Mat imgResult;
vCapture.open(0); //at this point, there is a green sheet in front of the camera
vCapture.retrieve(imgResult); //image with green sheet is retrieved
Sleep(100000); //change green sheet with red sheet
vCapture.grab(); //returns true
vCapture.retrieve(imgResult); //green sheet is retrieved
vCapture.retrieve(imgResult); //red sheet is retrieved
Sleep(100000); //change red sheet with blue sheet
vCapture.retrieve(imgResult); //red sheet is retrieved
vCapture.retrieve(imgResult); //blue sheet is retrieved

Expected behavior:

VideoCapture vCapture;
Mat imgResult;
vCapture.open(0); //at this point, there is a green sheet in front of the camera
vCapture.retrieve(imgResult); //error or image with green sheet is retrieved
Sleep(100000); //change green sheet with red sheet
vCapture.grab(); //returns true
vCapture.retrieve(imgResult); //red sheet is retrieved

Per OpenCV documentation:

VideoCapture::grab: The methods/functions grab the next frame from video file or camera and return true (non-zero) in the case of success.

VideoCapture::retrieve: The methods/functions decode and return the just grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more frames in video file), the methods return false and the functions return NULL pointer.

解决方案

Please try this code with the following instructions:

  1. before and while you start the program, hold a red sheet in front of the camera. That moment, the first .grab will be called.

  2. Once you see the black window popping up, remove the red sheet and hold a blue sheet or something else (except the red or the green sheet) in front of the camera. Then press keyboard key 'q'.

  3. Now you have 5 seconds time to change the scene again. Hold hold the green sheet in front of the camera and wait. The black window will be switched to one of your camera images.

    int main(int argc, char* argv[])
    {
        cv::Mat input = cv::Mat(512,512,CV_8UC1, cv::Scalar(0));
    
        cv::VideoCapture cap(0);
    
    
        while (cv::waitKey(10) != 'q')
        {
            cap.grab();
            cv::imshow("input", input);
        }
        cv::waitKey(5000);
        cap.retrieve(input);
    
        cv::imshow("input", input);
        cv::waitKey(0);
        return 0;
    }
    

3 possible results:

  1. you see the red sheet: this means that the first grab was called and fixed the image, until a retrieve was called.

  2. you see blue sheet: this means every .grab call "removes" one image and the camera will capture a new image on the next call of .grab

  3. you see the green sheet: this means your .retrieve doesn't need a .grab at all and just grabs images automatically.

For me, result 1 occurs, so you can't grab and grab and grab and just .retrieve the last image.


Test 2: control about everything:

  • looks like you are right, on my machine no matter when or how often I call grab, the next image will be the one captured at the time when I called the previous .retrieve and the calls of .grab don't seem to influence the time position of capturing at all.

Would be very interesting whether the same behaviour occurs for different (all) kind of cameras and operating systems.

I've tested on the internal camera of a T450s and Windows 7.

int main(int argc, char* argv[])
{
    cv::Mat input = cv::Mat(512,512,CV_8UC1, cv::Scalar(0));

    cv::VideoCapture cap(0);

    bool grabbed;
    bool retrieved;

    while (true)
    {
        char w = cv::waitKey(0);
        switch (w)
        {
        case 'q':  return 0;
        case 27:  return 0;
        case ' ': retrieved = cap.retrieve(input); break;
        case 'p': grabbed = cap.grab(); break;
        }

        cv::imshow("input", input);
    }

    return 0;
}


In addition, this simple code seems to be off 1 frame for my camera (which therefore probably has a buffersize of 2??):

while (true)
    {
        cap >> input;

        cv::imshow("input", input);
        cv::waitKey(0);
    }

这篇关于OpenCV抓取在网络摄像头什么都不做的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆