一步一步学OAK之八:通过OAK相机实现视频帧拼接

news2024/11/18 10:45:38

帧拼接在有些场景下非常有用,比如将一个较大的帧输入到尺寸较小的神经网络中时。可以将较大的帧拆分成多个较小的帧,并将这些较小的帧输入到神经网络中。

这里我们使用 2 个 ImageManip 将原始预览帧拆分为两个帧。

这里写目录标题

  • 涉及到的节点内容
    • ColorCamera节点
    • ImageManip 节点
    • XLinkOut节点
  • 实现步骤
    • Setup 1: 创建文件
    • Setup 2: 安装依赖
    • Setup 3: 导入需要的包
    • Setup 4: 创建pipeline
    • Setup 5: 创建节点
      • 创建相机节点
      • 创建ImageManip节点并建立连接
    • 创建XLinkOut并建立连接
    • Setup 6: 连接设备并启动管道
    • Setup 7: 创建与DepthAI设备通信的输入队列和输出队列
    • Setup 8: 主循环
    • Setup 9:运行程序

涉及到的节点内容

ColorCamera节点

ColorCamera 节点是图像帧的来源。其输入输出如下图所示:
在这里插入图片描述

ImageManip 节点

ImageManip 节点可用于裁剪、旋转矩形区域或执行各种图像变换:旋转、镜像、翻转、透视变换。其输入输出如下图所示:
在这里插入图片描述

XLinkOut节点

XLinkOut节点用于通过XLink将数据从设备发送到主机。其输入输出如下图所示:
在这里插入图片描述

实现步骤

Setup 1: 创建文件

  • 创建新建10-imageManip-tiling文件夹
  • 用vscode打开该文件夹
  • 新建一个main.py 文件

Setup 2: 安装依赖

安装依赖前需要先创建和激活虚拟环境,我这里已经创建了虚拟环境OAKenv,在终端中输入cd…退回到OAKenv的根目录,输入 OAKenv\Scripts\activate激活虚拟环境

安装pip依赖项:

pip install numpy opencv-python depthai blobconverter --user

Setup 3: 导入需要的包

在main.py中导入项目需要的包

import cv2
import depthai as dai

Setup 4: 创建pipeline

pipeline = dai.Pipeline()

Setup 5: 创建节点

创建相机节点

camRgb = pipeline.createColorCamera()
camRgb.setPreviewSize(1000, 500)
camRgb.setInterleaved(False)
maxFrameSize = camRgb.getPreviewHeight() * camRgb.getPreviewWidth() * 3
  • 创建一个ColorCamera(camRgb),并设置其预览尺寸为1000x500像素。设置摄像头的数据格式为非交错格式(非交错表示像素数据是按照RGB或BGR的顺序连续存放的,而不是交错存储)。

  • maxFrameSize = camRgb.getPreviewHeight() * camRgb.getPreviewWidth() * 3
    计算最大帧尺寸。通过将camRgb摄像头节点的预览高度乘以预览宽度,再乘以3(代表每个像素有3个通道:红、绿、蓝),来计算最大帧尺寸。最终的结果将存储在变量maxFrameSize中。

创建ImageManip节点并建立连接

manip1 = pipeline.createImageManip()
manip1.initialConfig.setCropRect(0, 0, 0.5, 1)
manip1.setMaxOutputFrameSize(maxFrameSize)
camRgb.preview.link(manip1.inputImage)
  • 创建了一个图像处理节点(manip1)。

  • 通过调用initialConfig.setCropRect()方法,设置图像处理节点的裁剪区域。这里的参数(0, 0, 0.5, 1)代表裁剪区域的位置和大小。(0, 0)代表裁剪区域的左上角坐标,0.5代表裁剪区域的宽度占原始图像宽度的比例(这里为原始图像宽度的一半),1代表裁剪区域的高度占原始图像高度的比例(这里为原始图像高度的全部)。

  • 调用manip1.setMaxOutputFrameSize()方法,设置图像处理节点的最大输出帧尺寸为之前计算得到的maxFrameSize。

  • 通过调用camRgb.preview.link(manip1.inputImage)方法,将摄像头节点的预览输出连接到图像处理节点的输入。这样,图像处理节点将接收到来自摄像头的预览图像,并进行预定义的裁剪和调整尺寸操作。

manip2 = pipeline.createImageManip()
manip2.initialConfig.setCropRect(0.5, 0, 1, 1)
manip2.setMaxOutputFrameSize(maxFrameSize)
camRgb.preview.link(manip2.inputImage)

创建了另一个图像处理节点(manip2)。

  • 通过调用manip2.initialConfig.setCropRect()方法,设置图像处理节点的裁剪区域。这里的参数(0.5, 0, 1, 1)代表裁剪区域的位置和大小。(0.5, 0)代表裁剪区域的左上角坐标,1代表裁剪区域的宽度占原始图像宽度的比例(这里为原始图像宽度的一半之后的部分),1代表裁剪区域的高度占原始图像高度的比例(这里为原始图像高度的全部)。

  • 调用manip2.setMaxOutputFrameSize()方法,设置图像处理节点的最大输出帧尺寸为之前计算得到的maxFrameSize。

  • 通过调用camRgb.preview.link(manip2.inputImage)方法,将摄像头节点的预览输出连接到第二个图像处理节点的输入。这样,第二个图像处理节点将接收到来自摄像头的预览图像,并进行预定义的裁剪和调整尺寸操作。

