PS和PL的交互方式汇总

最近有个项目关于FPGA加速神经网络,因此需要了解相关PS和pl交互的方法,从而将权重数据存放在PS的DDR中 ,并在需要时完成数据的存入和读出。这是一篇归纳性的文章,具体的还需要自行查阅资料。

https://wallhaven.cc/

PS-PL数据交互方式

1、IO


个数
分布控制
MIO54BANK0, 1PS直接控制
EMIO64BANK2, 3需要PL配置引脚
GPIOAXI-GPIO

MIO :ZYNQ 分为 PS 和 PL 两部分,那么器件的引脚(Pin)资源同样也分成了两部分。ZYNQ PS 中的外设可以通过 MIO(Multiuse I/O,多用输入/输出)模块连接到 PS 端的引脚上,也可以通过 EMIO 连接到 PL 端的引脚。Zynq-7000 系列芯片一般有 54 个 MIO,个别芯片如 7z007s 只有 32 个。

EMIO : PS 和外部设备之间的通信主要是通过复用的输入/输出(Multiplexed Input/Output,MIO)实现的。除此之外,PS 还可以通过扩展的 MIO(Extended MIO,EMIO)来实现与外部设备的连接。EMIO 使用了 PL 的I/O 资源,当 PS 需要扩展超过 54 个引脚的时候可以用 EMIO,也可以用它来连接 PL 中实现的 IP 模块。

在大多数情况下,PS 端经由 EMIO 引出的接口会直接连接到 PL 端的器件引脚上,通过 IO 管脚约束来指定所连接 PL 引脚的位置。通过这种方式,EMIO 可以为 PS 端实现额外的 64 个输入引脚或 64 个带有输出使能的输出引脚。EMIO 还有一种使用方式,就是用于连接 PL 内实现的功能模块(IP 核),此时 PL 端的 IP 作为 PS 端的一个外部设备。(EMIO既可以将ps和pl端的引脚相连,也可以和pl中的模块相连)

PS 与 PL 最主要的连接方式则是一组 AXI 接口。AXI 互联和接口作为 ZYNQ PS 和 PL 之间的桥梁,能够使两者协同工作,进而形成一个完整的、高度集成的系统。

GPIO : AXI GPIO IP 核为 AXI 接口提供了一个通用的输入/输出接口。与 PS 端的 GPIO 不同,AXI GPIO 是一个软核(Soft IP),即 ZYNQ 芯片在出厂时并不存在这样的一个硬件电路,而是由用户通过配置 PL 端的逻辑资源来实现的一个功能模块。而 PS 端的 GPIO 是一个硬核(Hard IP),它是一个生产时在硅片中实现的功能电路。 AXI GPIO IP 模块的左侧实现了一个 32 位的 AXI4-Lite 从接口,用于主机访问 AXI GPIO 内部各通道的寄存器。

AXI GPIO 框图

中断

参考:

https://blog.csdn.net/wangjie36/article/details/116081755

中断是一种当满足要求的突发事件发生时通知处理器进行处理的信号。中断可以由硬件处理单元和外部设备产生,也可以由软件本身产生。对硬件来说,中断信号是一个由某个处理单元产生的异步信号,用来引起处理器的注意。对软件来说,中断还是一种异步事件,用来通知处理器需要改变代码的执行,不过,轮询所产生的中断的过程是同步的。

Zynq 芯片的 PS 部分是基于使用双核 Cortex-A9 处理器和 GIC pl390 中断控制器的 ARM 架构。中断结构与 CPU 紧密链接,并接受来自 I/O 外设(IOP)和可编程逻辑(PL)的中断。

中断控制器架构图

ZYNQ CPU 软件中断(SGI,Software generatedinterrupts):ZYNQ 共有两个 CPU,每个 CPU 具备各自的 16 个软件中断(中断号0-15)(16–26 reserved):被路由到一个或者两个CPU上,通过写ICDSGIR寄存器产生SGI。

CPU私有外设中断(PPI,private peripheralinterrupts ):私有中断是固定的不能修改。这里有 2 个 PL 到 CPU 的快速中断 nFIQ(中断号27-31):每个CPU都有一组PPI,包括全局定时器、私有看门狗定时器、私有定时器和来自PL的FIQ/IRQ。

