基于M5Stack UnitV2 的流水线异常品目标检测
本项目实现了任务二,通过深度学习目标检测,来甄别流水线的异常品,发现异常品后记录,上传至网站。
标签
M5Stack
UnitV2
AI摄像头
图像识别
目标检测
深度学习
枫雪天
更新2021-07-20
1081

硬件介绍

   首先介绍本期活动的主角,M5Stack推出的Unit V2开发板,这是一块很小的嵌入式Linux开发板,主控是一颗ARM Cortex-A7的双核处理器,主频是1.2Ghz。同时主板集成了128M内存和512M的Flash,同时预留了TF卡槽,可以用来扩展更多的存储空间。

FimTaiwKvXfyJX5g8xA_VkgJoUGG

   模块有以下主要参数:

  • ARM 双核 Cortex-A7 1.2Ghz 处理器,带Neno和FPU的硬件加速器

  • 128MB DDR3内存

  • 512MB NAND Flash

  • GC2145 1080P 摄像头

  • 麦克风、TF卡插槽、UART端口

  • WiFi 2.4GHz、USB有线网卡

 

任务分析

    活动一共设置了四种任务,简单概括一下这四种任务,都是通过图像识别来分析一些场景信息,并记录下来。只是分析对象不同。

    我选做的是任务2,任务2的核心问题就是训练一个针对流水线的目标检测模型。这一步可以有很多种实现方法,可以基于官方的V-training平台来一站式地获得模型,也可以自己在本地通过PyTorch等深度学习框架来自己训练模型。在模型的部署方面,也有两种方案,即可以使用官方提供的框架来推理模型,也可以使用NCNN提供的C++库来自己编写推理程序。但是在实际运行系统后,发现根文件系统是基于busybox构建的。为了保持足够小的体积,精简掉了gcc等工具链,也没有包管理器来他们安装它们。如果自行构建功能更完整的根文件系统并切换上去,要花费很多的时间。因此最终还是选择使用官方提供的可执行程序来进行推理。

硬件平台搭建

    我选择的流水线识别对象是一些螺丝刀的可拆卸刀头,把其中的六角刀头定义为异常品,其他种类的刀头定义为正常。用A4纸和手机支架搭建了一个简单的模拟流水线。

    由于Unit V2开发板内嵌了Linux操作系统,已经集成任务所需的硬件资源,我们只需要使用手机支架把它布置到合适的位置即可。

    最后把工件放置在A4纸上,通过移动A4纸,就可以模拟流水线上工件移动的效果。布置完成的效果如下。

Fls7UEKtPaEVPn8NSHg2dyREK8_N

FvvKdXGhrbo4-pZ2GzJBjuOJPAxn

软件平台搭建

    任务主要需要两个平台,一个是运行监控网站的笔记本电脑或阿里云服务器,另一个则是Unit V2开发板。

    开发与部署所需的软件如下:

  • VSCode: 用来开发Python代码
  • IDEA: 用来开发Java网站
  • XShell:连接Unit V2开发板的SSH终端
  • XFTP:和开发板间传输文件
  • Spring Boot + SSM :编写Java网站所需的框架与中间件

实现流程

1. 训练模型   

     我们使用官方提供的V-training训练平台,来训练自己的模型。首先通过Unit V2提供的拍照功能,拍下30多张图片,上面分别是各种情况下的流水线。接下来上传图片,标定目标数据集,然后开始训练,一段时间后就可以下载模型。

FhSFrviupivRmM8wIqumzh-LiYQG

FpEctDnzCBHN_7kQUHiDnNhH97AT

2. 上传并运行模型 

    上一步下载得到的模型文件为压缩包格式,我们把它上传到模块中,就可以直接运行模型,得到可视化的结果和输出信息。

FkkrDbmaSey97eUan7RhZuda_Hvm

FsPLYDrDoPuSpBr2adM-zZhPCFXJ

3. 分析程序输出并上传至服务器 

    目标检测程序的输出信息是json的格式,我们可以写一个python程序。调用目标检测程序。并分析它的输出。当输出内容中含有异常品时,就把它记录下来。为了更好地记录和可视化结果,我们使用POST请求,将异常件的数量与图像信息发送至服务器。

Ftum6xXTisK1E30SaihRiCc6a9Wx

    运行在Unit V2开发板的Python主程序如下:

from json.decoder import JSONDecodeError
import subprocess
import json
import requests
import base64
import time

