如何将OAK相机当作可移除背景的网络摄像头?
我们之前出过一个教程,是说如何将OAK相机当作网络摄像头使用,本期教程在这个基础上再增加了一个移除背景的效果。教程来源于Victor Sonck,由OAK中国整理发布。
本教程演示使用的设备是单目的OAK-1,当然你也可以用其他OAK相机,比如OAK-D、OAK-D-Lite等。
OAK简介
Victor最开始是在kickstarter上看到OpenCV的众筹活动,而心动买了一台OAK-1和OAK-D。OpenCV人工智能套件(OAK)本质上是开源相机板,内置Myriad X芯片,用于板上计算机视觉处理。鉴于它们的嵌入式性质,这意味着与NVIDIA Jetson系列等全Linux板相比,它们的功耗低,速度快。有什么理由不喜欢呢?
硬件展示
OAK-1自带一根USB-C线,仅此而已。OAK-D配备了一个额外的5v电源适配器,旁边是与OAK-1相同的USB-C线。
Victor对于相机的铝制外壳质量印象深刻,看起来很不错,相机背面有一个标准的摄像头支架,便于安装。总的来说,它看起来真的很整洁!
两个OAK都有相同的IMX378 4K 60fps传感器,OAK-D有2个额外的双目摄像头。更多的规格信息可在产品页面查看:OAK-1,OAK-D。甚至还提供每个的3d模型,所以你可以自己围绕它们设计配件!厉害!
快速启动
根据这个文档来安装、启动、运行,Victor用起来表示这些都是轻而易举的事。只需按照上面链接中的说明操作,你马上就可以开始运行了。
使用OAK-1作为网络摄像头
Victor是一个开源迷,喜欢使用Firefox作为日常驱动程序,但谷歌会议(Google Meet)不支持Firefox中的背景移除。是时候改变了!
让我们构建一个定制的OpenCV AI Kit管道,运行一个背景替换模型,并将其连接到一个虚拟网络摄像头,以便在任何会议软件中使用!
模型
谷歌会议,像许多其他会议软件一样,允许你删除你的背景,并以模糊的版本甚至任何其他你想要的图像来取代它。但与其他会议软件不同的是,谷歌在Apache许可证下免费提供了他们的背景去除模型
你可以在Google ai的博文中读到更多的信息。他们深入研究了他们如何将TensorFlow Lite模型部署到浏览器上,并在非常低规格的硬件上运行后台分割。
作为Edge社区CV的真正英雄,PINTO0309将该模型移植到了takes a breath。TFJS(Float32/Flot16),TF-TRT(Float32/Float16),TFLite(Float32/Float16,INT8),OpenVINO(FP32/FP16)和CoreML。
所有这些以及更多的东西都可以在他的model zoo里找到,强烈推荐!
转换模型格式
OAK建立在英特尔Myriad X芯片之上,该芯片也在英特尔的神经计算棒2中。这意味着我们需要将任何模型转换成Myriad可以读取的blob格式。OAK背后的公司Luxonis提供了一个很好的转换工具,可以将Caffe、Tensorflow或OpenVINO模型转换成所需的blob格式。你也可以通过安装OpenVINO或运行英特尔自己的docker容器来自己做。
这个步骤对于边缘加速器来说是很正常的。例如,Coral边缘TPU就必须做类似的转换步骤。
管道
作为嵌入式设备也意味着没有Linux发行版,一切都必须通过USB线。然而,幸运的是,使用他们的管道-节点模型,部署代码是令人耳目一新的简单。你使用不同的节点建立一个管道,然后将它们相互连接或连接到输入或输出队列。这些节点实际上就是Python队列,你可以从其中获取(),然后做你想做的事情。
彩色摄像机有两个输出:视频和预览。这些可以同时被处理。它是为ML设计的:将预览尺寸设置为神经网络输入,并将其发送给神经网络。把视频放到一个不同的队列中,并把这些帧保留到以后,当我们想要高质量的结果时。
def create_pipeline(self):
# Create pipeline and set version
pipeline = dai.Pipeline()
pipeline.setOpenVINOVersion(version=dai.OpenVINO.Version.VERSION_2021_3)
# Camera specific settings
cam = pipeline.createColorCamera()
cam.setPreviewSize(*self.nn_shape)
cam.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P)
cam.setInterleaved(False)
cam.setBoardSocket(dai.CameraBoardSocket.RGB)
cam.setColorOrder(dai.ColorCameraProperties.ColorOrder.RGB)
cam.setPreviewKeepAspectRatio(False)
# Set camera high quality output
cam_xout = pipeline.createXLinkOut()
cam_xout.setStreamName("high_quality_out")
cam_xout.input.setBlocking(False)
# Define a neural network that will make predictions based on the source frames
detection_nn = pipeline.createNeuralNetwork()
detection_nn.setBlobPath(self.nn_path)
detection_nn.input.setBlocking(False)
# Create neural network output
detection_nn_xout = pipeline.createXLinkOut()
detection_nn_xout.setStreamName("detection_out")
detection_nn_xout.input.setBlocking(False)
# Link different inputs and outputs
# Send the resized 'preview' stream to the nn, while the high quality output is sent to another queue
cam.video.link(cam_xout.input)
cam.preview.link(detection_nn.input)
detection_nn.out.link(detection_nn_xout.input)
return pipeline
现在我们需要启动管道,定义2个输出队列:detections和hq_images,然后把它们混在一起,生成一个替换了背景的帧。将生成的帧推送到最后一个队列,该队列将把它发布到一个虚拟的网络摄像头上,供任何会议软件使用。
def run(self):
pipeline = self.create_pipeline()
# Pipeline defined, now the device is connected to
with dai.Device(pipeline) as device:
# Start pipeline
device.startPipeline()
# Set queues to be read from later
self.high_quality_out = device.getOutputQueue(name="high_quality_out", maxSize=4, blocking=False)
self.detection_out = device.getOutputQueue(name="detection_out", maxSize=4, blocking=False)
# Create a separate thread which will read the final frames from a queue
# and ingest them in a virtual webcam
t = threading.Thread(target=self.pipe_to_virtual_webcam)
t.start()
# Start processing the detections frame by frame by reading from the 2 queues above
final_frame = self.process_detections()
# Add the final frame (with background replaced) to the queue for the virtual webcam to read from
self.webcam_queue.put(cv2.cvtColor(final_frame, cv2.COLOR_BGR2RGB))
# Wait for thread to finish
t.join()
self.webcam_queue.join()
虚拟网络摄像头
Python有一个很好的包来处理向虚拟网络摄像头发布帧。它也有很好的关于如何设置的文档。我们只需创建一个线程,从webcam_queue中读取并将这些帧发布到虚拟摄像机中。
一个虚拟摄像机在你的系统中看起来就像一个普通的网络摄像机,但你可以自己控制摄像机 “看到 “的东西。
def pipe_to_virtual_webcam(self):
with pyvirtualcam.Camera(width=854, height=480, fps=30) as cam:
print(f'Using virtual camera: {cam.device}')
while self.is_running:
frame = self.webcam_queue.get()
cam.send(frame)
cam.sleep_until_next_frame()
演示
谷歌做了更多复杂的后期处理来使悲剧变得漂亮和干净。本教程只是把处理能力扔给了一个jointiblinefilter(联合双线性过滤器),但是结果还不错!这就是了,在火狐上运行!
Victor的使用感受
OpenCV AI Kit玩起来真的很酷,它构建得很好,文档也很好,社区支持也很棒。使用python(还有一个C++ API)很容易构建一个管道并与之交互。乍一看,与类似的TFLite型号相比,我确实看到了性能上的损失,但我没有进行正面比较,所以我不能支持这一点。
一定要看看谷歌会议背景分割模型,这是一个很酷的小模型和附带的博客帖子也很值得一读。
现在,我还可以在Firefox中替换我的背景,我甚至可以添加MP4背景,这是Google meet目前还不支持的。
最后,我现在只真正玩过OAK-1,我很高兴在以后的博客或YouTube视频中与OAK-D及其深度视觉进行较量!