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

Capturing real time video with opencv in c++?

本文关键字:实时视频 opencv c++      更新时间:2023-10-16

我正在使用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 filenn";   
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. 打开cv::VideoCapture对象并调用isOpened()以验证是否成功打开。我通常更喜欢单独声明捕获对象,然后使用open(0)打开它,但要测试什么对您有效
  2. 将帧读取到cv::Mat对象中。您可以使用read()或使用<<运算符执行进近
  3. 使用empty()验证帧是否为空
  4. 处理循环中的图像

使用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);

更新日志:

  • 根据@api55的评论,添加了isOpen()检查完整性
  • 为waitkey()添加了讨论
  • 建议评论掉目前打破循环的部分