创建XLinkOut并建立连接

xout1 = pipeline.create(dai.node.XLinkOut)
xout1.setStreamName('out1')
manip1.out.link(xout1.input)

创建XLinkOut节点,命名为xout1,并设置它的输出流名称为’out1’。然后,将manip1节点的输出链接到xout1节点的输入。这样,manip1节点处理后的图像数据将通过xout1节点输出。

xout2 = pipeline.create(dai.node.XLinkOut)
xout2.setStreamName('out2')
manip2.out.link(xout2.input)

创建第二个XLinkOut节点,命名为xout2,并设置它的输出流名称为’out2’。然后,将manip2节点的输出链接到xout2节点的输入。这样,manip2节点处理后的图像数据将通过xout2节点输出。

Setup 6: 连接设备并启动管道

with dai.Device(pipeline) as device:

Setup 7: 创建与DepthAI设备通信的输入队列和输出队列

    q1 = device.getOutputQueue(name="out1", maxSize=4, blocking=False)
    q2 = device.getOutputQueue(name="out2", maxSize=4, blocking=False)

创建两个输出队列q1和q2。

第一个输出队列q1通过设备的getOutputQueue方法创建,传入参数name="out1"表示要获取名称为"out1"的输出流。同时指定了队列的最大大小为4,blocking=False表示在队列满时不会阻塞添加新的元素。

第二个输出队列q2也是通过设备的getOutputQueue方法创建,传入参数name="out2"表示要获取名称为"out2"的输出流。同样地,指定了队列的最大大小为4,blocking=False表示在队列满时不会阻塞添加新的元素。

Setup 8: 主循环

    while True:

从输出队列q1和q2中获取帧数据并显示在窗口中

        if q1.has():
            cv2.imshow("Tile 1", q1.get().getCvFrame())

        if q2.has():
            cv2.imshow("Tile 2", q2.get().getCvFrame())

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

使用q1.has()q2.has()检查输出队列q1和q2是否有可用的帧数据。
如果输出队列q1有可用的帧数据,就使用q1.get().getCvFrame()获取最新的帧,并使用OpenCV的cv2.imshow()方法在名为"Tile 1"的窗口中显示。

如果输出队列q2有可用的帧数据,就使用q2.get().getCvFrame()获取最新的帧,并使用OpenCV的cv2.imshow()方法在名为"Tile 2"的窗口中显示。

使用cv2.waitKey(1)等待用户按下键盘上的键。如果检测到按键为字符’q’,则退出循环,结束程序。

Setup 9:运行程序

在终端中输入如下指令运行程序

python main.py

运行后的效果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/700062.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32实战项目—停车计费系统

文章目录 一、任务要求1.1 概述1.2 串口收发1.2.1 串口输出内容1.2.2 串口接收内容 1.3 说明 二、实现思路2.1 指令判别2.1 车辆进入2.2 车辆驶出2.3 费率调整 三、程序设计3.1 串口接收消息处理3.2 车辆驶入处理函数3.3 车辆驶出处理函数3.4 费率调整处理函数 题目原型是第十二…

4-Python如何创建等比数列?【视频版】

目录 问题视频解答 问题 视频解答 点击观看: 4-如何创建等比数列?

windows无法启动RemoteDesktopServices服务(位于本地计算机上)。错误126:找不到指定的模块。

win10的搜索栏输入 注册表编辑器。打开,找到如下路径 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TermService\Parameters 将指定数值项ServiceDll的数值数据改成默认值: %SystemRoot%\System32\termsrv.dll 再重新尝试就好了。 …

Java(七):项目部署

项目部署 运行容器解决Centos8中yum命令遇到的问题打包项目拷贝.jar到容器中安装jdk后台运行.jar后台运行.jar并输入日志实时查看日志查看/杀死运行程序目录结构日志配置 运行容器 $ docker run -d -p 8001:8001 -p 8081:8081 -p 8082:8082 --namelocal_centos --privilegedtr…

DigiCert SSL证书有什么优势?

DigiCert是全球领先的SSL证书颁发机构,2017年收购赛门铁克数字证书业务后,成为全球市场占有率领先的SSL证书提供商,提供高保证TLS/SSL证书和自动化解决方案,也是沃通CA在全球信任数字证书业务方面的重要合作伙伴。 与全球其他品牌…

AI聊天对话工具,让沟通更简单轻松

人工智能技术的发展不断为我们带来新的惊喜和变革,其中之一就是ai聊天对话应用。这种应用利用自然语言处理、机器学习和对话管理等技术,在智能手机、电脑等设备上实现了人机对话,让人们更轻松地与计算机之间进行交流和互动。随着移动互联网的…

基于SpringBoot的电脑商城项目

