Py学习  »  机器学习算法

经典教程 | 如何用FPGA在嵌入式视觉应用实现机器学习

新机器视觉 • 4 年前 • 358 次点击  

关键词: FPGA,ML平台,机器学习,嵌入式视觉,推理引擎


随着摄像头和其他设备产生的数据在快速增长,促使人们运用机器学习从汽车、安防和其他应用产生的影像中提取更多有用的信息。专用器件有望在嵌入式视觉应用中实现高性能机器学习 (ML) 推理。但是此类器件大都处于早期开发阶段,因为设计人员正在努力寻找最有效的算法,甚至人工智能 (AI) 研究人员也在迅速推演新方法。

 

目前,开发人员一般使用针对ML的可用FPGA平台来构建嵌入式视觉系统,以期满足更高的性能要求。与此同时,他们可以保持所需的灵活性,以跟上机器学习发展的步伐。

 

本文将介绍ML处理的要求,以及为何FPGA能解决许多性能问题。然后,将介绍一个合适的基于FPGA的ML平台及其使用方法。


机器学习算法和推理引擎


在ML算法中,卷积神经网络 (CNN) 已成为图像分类的首选解决方案。其图像识别的准确率非常高,因而得以广泛应用于多种应用,跨越不同的平台,例如智能手机、安防系统和汽车驾驶员辅助系统。作为一种深度神经网络 (DNN),CNN使用的神经网络架构由专用层构成。在对标注图像进行训练期间,它会从图像中提取特征,并使用这些特征给图像分类
 
CNN开发人员通常在高性能系统或云平台上进行训练,使用图形处理单元(GPU) 加速在标注图像数据集(通常数以百万计)上训练模型所需的巨量矩阵计算。训练完成之后,训练好的模型用在推理应用中,对视频流中的新图像或帧进行分类。推理部署完成后,训练好的模型仍然需要执行同样的矩阵计算,但由于输入量要少很多,开发人员可以将CNN用于在通用硬件上运行的普通机器学习应用。
 
然而,对于许多应用而言,通用平台缺乏在CNN推理中同时实现高准确率和高性能所需的性能。优化技术和替代CNN架构(如MobileNet或SqueezeNet)有助于降低平台要求,但通常会牺牲准确率并增加推理延时,而这可能与应用要求相冲突。
 
与此同时,快速发展的算法使得机器学习IC的设计工作变得复杂,因为需要机器学习IC既要足够专门化以加速推理,又要足够通用化以支持新算法。FPGA多年来一直扮演着这一特定角色,提供加速关键算法所需的性能和灵活性,解决了通用处理器性能不足或没有专用器件可用的问题。

FPGA作为机器学习平台


对于机器学习而言,GPU仍然是标杆——这是早期的FPGA根本无法企及的。最近出现的一些器件,如Intel Arria 10 GX FPGA和Lattice Semiconductor ECP5 FPGA,大大缩小了先进FPGA和GPU之间的差距。对于某些使用紧凑的整数数据类型的DNN架构来说,此类FPGA的性能/功耗比甚至高于主流GPU。
 
高级FPGA组合了嵌入式存储器和数字信号处理 (DSP) 资源,对于一般矩阵乘法 (GEMM) 运算能够实现很高的性能。其嵌入式存储器靠近计算引擎,从而缓解了CPU存储器瓶颈,而这种瓶颈通常会限制通用处理器上机器学习算法的性能。反之,相比于典型DSP器件(图1),FPGA上的嵌入式DSP计算引擎提供了更多的并行乘法器资源。FPGA厂商在交付专门用于机器学习的FPGA开发平台时充分利用了这些特性。


图1:Lattice Semiconductor ECP5之类的高级FPGA提供了实现高性能推理所需的并行处理资源和嵌入式存储器。(图片来源:LatticeSemiconductor)
 
例如,Intel最近推出的支持FPGA的OPENVINO™扩展了该平台将推理模型部署到不同类型设备(包括GPU、CPU 和 FPGA)的能力。在该平台上,开发人员可使用Intel的深度学习推理引擎工作流程,其中整合了Intel深度学习部署工具包和在Intel OPENVINO工具包中提供的Intel计算机视觉软件开发套件 (SDK)。开发人员使用SDK的应用编程接口 (API) 构建模型,并且可利用Intel的运行模型优化器针对不同硬件平台进行优化。
 