ZYNQ PS 和 PL 共享中断(SPI,shared peripheralinterrupts):共享中断就是一些端口共用一个中断请求线:(中断号32-95)。由PS和PL上的各种I/O控制器和存储器控制器产生,这些中断信号被路由到相应的CPU, PL部分有16个共享中断,它们的触发方式可以设置。

FIFO

https://zhuanlan.zhihu.com/p/47847664

FIFO类型读接口写接口
AXI Data FIFOAXI4-fullAXI4-full
AXI-Stream FIFOPS axi4-litePL axi-stream
AXI4-Stream Data FIFOaxi-streamaxi-stream

通过AXI-Stream FIFO完成PS和PL部分的数据交互

  • S_AXI, PS读写FIFO数据接口
  • AXI_STR_TXC, 发送控制端口
  • AXI_STR_TXD,发送数据端口
  • AXI_STR_RXD,接收数据端口

读写fifo例程:

写fifo

//write fifo us1
always@(posedge  wrclk, negedge sys_reset_n_i)
begin
    if (!sys_reset_n_i)
    begin
        fifo_wrreq_ddr3_us <= 0 ;
        fifo_data_ddr3_us <= 0 ;
    end
    else
    begin
        if(fifo_prog_full_ddr3_us!= 1) 
            fifo_wrreq_ddr3_us <= 1 ;
        else
            fifo_wrreq_ddr3_us <= 0 ;        
        if(fifo_wrreq_ddr3_us == 1) 
         begin            
             if(fifo_data_ddr3_us < 64'b1111_1111_1111_1111_1111_1111)
                fifo_data_ddr3_us <=fifo_data_ddr3_us + 1 ;                  
             else 
                 fifo_data_ddr3_us <= 0  ; 
         end  
         else
             fifo_data_ddr3_us <= fifo_data_ddr3_us ;                
    end
end
endmodule

读fifo

assign fifo_rdreq_ddr3_ds = !fifo_empty_ddr3_ds;

always@(posedge sys_clk_i,negedge sys_reset_n_i)
begin
    if(!sys_reset_n_i)
         rd_ck_flag_cp<= 1'b0;
    else
    begin
        if (fifo_q_ddr3_ds_r!==fifo_q_ddr3_ds)
            rd_ck_flag_cp<= 1'b1;  
        else
            rd_ck_flag_cp<= 1'b0;
    end    
end
 //jiao yan cuo wu ji shu    jiao yan wei zi zeng       
always@(posedge sys_clk_i,negedge sys_reset_n_i)
begin
    if(!sys_reset_n_i)
    begin
         rd_ck_cnt <= 64'b0;
         fifo_q_ddr3_ds_r <= 64'b0 ;  
    end
    else  
    begin
        if(rd_ck_flag_cp==1)
            rd_ck_cnt <=rd_ck_cnt+1'b1;
        else
            rd_ck_cnt <= rd_ck_cnt;
             
         if ( ( fifo_rdreq_ddr3_ds==1 ) && (fifo_q_ddr3_ds_r < 64'b1111_1111_1111_1111_1111_1111) )
            
             fifo_q_ddr3_ds_r <= fifo_q_ddr3_ds_r + 1'b1 ; 
         else
             fifo_q_ddr3_ds_r <= 64'b0; 
     end
end

endmodule

BRAM

在 ZYNQ SOC 开发过程中,PL 和 PS 之间经常需要做数据交互。对于传输速度要求较高、数据量大、地址连续的场合,可以通过 AXI DMA 来完成。而对于数据量较少、地址不连续、长度不规则的情况,此时 AXIDMA 便不再适用了。针对这种情况,可以通过 BRAM 来进行数据的交互。

BRAM(Block RAM)是 PL 部分的存储器阵列,PS 和 PL 通过对 BRAM 进行读写操作,来实现数据的交互。在 PL 中,通过输出时钟、地址、读写控制等信号来对 BRAM 进行读写操作;而在 PS 中,处理器并不需要直接驱动 BRAM 的端口,而是通过 AXI BRAM 控制器来对 BRAM 进行读写操作。AXI BRAM 控制器是集成在 Vivado 设计软件中的软核,可以配置成 AXI4-lite 接口模式或者 AXI4 接口模式。

AXI4 接口模式的 BRAM 控制器支持的数据位宽为 32 位、64 位、128 位、512 位和 1024 位,而 AXI4-Lite 接口仅支持 32 位数据位宽。由图 14.1.1 可知,PS 通过 AXI4-Lite 接口访问 BRAM,当使能 ECC 选项时,ECC 允许 AXI 主接口检测和纠正 BRAM 块中的单位和双位错误。AXI BRAM 控制器作为 AXI 总线的从接口,和 AXI 主接口实现互联,来对 BRAM 进行读写操作。针对不同的应用场合,该 IP 核支持单次传输和突发传输两种方式。

PS 端的 M_AXI_GP0 作为主端口,与 PL 端的 AXI BRAM 控制器 IP 核和 PL 读 BRAMIP 核(pl_bram_rd)通过 AXI4 总线进行连接。其中,AXI 互联 IP(AXI Interconnect)用于连接 AXI 存储器映射(memory-mapped)的主器件和从器件;AXI BRAM 控制器作为 PS 端读写 BRAM 的 IP 核;PL 读BRAM IP 核是我们自定义的 IP 核,实现了 PL 端从 BRAM 中读出数据的功能,除此之外,PS 端通过 AXI总线来配置该 IP 核读取 BRAM 的起始地址和个数等。

DMA

DMA(Direct Memory Access,直接存储器访问)是计算机科学中的一种内存访问技术。它允许某些计算机内部的硬件子系统可以独立地直接读写系统内存,而不需中央处理器(CPU)介入处理。DMA 是一种快速的数据传送方式,通常用来传送数据量较多的数据块,很多硬件系统会使用 DMA,包括硬盘控制器、绘图显卡、网卡和声卡,在使用高速 AD/DA 时使用 DMA 也是不错的选择。DMA 是用硬件实现存储器与存储器之间或存储器与 I/O 设备之间直接进行高速数据传输。使用 DMA时,CPU 向 DMA 控制器发出一个存储传输请求,这样当 DMA 控制器在传输的时候,CPU 执行其它操作,传输操作完成时 DMA 以中断的方式通知 CPU。

为了发起传输事务,DMA 控制器必须得到以下数据:
• 源地址 — 数据被读出的地址
• 目的地址 — 数据被写入的地址
• 传输长度 — 应被传输的字节数

DMA 存储传输的过程如下:

  1. 为了配置用 DMA 传输数据到存储器,处理器发出一条 DMA 命令
  2. DMA 控制器把数据从外设传输到存储器或从存储器到存储器,而让 CPU 腾出手来做其它操作。
  3. 数据传输完成后,向 CPU 发出一个中断来通知它 DMA 传输可以关闭了。

ZYNQ 提供了两种 DMA,一种是集成在 PS 中的硬核 DMA,另一种是 PL 中使用的软核 AXI DMAIP。在 ARM CPU 设计的过程中,已经考虑到了大量数据搬移的情况,因此在 CPU 中自带了一个 DMA 控制器 DAMC,这个 DAMC 驻留在 PS 内,而且必须通过驻留在内存中的 DMA 指令编程,这些程序往往由CPU 准备,因此需要部分的 CPU 参与。DMAC 支持高达 8 个通道,所以多个 DMA 结构的核可以挂在单个DMAC 上。DAMC 与 PL 的连接是通过 AXI_GP 接口,这个接口最高支持到 32 位宽度,这也限制了这种模式下的传输速率,理论最高速率为 600MB/s。这种模式不占用 PL 资源,但需要对 DMA 指令编程,会增加软件的复杂性。为了获取更高的传输速率,可以以空间换时间,在 PL 中添加 AXI DMAIP 核,并利用 AXI_HP 接口完成高速的数据传输。

为了获取更高的传输速率,可以以空间换时间,在 PL 中添加 AXI DMAIP 核,并利用 AXI_HP 接口完成高速的数据传输,通过 PL 的 DMA 和 AXI_HP 接口的传输适用于大块数据的高性能传输,带宽高。各种接口方式的比较如下表所示:

ZYNQ 开发板上使用 PL 的 AXI DMA IP 核从 DDR3 中读取数据,并将数据写回到 DDR3 中。

在实际应用中,DMA 一般与产生数据或需求数据的 IP 核相连接,该 IP 核可以是带有 Stream 接口的高速的 AD(模拟转数字)或 DA(数字转模拟) IP 核。不失一般性,在本次实验中,我们使用 AXI4 Stream Data FIFO IP 核来充当这类 IP 进行 DMA 环回实验。

AXI Direct Memory Access重要端口说明:

  • S_AXI_LITE: 配置DMA工作模式
  • M_AXI_MM2S:DDR到DMA数据接口
  • M_AXI_S2MM:DMA数据到DDR接口
  • S_AXIS_S2MM: 接收的DMA数据输出端口
  • M_AXIS_MM2S: 想通过DMA输出的数据写入端口

DDR3

通过对AXI HP接口的操作来实现

AXI 的英文全称是 Advanced eXtensible Interface,即高级可扩展接口,它是 ARM 公司所提出的 AMBA(Advanced Microcontroller Bus Architecture)协议的一部分。

AXI4 协议支持以下三种类型的接口:
1、 AXI4:高性能存储映射接口。
2、 AXI4-Lite:简化版的 AXI4 接口,用于较少数据量的存储映射通信。
3、 AXI4-Stream:用于高速数据流传输,非存储映射接口。

AXI4 协议支持突发传输,主要用于处理器访问存储器等需要指定地址的高速数据传输场景。AXI-Lite为外设提供单个数据传输,主要用于访问一些低速外设中的寄存器。而 AXI-Stream 接口则像 FIFO 一样,数据传输时不需要地址,在主从设备之间直接连续读写数据,主要用于如视频、高速 AD、PCIe、DMA 接口等需要高速数据传输的场合。

读传输

AXI 总线中的每个通道都包含了一组信息信号,还有一个 VALID 和一个 READY 信号,VALID 信号由源端(source)产生,表示当前地址或者数据线上的信息是有效的;而 READY 信号由目的端(destination)产生,则表示已经准备好接收地址、数据以及控制信息。

通过自定义一个 AXI4 接口的 IP 核,通过 AXI_HP 接口对 PS 端 DDR3 进行读写测试。

AXI_HP总线:只能单向传输,从PL到PS端,适用于大数据传输。

系统图

PL实现AXI4接口,通过S_AXI_HP接口读取ps侧DDR3数据. 例程功能:PL,PS向指定地址写数据,对方来读.

AXI-DMA:实现从PS内存到PL高速传输高速通道AXI-HP<—->AXI-Stream的转换
AXI-Datamover:实现从PS内存到PL高速传输高速通道AXI-HP<—->AXI-Stream的转换,只不过这次是完全由PL控制的,PS是完全被动的。
AXI-VDMA:实现从PS内存到PL高速传输高速通道AXI-HP<—->AXI-Stream的转换,只不过是专门针对视频、图像等二维数据的。
AXI-CDMA IP: 这个是由PL完成的将数据从内存的一个位置搬移到另一个位置,无需CPU来插手。这个和我们这里用的Stream没有关系

自定义AXI接口IP

一般应用场景在于PS对某些寄存器的配置,传输少量的数据信息。

少年游

芦叶满汀洲,寒沙带浅流。二十年重过南楼。柳下系船犹未稳,能几日,又中秋。黄鹤断矶头,故人今在否?旧江山浑是新愁。欲买桂花同载酒,终不似,少年游。 《唐多令》宋·刘过

少年偏爱摇摇欲坠的日落黄,殊不知此刻正拥有的,是一生中最明媚的曙光。

春日游,杏花吹满头。陌上谁家年少,足风流。

韶华不为少年留,恨悠悠,几时休。

可是我现在依然不太会转弯
虽然孤单的人偶尔也想有个伴
冷风又吹的时候想说
这生活会不会有点难
难道是因为当初有话没讲完
堵在喉咙里却始终不敢大声喊
算了 别哭 ————-毛不易《呓语》

HLS打包ip报错解决方法:

在HLS进行ip核打包的时候,出现了Vivado fails to export IPs with the error message “Bad lexical cast: source type value could not be interpreted as target”错误 ,在xilinx官网找到了解决办法:

以下是原帖

https://support.xilinx.com/s/question/0D52E00006uxy49SAA/vivado-fails-to-export-ips-with-the-error-message-bad-lexical-cast-source-type-value-could-not-be-interpreted-as-target?language=en_US

https://support.xilinx.com/s/question/0D52E00006uxnnFSAQ/2022-timestamp-overflow-error-2201011128-is-an-invalid-argument-please-specify-an-integer-value?language=en_US

错误是 Vivado 在导出 IP 步骤 (export_design) 中失败。

上面是错误截图,从2021年变成2022年之后就开始出现了。

我尝试重新启动并运行相同的命令来导出以前测试过的设计上的 xo 文件。他们都提示同样的错误

你好,

我正在尝试从 Vitis HLS 导出 Vivado IP(我尝试了 2020.1、2020.2 和 2021.1 版本)。一切都过去正常工作。

但是,现在它会打印以下错误消息:

错误:“2201011128”是无效参数。请指定一个整数

我注意到机器生成的 tcl 脚本使用当前日期作为修订的名称。正如您在下面的屏幕截图中看到的

图片

上面的屏幕截图来自 2021 年 12 月 31 日的设计,效果很好。以下来自 2022 年无效的设计。

图片似乎数字 22 造成了整数溢出。因为 2^31 小于当前修订号。

这个问题有简单的解决方法吗?

请尝试以下解决方法解决此问题:

1.修改vitis_​​hls项目解决目录下的run_ippack.tcl文件

XX\test\solution1\impl\ip\run_ippack.tcl

示例修改: 

 设置修订版“2201012126”-> 设置修订版“2001012126”

但修改后:

修改修订后,如果我再次开始综合,更改将被覆盖。我如何完成生成设计?

最终解决方案:

我将计算机的日期设置回滚到 2021 年,并禁用了自动时间和日期选项。

YOLO系列(二):yolov1

YOLOv1属于一阶段、anchor-free 目标检测

整体来看,Yolo算法采用一个单独的CNN模型实现end-to-end的目标检测,整个系统如图5所示:首先将输入图片resize到448×448,然后送入CNN网络,最后处理网络预测结果得到检测的目标。相比R-CNN算法,其是一个统一的框架,其速度更快,而且Yolo的训练过程也是end-to-end的。

具体来说,Yolo的CNN网络将输入的图片分割成 \(S \times S\) 网格,然后每个单元格负责去检测那些 中心点落在该格子内的目标,如图6所示,可以看到狗这个目标的中心落在左下角一个单元格内, 那么该单元格负责预测这个狗。每个单元格会预测 \(B\) 个边界框 (bounding box) 以及边界框的 置信度 (confidence score) 。所谓置信度其实包含两个方面,一是这个边界框含有目标的可能性 大小,二是这个边界框的准确度。前者记为 \(\operatorname{Pr}(object)\) ,当该边界框是背景时 (即不包含目 标),此时 \(\operatorname{Pr}(object)=0\) 。而当该边界框包含目标时, \(\operatorname{Pr}(object)=1\) 。边界框的准 确度可以用预测框与实际框 (ground truth) 的IOU (intersection over union,交并比) 来表 征,记为 \(\mathrm{IOU}{\text {pred }}^{\text {truth }}\) 。因此置信度可以定义为 \(\operatorname{Pr}(object) * \mathrm{IOU}{\text {pred }}^{\text {truth }}\) 。很多人可能将Yolo 的置信度看成边界框是否含有目标的概率,但是其实它是两个因子的乘积,预测框的准确度也反映 在里面。边界框的大小与位置可以用4个值来表征: (x, y, w, h),其中 (x, y) 是边界框的中 心坐标,而 w和 h 是边界框的宽与高。还有一点要注意,中心坐标的预测值 (x, y) 是相对于 每个单元格左上角坐标点的偏移值,并且单位是相对于单元格大小的,单元格的坐标定义如图6所 示。而边界框的 \(w\) 和 \(h\) 预测值是相对于整个图片的宽与高的比例,这样理论上4个元素的大小 应该在 \([0,1]\) 范围。这样,每个边界框的预测值实际上包含 5 个元素: \((x, y, w, h, c)\) ,其中 \((x, y)\) 是边界框的中 心坐标,而 \(w\) 和 \(h\) 是边界框的宽与高。还有一点要注意,中心坐标的预测值 \((x, y)\) 是相对于 每个单元格左上角坐标点的偏移值,并且单位是相对于单元格大小的,单元格的坐标定义如图所示。而边界框的\(w\) 和 \(h\) 预测值是相对于整个图片的宽与高的比例,这样理论上4个元素的大小 应该在 \([0,1]\) 范围。这样,每个边界框的预测值实际上包含 5 个元素: \((x, y, w, h, c)\) ,其中 前 4 个表征边界框的大小与位置,而最后一个值是置信度。

还有分类问题,对于每一个单元格其还要给出预测出 C个类别概率值,其表征的是由该单元格负 责预测的边界框其目标属于各个类别的概率。但是这些概率值其实是在各个边界框置信度下的条件 概率,即 \(\operatorname{Pr}\left(\right. class _{i} \mid object )\) 。值得注意的是,不管一个单元格预测多少个边界框,其只预测 一组类别概率值,这是Yolo算法的一个缺点,在后来的改进版本中,Yolo9000是把类别概率预测 值与边界框是绑定在一起的。同时,我们可以计算出各个边界框类别置信度(class-specific confidence scores):


边界框类别置信度表征的是该边界框中目标属于各个类别的可能性大小以及边界框匹配目标的好 坏。后面会说,一般会根据类别置信度来过滤网络的预测框。
总结一下,每个单元格需要预测 \((B * 5+C)\) 个值。如果将输入图片划分为 \(S \times S\) 网格,那 么最终预测值为 \(S \times S \times(B * 5+C)\) 大小的张量。整个模型的预测值结构如下图所示。对 于PASCAL VOC数据,其共有20个类别,如果使用 \(S=7, B=2\) ,那么最终的预测结果就是 \(7 \times 7 \times 30\) 大小的张量。在下面的网络结构中我们会详细讲述每个单元格的预测值的分布位 置。

Yolo采用卷积网络来提取特征,然后使用全连接层来得到预测值。网络结构参考GooLeNet模型,包含24个卷积层和2个全连接层,如图8所示。对于卷积层,主要使用1×1卷积来做channle reduction,然后紧跟3×3卷积。对于卷积层和全连接层,采用Leaky ReLU激活函数:max(x, 0.1x) 。但是最后一层却采用线性激活函数。

损失函数计算如下:

其中第一项是边界框中心坐标的误差项, \(1_{i j}^{obj}\) 指的是第 \(i\) 个单元格存在目标,且该单元格中的第 \(j\) 个边界框负责预测该目标。第二项是边界框的高与宽的误差项。第三项是包含目标的边界框 的置信度误差项。第四项是不包含目标的边界框的置信度误差项。而最后一项是包含目标的单元格 的分类误差项, \(1_{i}^{\text {obj }}\) 指的是第 \(i\) 个单元格存在目标。这里特别说一下置信度的target值 \(C_{i}\) , 如果是不存在目标,此时由于 \(\operatorname{Pr}( object )=0\) ,那么 \(C_{i}=0\) 。如果存在目标,
\(\operatorname{Pr}( object )=1\) ,此时需要确定 \(\mathrm{IOU}{\text {pred }}^{\text {truth }}\) ,当然你希望最好的话,可以将IOU取 1 ,这样 \(C{i}=1\) ,但是在 YOLO实现中,使用了一个控制参数 rescore (默认为 1 ),当其为 1 时,IOU不 是设置为 1 ,而就是计算truth和pred之间的真实 IOU

网络预测: 基于非极大值抑制算法

这个算法不单单是针对Yolo算法的,而是所有的检测算法中都会用到。NMS算法主要解决的是一个目标被多次检测的问题,如图11中人脸检测,可以看到人脸被多次检测,但是其实我们希望最后仅仅输出其中一个最好的预测框,比如对于美女,只想要红色那个检测结果。那么可以采用NMS算法来实现这样的效果:首先从所有的检测框中找到置信度最大的那个框,然后挨个计算其与剩余框的IOU,如果其值大于一定阈值(重合度过高),那么就将该框剔除;然后对剩余的检测框重复上述过程,直到处理完所有的检测框。Yolo预测过程也需要用到NMS算法。

下面就来分析Yolo的预测过程,这里我们不考虑batch,认为只是预测一张输入图片。根据前面的分析,最终的网络输出是 7×7×30 ,但是我们可以将其分割成三个部分:类别概率部分为 [7,7,20] ,置信度部分为 [7,7,2] ,而边界框部分为 [7,7,2,4] (对于这部分不要忘记根据原始图片计算出其真实值)。然后将前两项相乘(矩阵 [7,7,20] 乘以 [7,7,2] 可以各补一个维度来完成 [7,7,1,20]×[7,7,2,1] )可以得到类别置信度值为 [7,7,2,20] ,这里总共预测了 7∗7∗2=98 个边界框。

所有的准备数据已经得到了,那么我们先说第一种策略来得到检测框的结果,我认为这是最正常与自然的处理。首先,对于每个预测框根据类别置信度选取置信度最大的那个类别作为其预测标签,经过这层处理我们得到各个预测框的预测类别及对应的置信度值,其大小都是 [7,7,2] 。一般情况下,会设置置信度阈值,就是将置信度小于该阈值的box过滤掉,所以经过这层处理,剩余的是置信度比较高的预测框。最后再对这些预测框使用NMS算法,最后留下来的就是检测结果。一个值得注意的点是NMS是对所有预测框一视同仁,还是区分每个类别,分别使用NMS。Ng在deeplearning.ai中讲应该区分每个类别分别使用NMS,但是看了很多实现,其实还是同等对待所有的框,我觉得可能是不同类别的目标出现在相同位置这种概率很低吧。

上面的预测方法应该非常简单明了,但是对于Yolo算法,其却采用了另外一个不同的处理思路(至少从C源码看是这样的),其区别就是先使用NMS,然后再确定各个box的类别。其基本过程如图12所示。对于98个boxes,首先将小于置信度阈值的值归0,然后分类别地对置信度值采用NMS,这里NMS处理结果不是剔除,而是将其置信度值归为0。最后才是确定各个box的类别,当其置信度值不为0时才做出检测结果输出。这个策略不是很直接,但是貌似Yolo源码就是这样做的。Yolo论文里面说NMS算法对Yolo的性能是影响很大的,所以可能这种策略对Yolo更好。但是我测试了普通的图片检测,两种策略结果是一样的。

YOLO系列(五)yolov4-tiny

YOLOv4-tiny结构是YOLOv4的精简版,属于轻量化模型,参数只有600万相当于原来的十分之一,这使得检测速度提升很大。整体网络结构共有38层,使用了三个残差单元,激活函数使用了LeakyReLU,目标的分类与回归改为使用两个特征层,合并有效特征层时使用了特征金字塔(FPN)网络。其同样使用了CSPnet结构,并对特征提取网络进行通道分割,将经过3×3卷积后输出的特征层通道划分为两部分,并取第二部分。在COCO数据集上得到了40.2%的AP50、371FPS,相较于其他版本的轻量化模型性能优势显著。其结构图如下图所示。

YOLOv4-tiny具有多任务、端到端、注意力机制和多尺度的特点。多任务即同时完成目标的分类与回归,实现参数共享,避免过拟合;端到端即模型接收图像数据后直接给出分类与回归的预测信息;注意力机制是重点关注目标区域特征进行详细处理,提高处理速度;多尺度的特点是将经过下采样和上采样的数据相互融合,其作用是能够分割出多种尺度大小的目标。在对模型进行训练时可以使用Mosaic数据增强、标签平滑、学习率余弦退火衰减等方法来提升模型的训练速度和检测精度。