抓取帧 NTSC转USB加密狗,opencv2,python封装

6 投票
3 回答
10248 浏览
提问于 2025-04-17 20:36

背景:

我最近在玩Python和OpenCV2的结合。我想尝试一些想法,使用一个类似于汽车后视镜的广角摄像头。我从一辆报废的事故车上拆下了一个(它有四根线),根据线的颜色我做了一些猜测,把它连接起来,用USB A口给电源和接地线供电,并通过RCA接口传输NTSC复合信号。

我还买了一个NTSC转USB的转换器,像这个

这个转换器附带了驱动程序和一些现成的VHS转DVD软件。

问题:

我使用网上常见的示例来测试它,像这样:

import numpy as np
import cv2

cam_index=0
cap=cv2.VideoCapture(cam_index)


print cap.isOpened()
ret, frame=cap.read()

#print frame.shape[0]
#print frame.shape[1]

while (cap.isOpened()):
    ret, frame=cap.read()
    #gray=cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)


    cv2.imshow('frame', frame)


    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

#release and close 
cap.release()
cv2.destroyAllWindows() 

这是命令行的输出:

True

Traceback (most recent call last):
  File "C:/../cam_capture_.py", line 19, in <module>
    cv2.imshow('frame', frame)
error: ..\..\..\..\opencv\modules\highgui\src\window.cpp:261: error: (-215) size.width>0 && size.height>0 in function cv::imshow

>>> 

关键观察:

截图

  1. 在控制面板中,USB设备显示为“OEM捕获”,在“声音、视频和游戏控制器”下。因此,它并没有被识别为简单的即插即用网络摄像头,没在“成像设备”下显示。

  2. 如果我打开VHS转DVD软件,我需要配置两个方面:

    • 设置为复合信号
    • 设置编码为NTSC 这样模拟摄像头的画面就能在VHS转DVD应用中正常显示。
  3. 当我在FLV(设备捕获)中打开设备视频通道时,设备流只是黑屏,但如果我在FLV流媒体播放的同时打开VHS转DVD软件,我就能在FLV中看到摄像头的画面,而VHS转DVD的画面仍然是黑屏。另一个重要的区别是,当在FLV中流媒体播放时,延迟大约有0.5秒,而在VHS转DVD中则没有。

  4. 当我运行“cam_capture.py”这个示例代码时,在某个运行时刻,我最终会遇到停止错误代码0x0000008e:

详细信息:

stop: 0x0000008E (0xC0000005, 0xB8B5F417, 0X9DC979F4, 0X00000000 )

ks.sys - Address B8B5F417 base at B8B5900, Datestamp...

beg mem dump
phy mem dump complete

5.如果我尝试打印frame.shape[0]或frame.shape[1],我会得到一个类型错误,提示我无法打印类型为None的内容。

6.如果我尝试其他的cam_index,结果总是为false。

总结:

在“控制面板”中,摄像头设备在“声音、视频和游戏控制器”下,而不是在“成像设备”下;

cam_index==零;

capture.isOpened()=真;

帧大小为None;

如果VHS转DVD正在运行并配置为复合NTSC,摄像头就能工作,虽然你不能通过截图看到图像,但相信我!;)

有没有什么方法可以初始化与这个设备的通信,比如模拟VHS转DVD的设置(复合+NTSC)?我本以为这只是一个简单的解决方案,但现在感觉我在做一些超出预期的事情。

任何建设性的见解、建议或纠正都非常欢迎!

谢谢

祝好

3 个回答

1

我也遇到了同样的问题。作为解决办法,我首先尝试了@user3380927提出的方案,结果确实有效。不过因为我不想依赖外部软件,所以我开始用Python中的opencv调整参数。

这段代码效果很好(你需要在第一次读取画面之前插入这些代码):

cam.set(cv2.CAP_FFMPEG,True)
cam.set(cv2.CAP_PROP_FPS,30)

所以,基本的摄像头读取完整代码如下:

import cv2

cam = cv2.VideoCapture(1)
cam.set(cv2.CAP_FFMPEG,True)
cam.set(cv2.CAP_PROP_FPS,30)

while(True):
    ret,frame = cam.read()
    cv2.imshow('frame',frame)
    if (cv2.waitKey(1) & 0xFF == ord('q')):
        break

cam.release()
cv2.destroyAllWindows()

之后你就可以像往常一样进行图像处理了。顺便提一下,这是我的配置:

  • Opencv 3.1.0
  • Python 2.7.5
  • Windows 8.1
  • Elgato视频捕捉设备(在设备管理器中也显示为声音、视频和游戏控制器)
1

虽然这个回答晚了几个月,但可能对你有帮助。我在一台Windows电脑上工作,安装了设备自带的驱动程序。我用和你问题里一样的代码,尝试了Somagic的Ezcap,结果也遇到了同样的错误。因为出现了“frame is None”的情况,我决定在这段代码周围加一个if语句,想看看是不是初始化出错了。把它放进循环里:

if frame is None:
    print 0
else:
    print 1

结果是:01110111111111111111111111111...

如果把frame = cap.read()放在循环上面,并注释掉,得到的结果是:00111111111111111...

所以对于我的捕捉设备来说,似乎从第5帧开始的所有帧都能正常捕捉。我不太清楚为什么会这样,但现在这可能是一个有用的解决办法。

免责声明:不幸的是,我的摄像头输入目前在一个辐射场里,所以我得等几周才能确认它是否真的能正常工作。不过,现在的图像是黑色的框(没有正确输入是正常的)。

7

好的,经过深入调查,最初的怀疑得到了确认。也就是说,因为NTSC的接收器并不是被当作一个图像设备来处理(它被视为一个视频控制器,类似于电视调谐器卡的模拟),所以虽然我们可以用cam_index=0来调用cv2.VideoCapture,但视频通道本身并没有传输,因为我们需要定义一堆参数。

  1. 编码方式
  2. 帧大小
  3. 每秒帧数等

问题在于,由于这个设备不被支持为图像设备,调用cv2.VideoCapture.set(parameter, value)似乎对原始视频流没有任何影响。

我没有找到解决方案,但我找到了一种变通办法。网上似乎有很多选项。可以搜索关键词“DV转网络摄像头”或者“摄像机作为网络摄像头”。

我使用了DVdriver(http://www.trackerpod.com/TCamWeb/download.htm),我用的是试用版,因为我比较节省!

为什么它有效?

据我了解,DVdriver从被设置为视频控制器的设备中接收数据(类似于从“Windows Movie Maker”或ffmpeg捕获),然后通过“fairydust”将帧输出到cam_index=0(假设没有其他摄像头连接),作为一个“图像设备”的网络摄像头。

总结

简单来说,使用DVdriver或类似的软件。

我找到了一种变通办法,但我真的想从基本原理理解它,并可能在Python中生成类似的NTSC接收器初始化,而不依赖其他软件。不过在那之前,希望这能帮助到那些也在苦苦挣扎或者认为这是硬件问题的人。

最后留给你们一些贝克特的话:尝试过。失败过。没关系。再试一次。再失败一次。失败得更好。(!)

撰写回答