深度学习部署工具包旨在与Intel DK-DEV-10AX115S-A Arria 10 GXFPGA开发套件配合使用,让开发人员能从领先的ML框架(包括Caffe和TensorFlow)导入训练好的模型(图2)。在诸如Arria 10 GX FPGA开发套件之类目标平台或使用Arria 10 GX FPGA器件的定制设计上,工具包中的模型优化器和推理引擎分别处理模型转换和部署。


图2:支持FPGA的Intel OPENVINO 工具包提供了一套必需的完整工具链,可将在Caffe、TensorFlow和其他框架上训练的模型部署到Arria 10 GX FPGA开发套件或围绕Arria 10 GX FPGA构建的定制设计上。 (图片来源:Intel)
 
为了迁移预训练模型,开发人员使用基于 Python 的模型优化器生成了一个中间表示 (IR),该表示包含在一个提供网络拓扑的xml文件和一个以二进制值提供模型参数的bin文件中。除了生成IR之外,模型优化器还会执行一项关键功能——移除模型中用于训练但对推理毫无作用的层。此外,该工具会在可能的情况下将每个提供独立数学运算的层合并到一个组合层中。
 
通过这种网络修剪和合并,模型变得更紧凑,进而加快推理时间并减少对目标平台的存储器需求。
 
Intel推理引擎是一个C++库,其中包含一组C++类。这些类对于受支持的目标硬件平台来说是通用的,因此可以在各个平台上实现推理。对于推理应用而言,开发人员使用像CNNNetReader这样的类来读取xml文件 (ReadNetwork) 中包含的CNN拓扑以及bin文件 (ReadWeights) 中包含的模型参数。模型加载完成后,调用类方法Infer()执行阻塞推理,同时调用类方法StartAsync()执行异步推理,当推理完成时使用等待或完成例程处理结果。
 
Intel在OPENVINO环境提供的多个示例应用程序中演示了完整的工作流程和详细的推理引擎API调用。例如,安全屏障摄像机示例应用程序展示了使用推理模型流水线,以首先确定车辆边界框(图3)。流水线中的下一个模型检查了边界框中的内容,识别车辆类别、颜色和车牌位置等车辆属性。


图3:Intel安全屏障摄像机示例应用程序演示了使用推理流水线,先识别车辆(绿色边界框),再识别颜色、类型和车牌位置(红色框)等车辆属性,最后识别车牌字符(红色文本)。(图片来源:Intel Corp.)

 

流水线中的最后一个模型使用这些车辆属性从车牌中提取字符。为了使用该模型进行推理,示例代码显示了利用推理模型 C++库创建对象 (LPR),而该对象则是名为LPRDetection的结构的一个实例。此结构使用推理引擎API类对象来读取 (CNNNetReader) 并验证模型输入和输出(列表1)。
滑动滚轮查看详情↓

CNNNetwork read() override {

        std::cout << "[ INFO ] Loading network files for Licence Plate Recognition (LPR)" << std::endl;

        CNNNetReader netReader;

        /** Read network model **/

        netReader.ReadNetwork(FLAGS_m_lpr);

        std::cout << "[ INFO ] Batch size is forced to  1 for LPR Network" << std::endl;

        netReader.getNetwork().setBatchSize(1);

        /** Extract model name and load it's weights **/

        std::string binFileName = fileNameNoExt(FLAGS_m_lpr) + ".bin";

        netReader.ReadWeights(binFileName);

 

        /** LPR network should have 2 inputs (and second is just a stub) and one output **/

        // ---------------------------Check inputs

        std::cout << "[ INFO ] Checking LPR Network inputs" << std::endl;

        InputsDataMap inputInfo(netReader.getNetwork().getInputsInfo());

        if (inputInfo.size() != 2) {

            throw std::logic_error("LPR should have 2 inputs");

        }

        InputInfo::Ptr& inputInfoFirst = inputInfo.begin()->second;

        inputInfoFirst->setInputPrecision(Precision::U8);

        inputInfoFirst->getInputData()->setLayout(Layout::NCHW);

        inputImageName = inputInfo.begin()->first;

        auto sequenceInput = (++inputInfo.begin());

        inputSeqName = sequenceInput->first;

        if (sequenceInput->second->getTensorDesc().getDims()[0] != maxSequenceSizePerPlate) {

            throw std::logic_error("LPR post-processing assumes certain maximum sequences");

        }

 

        // ---------------------------Check outputs

        std::cout << "[ INFO ] Checking LPR Network outputs" << std::endl;

        OutputsDataMap outputInfo(netReader.getNetwork().getOutputsInfo());

        if (outputInfo.size() != 1) {

            throw std::logic_error("LPR should have 1 output");

        }

        outputName = outputInfo.begin()->first;

        std::cout << "[ INFO ] Loading LPR model to the "<< FLAGS_d_lpr << " plugin" << std::endl;

 

        _enabled = true;

        return netReader.getNetwork();

    }


