使用c ++中的opencv捕获实时视频?

时间:2017-11-16 06:27:15

标签: c++ opencv video

我正在使用opencv和c ++开发一个板数检测应用程序。

对于检测试用版,我想使用VideoCapture()功能从我的网络摄像头捕获实时视频:

int main(void)
{
  // input image
  cv::Mat imgOriginalScene;      

  cv::VideoCapture cap = cv::VideoCapture(0); 

  for (;;) {
    cv::Mat frame;
    cap.read(frame);
    double timestamp = cap.get(CV_CAP_PROP_POS_MSEC);

    if (cap.read(frame)) {
      imgOriginalScene = frame;
      cv::Size size(1000, 600);
      resize(imgOriginalScene, imgOriginalScene, size);

      if (imgOriginalScene.empty()) {              
        std::cout << "error: image not read from file\n\n";   
        return(0);                        
      }

      std::vector<PossiblePlate> vectorOfPossiblePlates = 
          detectPlatesInScene(imgOriginalScene);    
      vectorOfPossiblePlates = detectCharsInPlates(vectorOfPossiblePlates);                 

      cv::imshow("imgOriginalScene", imgOriginalScene);      

      if (vectorOfPossiblePlates.empty()) {                         
        std::cout << std::endl << "no license plates were detected" << std::endl;    
      }
      else {                                      
        std::sort(vectorOfPossiblePlates.begin(), vectorOfPossiblePlates.end(), 
            PossiblePlate::sortDescendingByNumberOfChars);

        // suppose the plate with the most recognized chars
        // (the first plate in sorted by string length descending order) 
        // is the actual plate
        PossiblePlate licPlate = vectorOfPossiblePlates.front();

        cv::imshow("imgPlate", licPlate.imgPlate);      
        cv::imshow("imgThresh", licPlate.imgThresh);

        // if no chars were found in the plate
        if (licPlate.strChars.length() == 0) {                            
          // show message
          std::cout << std::endl << "no characters were detected" << std::endl << std::endl;    
        }

        // draw red rectangle around plate
        drawRedRectangleAroundPlate(imgOriginalScene, licPlate);        

        // write license plate text to std out
        std::cout << std::endl << "license plate read from image = " << licPlate.strChars << std::endl;   
        std::cout << std::endl << "-----------------------------------------" << std::endl;
        outfile << licPlate.strChars << "  " << timestamp / 1000 << " Detik" << std::endl;

        // write license plate text on the image
        writeLicensePlateCharsOnImage(imgOriginalScene, licPlate);        

        // re-show scene image
        cv::imshow("imgOriginalScene", imgOriginalScene);             

        // write image out to file
        cv::imwrite("imgOriginalScene.png", imgOriginalScene);          
      }
      cvWaitKey(34);
    }
    else {
      cap.set(CV_CAP_PROP_POS_FRAMES, 1.0);
      cvWaitKey(1000);
    }
    if (cap.get(CV_CAP_PROP_POS_FRAMES) == cap.get(CV_CAP_PROP_FRAME_COUNT)) {
      break;
    }
  }

  outfile.close();

  // hold windows open until user presses a key
  cv::waitKey(0);         

  return(0);
}

但是在运行代码之后,我的网络摄像头显示的视频被卡住了,就像只显示第一帧然后停止一样。 所以我无法检测到任何内容,因为视频被卡住了。

任何人都面临同样的问题?

1 个答案:

答案 0 :(得分:1)

通常,从相机中读取steps are as follows

  1. 打开cv :: VideoCapture对象并调用isOpened()以验证是否成功打开。我通常更喜欢单独声明捕获对象,然后使用open(0)打开它,但测试哪些对你有用。
  2. 将一个帧读入cv::Mat个对象。您可以使用read(),也可以使用<<运算符
  3. 实现接近
  4. 使用empty()验证框架是否为空。
  5. 处理循环中的图像。
  6. 使用waitKey()

    请记住waitKey(0)将暂停您的程序,直到用户按下某个键。在循环结束时放置waitKey(30)一次将使用imshow()显示已处理和排队的图像。您不需要在整个循环中多次使用waitKey(),并且可能需要一些其他计时器用于计时目的。

    可能的错误点

    您的代码可能挂在您的第一个if语句上。您正在紧接呼叫cap.read(frame),这可能对网络摄像头进行处理太快...导致它在第一次迭代后返回false。相反,请尝试使用frame.empty()的实现来检查在调用cap.read(frame)后是否有要处理的图像。

    cv::Mat imgOriginalScene;           // input image
    
    cv::VideoCapture cap = cv::VideoCapture(0); 
    
    if(!cap.isOpened()){
        cerr << "Error Opening Capture Device" << endl; //Use cerr for basic debugging statements
        return -1;
    }
    
    for (;;) {
        cv::Mat frame;
        cap.read(frame);
        double timestamp = cap.get(CV_CAP_PROP_POS_MSEC);
    
        if (frame.empty()) {
             /*... do something ...*/
        }
        else {
            cap.set(CV_CAP_PROP_POS_FRAMES, 1.0);
            cvWaitKey(1000);
        }
         //Try removing this for debug...
    /*
        if (cap.get(CV_CAP_PROP_POS_FRAMES) == cap.get(CV_CAP_PROP_FRAME_COUNT)) {
            //break;
    
        }
    */  
        cv::waitKey(0);                 // hold windows open until user presses a key
    }
    
    outfile.close();
    cv::waitKey(0);                 // hold windows open until user presses a key
    
    return(0);
    

    更新日志:

    • Per @ api55的评论,添加了isOpened()检查完整性
    • 添加了对waitkey()的讨论
    • 建议评论现在打破循环的部分