运动标记校正检测

2023-11-08

该项目的目的是开发一个使用OpenCV的手势跟踪系统,该系统使用现场可编程门阵列(FPGA)作为嵌入式系统。 通常,锻炼手臂某些部位的人运动不正确且没有任何反馈。 因此,该项目的动机是识别特定手势并向用户提供有意义的纠正反馈。

该项目使用3D立体相机,与双核ARM-A9硬核处理器系统(HPS)配对的DE1-SoC Cyclone V FPGA和VGA设置,以使用OpenCV执行标记检测,简单的手势识别和3D立体视频输出。 该项目分为以下几个部分:1)系统安装,包括安装OpenCV,2)使用OpenCV进行标记检测,3)FPGA架构,使用片上和片外存储器流式传输和处理视频,4)使用 FPGA和HPS。

高层设计

总体而言,该系统实时跟踪运动物体上的标记。 该设计利用FPGA和HPS来处理和处理视频输入和输出。 我们使用HPS来运行包括OpenCV在内的外部软件并执行标记检测,而我们使用FPGA来流播浮雕视频并确定有关用户移动的反馈。 下面的框图描述了FPGA和HPS的作用以及用于增加图像处理能力的中间硬件。 \

HPS组件

视频输入:USB摄像头与Linux系统的接口很好,并且OpenCV只需很少的配置即可读取视频捕获,因此输入流在HPS端处理。 输入视频是数据流而不是视频流的形式。

标记检测:使用OpenCV中的Aruco模块检测标记。 标记的检测和处理是在HPS上完成的,因为与直接在FPGA上实现检测相比,这些库的使用更加简便快捷。 这也使我们可以使用更复杂的标记。

用户界面:方向性反馈(例如,指示用户上下移动,记录检测到的标记以及来自FPGA的相关反馈以及将此信息写入VGA系统)由HPS处理。

FPGA组件

存储器接口:我们开发了具有片外存储器的接口,因此HPS可以快速写入,而FPGA可以快速读取图像。 要写入VGA,必须在片上存储器中写入像素颜色。 为此,我们使用SRAM处理直接在FPGA上产生的立体图像。

反馈:给定x,y和z坐标(z为深度),FPGA跟踪y或z方向(横向或深度运动)的位置变化,并将方向信号发送回HPS。 它还执行校准以测量用户的基线/起始位置。

硬件和软件折衷

该项目必须解决的主要折衷是HPS和FPGA之间的分工。 由于存在像OpenCV这样的库,因此在HPS上进行困难的图像处理和标记检测是一种自然的选择。 从头开始在FPGA上实现这些算法会略微加快该过程,但会花费更多时间。 此外,该项目还探讨了将FPGA用作嵌入式系统而不是硬件加速器的用途。 最终,FPGA主要处理存储器管理和视频处理,这在FPGA上比在HPS上更快,更有效。

实现

Linux安装

为了简化OpenCV的安装,我们使用Ubuntu 16.04映像。 Terasic网站为Altera DE1-SoC板(rev.F板)提供了磁盘映像(CD-ROM部分)。需要16 GB SD卡来存储映像并在FPGA本身上运行操作系统。 SD卡上的默认映像设置包括用于HPS文件系统的4 GB内存,用于操作系统本身的大约2 GB内存以及剩余的未分配空间。最初,我们使用此默认值以及SD卡(具有相同的分区)来安装OpenCV和必要的软件包。但是,我们发现OpenCV构建不断失败,因为文件系统大小太小。此外,创建具有4 GB内存的交换文件仍然不会为我们的项目文件留出足够的空间。交换文件实质上是硬盘上被视为虚拟内存的空间,因此操作系统可以模仿RAM。要创建一个文件,需要增加文件系统的大小。因此,我们使用64位Windows 10操作系统来设置SD卡,并通过以下步骤成功设置了OpenCV:

GParted Live运行后,我们插入了SD卡并重新分区了磁盘,以便将所有未分配的内存分配给4 GB FAT32文件系统。 本教程对实际分区很有帮助。 一旦SD卡准备就绪,就可以通过以下步骤在FPGA上设置Ubuntu Linux:

相机

首先,我们尝试了DMC GF5松下立体声相机。 尽管我们能够获取左右图像,然后将其处理成立体图像,但没有视频或流媒体支持。 因此,我们订购了支持实时,3D视频,图像和流的SVPRO Synchronization 3D VR USB 2.0 MJPEG 60 FPS。 该摄像机具有左右鱼眼镜头,因此生成了两个视频流。 由于Windows不支持该相机,因此我们首先在Android设备上的3D相机Android应用(任何可使用3D相机的应用)上测试了SVPRO,并能够成功捕获视频。 为了访问FPGA上的摄像头,我们通过USB连接了摄像头,并能够检查系统是否在devices文件夹中识别了该摄像头。 由于缺少UVC驱动程序,我们无法将相机用于初始Linux版本。 但是,Ubuntu安装程序可以在相机上正常运行。

