OpenCV抓取在网络摄像头上没有任何作用

时间:2016-04-28 11:47:18

标签: c++ opencv

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

我在OpenCV 2.4和3.1上都测试了它,在Windows上使用Logitech C920相机。

示例:

<div class="wrap">
  <div class="rect-left">
    <div class="inner"></div>
  </div>
  <div class="rect">&nbsp;<span class="circle"></span>
    <div class="avatar"></div>
  </div>
  <div class="rect-right">
    <div class="inner"></div>
  </div>
</div>

我也试过了:

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

检索始终返回true并检索一个框架,即使打开vCapture后没有调用任何抓取。

我目前的解决方案是检索帧两次(多线程)以确保最新帧,但它不足以同步两个摄像头。任何人都可以了解如何强迫相机抓住当前帧吗?

谢谢!

编辑:

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

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

预期行为:

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

每个OpenCV文档:

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 :方法/函数从视频文件或摄像机中获取下一帧,并在成功的情况下返回true(非零)。

VideoCapture::grab:方法/函数解码并返回刚捕获的帧。如果没有抓取帧(摄像机已断开连接,或视频文件中没有帧),则方法返回false,函数返回NULL指针。

2 个答案:

答案 0 :(得分:2)

请按照以下说明尝试此代码:

  1. 在启动程序之前和之后,请在相机前面放一张红色的纸张。那一刻,第一个.grab将被召唤。

  2. 一旦看到黑色窗口弹出,请取下红色表并在相机前面放一块蓝色的纸或其他东西(红色或绿色纸除外)。然后按键盘键&#39; q&#39;

  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;
    }
    
  4. 3个可能的结果:

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

    2. 你看到蓝色表:这意味着每个.grab电话&#34;删除&#34;一个图像和相机将在下次调用.grab

    3. 时捕获新图像
    4. 你看到绿色表:这意味着你的.retrieve根本不需要.grab并且只是自动抓取图像。

    5. 对我来说,结果1出现了,所以你不能抓住并抓住并且只是.retrieve最后一张图片。

      测试2:控制一切:

      • 看起来你是对的,在我的机器上,无论我何时或多久调用一次抓取,下一张图片将是我在调用前一个.retrieve时调用的图像和{{1根本不会影响捕获的时间位置。

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

      我已经在T450和Windows 7的内置摄像头上进行了测试。

      .grab

      另外,对于我的相机来说,这个简单的代码似乎是1帧(因此可能有2个缓冲区大小):

      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;
      }
      

答案 1 :(得分:0)

我运行了测试并注意到.garab和.retrive函数的非常奇怪的行为。 这是一个例子:

cv::Mat input = cv::Mat(512, 512, CV_8UC1, cv::Scalar(0));
cv::VideoCapture cap(0);

while (true)
{
    cap.grab();
    cap.retrieve(input, 5);
    cv::imshow("input", input);
    cv::waitKey(0);
}

如果你慢慢地按任意键,大约每5秒钟一次,并在按下之前改变相机前面的某些东西,图像上物体的位置将改变每一秒显示的图像,即每秒钟的一次调用。抓住和.retrive功能。

如果您快速按任意键,大约每1秒钟,并且在按下之间也会更改相机前面的某些内容,则每个显示的图像都会更改图像上对象的位置。

这种情况表明此功能可用于同步相机。