我想通过OpenCV将视频图像叠加到传入的网络摄像头流上。作为第一步,我试图将传入的视频从网络摄像头/dev/video0
流式传输到/dev/video1
(v4l2loopback)的虚拟视频设备。不幸的是,我无法将网络摄像头流转发到v4l2loopback设备。无法将网络摄像头视频路由到Linux上的虚拟视频设备(通过OpenCV)
我发现这个帖子:How to write/pipe to a virtual webcam created by V4L2loopback module?,但那里的链接并没有真正帮助我。
从网络摄像头获取并观看流可以很好地与OpenCV页面中的一些小演示代码一起使用。以及来自v4l2loopback页面的示例代码,例如,播放静态视频文件到/dev/video1
效果很好。我可以看视频当我连接VLC /dev/video1
我已经读过,必须通过常规Linux驱动程序命令(打开,ioctl,写等)来控制v4l2loopback设备。所以OpenCV中没有包装类来写入回送设备。我的摄像头以640x480流媒体和MJPG。有趣的是,我可以通过VLC连接到回送设备,当按下播放按钮时,我可以看到正确的分辨率,编解码器和FPS。进度条上的时间计数器也开始运行。但屏幕仍然是黑色的(带有VLC标志)。
什么我大致做的是这个(BTW:代码可能无法编译...不想在这里杂乱的一切...让我知道,如果你需要更多的细节):
int main (int argc, char **argv) {
cv::VideoCapture cap;
struct v4l2_format vid_format;
size_t framesize = 640 * 480 * 3; // 3 Bytes per pixel
__u8 *buffer = null;
int fd = null;
cap.open ("/dev/video0");
fd = open ("/dev/video1", O_RDWR);
memset (&vid_format, 0, sizeof(vid_format));
vid_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
vid_format.fmt.pix.width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
vid_format.fmt.pix.height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
vid_format.fmt.pix.pixelformat = { 'M', 'J', 'P', 'G' };
vid_format.fmt.pix.sizeimage = framesize;
vid_format.fmt.pix.field = V4L2_FIELD_NONE;
vid_format.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
ioctl (fd, VIDIOC_S_FMT, &vid_format);
buffer = (__u8*) malloc (sizeof(__u8) *framesize);
memset (buffer, 0, framesize);
for(;;) {
cv::Mat frame;
cap >> frame;
write (fd, &frame.data, framesize);
}
}
如果有人能够给我一个提示,我需要如何转换wecam数据才能被VLC接受,那将会非常棒。
我不是完全熟悉V4L2,但是当将像素格式设置为MJPEG时,您应该编写MJPEG编码帧而不是原始BGR像素数据? –
确实这是一个很好的问题。我也不是很熟悉所有这些(相当混乱)pixelformat,colorspace等东西。我试图深入一点,但这个人杀了我:https://wiki.videolan.org/YUV/ – Bernd