SoC FPGA加accsytem加神经网络算子实现: 车牌识别BMP版本

一、开发工具

Quartus prime 18.1
作为HLS实验环境搭建的必要软件之一,经验证Quartus Prime 17.1以及18.1版本可支持HLS开发。该软件可在Intel官网上注册后直接下载并按默认选项安装即可。

Modelsim Starter Edition 10.5b
ModelSim是Quartus Prime的附加软件之一。安装Quartus Prime的同时也会安装相应版本的ModelSim,所以无需专门安装该软件。
在此次HLS实验中,使用的版本是ModelSim Starter Edition 10.5b,此为HLS的默认调用版本并且不需要License。

Microsoft Visual Studio 2010 (Visual C++, 未使用license)
在整个HLS实验环境搭建中,建议安装使用Microsoft Visual Studio 2010因为经验证更新后的版本将不支持HLS开发。其中Profession、Ultimate、Standard三个版本均可从网上下载安装并未使用License,但是需要注意的是Standard版本仅支持HLS 18.1以及HLS 19.1,所以到时候需要手动匹配HLS版本方可运行。此外,在安装过程中需确保Visual C++被成功勾选。
在此次HLS实验中,使用的版本是Microsoft Visual Studio 2010 Ultimate。
(需要注意的是在全部软件安装完成后,环境变量都已自动被设置,故而无需再手动设置。)

C5MB_GHRD的黄金参考工程

二、利用HLS编译相关算子

重要说明:
Width 输入图像宽度
Height 输入图像高度
OutDir 如果是1的话,将卷积结果存放在LocalMap中;如果是0保存在Result中
Accmulate 如果是1表示需要累加
maps weight localmap result分别是4块独立的内存区域

一下代码的int main() 这个函数可以加可不加

如图下面四个C文件

文件名 描述
conv.c 卷积算子
biasrelu.c 偏置算子
pooling.c 池化算子
full_connecttion.c 全连接算子

1.conv.c

#include <HLS/stdio.h>
#include "HLS/hls.h"

component void AccConvolution(int Width,
                              int Height,
                              int OutDir,
                              int Accmulate,
                              ihc::mm_master<float> &maps,
                              ihc::mm_master<float> &Weight,
                              ihc::mm_master<float> &LocalMap,
                              ihc::mm_master<float> &Result) {

    float   temp;
    int _height = Height - 2;
    int _width = Width - 2;
    int index = 0;

    for(int h = 0;h < _height ;h++) {
        for(int w = 0;w < _width ;w++) {

            temp    =   maps[ (h    ) * Width + w     ]     * Weight[0]    +
                        maps[ (h    ) * Width + w + 1 ]     * Weight[1]    +
                        maps[ (h    ) * Width + w + 2 ]     * Weight[2]    +
                        maps[ (h + 1) * Width + w     ]     * Weight[3]    +
                        maps[ (h + 1) * Width + w + 1 ]     * Weight[4]    +
                        maps[ (h + 1) * Width + w + 2 ]     * Weight[5]    +
                        maps[ (h + 2) * Width + w     ]     * Weight[6]    +
                        maps[ (h + 2) * Width + w + 1 ]     * Weight[7]    +
                        maps[ (h + 2) * Width + w + 2 ]     * Weight[8]    ;

            index = h * (Width - 2) + w;
            if(Accmulate)   
                temp    +=  LocalMap[index];

            if(OutDir)
                LocalMap[index] =   temp;
            else
                Result[index] =   temp;
        }
    }
}
int main()
{
    
    int Width = 5;
    int Height = 5;
    int OutDir = 1; //输出特征图保存在LocalMap
    int Accmulate = 0; //不叠加LocalMap

    float maps[5*5] = {     //保存输入特征图
                    1,1,1,0,0,
                    0,1,1,1,0,
                    0,0,1,1,1,
                    0,0,1,1,0,
                    0,1,1,0,0 
                }; 

    float Weight[3*3] = {   //卷积窗3*3
                    1,0,1,
                    0,1,0,
                    1,0,1
                    };      
    float LocalMap[3*3] = {0.0}; //输出特征图尺寸3*3
    float Result[3*3] = {0.0} ;//输出特征图尺寸3*3
    


    //打印输入的特征图
    printf("input picture:\n");
    for(int i=0;i<25;i++)
    {
        printf("%.1f ",maps[i]);
        if((i+1)%5==0)
        {
            printf("\n");
        }
    }

    //打印输入的权重
    printf("input Weight:\n");
    for(int i=0;i<9;i++)
    {
        printf("%.1f ",Weight[i]);
        if((i+1)%3==0)
        {
            printf("\n");
        }
    }

    ihc::mm_master<float> mm_maps(maps,sizeof(float)*25);
    ihc::mm_master<float> mm_Weight(Weight,sizeof(float)*9);
    ihc::mm_master<float> mm_LocalMap(LocalMap,sizeof(float)*9);
    ihc::mm_master<float> mm_Result(Result,sizeof(float)*9);

    //调用component
    AccConvolution(Width,Height,OutDir,Accmulate,mm_maps,mm_Weight,mm_LocalMap,mm_Result);
    
    //打印Result中的结果
    printf("result in LocalMap:\n");
    for(int i=0;i<9;i++)
    {
        printf("%.1f ",LocalMap[i]);
        if((i+1)%3==0)
        {
            printf("\n");
        }
    }
    return 0;
}