列表1:此代码片段来自Intel OPENVINO 工具包中的安全屏障摄像机示例应用程序,演示了使用Intel推理引擎C++库API将模型及其参数读入推理引擎的设计模式。(代码来源:Intel)

 

为了执行推理,该代码加载数据并调用submitRequest方法,该方法启动推理周期并等待结果,然后显示识别的车牌字符(列表2)。

滑动滚轮查看详情↓

if (LPR.enabled()) {  // licence plate

         // expanding a bounding box a bit, better for the license plate recognition

         result.location.x -= 5;

         result.location.y -= 5;

         result.location.width += 10;

         result.location.height += 10;

         auto clippedRect = result.location & cv::Rect(0, 0, width, height);

         cv::Mat Plate = frame(clippedRect);

         // ----------------------------Run License Plate Recognition

         LPR.enqueue(Plate);

         t0 = std::chrono::high_resolution_clock::now();

         LPR.submitRequest();

         LPR.wait();

         t1 = std::chrono::high_resolution_clock::now();

         LPRNetworktime += std::chrono::duration_cast(t1 - t0);

         LPRInferred++;

         // ----------------------------Process outputs

         cv::putText(frame,

                     LPR.GetLicencePlateText(),

                     cv::Point2f(result.location.x, result.location.y + result.location.height + 15),

                     cv::FONT_HERSHEY_COMPLEX_SMALL,

                     0.8,

                     cv::Scalar(0, 0, 255));

         if (FLAGS_r) {

             std::cout << "License Plate Recognition results:" << LPR.GetLicencePlateText() << std::endl;

         }

     }

     cv::rectangle(frame, result.location, cv::Scalar(0, 0, 255), 2);

 }


列表2:此代码片段来自Intel OPENVINO工具包中的安全屏障摄像机示例应用程序,展示了加载模型、执行推理和生成结果的设计模式。(代码来源:Intel)


集成式嵌入式视觉平台



Intel的OPENVINO方法强调平台重定向,而Lattice的SensAI平台完全聚焦于FPGA推理。SensAI平台的特性之一是为DNN架构(包括CNN和一个称为二值化神经网络 (BNN) 的紧凑架构)提供FPGA IP。针对嵌入式视觉,SensAI CNN IP为完整的推理引擎提供框架,将控制子系统、存储器、输入和输出的接口与实现不同类型模型层(包括卷积、BatchNorm归一化、ReLu激活、池化和其他)的资源结合在一起(图4)。


图4:Lattice Semiconductor CNN IP实现了一个完整的推理系统框架,将专用引擎和用于控制、存储器、输入、输出的接口结合在一起。(图片来源:Lattice Semiconductor)

 

为了实现CNN模型,开发人员首先要在针对ECP5 FPGA的Lattice Diamond设计环境中或针对其他Lattice FPGA系列的Radiant设计环境中,利用Lattice Clarity配置工具配置CNN。这里,开发人员可以指定模型类型(CNN或BNN)、卷积引擎数(最多8个)及每层的内部存储大小(最多16Kb)或二进制大对象 (blob)。配置CNN之后,开发人员使用设计环境生成核心,作为FPGA比特流。

 

开发人员单独将通过Caffe或TensorFlow开发并训练好的模型导入SensAI平台。这里,Lattice神经网络编译器将训练好的Caffe或TensorFlow模型转换为一组包含神经网络模型参数和执行命令序列的文件。SensAI平台将来自设计环境和编译器的单独输出一起并入FPGA,以提供最终的推理模型(图5)。


图5:Lattice Semiconductor SensAI平台将其CNN和BNN IP与其神经网络编译器结合在一起,使开发人员能够转换Caffe或TensorFlow模型,以在Lattice FPGA上作为推理引擎来运行。(图片来源:Lattice Semiconductor)

 

