ZYNQ图像处理项目——帧差法运动目标跟踪

这篇具有很好参考价值的文章主要介绍了ZYNQ图像处理项目——帧差法运动目标跟踪。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、帧差法运动目标跟踪概述

1.1 基本原理

帧差法顾名思义就是对输入的前后两帧图像做差值,然后检测出两帧图像不同的地方,并且可以实时跟踪运动的目标轮廓。
本设计是基于ZYNQ7010和VIVADO2018.3实现的帧差法运动目标检测,针对运动目标检测算法在传统 PC端上实时性较差的问题,设计了一种基于 ZYNQ 硬件加速的运动目标实时检测系统。将摄像头采集的彩色视频流转换为灰度视频流并进行图像处理来实现运动目标检测,并将检测后的结果与原彩色视频流叠加来显示实时检测结果。

1.2 效果展示

本设计使用到的硬件有ZYNQ7010、768P显示屏、OV5640摄像头这些硬件,在原有的摄像头显示例子上搭建完成,关于显示环境的搭建可以参照前面的文章。
帧差法项目通过pl端两个按键分别控制帧差的阈值和输出图像的类型。按键1控制阈值为40-100递增,按键2控制输出图像类型为原始RGB图像、灰度图像、帧差结果图像以及RGB叠加检测框图像。

ZYNQ图像处理项目——帧差法运动目标跟踪
原始图像

ZYNQ图像处理项目——帧差法运动目标跟踪
灰度图像

ZYNQ图像处理项目——帧差法运动目标跟踪
帧差结果图像

ZYNQ图像处理项目——帧差法运动目标跟踪
ZYNQ图像处理项目——帧差法运动目标跟踪
ZYNQ图像处理项目——帧差法运动目标跟踪
原始图像迭代帧差结果图像

二、帧差法的实现

2.1 帧差法项目架构

这边的项目架构主要是参照了《基于ZYNQ加速的帧差法运动目标检测》这样一篇论文,大家可以去下载看看。然后视频教程的话,我是看了B站up主大磊FPGA的视频,大家也可以去看看。
下图是我的帧差法实现运动目标检测跟踪的整体框图了。大致的原理过程是这样子的,首先OV5640采集图像,将采集到的图像分别送入到vdma0和vdma1中,然后两个vdma缓存不同的帧数,达到帧差的效果;之后将两帧图像送入到自己编写的帧差模块进行差值计算,之后将结果输出到vdma2;最后经过DVI模块将信号送至hdmi显示屏上显示。
ZYNQ图像处理项目——帧差法运动目标跟踪
下面这张图呢是我参照b站视频里面的,帧差代码也主要完成下面这个框图。将其中一个vdma,比如vdma0中的数据送到fifo进行缓存。然后当vdma1中的数据的user来到时,从fifo中读数据,这样可以对齐信号。因为从fifo中读数据需要耗费两个时钟周期,所以vdma1的数据延迟2clk,之后就是转灰度,做差值,都比较简单。
ZYNQ图像处理项目——帧差法运动目标跟踪
然后这边需要说一下这个握手的协议。它是有五组信号组成,data是数据信号,user是一帧图像的开始信号,last是一帧图像每一行结束的信号,当valid和ready拉高时数据有效。
ZYNQ图像处理项目——帧差法运动目标跟踪

2.2 帧差法模块代码

首先是信号的定义,有三组信号,分别是vdma0和vdma1的输入,以及输出到vdma2这样的三组信号。

module  frame_diff(
    input clk,
    input rst_n,

    //control key
    input key0,
    input key1,

    //data stream from vdma0
    input [23:0]    s0_axis_tdata,
    input           s0_axis_tvalid,
    output          s0_axis_tready,
    input           s0_axis_tuser,
    input           s0_axis_tlast,

    //data stream from VDMA1
    input [23:0]    s1_axis_tdata,
    input           s1_axis_tvalid,
    output          s1_axis_tready,
    input           s1_axis_tuser,
    input           s1_axis_tlast,

    //data stream to VDMA2
    output reg [23:0]       m_axis_tdata,
    output reg              m_axis_tvalid,
    input                   m_axis_tready,
    output reg              m_axis_tuser,
    output reg              m_axis_tlast
);

接着就是信号缓存了,对vdma0来的数据到user来临时就开始存;然后当vdma1的user来临时就开始从fifo中读数据。注意vdma1的数据延迟2clk来同比,具体可以看代码。

//-------------------------------------------------------
//          fifo write and read data from vdma0
//-------------------------------------------------------

reg [23:0] data_in;
reg data_wr;
reg data_wr_en;
wire data_alfull;
wire [23:0] data_out;
reg data_rd;
reg data_rd_en;
reg [23:0] s0_axis_tdata_dy1;
reg [23:0] s0_axis_tdata_dy2;

