• 解决OpenCV捕捉USB摄像头时抓帧失败的问题


    笔记本上外接了一个USB相机,用OpenCV打开摄像头捕捉图像结果报错如下:

    [ WARN:1] videoio(MSMF): OnReadSample() is called with error status: -2147024809
    [ WARN:1] videoio(MSMF): async ReadSample() call is failed with error status: -2147024809
    [ WARN:0] videoio(MSMF): can't grab frame. Error: -2147024809
    
    • 1
    • 2
    • 3

    最开始的代码:

    
    #include 
    
    #include "opencv2/opencv.hpp"
    using namespace std;
    using namespace cv;
    int main() {
    	VideoCapture cap(0); 
    	if (!cap.isOpened()) {
    		return -1;
    	}
    	namedWindow("frame", WINDOW_AUTOSIZE);
    	for (;;) {
    		Mat frameIn;
    		cap >> frameIn;
    		imshow("frame", frameIn);
    		if (waitKey(30) >= 0) break;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    videoio(MSMF): can’t grab frame. Error: -2147024809这个报错显示为抓帧失败,以前从来没遇到过这个问题,程序是最简化的程序了肯定不会有问题,一度怀疑是相机不能用。
    其实这个问题只与USB相机的ID号有关,可以通过下面两种方式获取ID号:
    1.参考网上的方法进行暴力破解cv2.VideoCapture(0)获取USB摄像头失败解决方案,等待的时间稍微有点长,一般而言最后出来的ID都是700(待会在第二种方法下面解释原因),将VideoCapture cap(id)中的id改为700即可正常显示:

    
    #include 
    
    #include "opencv2/opencv.hpp"
    using namespace std;
    using namespace cv;
    int main() {
    	int id = 3;
    	while (true)
    	{
    		VideoCapture cap(id);  //ID:700
    		if (!cap.isOpened())
    			id += 1;
    		else break;
    	}
    	cout << "id:" << id << endl;
    	VideoCapture cap(id);  //ID:700
    	if (!cap.isOpened()) {
    		return -1;
    	}
    	namedWindow("frame", WINDOW_AUTOSIZE);
    	for (;;) {
    		Mat frameIn;
    		cap >> frameIn;
    		imshow("frame", frameIn);
    		if (waitKey(30) >= 0) break;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2.一般来说电脑能够外接数量也是有限的,电脑相机的ID无非是0、1、2,所以外接设备的ID号也应该是其中之一,如果有多个摄像头无法确定其对应的ID,可以参照C++跟C#获取电脑上连接的多个摄像头名称与编号来获取每个相机的名称和对应的ID。
    我的输出结果如下图所示,说明我的外接设备的ID是0,问题是我最开始的ID就是VideoCapture cap(0); 按理说没问题才对啊?这就涉及到另一个问题:DShowopencv打开摄像头与DShow相关
    在这里插入图片描述
    所以此时我将VideoCapture cap(0); 改为:VideoCapture cap(0,CAP_DSHOW);
    原始程序变为:

    
    #include 
    
    #include "opencv2/opencv.hpp"
    using namespace std;
    using namespace cv;
    int main() {
    	VideoCapture cap(0,CAP_DSHOW);  //ID:700
    	if (!cap.isOpened()) {
    		return -1;
    	}
    	namedWindow("frame", WINDOW_AUTOSIZE);
    	for (;;) {
    		Mat frameIn;
    		cap >> frameIn;
    		imshow("frame", frameIn);
    		if (waitKey(30) >= 0) break;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    所以归根结底还是摄像头需要进一步指定DShow(DirectShow)来打开,其对应的ID值就是700.

  • 相关阅读:
    Transformer笔记
    【论文阅读】Weakly Supervised Semantic Segmentation using Out-of-Distribution Data
    ModelSim相关实用设置
    vscode配置vue
    learning vim
    [go学习笔记.第十六章.TCP编程] 2.项目-海量用户即时通讯系统
    一个程序员离职,成本竟然这么恐怖!
    软件工程——设计模式之创建型模式(单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。)
    第 112 场 LeetCode 双周赛题解
    C++的学习顺序
  • 原文地址:https://blog.csdn.net/Asabc12345/article/details/127219247