在这里插入图片描述

2.biasrelu.c

#include <HLS/stdio.h>
#include "HLS/hls.h"

component void AccBiasRelu(int Width,
                           int Height,
                           int InDir,
                           int OutDir,
                           ihc::mm_master<float> &LocalMap, 
                           ihc::mm_master<float> &maps,
                           ihc::mm_master<float> &Result,
                           ihc::mm_master<float> &Weight) {

    int Exit    =   Width * Height;
    float temp;
    float *temp1;
    float *inputbuffer;
    if(InDir)
    	inputbuffer =   LocalMap;
    else 
    	inputbuffer =   maps;

    if(OutDir)
    	temp1 = LocalMap;
    else
	    temp1 = Result;

    #pragma ivdep
    for(int i = 0;i < Exit;i++) {
        temp            =   inputbuffer[i] + Weight[0];
        temp1[i]          =   (temp > 0)  ?   temp   :    0;
    }
}
int main()
{
    int Width = 3;
    int Height = 3;
    int InDir = 1;   //从LocalMap取数据(也就是卷积后的数据)
    int OutDir = 1;  //从LocalMap取数据(加偏置后的数据)

    float LocalMap[3*3]  = {   //激活后的结果保存在LocalMap里面,激活的输入数据来自于私有存储器
            4.0 ,3.0, 4.0,
            2.0 ,4.0, 3.0,
            2.0 ,3.0, 4.0
    };

    //打印输入的图片
    printf("input picture:\n");
    for(int i=0;i<9;i++)
    {
        printf("%.1f ",LocalMap[i]);
        if((i+1)%3==0)
        {
            printf("\n");
        }
    }

    float maps[3*3] = {0.0};
    float Result[3*3] = {0.0};

    float Weight[3*3] = {   //加载偏置数据到FPGA的Weight存储器中
        1.0 ,0.0, 1.0,
        0.0 ,1.0, 0.0,
        1.0 ,0.0, 1.0
    };

    //打印输入的权重
    printf("input Weight:\n");
    for(int i=0;i<9;i++)
    {
        printf("%.1f ",Weight[i]);
        if((i+1)%3==0)
        {
            printf("\n");
        }
    };
    
    ihc::mm_master<float> mm_maps(maps,sizeof(float)*9);
    ihc::mm_master<float> mm_Weight(Weight,sizeof(float)*9);
    ihc::mm_master<float> mm_LocalMap(LocalMap,sizeof(float)*9);
    ihc::mm_master<float> mm_Result(Result,sizeof(float)*9);

    //调用component
    AccBiasRelu(Width,Height,InDir,OutDir,mm_LocalMap, mm_maps,mm_Result,mm_Weight);

    //打印LocalMap中的结果
    printf("LocalMap data:\n");
    for(int i=0;i<9;i++)
    {
        printf("%.1f ",LocalMap[i]);
        if((i+1)%3==0)
        {
            printf("\n");
        }
    }
    return 0;
}

在这里插入图片描述

3.pooling.c

#include <HLS/stdio.h>
#include "HLS/hls.h"

#include <HLS/stdio.h>
#include "HLS/hls.h"

component void AccPool( int Width, 
                        int Height,
                        int InDir, 
                        int OutDir,
                        ihc::mm_master<float>&LocalMap,
                        ihc::mm_master<float>&maps,
                        ihc::mm_master<float>&Result) {

    float PoolWindow[2][2];
    float temp0;
    float temp1;
    float temp2;
    int _height = Height >> 1;
    int _width = Width >> 1;
    int index = 0;
    int _index = 0;
    int _index_1 = 0;

    float *input;
    float *output;
    if(InDir)
        input = LocalMap;
    else
        input = maps;

    if(OutDir)
        output = LocalMap;
    else
        output = Result;

    for(int h = 0;h < _height;h++) {
	#pragma ivdep
        for(int w = 0;w < _width;w++) {
            _index = h * 2 * Width + w * 2;
            _index_1 = (h * 2 + 1) * Width + w * 2;
            PoolWindow[0][0] = input[ _index ];
            PoolWindow[0][1] = input[ _index + 1];
            PoolWindow[1][0] = input[ _index_1 ];
            PoolWindow[1][1] = input[ _index_1 + 1];

            temp0    =   (PoolWindow[0][0] > PoolWindow[0][1]) ? PoolWindow[0][0] : PoolWindow[0][1];
            temp1    =   (PoolWindow[1][0] > PoolWindow[1][1]) ? PoolWindow[1][0] : PoolWindow[1][1];
            temp2    =   (temp0 > temp1) ? temp0 : temp1;
            output[h*_width + w] = temp2;
        }
    }
}
int main()
{
    int Width = 4;
    int Height = 4;
    int InDir = 1; //从 Localmap 读取图片数据
    int OutDir = 0;   //将输出结果放到 Result中

    
    float LocalMap[4*4] = {
        1,  2,  3,  4,
        5,  6,  7,  8,
        9,  10, 11, 12,
        2,  2,  3,  4
    };

    //打印从LocalMap获取的数据
    printf("input LocalMap:\n");
    for(int i=0;i<16;i++)
    {
        printf("%.1f  ",LocalMap[i]);
        if((i+1)%4==0)
        {
            printf("\n");
        }
    }

    float maps[4*4] = {
        1,  2,  3,  4,
        5,  6,  7,  8,
        9,  10, 11, 12,
        2,  2,  3,  4
    };

    float Result[2*2] = {0.0};
    

    ihc::mm_master<float> mm_maps(maps,sizeof(float)*16);
    ihc::mm_master<float> mm_LocalMap(LocalMap,sizeof(float)*16);
    ihc::mm_master<float> mm_Result(Result,sizeof(float)*4);

    //调用组件
    AccPool(Width, Height,InDir, OutDir,mm_LocalMap,mm_maps,mm_Result);

    //打印 Result 内存中的结果
    printf("pooling result:\n");
    for(int i=0;i<4;i++)
    {
        printf("%.1f  ",Result[i]);
        if((i+1)%2==0)
        {
            printf("\n");
        }
    }
    return 0;
}