//write data to fifo
assign s1_axis_tready=~data_alfull; //always ready until fifo is full

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
      data_wr<=1'b0;
      data_wr_en<=1'b0;
      data_in<=24'd0;
    end
    else begin
      if(s1_axis_tvalid & s1_axis_tready & s1_axis_tuser)begin  //when s0_user is come,wr_en is high,make corrsponding 
        data_wr_en<=1'b1;
      end
      if(s1_axis_tvalid & s1_axis_tready)begin  //begin to write data to fifo
        data_wr<=1'b1;
        data_in<=s1_axis_tdata;
      end
      else begin
        data_wr<=1'b0;
        data_in<=data_in;
      end
    end
end

//read data from fifo
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
      data_rd<=1'b0;
      data_rd_en<=1'b0;
    end
    else begin
      if(s0_axis_tvalid & s0_axis_tready & s0_axis_tuser)begin//unfull    //when fifo is alfull and data from camera is come,rd_en is high 
        data_rd_en<=1'b1;
      end
      if(s0_axis_tvalid & s0_axis_tready)begin
        data_rd<=1'b1;
      end
      else begin
        data_rd<=1'b0;
      end
    end
end

//fifo define 24*1024
fifo_generator_0 u_fifo_generator_0 (
  .clk        (clk),                  // input wire clk
  .srst       (~rst_n),                // input wire srst
  .din        (data_in),                  // input wire [23 : 0] din
  .wr_en      (data_wr_en & data_wr),              // input wire wr_en
  .rd_en      (data_rd_en & data_rd),              // input wire rd_en
  .dout       (data_out),                // output wire [23 : 0] dout
  .full       (),                // output wire full
  .almost_full(data_alfull),  // output wire almost_full
  .empty      (),              // output wire empty
  .data_count ()              // output wire [10 : 0] data_count
);

//read from fifo cost 2 clk, so data from camera need delay 2 clk too
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
      s0_axis_tdata_dy1<=24'd0;
      s0_axis_tdata_dy2<=24'd0;
    end
    else begin
      s0_axis_tdata_dy1<=s0_axis_tdata;
      s0_axis_tdata_dy2<=s0_axis_tdata_dy1;
    end
end

然后我这边又定义了两个按键检测和滤波信号,其实就是为了控制输出的阈值大小和图像类型,这部分内容很简单。

//-------------------------------------------------------
//   key filter and throshold control and state chose
//-------------------------------------------------------

reg [7:0] Frame_Diff_Throshold;
reg [1:0] state;
wire key0_flag;
wire key1_flag;

key_filter u_key_filter0(
    .clk    ( clk    ),
    .rst_n  ( rst_n  ),
    .key_in ( key0 ),
    .key_flag  ( key0_flag  )
);

key_filter u_key_filter1(
    .clk    ( clk    ),
    .rst_n  ( rst_n  ),
    .key_in ( key1 ),
    .key_flag  ( key1_flag  )
);

always @(posedge clk or negedge rst_n) begin
  if(~rst_n)begin
    Frame_Diff_Throshold<=8'd70;
  end
  else if(key0_flag==1'b1 & Frame_Diff_Throshold<8'd100)begin
    Frame_Diff_Throshold<=Frame_Diff_Throshold+4'd10;
  end
  else if (key0_flag==1'b1 & Frame_Diff_Throshold>=8'd100)begin
    Frame_Diff_Throshold<=8'd40;
  end
  else begin
    Frame_Diff_Throshold<=Frame_Diff_Throshold;
  end
end

