解决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

最开始的代码:


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

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

2.一般来说电脑能够外接数量也是有限的,电脑相机的ID无非是0、1、2,所以外接设备的ID号也应该是其中之一,如果有多个摄像头无法确定其对应的ID,可以参照C++跟C#获取电脑上连接的多个摄像头名称与编号来获取每个相机的名称和对应的ID。
我的输出结果如下图所示,说明我的外接设备的ID是0,问题是我最开始的ID就是VideoCapture cap(0); 按理说没问题才对啊?这就涉及到另一个问题:DShowopencv打开摄像头与DShow相关
解决OpenCV捕捉USB摄像头时抓帧失败的问题_第1张图片
所以此时我将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;
}

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

你可能感兴趣的:(OpenCV,USB相机,opencv,计算机视觉,人工智能)