在这里插入图片描述

4.full_connection.c

#include <HLS/stdio.h>
#include "HLS/hls.h"

component void AccFullConnect(ihc::mm_master<float>&maps,
                              ihc::mm_master<float>&Weight,
                              ihc::mm_master<float>&Result) {

    float temp[16];
    float tmp = 0.0;
    float *result;
    result = Result;
    #pragma unroll
    for(int i = 0;i < 16;i++)
    {
        temp[i] = maps[i] * Weight[i];
    }

    #pragma unroll
    for(int i=0; i< 16;i++)
    {
        tmp += temp[i];
    }

    result[0] = tmp;
}
int main()
{
    float maps[16]={1,1,1,0,0,1,1,1,0,0,1,1,0,0,1,1};

    //打印maps中的数据
    printf("input maps:\n");
    for(int i=0;i<16;i++)
    {
        printf("%.1f ",maps[i]);
    }
    printf("\n");

    float Weight[16] = {1,0,1,1,0,1,0,0,1,0,1,1};

    //打印Weight中的数据
    printf("input Weight:\n");
    for(int i=0;i<16;i++)
    {
        printf("%.1f ",Weight[i]);
    }
    printf("\n");

    float Result[16] = {0.0f};

    ihc::mm_master<float> mm_maps(maps,16*sizeof(float));
    ihc::mm_master<float> mm_Weight(Weight,16*sizeof(float));
    ihc::mm_master<float> mm_Result(Result,16*sizeof(float));

    //调用组件
    AccFullConnect(mm_maps,mm_Weight,mm_Result);

    //打印 Result 内存中的数据  
    printf("full_connection Result:\n");
    printf("%.1f \n",Result[0]);
    return 0;
}

在这里插入图片描述

编译方式因为都一样(雷同) 所以只拿conv.c 做例子

①先初始化环境(命令根据自己的路径来定)

d:\FPGA\intelFPGA\18.1\hls\init_hls.bat

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
车牌识别系统是一个常见的计算机视觉应用,基于SoC(System on Chip)的设计可以提供高效的实时性能和低功耗。下面是一个基于SoC的卷积神经网络(CNN)车牌识别系统的设计流程: 1. 数据集收集与预处理:首先,收集包含各种车牌图像的数据集。对数据集进行预处理,包括图像增强、裁剪和大小调整等操作,以提高训练和测试的准确性。 2. 网络架构选择:选择适合车牌识别任务的CNN网络架构,如VGGNet、ResNet或MobileNet等。根据硬件资源和性能需求进行权衡选择。 3. 模型训练:使用准备好的数据集对选定的CNN网络进行训练。训练过程中,可以采用数据增强技术,如平移、旋转和缩放等,增模型的泛化能力。 4. 模型量化与优化:将训练好的模型进行量化和优化,以适应SoC的计算和存储资源限制。常见的优化方法包括权重剪枝、量化和模型压缩等。 5. 部署与集成:将经过优化的模型部署到SoC中,并与摄像头或视频输入设备进行集成。设计适当的接口和数据传输机制,以实现实时的车牌识别功能。 6. 实时车牌识别:在SoC上运行车牌识别系统,通过摄像头或视频输入获取图像数据,经过预处理后输入到CNN模型中进行推理。根据模型的输出结果,进行车牌位置检测和字符识别,最终实现车牌的识别和提取。 需要注意的是,基于SoC的设计需要考虑硬件资源和性能的限制,并进行针对性的优化。同时,还需要进行充分的测试和调试,以保证系统的准确性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值