OpenCV

我们使用OpenCV进行标记检测。我们使用以下模块编译了OpenCV:

  • aruco
  • core
  • highgui
  • calib3d
  • features2d
  • flann
  • imgcodecs
  • imgproc
  • video

通过SDRAM将HPS转换为FPGA

由于生成了两个视频流(左右),因此我们选择创建一个浮雕视频流并在FPGA本身上处理图像。 为了快速连续写入240x320帧,HPS将每个左右传入帧写入SDRAM。 然后,FPGA可以通过定制的总线主控读取SDRAM。

要使用SDRAM,我们使用了ECE 5760 SDRAM总线主站示例以及Altera提供的SDRAM指南。 SDRAM本身不在芯片上,其容量为64 MB,这表明我们一次可以容纳大约30个8位帧(左右)。 从HPS写入SDRAM要求内存将虚拟地址映射到物理地址空间,并使用memcpy将映像写入内存。 在FPGA方面,必须通过QSYS设计的定制总线主控读取SDRAM。

HPS:当通过Mat对象通过OpenCV捕获输入视频时,图像将分为左右图像。 然后缩放两个图像。 为了将这两个图像都写入存储器,以便FPGA可以同步读取每个左右像素,我们创建了一个图像阵列,将特定坐标的每个左右8位RGB像素值压缩为16位短。 因为OpenCV数据格式是3色通道(红色,蓝色,绿色)的8位无符号字符,所以将每个RGB值提取并转换为8位像素颜色。 对左右图像进行此操作,然后将其压缩为16位值。 然后将16位值存储在图像数组中。 选择16位作为默认值,因为SDRAM在内部配置为处理16位数据。

Qsys:要读取存储器中的图像,FPGA无法直接从SDRAM读取。 必须设置一个Avalon总线主设备外设来驱动SDRAM,以抽象出片外存储模块。 我们建立了一个到Avalon桥(EBAB)的外部总线,其中avalon_master连接到SDRAM的avalon从站。 Qsys生成一系列外部信号,这些信号使我们能够与SDRAM接口。 这些信号包括地址,读/写信号,读/写数据和总线确认信号,表明总线已准备好读/写。 总线主机与计算机系统和HPS共享时钟并复位。

FPGA:FPGA仅与名为Bus_master_video的总线主机进行接口。 如果总线主机已准备就绪(总线确认为高),则顶级状态机(如上所述)将读取与位置(x,y)中的像素相对应的内存。 数据将被分为左右图像的RGB值。 所有这些都在一个时钟周期内发生,因为地址被设置为先前的状态(绘制先前的坐标时)。 一旦像素颜色值存储在寄存器中,我们就可以写入VGA了。

FPGA利用VGA

Qsys:一个名为“ onchip_vga_buffer”的双端口双时钟SRAM模块用于流化从SDRAM的视频流产生的立体图像。 第二个内存映射从设备连接到VGA子系统中的pixel_dma_master,该子系统处理给定像素颜色的屏幕写入。 该模块与计算机系统和HPS共享时钟并复位,并且另一个从端口被导出,因此FPGA可以写入数据。 请注意,无法删除默认的OnChip_SRAM模块,因为HPS似乎出于未知原因而使用它。 我们观察到,取消布线或使用它代替我们自己的SRAM模块,可以防止发生任何绘制。

FPGA:左右图像的RGB值的8位组合,以写入8位像素的颜色。在一个时钟周期内,我们将8位组合写入对应于SDRAM图像的(x,y)坐标/位置的SRAM。

Qsys和模块设计如下所示。

浮雕版本

为了创建立体图和不同的图像类型,我们使用了板上的开关来设置流的输出。 为了创建立体图,我们将右侧图像的红色像素颜色与左侧图像的蓝色和绿色放在一起,反之亦然。 下表列出了所有可能的输出。

顶层状态机

顶层状态机(如下图所示)唯一地控制SDRAM和SRAM之间的流。 状态机从高层次描述流。 在这里,重要的是要注意,在写入SRAM时,通过设置SDRAM地址将时钟周期数减少了一半(从4减少到2)。 虽然,我们的运行速度为CLOCK_50,但这仍在一定程度上提高了读取和写入帧的速度。

