YOLOV5模型部署到安卓端(复现)

主要参考Yolov5自定义图片训练测试及模型调优(详细过程)记录历经三天将自己的yolov5模型部署到Android安卓手机进行部署复现,此处针对遇到的问题进行记录,分为部署思路和遇到的问题以及解决

一、部署思路

获取图片数据集——训练模型——模型导出为onnx格式——ubuntu环境中实现onnx转换为ncnn格式——将ncnn的模型权重和参数文件复制到ncnn-android-yolov5文件中,并使用android studio编译工程,安装到手机上

1.训练模型

1)数据集获取:采用Le2i视频数据集,通过python脚本方式将跌倒帧图片采集

Le2i:

图片提取:

源码:

import cv2
import os
import numpy as np
import pandas
""" 整体功能是实现视频按照对应txt文件中前两行帧数决定具体选择哪些帧作为图片
(我选择跌倒开始帧、跌倒开始帧加10、跌倒结束帧、跌倒结束帧加10) ,图片存放在递增的文件夹中"""
#该函数实现视频转换为图片
def video_to_frames(video_path,output_path):
    cap=cv2.VideoCapture(video_path)
    count=0
    numForname=1
    savedPic=read_tablemethod(txtPath)
    #判断视频是否打开,是则返回true
    while cap.isOpened():
        #ret是标志位,判断视频帧是否读到frame中,是则返回true
        ret,frame=cap.read()
        if ret:
            #此处判断视频帧是否是我设定想取得的帧编号,是则生成对应的jpg并count加一,不是则count加一去找下一个
            if count in (savedPic[0],savedPic[0]+10,savedPic[1],savedPic[1]+10):
                #这个try没有太大作用,此处通过join实现路径拼接即imwrite(路径,帧),而他的路径又通过join函数拼接
                try:    
                    cv2.imwrite(os.path.join(output_path,f"0{k:02d}frame{numForname:04d}.jpg"),frame)
                    numForname +=1
                except: 
                    # os.makedirs("./fall-dataset/pic/03")
                    print("输出目录不存在")
                count +=1 
            else :
               count +=1
        else:
            break
    cap.release()

#该方法目的在于读取txt文件前两行的内容,进而确定需要截取的帧
def read_tablemethod(filepath):
    #panda的读取文件获得的是一个表,属性是DataFrame,所以需要对其进行格式转换
    data=pandas.read_table(filepath,header=None,delim_whitespace=True)
    #我这里先给他取出来成为一维向量,然后再进行格式转换为int
    firstTwoFps=np.array([data.at[0,0],data.at[1,0]]).astype(int)
    return firstTwoFps

""" def file_remove():
    savedPic=read_tablemethod("./FallDataset/Coffee_room_01/Annotation_files/video (1).txt")
    i=0
    match filename:


    path="./fall-dataset/pic/"+file_name+".jpg"
    os.remove(path) """

if __name__=="__main__":
    """ data=loadTxtMethod("./FallDataset/Coffee_room_01/Annotation_files/video (1).txt")
    print(data) """
    #获取文件夹内视频文件的个数,看需要更改多少次文件路径
    files=os.listdir("./FallDataset/Home_01/Videos")
    num_videos=len(files)
    k=1
    for k in range(1,num_videos+1):
        #每次更改txt和video的文件路径,通过makedirs命令创建存储图片的文件夹
        txtPath="./FallDataset/Home_01/Annotation_files/video ("+str(k)+").txt"
        videoPath="./FallDataset/Home_01/Videos/video ("+str(k)+").avi"
        picPath="./fall-dataset/pic/0"+str(k)
        os.makedirs(picPath)
        #将视频转换为图片
        video_to_frames(videoPath,picPath)
2)图片标注:采取Yolov5自定义图片训练测试及模型调优(详细过程) 的方法,使用Maksense.Ai进行图片上传及标注,具体流程大佬的文章已阐述,此处补充一下遇到的问题

