草庐IT

基于FPGA:多目标运动检测(手把手教学①)

千歌叹尽执夏 2023-10-09 原文

目录

日常·唠嗑:

      在3月份发表了基于FPGA:运动目标检测(原理图+源码+硬件选择,可用毕设)后反应很强,很多同学表示,希望我们能在运动目标检测的基础上做多目标运动检测。最近跟其他两个工程师刚好有空,就把就版本的工程做了一次超大升级。
      本次工程,花了很多时间,所以整个设计写的都很详细,想学的同学可以慢慢嚼。

一、视频效果

话不多说,直接看效果

FPGA帧差法多运动目标检测(演示)

二、新旧版本比较

      本算法是针对已经进行了二值化的图像进行目标分割和标记。如帧差法运动目标检测算法,已经进行了帧间差、二值化、腐蚀、膨胀这些算法后得到的二值化图像。分割采样距离判别的方法,标记则采用矩形包围盒。

      本算法模块应用在新版本的“FPGA帧差法运动目标检测中”,可以直接替换老版本中的包围盒算法模块:find_box模块,接口定义兼容,同时新日两版本的区别也是在于本模块,所以在老版本基础上只需要额外理解本算法模块即可理解新版本代码。

三、新版本特色

1、开发环境

硬件环境: DMK301 FPGA开发板(EP4CE10)、AN5640摄像头模组。
软件环境: Quartusii13.1+配套的Modelsim-ase。

2、功能

1、OV5640摄像头采集实时视频
2、对视频进行帧差法运动目标检测算法处理
3、使用包围盒框选出目标,并实时显示在VGA显示屏
4、串口输出信息

3、特点

1、全套实物(含资料)
2、上电即出功能效果
3、最多支持16个目标
4、最大支持目标数量参数化可调
5、包围盒颜色参数化可调
6、串口输出目标位置和目标数量
7、提供源代码工程(Verilog)
8、提供Modelsim仿真
9、提供讲解视频&提供售后答疑

四、工程设计

1、原理说明

1、包装盒定义

      将目标所有部分都包含的面积最小的矩形。如下图中所示,图1中的矩形框是符合包围盒定义的,图2中的矩形框虽然包含了目标所有部分但面积不是最小的,图3中的矩形框虽然面积小,但是未包含目标的所有部分。

                                                                  图1

                                                                  图2

                                                                  图3

2、包围盒定位

2.1、单个目标定位

     在描述多目标定位原理前,先理解单个目标定位,这将有助于理解多目标的定位原理。

     单个目标定位本质上就是找到目标中所有像素点的横、纵坐标的最大和最小值,计为Xmax、Ymax、Xmin、Ymin,则包围盒就是由(XMin,Ymin)为左上角点坐标、(Xmax,Ymax)为右下角点坐标确定的矩形。

     实现原理是,在当前输入点灰度为1时,如果当前点的横坐标小于等于Xmin,则把Xmin更新为当前点的横坐标;如果当前点的横坐标大于等于Xmax,则把Xmax更新为当前点的横坐标;以此类推,对Ymax和Ymin也一样。核心代码描述如下:

if( per_img_Y == 1 'b1) begin
if(Ymin > y_cnt) Ymin <= y_cnt ;else
Ymin <= Ymin ;
if(Ymax < y_cnt) Ymax<= y_cnt ;else
Ymax<= Ymax ;
if(xmin > x_cnt) xmin<=x_cnt ;else
xmin <= xmin ;
if(Xmax < x_cnt) Xmax<= x_cnt ;else
Xmax<=Xmax ;
end

2.2、多个目标定位(解释的比较详细,认真看)

     定义N组寄存器用于储存N个包围盒的坐标,每个包围盒坐标以(Xmin[i],Ymin[])、(Xmax[],Ymax[1])表示,其中i∈[0,N-1]。图像像素从左上到右下的顺序扫描,依次输入每个像素,根据这一特性,对每一个输入为1的像素进行归属判断,看其属于哪个包围盒的范围,若不属于任何一个已存在的包围盒,则新生成一个包围盒。新生成的包围盒的Xmin和Xmax都赋值为当前点的横坐标,Ymin和Ymax都赋值为当前点的纵坐标。

     归属判断根据距离进行,当灰度为1的输入点距离某个包围盒小于设定的阈值时,则认为该点属于此包围盒,根据该点的坐标更新包围盒坐标。判断顺序按照包围盒的序号从小到大的顺序进行,只要该点属于任意一个包围盒则终止判断,即不再判断是否属于后续的包围盒。如图4所示,在A点输入时,原先的包围盒区域是左图中的区域,A点输入后,由于A点距离该包围盒较近即距离小于阈值,所以根据A点的坐标更新包围盒,可以看到Xmin和Ymax得到了更新,Xmin更新为A的横坐标,Ymax更新为A的纵坐标,而Xmax和Ymin则未更新,这是由于A的横坐标小于Xmax,A的纵坐标大于Ymin。这其实就是根据距离来对不同目标进行分割,不过该方法有个瑕疵,就是距离阈值的选取不能太小也不能太大,阈值太小则可能导致同一个目标的不同部分被分割为不同目标,就比如图4中,如果阈值过小,则会在A点输入时判断出A点不属于已存在的任何一个包围盒,从而以A点的坐标生成一个新的包围盒。反之,若阈值太大,可能导致不是同一个目标,但是由于距离较近而被识别成同一个目标。

图4:

3、包围盒绘制

     包围盒绘制实际上就是绘制已经定位出的包围盒矩形框,用比较醒目的颜色如红色为包围盒的矩形框着色。理论上包围盒的边框宽度是1,即矩形的4条边都是占用1像素宽度的线段,为了使包围盒更加突出明显,便于人眼观察,可以适当加宽矩形框4条边的宽度。根据输入图像的像素点坐标是否是包围盒的边框,决定该像素输出的像素值是原像素值还是包围盒的颜色,如以下代码描述:这里的2’d3即代表包围盒边框宽度为4,Box_COLOR是定义包围盒颜色的参数,x_min、y_min、x_max、y_max则是包围盒的坐标。
代码:

if( (( (x_cnt+2'd3 >= x_min && x_cnt 〈= x_min) ll (x_cnt 〈= x_max+2'd3 && x_cnt>= x_max)) && y_cnt+2 'd3 >= y_min 8& y_cnt <= y_max+2'd3)ll
(( (y_cnt+2'd3 >= y_min && y_cnt 〈= y_min)ll (y_cnt <= y_max+2'd3 &8 y_cnt>= y_max)) && x_cnt+2'd3 >= x_min && x_cnt <= x_max+2 'd3)
o_data <= Box_COLOR;
elseo_data <= i_data;

     上述代码只是针对1个包围盒的绘制,如果需要绘制多个包围盒,则可以例化多个相同的模块,前后串行连接,即先绘制第一个包围盒,再绘制第二个包围盒,类似添加不同的图层,每个模块负责一个图层,经过多个模块叠加绘制后,即可绘制出多个包围盒。
     这实际上是流水线操作的思想,每个包围盒绘制模块就负责一级流水线操作,当然这会导致从图像输入到图像输出会存在N个时钟的延迟,这里的N就代表使用几个包围盒绘制模块(这里默认包围盒绘制模块的延迟是1个clk,实际上我们的verilog程序最终实现的结果就是这样的)。

2、模块框图

     如图5所示是多目标包围盒算法的模块框图,输入两路视频、输出一路视频。
     Video Bin是经过帧间差、二值化、腐蚀、膨胀后得到的二值化图像,其中已包含目标,需要根据Video Bin进行包围盒定位;
     Video Org是原始图像,根据包围盒坐标在原始图像上叠加包围盒的矩形框;
     Video Output则是在原始图像上叠加过包围盒的结果。

     multy_locate模块功能是定位各个目标的包围盒坐标,其包含多个signle_locate模块的串联,每个single_locate模块记录1个包围盒信息,这个信息包括包围盒的坐标位置和包围盒是否生效。

     multy_locate模块还包含一个count_1s的模块,这个模块用来统计生效的包围盒个数,其实就是对多bit的数据进行"数1"运算,计算总计有多少个“1”"。

     bounding_box_draw模块则是根据1个包围盒坐标,在图像上叠加一个特定颜色的矩形框即画1个包围盒,每个模块最多只画1个(也可能不画,要看该包围盒是否生效)包围盒。

     多个bounding_box_draw模块串联,第一个模块画第一个包围盒、第二个模块画第二个包围盒,以此类推,以流水线方式操作直到最后一个模块叠加完成输出Video Output,每个bounding_box_draw模块会导致视频流产生1个时钟的延迟。
图5:

3、手把手教模块

1、bounding_box_top模块:

功能说明:
     多目标包围盒算法模块的顶层模块,例化multy_locate模块和bounding_box_draw模块。

参数定义:


接口定义:

—————————————————————————————————

五、未完、待续……

今天就先讲到这里,有兴趣的同学可以关注,后面持续更新~~

需要套件的同学,可以私信我预定,7月20号准时上架,开用竞赛、毕设等。

发货清单:
FPGA开发板(EP4CE10F17C8)
AN5640摄像头模组(OV5640)
USB Blaster下载器
VGA线
USB供电线。资料
工程源码。
设计报告。
开发板原理图。
摄像头模块资料售后服务
本产品提供售后技术支持和答疑服务,但只针对产品本身的相关内容或问题进行答疑,不提供二次开发的技术支持或答疑服务。

后面会继续讲解模块:
模块仿真
multy_locate模块
single_locate模块count_1s模块
bounding_box_draw模块

待续……

有关基于FPGA:多目标运动检测(手把手教学①)的更多相关文章

  1. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  2. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  3. 电脑0x0000001A蓝屏错误怎么U盘重装系统教学 - 2

      电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。  准备工作:  1、U盘一个(尽量使用8G以上的U盘)。  2、一台正常联网可使用的电脑。  3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。  4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。  U盘启动盘制作步骤:  注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注

  4. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  5. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  6. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  7. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  8. ruby - 检测由 RSpec、Ruby 运行的代码 - 2

    我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题

  9. ruby - 使用 Ruby Daemons gem 检测停止 - 2

    我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe

  10. ruby-on-rails - (Ruby,Rails) 基于角色的身份验证和用户管理...? - 2

    我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源

随机推荐