当我们写入SRAM时,我们还将增加当前的x和y坐标以确定下一个SDRAM地址。 x的范围是320,y的范围是240,以便在VGA屏幕的左上角创建320x240的显示。 一旦计算出帧中的每个像素,坐标就会重置。 通过将32位x值与比例为320的y值相加来计算SDRAM地址。在读取SDRAM时计算SRAM地址。 与SDRAM相同,我们使用x和y坐标确定地址偏移量,该地址偏移量将添加到基本内存地址(0)中以呈现匹配尺寸的图像。

反馈机制

向用户提供反馈的一种简单方法是纠正其运动的稳定性。 例如,如果标记从位置(0,0,0)开始,一旦完成移动,它应返回到位置(0,0,0)。 类似地,对于手部动作,完整而正确的动作假定在同一位置开始和结束。

标定

为了确定三个标记的大致起始位置,我们可以选择校准和重置系统。 为了进行校准,我们实际上采用了一些视频流帧的平均起始坐标(我们尝试了16、32或128帧)。 当按下KEY [0]时,计数器会跟踪捕获的帧数,并为每个x_start,y_start,z_start添加当前的x,y,z。 捕获到帧后,将所有起始位置位移相应的2的幂(4、5或7),并用作计算位置变化的基准。

反馈状态机

给定起点(x,y,z),预定义的阈值用于计算垂直距离(y)或深度的变化。 以y方向为例。 对于每个坐标,将当前y位置和起始y位置的绝对差值与预定阈值进行比较。 如果位移超出阈值的范围,则反馈信号将根据差值是正值还是负值发送“向上移动”或“向下移动”信号。 如果差异为正,则用户应收到“向下移动”,如果为负,则应“向上移动”,否则,反馈将显示为“保持静止”。 该阈值等于在特定方向上移动的像素数。 该值需要调整,更多细节可以在测试部分中找到。 此机制的状态机如下所示。

并行I / O端口

为了不断读取(x,y,z),我们为每个标记设置了一个端口的24位并行端口,并一次性发送了每个8位坐标。 为了跟踪我们实际评估的标记,标记号通过2位并行端口发送。 我们还具有用于阈值,反馈和启动开关的端口,以启动系统。 这些在下面详细说明。

测试和结果

标记检测

首先测试标记检测,我们使用模式生成器打印出Aruco Checkerboard,并使用Linux Ubuntu SetUp来查看是否实际检测到了标记。 Ubuntu允许我们使用视频观看gui,以便我们可以准确地查看左右图像中是否都检测到正确的标记。 我们使用此设置还可以测试左右图像之间的匹配标记。

一旦我们确信检测正常,便保留了Linux Ubuntu映像,但不使用VGA设置,桌面GUI或视频GUI。我们通常在坐标上使用打印语句来调试其余数据处理。

在FPGA的VGA上进行视频流传输后,我们在FPGA端使用HPS接口和SignalTap测试了标记。 我们在细木棍上放置了三个标记(如下图所示),以模拟手臂的运动,并在坐标,反馈和标记ID上使用了打印语句,以检查检测和反馈是否正常工作。

阈值和反馈

详情参阅 - 亚图跨际

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

运动标记校正检测 的相关文章