reconizer = subprocess.Popen(['/home/m5stack/payload/bin/object_recognition', '/home/m5stack/payload/uploads/models/v2model_2990349c31e07065'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

url = 'http://10.254.239.226:80'
header = { 'content-type':'application/json'}

reconizer.stdin.write("_{\"stream\":1}\r\n".encode('utf-8'))
reconizer.stdin.flush()

img = b''
time = 0
lastNum = 0

numChanged = False
while True:
    doc = json.loads(reconizer.stdout.readline().decode('utf-8'))
    time = time + 1

    num = 0
    hasBad = False

    if 'img' in doc:
        img = doc["img"]

    if 'obj' in doc:
        for e in doc['obj']:
            if e['type'] == 'bad':
                num=num+1
                hasBad = True
        
        numChanged = (doc["num"] != lastNum)
        
        if hasBad and numChanged and time>20:
            print("bad dected!")
            time = 0
            msg = {'name':'bad', 'count':num, 'img': img}
            r = requests.post(url + '/history/create', data=json.dumps(msg),headers=header)
            print(r)
            print(r.content)
            numChanged = False

        lastNum = doc["num"]

4. 网站服务器接收记录,并存储、展示   

    我用Java编写了一个简单的网站,它可以接收Unit V2开发板发来的检测到异常品的时间和实时的照片,并保存到MySQL数据库中,还可以通过前端的页面展示出来。

    Java网站的部分后端程序如下:

package com.yu.crm.web.controller;

import com.yu.crm.model.CRUDResult;
import com.yu.crm.model.LogEntry;
import com.yu.crm.model.PageResult;
import com.yu.crm.service.ILogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Decoder;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

@Controller
@RequestMapping("history")
public class ListController {

    @Autowired
    ILogService service;
    @Autowired
    SimpleDateFormat sdf;

    @RequestMapping("list")
    public String list(){
        return "history/list";
    }

    @RequestMapping("create")
    @ResponseBody
    public CRUDResult create(@RequestBody Map<String, Object> req){

        final String name = req.get("name").toString();
        final int count = Integer.parseInt(req.get("count").toString());
        final String img = req.get("img").toString();
        final Date date = new Date();
        final String pic = sdf.format(date).toString() + ".jpg";

        try {
            String path = "D:/data/";
            String fakePath = "/image/" + pic;
            final String realPath = path + pic;
            final LogEntry entry = new LogEntry(null, name, count, date, fakePath);
            service.create(entry);
            decoderBase64File(img, realPath);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new CRUDResult(1,"OK");
    }

    @RequestMapping("listJson")
    @ResponseBody
    public PageResult<LogEntry> listJson(LogEntry condition, int page, int limit){

        PageResult<LogEntry> pageResult = service.findPageResult(condition, page, limit);
        return pageResult;
    }

    public void decoderBase64File(String base64Code,String targetPath) {
        try {
            byte[] buffer = new BASE64Decoder().decodeBuffer(base64Code);
            FileOutputStream out = new FileOutputStream(targetPath);
            out.write(buffer);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Bean
    public SimpleDateFormat getSimpleDateFormat() {
        return new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
    }
}

遇到的问题

    由于Unit V2提供的软硬件功能已经相当完善,遇到的问题主要是在实现方案的选择与开发中的实现细节,具体如下:

1. 模型推理的方案选择 

    项目最开始的计划是选用PyTorch在本地自己训练模型,并使用C++库编写NCNN推理程序,这样实现细节可控,但是查看开发板的系统后发现,板载的根文件系统只提供了完整的Python环境,C++开发环境工具链缺失,也无法通过包管理器来安装。官方框架的推理程序只提供了二进制可执行文件,推理源码也并没有开源。因此最终选择了使用Python调用官方的推理程序。

2. 向网站后端服务器传输图片与其他信息 

    为了在网站上提供更好的展示效果,决定向后端服务器发送图片和文本信息,但是最开始对图像的传输编码不了解,经过一些尝试,确定图片就是原始JSON的img字段,并且是Base64编码过后的。最终在后端服务器上编写了Base64解码与文件保存部分,实现了在一次POST请求中同时传输图片与文本信息。

3. UnitV2有限网卡与电脑的联网优先级 

    同时使用UnitV2有限网卡和电脑本身的网卡联网时,有时会导致电脑无法联网。经过群内的讨论,发现在Windows系统中可以通过调整网卡跃点数来修改网卡的联网优先级。经过修改后,电脑能够正常联网,这也是通过本次活动学到的一个继续你的小技巧。

未来的计划建议

   M5Stack官方给UnitV2的定位是AI识别模块,这块开发板给我印象最深刻的就是在宣传片中,它流畅地运行一些小型的深度学习目标检测模型。这一点非常有吸引力,因为能够在如此有限的板载资源下运行深度学习模型,是有一定的技术难度的,所以我报名参加了本次的活动,希望能够一探究竟,学习一下Unit V2的软硬件设计。

    经过活动中一段时间的熟悉,总结了几个对UnitV2的小建议,很希望能够在下一版本或UnitV3中看到它们:

  1. 完善根文件系统。UnitV2的根文件系统是基于Busybox构建的,虽然能够保持足够小的体积,但也同样限制了它的可扩展性。目前用户只能通过Python等高级语言来进行编程,不能够使用C++等语言进行更灵活的编程,也不能安装自己想要的系统应用。希望下一版的根文件系统可以考虑基于Debian等扩展性更强的文件系统来构建,文件系统可以移动到TF卡中,便于升级和修改,也进一步提高模块的自由度和可玩性。
  2. 加大开源力度。目前UnitV2系统中使用的目标检测程序是以为禁止可执行程序bin文件的方式提供的,在官方的github中并没有提供源码,在main文件夹下也只提供了camera_stream功能的源码,希望能够在接下来的更新中通过源码学习到更多的内容,而不是只调用编译好的可执行文件。
  3. 硬件升级。UnitV2作为一款AI识别模块,核心功能应该是图像识别功能,在实际运行的过程中,机器运行目标检测模型如nanodet的时候,流畅度还是不够高,当运行yolo模型的时候会更加明显,希望能够在下一代硬件中,升级处理器,或者添加一块专门的AI推理芯片,目前市场上还是有一些优秀的AI推理芯片的。相信通过硬件升级,Unit主打的图像识别能力会得到显著增强。

   最后,感谢硬禾学堂和M5Stack的大力支持,以及交流群中老师和小伙伴们的奇思妙想,祝愿硬禾学堂的活动越办越好!

 

附件下载
run.py
推理与分析程序(运行在UnitV2)
crm.zip
网站程序(运行在服务器)
v2model_2990349c31e07065.tar
训练得到的模型
团队介绍
个人
团队成员
枫雪天
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号