问题:网站一次只能上传一张图片,对于大量图片的上传有点麻烦

解决方法:考虑使用selenium实现自动化上传

源码:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.common.action_chains import ActionChains
import os
""" 标注网站无法上传所有图片,所以提出这个脚本进行自动化处理,主要目的是实现图片批量化上传 """

url="https://www.makesense.ai/"
driver=webdriver.Chrome()


def login():
    #打开网页并进入
    driver.get(url)
    driver.find_element(By.XPATH,"/html/body/div/div/div/div[4]/div[4]").click()
    driver.fullscreen_window()
    time.sleep(1)
    #此处通过input文件属性上传一张图片,以开始图像标注
    driver.find_element_by_xpath("//input[@type='file']").send_keys('C:/Users/niejl/Desktop/yolov5/fall-dataset/pic/Home_01/01/01frame0001.jpg')
    time.sleep(1)
    driver.find_element_by_xpath("/html/body/div[1]/div/div/div[4]/div[2]/div[2]/div[1]").click()
    time.sleep(1)
    driver.find_element_by_xpath("/html/body/div/div/div[2]/div/div[3]/div[2]").click()

def fileUpLoad():
    #上传图片的逻辑
    time.sleep(1)
    i=1
    #输入需要上传的图片目录,通过for循环遍历
    files=os.listdir("C:/Users/niejl/Desktop/yolov5/fall-dataset/pic/Home_01")
    num=len(files)
    for i in range(1,num+1):
        picPath=f"C:/Users/niejl/Desktop/yolov5/fall-dataset/pic/Home_01/0{i}/0{i}frame0004.jpg"
        #点击ACTION按钮
        driver.find_element_by_xpath("/html/body/div/div/div/div[1]/div[2]/div[2]/div/div[1]").click()
        #点击上传图片
        driver.find_element_by_xpath("/html/body/div/div/div/div[1]/div[2]/div[2]/div/div[3]/div[2]").click()
        #默认上传0004结尾的图片,也就是一定跌倒的图片,如果没有,则上传0002的图片
        try:
            driver.find_element_by_xpath("//input[@type='file']").send_keys(picPath)
        except:
            picPath=f"C:/Users/niejl/Desktop/yolov5/fall-dataset/pic/Home_01/0{i}/0{i}frame0002.jpg"
            driver.find_element_by_xpath("//input[@type='file']").send_keys(picPath)
        #选择上传
        driver.find_element_by_xpath("/html/body/div/div/div[2]/div/div[3]/div[2]").click()

    
if __name__=="__main__":
    login()
    fileUpLoad()
3)模型训练:

方法同:Yolov5自定义图片训练测试及模型调优(详细过程) 

更改配置文件并进行训练

python train.py --cfg models/yolov5s_fall.yaml --data data/coco128_fall.yaml --weights yolov5s.pt --epoch 150 --batch-size 32

得到对应权重文件:


训练问题:

  • Numpy版本问题(我的是1.26.2,pip uninstall numpy;pip install numpy==1.22.4 解决)

  • xml转txt标注时出现此问题,标注文件格式不对,用原生txt的标注文件可以成功训练

问题代码:

更改后解决问题:

xml转txt源码:

import os
import xml.etree.ElementTree as ET

#是否需要转换,如果不需要转换的话记得配置好txt文件和images文件到newdir和picdir,然后就可以开始分割
beginXml2txt=1
#在目标目录的下一级创建dataset,并自动分割成yolov5所需训练集
targetdir='C:/Users/niejl/Desktop/yolov5/data/pp_fall'
#待转换数据集目录,转换后的txt文件生成在该路径下的txt文件夹中,同时更改该路径下图片文件夹中的图片
rawdir='C:/Users/niejl/Desktop/yolov5/data/pp_fall'


#待转换xml文件目录,根据具体标注文件夹的名称进行更改
dirpath=f'{rawdir}/Annotations'
#对应图片目录,程序会将标注文件里没有宽度标注的图片自动删除,所以需要提供对应的图片目录
picdir=f'{rawdir}/images'  
#输出txt文件目录
newdir=f'{rawdir}/txt'
#对应标签
dict_info={'fall':0}