基于SpringBoot的电脑商城项目 — 参考B站袁庭新老师项目 Maven多聚合项目 技术栈: Spring boot、MyBtis、Bootstrap、Layui,Redis,内网穿透等 功能: 后台:管理员登录、商品信息管理、订单管理、用户信息管理、统计图…

springbootbatis

1、maven <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.…

在 Maya、ZBrush、Substance 3D 和 UE5 中创建理发椅

今天瑞云渲染小编给大家带来Kevin J. Coulman 分享的理发椅项目背后的工作流程&#xff0c;详细介绍了如何在 Maya 和 ZBrush 中为道具建模&#xff0c;分享了制作准确材质的技巧&#xff0c;并解释了为什么选择 UE5 进行渲染。 介绍 大家好! 我的名字是Mehdi Benmansour&…

如何搭建和使用minio?保姆级教程

目录 前言搜索镜像找到bitnami/minio镜像拉取镜像查看下载好的镜像创建数据卷目录&#xff0c;并提升权限根据镜像创建一个minio容器参数说明 查看 minio 容器的启动日志查看 minio 容器的信息开放安全组端口访问minio进入首页创建桶设置权限上传文件 前言 如果公司想要自己搭…

ASEMI代理艾赛斯MOS管IXFH4N100Q的性能与应用

编辑-Z 在电子元件领域&#xff0c;MOS管是一种重要的半导体器件&#xff0c;它在电子设备中起着至关重要的作用。今天&#xff0c;我们将重点介绍一款特别的MOS管——IXFH4N100Q&#xff0c;探讨其性能特点和应用领域。 首先&#xff0c;让我们了解一下什么是MOS管。MOS管&am…

Linux--进入一个路径:cd

Linux系统中&#xff0c;磁盘上的文件和目录被组成一棵目录树&#xff0c;每个节点都是目录或文件 cd是change directory的简写 语法&#xff1a; cd 目录名 功能&#xff1a; 改变工作目录。将当前工作目录改变到指定的目录下。 举例&#xff1a; cd .. : 返回上级目录&…

BFS (Java) 广度优先搜索 简单介绍、模板、案例(一)

一. BFS的简单介绍 深度优先搜索DFS和广度优先搜索BFS是经常使用的搜索算法&#xff0c;在各类题目中都有广泛的应用。 深度优先搜索算法&#xff08;英语&#xff1a;Depth-First-Search&#xff0c;DFS&#xff09;是一种用于遍历或搜索树或图的算法。其过程简要来说是对每一…

学习c++第01天

学习c的第01天 前言1、变量是声明&#xff1f;2.建议定义数据都对其进行初始化3.有符号数和无符号数4.进制间的相互转换5.原反补码6.const 、register 、volatile和typedef关键字7.数据类型的自动转换8.左移<< &右移操作>>9.将data的指定位数进行0、1转化的应用…

javaee 使用监听器统计当前在线用户列表

ServletContextListener 和 HttpSessionBindingListener 需要配和使用 TestServletContextListener package com.yyy.listener;import java.util.ArrayList; import java.util.List;import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import …

复现论文ChineseBERT(ONTONOTES数据集)

记录一下自己复现论文《ChineseBERT: Chinese Pretraining Enhanced by Glyph and Pinyin Information》的过程&#xff0c;最近感觉老在调包&#xff0c;一天下来感觉什么也没干&#xff0c;就直播记录一下跑模型的过程吧 事前说明&#xff0c;这是跑项目的实况&#xff0c;如…

实用类详解

第二章 实用类介绍 目录 第二章 实用类介绍 1.枚举 2.包装类及其构造方法 3.Math类 4.Random类 5.String类 总结 内容仅供学习交流&#xff0c;如有问题请留言或私信&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 有空您就点点赞 1.枚举 枚举指由一…

python-注册nacos服务

一、首页 Nacos&#xff08;Naming and Configuration Service&#xff09;是一个用于实现服务注册和发现的开源项目。Nacos注册服务的主要作用是帮助微服务架构中的各个服务实例进行注册和发现&#xff0c;以便于服务之间的通信和协作&#xff0c;另外&#xff0c;也可以在nac…

基于高性能的STM32G031K4T6、STM32G031K6T6、STM32G031K8T6(ARM微控制器)64MHz 闪存 32-LQFP

STM32G0 32位微控制器 (MCU) 适合用于消费、工业和家电领域的应用&#xff0c;并可随时用于物联网 (IoT) 解决方案。这些微控制器具有很高的集成度&#xff0c;基于高性能ARM Cortex-M0 32位RISC内核&#xff0c;工作频率高达64MHz。该器件包含内存保护单元 (MPU)、高速嵌入式内…

大数据赋能交通业务管理——远眺智慧交通集成管控系统

随着交通管理需求的不断提升&#xff0c;原有系统管理模式的缺点逐渐显露&#xff0c;各业务系统的相互独立、各自为战&#xff0c;成为交通管理人员全局把控交通资源、实现交通综合管控的壁垒。 智慧交通集成管控平台通过统一标准&#xff0c;集成交警各类业务系统、整合相关数…