针对嵌入式视觉应用,Lattice LF-EVDK1-EVN嵌入式视觉开发套件(EVDK) 为运行CNN模型推理提供了理想的目标平台。EVDK提供了一个完整的80x80mm三板堆叠式视频平台,包括Lattice CrossLink视频输入板、带ECP5 FPGA的处理器板和HDMI输出板。开发人员可以将EVDK用作Lattice提供的多个示例CNN应用的目标平台。例如,Lattice速度标志检测参考设计运用EVDK来展示SensAI CNN IP在典型汽车应用中的应用(图6)。


图6:Lattice Semiconductor速度标志检测参考设计利用SensAI平台和Lattice LF_EVDK1-EVN嵌入式视觉开发套件提供一个完整的推理应用,开发人员可以对其立即操作或详细探索。(图片来源:Lattice Semiconductor)

 

此示例应用程序的项目文件包括全套文件,从Caffe caffemodel和TensorFlow pb格式的模型开始。因此,开发人员可以探索这些模型的细节。例如,使用TensorFlow import_pb_to_tensorboard.py实用程序,开发人员可以导入Lattice提供的pb模型,以查看此示例应用程序中使用的CNN的细节(图7)。本例中,所提供的模型是由四个“Fire”模块组成的序列,每个模块包括:

  • Conv2D 层,执行 3 x 3卷积以从输入流中提取特征

  • 激活层,执行 BatchNorm 归一化,然后执行修正线性单元(ReLU) 激活

  • MaxPool 池化层,用于对前一层的输出进行采


图7:Lattice速度标志检测示例应用程序包括TensorFlow pb模型,开发人员可以将其导入TensorBoard进行详细检查。注意:数据向上流过此图中的各层。(图片来源:Digi-Key Electronics)

 

开发人员可以使用SensAI平台生成模型文件,完成前面描述的模型流程。或者,开发人员可以使用所提供的文件直接跳转到部署阶段。任一情况下,文件都是通过接有适配器的microSD卡加载到EVDK中。

 

在操作中,EVDK上的摄像机向ECP5 FPGA提供视频流,其中配置的CNN加速器IP执行命令序列以执行推理。同任何推理引擎一样,每个输出通道都会产生一个结果,指出与该输出通道相关联的标签即为输入图像的校正标签的概率。本例中,模型是用每小时25、30、35、40、45、50、55、60和65英里的限速标志的标注图像进行训练的。因此,当模型在其输入字段中的任何位置检测到限速标志时,它会显示检测到的标志对应于每小时25、30、35、40、45、50、55、60或65英里限速的概率(图8)。


图8:Lattice速度标志检测演示运行在Lattice EVDK上,对视频输入流执行推理,生成输出值,指示捕获到的图像对应于与该特定输出相关联的标签的可能性。本例中,它显示限速标志最有可能是25mph。(图片来源:Lattice Semiconductor)


 总结 


为在嵌入式视觉应用中运用机器学习,开发人员使用可用硬件平台实现所需性能水平的能力受到了限制。然而,高性能FPGA的出现使得开发人员可以构建性能接近GPU的推理引擎。采用专为嵌入式视觉设计的机器学习FPGA平台,开发人员可以专注于特定需求,使用标准机器学习框架训练模型,并依靠FPGA平台实现高性能推理。


推荐阅读

(点击标题可跳转阅读)

最详细、最完整的相机标定讲解

深度学习+机器视觉=下一代检测

视觉检测系统最经典的结构你了解吗?

机器视觉技术的十大应用领域

工业相机和普通相机究竟有什么不同?

基于机器视觉和深度学习的智能缺陷检测

波士顿等移动机器人的视觉算法解析

2020年37个人工智能技术发展趋势

机器视觉的光源选型及打光方案分析

光学三维测量技术及应用

国内80%搞机器视觉的工程师,走的路子是错的!

视觉+机器人,如何实现连接器的自动装配?

机器视觉技术发展的五大趋势

搞懂机器视觉基本内容,这份PPT就够了

机器视觉:PC式视觉系统与嵌入式视觉系统区别  

基于HALCON的机器视觉开发,C++或C#如何选择? 

3D视觉技术在机器人抓取作业中的应用实例

基于机器视觉的粗糙度检测方案

机器视觉常用图像软件对比及分析

工业相机编程流程及SDK接口使用汇总



 End 


商务合作:QQ:1504328545

声明:部分内容来源于网络,仅供读者学习、交流之目的。文章版权归原作者所有。如有不妥,请联系删除。

更多是视觉资讯尽在“新机器视觉”微信公众号~


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/49320
 
358 次点击