images_train=f'{targetdir}/dataset/images/train'
images_test=f'{targetdir}/dataset/images/test'
images_val=f'{targetdir}/dataset/images/val'

labels_train=f'{targetdir}/dataset/labels/train'
labels_test=f'{targetdir}/dataset/labels/test'
labels_val=f'{targetdir}/dataset/labels/val'



def xml2txt():
    if not os.path.exists(newdir):
        os.makedirs(newdir)

    for fp in os.listdir(dirpath):
        if fp.endswith('.xml'):
            root=ET.parse(os.path.join(dirpath,fp)).getroot()

            xmin,ymin,xmax,ymax=0,0,0,0
            sz=root.find('size')
            width=float(sz[0].text)
            height=float(sz[1].text)
            filename=root.find('filename').text
            for child in root.findall('object'):
                sub=child.find('bndbox')
                label=child.find('name').text
                label_=dict_info.get(label)

                xmin=float(sub[0].text)
                ymin=float(sub[1].text)
                xmax=float(sub[2].text)
                ymax=float(sub[3].text)

                try:
                    x_center=(xmin+xmax)/(2*width)
                    x_center='%.6f' % x_center
                    y_center=(ymin+ymax)/(2*height)
                    y_center='%.6f' % y_center
                    w=(xmax-xmin)/width
                    w='%.6f' % w
                    h=(ymax-ymin)/height
                    h='%.6f' % h
                    with open(os.path.join(newdir,fp.split('.xml')[0]+'.txt'),'a+')as f:
                        f.write(''.join([str(label_),' ',str(x_center),' ',str(y_center),' ',str(w),' ',str(h)+'\n']))
                #这里加一个除以零的错误,因为确实有些标注数据给的宽度是0
                except ZeroDivisionError:
                    print(filename,'的width有问题')
                    #删除对应的图片
                    os.remove(os.path.join(picdir,filename))
                    break
def datasetInit():
    if not os.path.exists(images_train):
        os.makedirs(images_train)
    if not os.path.exists(images_test):
        os.makedirs(images_test)
    if not os.path.exists(images_val):
        os.makedirs(images_val)
    if not os.path.exists(labels_train):
        os.makedirs(labels_train)
    if not os.path.exists(labels_test):
        os.makedirs(labels_test)
    if not os.path.exists(labels_val):
        os.makedirs(labels_val)


def datasetSplit():
    datasetInit()
    divs=[8,1,1]
    k=0
    num=len(os.listdir(newdir))
    lab_target=[labels_train,labels_test,labels_val]
    pic_target=[images_train,images_test,images_val]
    for lb_t in lab_target:
        for div in divs:
            i=0
            for raw_txt in os.listdir(newdir):
                i+=1
                filename=raw_txt.split('.txt')[0]
                os.rename(os.path.join(newdir,raw_txt),os.path.join(lab_target[k],raw_txt))
                os.rename(os.path.join(picdir,filename+".jpg"),os.path.join(pic_target[k],filename+".jpg"))
                if i==int((num*divs[k])/(divs[0]+divs[1]+divs[2])):
                    if k==2:
                        break
                    else:
                        k+=1
                        break
        




if __name__=="__main__":
    if beginXml2txt :
        xml2txt()
    datasetSplit()
    print('ok')

2.导出模型

并且通过export.py命令导出onnx文件(原文章中没有include onnx engine,可能导致无法导出)

添加这个命令后可以正常导出onnx格式文件

python export.py --weights runs/train/exp2/weights/best.pt --include onnx engine

简化onnx文件

python -m onnxsim best.onnx best-sim.onnx

将这两个文件打包备用

3.ubuntu环境中进行onnx到ncnn格式转换

过程同记录历经三天将自己的yolov5模型部署到Android安卓手机_yolov5部署到手机-CSDN博客