随机推荐

  • MATLAB-基于长短期记忆网络(LSTM)的SP500的股票价格预测 股价预测 matlab实战 数据分析 数据可视化 时序数据预测 变种RNN 股票预测

    MATLAB 基于长短期记忆网络 LSTM 的SP500的股票价格预测 股价预测 matlab实战 数据分析 数据可视化 时序数据预测 变种RNN 股票预测 摘要 近些年 随着计算机技术的不断发展 神经网络在预测方面的应用愈加广泛 尤其是长
  • CMake option选项开关

    CMake option 使用场景 编译脚本传递参数 gt CMake脚本接收option gt 源代码宏 编译脚本传入参数 传入一个cmake option TEST DEBUG bin sh cmake DTEST DEBUG ON c
  • CentOS7安装JAVA Mysql Tomcat Nginx 详细步骤

    CentOS7安装JAVA Mysql Tomcat Nginx 1 CentOS 7 JAVA 安装 在usr local src 下创建文件夹 将jdk放到文件夹中 1 查看当前Linux系统是否已经安装java 输入 rpm qa g
  • 两种常见的缓存淘汰算法LFU&LRU

    1 LFU 1 1 原理 LFU Least Frequently Used 算法根据数据的历史访问频率来淘汰数据 其核心思想是 如果数据过去被访问多次 那么将来被访问的频率也更高 1 2 实现 LFU的每个数据块都有一个引用计数 所有数据
  • 我不允许2022年还没有程序员看过这份Docker学习笔记,看完就知道有多香

    前言 种一棵树最好的时间是十年前 其次是现在 很多程序员一开始在学习上找不到方向 但我想在渡过了一段时间的新手期之后这类问题大多都会变得不再那么明显 工作的方向也会逐渐变得清晰起来 但是没过多久 能了解到的资料就开始超过每天学习的能力 像是
  • Node.js中的断言处理

    在Node js中 可以利用assert模块进行断言处理 即书写一些判断用测试代码 如果判断结果为假 则抛出AssertionError异常 判断两个值是否相等 assert equal actual expected message ac
  • mysql清空表,id重新开始计算

    清空表 1 自增的id重新从1开始 如果有外键的话可能出错 使用方法2 truncate table 你的表名 2 先清除表 然后设置自增字段从1重新开始 DELETE FROM article ALTER TABLE article au
  • npm安装、切换淘宝镜像

    npm默认镜像源是国外的 安装依赖速度较慢 使用国内的镜像源速度会快一些 1 设置淘宝镜像源 npm config set registry https registry npmmirror com 2 查看当前镜像源 npm config
  • 拷贝、赋值和销毁

    拷贝 1 拷贝构造函数 如果一个构造函数的第一个参数是自身类类型的引用 且任何额外参数都有默认值 则此构造函数为拷贝构造函数 拷贝初始化不仅在我们用 定义变量时发生 以下情况也会发生 将一个对象作为实参传递给一个非引用类型的形参 从一个返回
  • redisCluster中模糊获取key

    在一个集群中 显然不能通过keys方法通过pattern直接获取key的集合 鉴于这种问题 产生了两种思路 如下 方案1 已知相同的tag的KV会在一个节点上 所以只要key带有相同的hashtag 则会在一个节点上 所以只要扫描该节点即可
  • base64原理+base64隐写

    借鉴一位大佬的博客 说一下base64原理及base64隐写的原理 转载自大佬博客 https www tr0y wang 2017 06 14 Base64steg BASE64 是一种编码方式 是一种可逆的编码方式 编码后的数据是一个字
  • Qt示例3:用Qt画一个温度计

    示例1 以下是用Qt绘制一个简单的温度计的示例代码 include
  • Docker 启动失败Starting docker (via systemctl): Job for docker.service failed

    Starting docker via systemctl Job for docker service failed See systemctl status docker service and journalctl xn for de
  • Hive 整合 Spark 全教程 (Hive on Spark)

    文章目录 Hive 引擎简介 环境配置 ssh已经搭好 JDK准备 Hadoop准备 部署 配置集群 配置历史服务器 配置日志的聚集 启动集群 LZO压缩配置 Hadoop 3 x 端口号 总结 MySQL准备 Hive 准备 Spark
  • 软件设计师---计算机网络

    计算机网络 网络设备 真题 协议簇 真题 TCP和UDP IP TCP UDP 区分 真题 SMTP和POP3 真题 ARP 真题 DHCP 真题 url 真题 浏览器 ip地址和子网划分 真题 IPV6 真题 无线网络 真题 Window
  • 论文阅读 - RNN生成文本《Generating Sequences With Recurrent Neural Networks》

    20201101 0 引言 昨天在整理论文的时候 看到了这篇论文 Generating Sequences With Recurrent Neural Networks 实际上这篇论文我很早就看了 只不过当时没有具体来理解 昨天仔细看了看
  • 1.Flutter 抽屉组件drawer 自定义宽度,触发按钮

    效果图如下 实现代码如下 详解都在代码内哦 drawer Drawer child ListView 抽屉里面一个list部件 padding EdgeInsets all 0 顶部padding为0 children
  • 【vue】——CDN或全局引入CSS、JS。

    在入口文件index html中添加 div div 转载于 https www cnblogs com fayin
  • 基于html 与c++ 交互

    前一阵 与c 交互 发现qt写页面实在太丑 于是便使用qwebchannel js 与c 进行交互 发现使用起来还不错 下面 看看qwebchannel的用法 首先 新建一个qwebchannel的对象 new QWebChannel qt
  • 运动标记校正检测

    该项目的目的是开发一个使用OpenCV的手势跟踪系统 该系统使用现场可编程门阵列 FPGA 作为嵌入式系统 通常 锻炼手臂某些部位的人运动不正确且没有任何反馈 因此 该项目的动机是识别特定手势并向用户提供有意义的纠正反馈 该项目使用3D立体