always @(posedge clk or negedge rst_n) begin
  if(~rst_n)begin
    state<=2'd0;
  end
  else if(key1_flag==1'b1)begin
    state<=state+1'b1;
  end
  else begin
    state<=state;
  end
end

对读出的两组信号将RGB图像转换成灰度图像,之后在把两张灰度图像进行帧差,最后注意fifo读用了两个clk、转灰度用了3clk、帧差用了1clk,所以握手信号也要延迟6clk,经过这些操作后,flag信号就是代表了帧差的结果了,接下来只需要提取出这些flag在图像上的范围和边界即可,具体代码如下所示。
更多的关于怎么找到边间画出边界,大磊FPGA里面有很详细的步骤,大家可以看视频,或者看我工程,这里就不叙述了。

//-------------------------------------------------------
//  current img data and past img data:RGB888 to RGB565 
//-------------------------------------------------------

wire [23:0] s0_data_gray;   //data from camera
wire [23:0] s1_data_gray;   //data from vdma0
wire [7:0] s0_data_gray1;
wire [7:0] s1_data_gray1;

assign s0_data_gray1=s0_data_gray[23:16];
assign s1_data_gray1=s1_data_gray[23:16];

rgb2gray u_rgb2gray1(
    .pclk       ( clk     ),
    .rst_n      ( rst_n    ),
    .rgb_data   ( s0_axis_tdata_dy2 ),
    .gray_data  ( s0_data_gray  )
);

rgb2gray u_rgb2gray2(
    .pclk       ( clk     ),
    .rst_n      ( rst_n    ),
    .rgb_data   ( data_out ),
    .gray_data  ( s1_data_gray  )
);

//-------------------------------------------------------
//               frame diff operation  
//-------------------------------------------------------

reg frame_diff_flag;
reg [10:0] x_cnt;
reg [10:0] y_cnt;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
      frame_diff_flag<=1'b0;
    end
    else begin
        if(s0_data_gray1>s1_data_gray1)begin
            if( ((s0_data_gray1-s1_data_gray1) > Frame_Diff_Throshold) && (x_cnt<H_DISP-5'd5) )begin
              frame_diff_flag<=1'b1;
            end
            else frame_diff_flag<=1'b0;
        end
        else begin
          if( ((s1_data_gray1-s0_data_gray1) > Frame_Diff_Throshold) && (x_cnt<H_DISP-5'd5) )begin
            frame_diff_flag<=1'b1;
          end
          else frame_diff_flag<=1'b0;
        end
    end
end

//-------------------------------------------------------
//              for signal of s0,delay 6 clk   
//-------------------------------------------------------

//fifo:2clk; rgb2gray:3clk; frame diff:1clk
//so 6 clk delay needed
wire s0_axis_tvalid_dy;
wire s0_axis_tuser_dy;
wire s0_axis_tlast_dy;
reg [5:0] s0_axis_tvalid_reg;
reg [5:0] s0_axis_tuser_reg;
reg [5:0] s0_axis_tlast_reg;

assign s0_axis_tvalid_dy=s0_axis_tvalid_reg[5];
assign s0_axis_tuser_dy=s0_axis_tuser_reg[5];
assign s0_axis_tlast_dy=s0_axis_tlast_reg[5];

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
      s0_axis_tvalid_reg<=6'd0;
      s0_axis_tuser_reg<=6'd0;
      s0_axis_tlast_reg<=6'd0;
    end
    else begin
      s0_axis_tvalid_reg<={s0_axis_tvalid_reg[4:0],s0_axis_tvalid & s0_axis_tready};
      s0_axis_tuser_reg<={s0_axis_tuser_reg[4:0],s0_axis_tvalid & s0_axis_tready & s0_axis_tuser};
      s0_axis_tlast_reg<={s0_axis_tlast_reg[4:0],s0_axis_tvalid & s0_axis_tready & s0_axis_tlast};
    end
end

2.3 帧差法软硬件设计

vivado工程中的block design就如下图所示了,可以看到例化了3个vdma,然后自己编写了frame diff模块,原理是和上面的架构是相同的。
ZYNQ图像处理项目——帧差法运动目标跟踪
综合布局布线完成后,我们把它导入到sdk设计中,sdk中c代码如下所示,就很基础,只是初始化3个vdma开启读和写通道就可以了。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "vdma_api/vdma_api.h"

//宏定义
#define VDMA_ID0          XPAR_AXIVDMA_0_DEVICE_ID
#define VDMA_ID1          XPAR_AXIVDMA_1_DEVICE_ID
#define VDMA_ID2		  XPAR_AXIVDMA_2_DEVICE_ID
//frame buffer的起始地址
unsigned int const frame_buffer_addr0 =0x03000000;
unsigned int const frame_buffer_addr1 =0x06000000;
unsigned int const frame_buffer_addr2 =0x09000000;

//驱动实例
XAxiVdma     vdma;

int main(void)
{
	int i;
	int j;
	int k;

	//配置VDMA
	i=run_vdma_frame_buffer(&vdma, VDMA_ID0,1024,768,frame_buffer_addr0,0,0,BOTH);
	j=run_vdma_frame_buffer(&vdma, VDMA_ID1,1024,768,frame_buffer_addr1,0,0,BOTH);
	k=run_vdma_frame_buffer(&vdma, VDMA_ID2,1024,768,frame_buffer_addr2,0,0,BOTH);
	printf("%d\r\n",i);
	printf("%d\r\n",j);
	printf("%d\r\n",k);
	while(1);
    return 0;
}

三、总结

这个工程采用了前后帧差法,完成了单运动目标的检测,是比较基础的实战项目。对于后期想扩展的方向,可以使用背景帧差法来更好的定位目标,或者完成多运动目标的检测和计数。文章来源地址https://www.toymoban.com/news/detail-472065.html

资源下载链接:
https://download.csdn.net/download/qq_40995480/86880974

到了这里,关于ZYNQ图像处理项目——帧差法运动目标跟踪的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ZYNQ图像处理(7)——sobel边缘检测

    所谓边缘是指其周围像素灰度急剧变化的那些象素的集合,它是图像最基本的特征。边缘存在于目标、背景和区域之间,所以,它是图像分割所依赖的最重要的依据。由于边缘是位置的标志,对灰度的变化不敏感,,因此,边缘也是图像匹配的重要的特征。边缘检测和区域划分

    2024年02月05日
    浏览(71)
  • ZYNQ图像处理(6)——均值滤波和中值滤波

    首先要做的是最简单的均值滤波算法。均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标象素为中心的周围 8 个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像

    2024年02月08日
    浏览(54)
  • FPGA + 图像处理(一)三种向zynq中DDR内导入图像数据的方法

    本文主要讲解三种本人已知的将图像数据传入ddr的方法(一些非图像数据也可以用),方便后续通过fpga对图像进行处理,在一些导入方法中,需要将图像转换成特定的格式,因此,需要用到matlab来实现图像的格式转换 这里先展示一下用到的图像,是一个ai随机绘制的图像 通

    2024年02月03日
    浏览(68)
  • XILINX Zynq UltraScale+ MPSoC 在 4K 视频图像处理和会议系统的应用

        赛灵思 Zynq UltraScale+™ MPSoC EV 器件的 4K 视频处理功能。EV 器件具有继承的多标准视频编解码器,能够以 60帧/秒 的速度同步编码和解码。       Arm 四核 Cortex-A53 核以及集成的定制化的视频处理引擎,ZU7EV 器件可以作为多媒体应用方案的主控。        ZCU106 评估套件可作

    2024年02月01日
    浏览(78)
  • 数字图像处理——图像退化(大气湍流模型与运动模糊模型)与图像复原(逆滤波与维纳滤波)

    一般来说,图像的退化模型可以表示为 其中g(x,y) 表示退化后的图像,h(x,y)表示退化模型,f(x,y)表示原图像,n(x,y)表示噪声。 在频域上面可以表示为 下面介绍常见的两种退化模型:基于大气湍流物理特性的大气湍流模型和运动模糊模型。 1.大气湍流模型 退化模型: 伴随着

    2024年02月05日
    浏览(43)
  • 图像处理 信号处理板 设计原理图:367-基于zynq XC7Z100 FMC接口通用计算平台

    基于zynq XC7Z100 FMC接口通用计算平台   板卡由SoC XC7Z100-2FFG900I芯片来完成卡主控及数字信号处理,XC7Z100内部集成了两个ARM Cortex-A9核和一个kintex 7的FPGA,通过PL端FPGA扩展FMC、光纤、IO等接口,PS端ARM扩展网络、USB、RS232等接口。板卡适应于图像处理、震动、通信、雷达等前端信号

    2024年02月11日
    浏览(52)
  • 008-关于FPGA/ZYNQ直接处理图像传感器数据输出的若干笔记(裸板采集思路)

    最近也是未来需要考虑做的一件事情是,如何通过FPGA/ZYNQ去做显微镜图像观测下的图像采集传输与后续的处理。目前显微镜观测领域通常是以PC端连接工业相机接口,这个接口可以是USB3.0,可以是网口,也可以是其它传输方式。常常通过工业相机输出的为视频流数据,厂商会

    2024年01月23日
    浏览(59)
  • Xilinx Zynq-7000系列FPGA多路视频处理:图像缩放+视频拼接显示,提供工程源码和技术支持

    Xilinx Zynq-7000系列FPGA多路视频处理:图像缩放+视频拼接显示,提供工程源码和技术支持 没玩过图像缩放和视频拼接都不好意思说自己玩儿过FPGA,这是CSDN某大佬说过的一句话,鄙人深信不疑。。。本文使用Xilinx Zynq7000系列FPGA Zynq7020实现HLS图像缩放+视频拼接,输入视频源采用

    2024年02月04日
    浏览(77)
  • 【OpenCV】“帧差法”实现移动物体的检测(车辆识别)

    目录 一、帧差法 1、概念 2、为什么帧差法可以检测运动的物体?  二、使用OpenCV配合帧差法实现车辆识别 1、加载视频 2、灰度处理+帧差计算 3、二值化 4、腐蚀 5、膨胀 6、框选出车辆 三、全部代码+实现效果 1、代码 2、车辆检测效果 四、帧差法存在不足之处         帧差

    2024年02月02日
    浏览(50)
  • 使用opencv结合帧差法和背景减法 检测场景异常情况

    帧差法是一种简单的背景减法技术,用于检测当前帧和背景帧之间的差异。以下是使用OpenCV实现帧差法的Python代码示例: 用于检测是否下雨,漏水等情况。 要截取摄像头的3秒时间并使用帧差法进行动态背景差异检测,你可以使用OpenCV库来完成这项任务。首先,你需要设置一

    2024年02月07日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包