部署环境过程中遇到安装 protobuf 依赖库不成功的问题,主要由于没有./autogen.sh所以执行不成功,此处百度解决方案ubuntu 20.04安装Protobuf_五班图20.04安装goolgle/protocbuf-CSDN博客并解决问题

导出两个文件,并打包备用

4.Android Studio进行工程编译并安装手机上

此处问题较多,主要是gradle和java版本不匹配的问题,调试后尝试出来一种搭配并成功编译安装

运行结果:

  • 14
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: yolov5_deepsort_pytorch是一种基于PyTorch框架的目标检测和跟踪算法,它结合了YOLOv5和DeepSORT两种算法的优点,能够在实时视频中高效地检测和跟踪多个目标。如果您想要复现这个算法,需要掌握PyTorch框架的基本使用方法,并且了解YOLOv5和DeepSORT的原理和实现方式。具体的复现步骤可以参考相关的论文和代码实现,也可以参考其他人的经验和教程。 ### 回答2: Yolov5是最近非常热门的目标检测算法,它可以在极短时间内完成大规模数据的检测任务,并且在准确率上也取得了非常不错的表现。而在这个基础上,我们还可以使用DeepSORT进行目标追踪。Yolov5+DeepSORT的结合,可以实现在实时数据场景下目标的检测和追踪,如视频监控、自动驾驶等领域。 以下是Yolov5+DeepSORT的复现步骤: 1.环境配置:首先需要安装好PyTorch、NumPy、OpenCV等常用的Python包。建议使用conda或者pip安装。 2.下载代码:Github上有很多公开的Yolov5和DeepSORT的代码,建议从这些仓库中下载。 3.数据预处理:需要将输入数据进行预处理,包括图像尺寸的缩放、像素均一化等操作。 4.检测模型的加载:使用Yolov5实现目标检测,并将检测结果传递给DeepSORT进行物体追踪。 5.物体追踪:这里使用DeepSORT算法进行目标追踪,将检测出来的目标和之前已经追踪到的目标进行匹配,并且根据目标的特征进行分类和更新。 6.绘制结果:最后将检测和追踪的结果用框标出来,并绘制在原始图像上。 在进行复现的过程中,还需要非常熟悉Yolov5和DeepSORT的原理,对目标检测、图像处理、机器学习等领域有一定的背景知识才能完成任务。 当然,这个过程并不是一次就能成功的,很可能还需要不断地修改和优化有关参数及代码,增加训练集,进行数据增强等操作,才能够得到良好的实验效果。因此,在进行复现之前,需要有足够的耐心和实践精神。 ### 回答3: Yolov5_deepsort_pytorch是一种神经网络模型,它结合了YoloV5和DeepSort算法。这个模型可以在视频中对动态物体进行实时目标检测和跟踪。复现这个模型,需要进行以下步骤: 1. 数据准备 首先,需要准备数据集。该数据集应包含视频片段以及用于训练和测试的图像及其对应的标注框。图片需要进行标准化和缩放,标注框需要进行转换。 2. 模型训练 使用准备好的数据集,我们需要训练模型。使用PyTorch框架可以很方便地构建、训练和保存深度学习模型。在这个过程中,需要选择合适的超参数,在损失函数等一系列参数上做出合适的选择。 3. 模型测试 当模型训练完成后,我们需要对模型进行测试。可以使用测试数据集来测试模型的准确性。测试结果可以评估模型的性能,并对其进行微调和优化。 4. 部署 当我们得到了可满足要求的模型以后,我们可以部署这个模型部署环境中,如公司内部网络或云环境等。可以在python中进行部署,并使用GPU实现快速推断。 总之,复现Yolov5_deepsort_pytorch模型需要进行数据准备、模型训练、模型测试和部署等一系列步骤。在整个过程中,需要仔细处理每个步骤,特别是数据的输入和模型训练的细节问题。最终,需要评估整个模型的准确性和性能,在实际应用中得到充分验证。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值