21年电赛F 题jetson nano+32F4识别数字(附源码和数据集)

这篇具有很好参考价值的文章主要介绍了21年电赛F 题jetson nano+32F4识别数字(附源码和数据集)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、Opencv采集数字图像

二、标记图像数字位置

三、yolov4-tiny机器学习训练

四、jetson nano识别数字

五、识别效果

单个数字识别

 ​​​

两个数字识别

 四个数字识别

命令行结果显示

小车OLED屏幕显示

总结+数据集权重文件+小车程序


前言


啊!四天三夜的电赛终于结束了,我们组做了两辆送药小车,先上作品图!

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

两辆车都能完成基础任务,配合后发挥任务一和二也都能完成,国赛初评结果是国二,勉勉强强吧,现在我来分享一下完成任务的过程,训练识别这里可以参考我之前写的第七届全国大学生工程训练大赛智能+赛道生活垃圾分类垃圾训练步骤(win10+yolov4-tiny)

一、Opencv采集数字图像


我用Python编写了一个OpenCV拍照脚本,代码如下:

import cv2
import os

print("=============================================")
print("=  热键(请在摄像头的窗口使用):             =")
print("=  z: 更改存储目录                          =")
print("=  x: 拍摄图片                              =")
print("=  q: 退出                                  =")
print("=============================================")
print()
class_name = input("请输入存储目录:")
while os.path.exists(class_name):
    class_name = input("目录已存在!请输入存储目录:")
os.mkdir(class_name)

index = 1
cap = cv2.VideoCapture(0)
width = 640
height = 480
w = 360
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)

crop_w_start = (width-w)//2
crop_h_start = (height-w)//2

print(width, height)

while True:
    # get a frame
    ret, frame = cap.read()
    # show a frame
    #frame = frame[crop_h_start:crop_h_start+w, 400]
    #frame = cv2.flip(frame,1,dst=None)
    cv2.imshow("capture", frame)

    input = cv2.waitKey(1) & 0xFF

    if input == ord('z'):
        class_name = input("请输入存储目录:")
        while os.path.exists(class_name):
            class_name = input("目录已存在!请输入存储目录:")
        os.mkdir(class_name)
    elif input == ord('x'):
        cv2.imwrite("%s/%d.jpg" % (class_name, index),
                    cv2.resize(frame, (224, 224), interpolation=cv2.INTER_AREA))
        print("%s: %d 张图片" % (class_name, index))
        index += 1
    if input == ord('q'):
        break

首先将USB摄像头固定在车上之后将车放在场地上进行拍照,每一个数字拍摄100-200张224*224的图像,然后保存在文件夹中。

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

二、标记图像数字位置


使用标记软件labelImg进行,生成就能保存数字在图像中的坐标和对象名称的xml标签文件:

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

三、yolov4-tiny机器学习训练


训练框架采用轻量的yolov4-tiny,使用win10电脑进行训练,将OpenCV摄像头采集到的数字图像新建文件夹JPEGImages保存,然后将标记好数字的xml标签文件新建一个Annotations文件夹保存。

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

然后编写Python脚本txt.py随机选择训练样本图片和对照样本图片,代码如下:

import os
import random

trainval_percent = 0.5
train_percent = 0.5
xmlfilepath = 'VOCdevkit/VOC2021/Annotations'
txtsavepath = 'VOCdevkit/VOC2021/ImageSets/Main'
total_xml = os.listdir(xmlfilepath)

num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
ptr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, ptr)

ftrainval = open(txtsavepath + '/trainval.txt', 'w')
ftest = open(txtsavepath + '/test.txt', 'w')
ftrain = open(txtsavepath + '/train.txt', 'w')
fval = open(txtsavepath + '/val.txt', 'w')

for i in list:
    name = total_xml[i][:-4] + '\n'
    if i in trainval:
        ftrainval.write(name)
        if i in train:
            ftrain.write(name)
        else:
            fval.write(name)
    else:
        ftest.write(name)

ftrainval.close()
ftrain.close()
fval.close()
ftest.close()

 然后编写Python脚本voc_label.py将标签文件中的名字和坐标位置提取出来生成一个txt文件,代码如下:

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join

sets=[('2021', 'train'), ('2021', 'val'), ('2021', 'test')]

classes = ["one","two","three","four","five","six","seven","eight"]


def convert(size, box):
    dw = 1./(size[0])
    dh = 1./(size[1])
    x = (box[0] + box[1])/2.0 - 1
    y = (box[2] + box[3])/2.0 - 1
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)

def convert_annotation(year, image_id):
    in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
    out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w')
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult)==1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
        bb = convert((w,h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb])+'\n')

wd = getcwd()

for year, image_set in sets:
    if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)):
        os.makedirs('VOCdevkit/VOC%s/labels/'%(year))
    image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()
    list_file = open('%s_%s.txt'%(year, image_set), 'w')
    for image_id in image_ids:
        list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
        convert_annotation(year, image_id)
    list_file.close()

os.system("cat 2021_train.txt 2021_val.txt 2021_train.txt 2021_val.txt > train.txt")
os.system("cat 2021_train.txt 2021_val.txt 2021_test.txt 2021_train.txt 2021_val.txt > train.all.txt")


新建coco.name文件记录识别类别名字:

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

新建coco.data文件记录类别数量,训练图像文件位置,测试图像文件位置,类别名字对象文件位置,生成权重文件保存位置:

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

新建yolov4-tiny-train文件记录训练图像大小,训练迭代最大次数等:

 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

 一切准备就绪后使用darknet.exe程序输入指令:darknet detector train object/coco.data object/yolov4-tiny-train.cfg yolov4-conv.29开始训练。

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

 迭代6500次后loss损失度已经降低到0.1左右后停止训练,得到权重文件:

21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

我会把训练的图片数据集还有生成的权重文件放到最后的总结部分,需要的同学可以自行下载哈。

四、jetson nano识别数字


编写Python脚本testimage.py加载权重文件识别数字,并将识别到的结果进行处理后将结果通过串口反馈给STM32F4单片机,识别流程:将第一次识别的数字作为目标变量target保存,在第二次识别到这个数字判断数字所在位置(假如在左侧),如果是近端或中端则通过串口发送字符i或r给单片机,i代表left在左侧,r代表right在右侧,如果是远端则等待第三次识别target数字然后通过串口发送字符i或r给单片机。代码如下:

def camera_thread():
    network, class_names, class_colors = darknet.load_network('object2/yolov4-tiny-test.cfg', 'object2/coco.data',
                                                              'object2/backup/yolov4-tiny4.weights', batch_size=1)

    cap = cv2.VideoCapture(0)
    width = 640
    height = 480
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
    w = 480
    crop_w_start = (width - w) // 2
    crop_h_start = (height - w) // 2
    while True:
        numbers = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight']
        number = [['number', 0], ['number', 0], ['number', 0], ['number', 0], ['number', 0], ['number', 0],
                  ['number', 0], ['number', 0]]
        x = [0.0, 0.0, 0.0, 0.0]
        y = [0.0, 0.0, 0.0, 0.0]
        worth = 0.0
        s = 1
        flag = 0
        counts = 0

        print("start")
        while True:
            input = cv2.waitKey(1) & 0xFF
            if input == ord('x'):
                print("stop")
                break
            ret, frame = cap.read()
            # frame = frame[crop_h_start:crop_h_start+w+60,crop_w_start:crop_w_start+w+60]
            image, detections = image_detection(frame, network, class_names, class_colors, 0.25)
            # darknet.print_detections(detections, True)
            cv2.imshow('Inference', image)
            counts = len(detections)
            # print("检测到",counts,"个数字")

            for i in range(0, counts, 1):
                # print(detections[i][0], detections[i][1], detections[i][2][0])
                # str,str,float,float,float,float
                # print(type(detections[i][0]),type(detections[i][1]),type(detections[i][2][0]),type(detections[i][2][1]),type(detections[i][2][2]),type(detections[i][2][3]))
                number[i][0] = detections[i][0]
                number[i][1] = int(detections[i][2][0])
                # print(numbers.index(number[i][0]))
                s = int(s + (detections[i][2][2] * detections[i][2][3]))
                worth = worth + float(detections[i][1])

            if s > counts and counts != 0:
                # serial_port.write(('d'+(str(s/counts))).encode())
                # print('distence:',s/counts)
                s = 0
            else:
                s = 0
            if worth > counts and counts >= 0:
                if worth / counts >= 70:

                    number_sort = sorted(number, key=lambda x: x[1])
                    # serial_port.write(('n'+(str(counts))).encode())

                    for i in range(0, counts, 1):
                        print(numbers.index(number_sort[7 - i][0]), number_sort[7 - i][1])
                        # serial_port.write((str(numbers.index(number_sort[7-i][0]))).encode())
                        if flag == 1 and target == numbers.index(number_sort[7 - i][0]):
                            if (counts == 4 and (i == 0 or i == 1)) or (counts == 2 and (i == 0)):
                                GPIO.output(13, GPIO.LOW)
                                print("right")
                                serial_port.write(str(target).encode())
                                serial_port.write('r'.encode())
                                while True:
                                    if serial_port.inWaiting() > 0:
                                        data = serial_port.read()
                                        # print(data)
                                        if data == 'o':
                                            flag = 2
                                            break
                                    input = cv2.waitKey(1) & 0xFF
                                    if input == ord('q'):
                                        break
                                # time.sleep(5)
                            elif (counts == 4 and (i == 2 or i == 3)) or (counts == 2 and (i == 1)):
                                GPIO.output(15, GPIO.LOW)
                                print("left")
                                serial_port.write('l'.encode())
                                while True:
                                    if serial_port.inWaiting() > 0:
                                        data = serial_port.read()
                                        # print(data)
                                        if data == 'o':
                                            flag = 2
                                        elif data == 'k':
                                            flag = 0
                                            break
                                    input = cv2.waitKey(1) & 0xFF
                                    if input == ord('q'):
                                        break
                            print(i)
                        elif flag == 2 and target == numbers.index(number_sort[7 - i][0]):
                            if (counts == 4 and (i == 0 or i == 1)) or (counts == 2 and (i == 0)):
                                GPIO.output(13, GPIO.LOW)
                                print("right")
                                serial_port.write('r'.encode())
                                while True:
                                    if serial_port.inWaiting() > 0:
                                        data = serial_port.read()
                                        # print(data)
                                        if data == 'o':
                                            flag = 3
                                        elif data == 'k':
                                            flag = 0
                                            break
                                    input = cv2.waitKey(1) & 0xFF
                                    if input == ord('q'):
                                        break
                                # time.sleep(5)
                            elif (counts == 4 and (i == 2 or i == 3)) or (counts == 2 and (i == 1)):
                                GPIO.output(15, GPIO.LOW)
                                print("left")
                                serial_port.write('l'.encode())
                                while True:
                                    if serial_port.inWaiting() > 0:
                                        data = serial_port.read()
                                        # print(data)
                                        if data == 'o':
                                            flag = 3
                                            break
                                    input = cv2.waitKey(1) & 0xFF
                                    if input == ord('q'):
                                        break
                            print(i)

                        elif flag == 0 and counts == 1:
                            target = numbers.index(number[0][0])
                            print("target:", target)
                            if target == 1:
                                serial_port.write('1'.encode())
                                while True:
                                    if serial_port.inWaiting() > 0:
                                        data = serial_port.read()
                                        # print(data)
                                        if data == 'o':
                                            flag = 3
                                            break
                                    input = cv2.waitKey(1) & 0xFF
                                    if input == ord('q'):
                                        break
                            elif target == 2:
                                serial_port.write('2'.encode())
                                while True:
                                    if serial_port.inWaiting() > 0:
                                        data = serial_port.read()
                                        # print(data)
                                        if data == 'o':
                                            flag = 3
                                            break
                                    input = cv2.waitKey(1) & 0xFF
                                    if input == ord('q'):
                                        break
                            else:
                                serial_port.write('t'.encode())
                                serial_port.write('t'.encode())
                                serial_port.write('t'.encode())

                                # time.sleep(1)p
                                flag = 1
                    # serial_port.write('o'.encode())
                    print("counts:", counts)
                number = [['number', 0], ['number', 0], ['number', 0], ['number', 0], ['number', 0], ['number', 0],
                          ['number', 0], ['number', 0]]
                worth = 0


            else:
                worth = 0
            k = cv2.waitKey(1)
            time.sleep(0.05)

五、识别效果


单个数字识别


 

 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

两个数字识别


 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

 四个数字识别


 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

命令行结果显示


 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

小车OLED屏幕显示


 21年电赛F 题jetson nano+32F4识别数字(附源码和数据集),Jetson nano,机器学习,计算机视觉,自动驾驶,人工智能

总结+数据集权重文件+小车程序

总结起来四天三夜做出来两辆车还是很困难的,更别说还需要搭建场地还有调试,中途还有很多问题,整个团队都是每天睡觉不到4小时,还好最后的结果还算令人满意,题目一开始看着不难,但是做的过程中就有很多莫名其妙的问题,在有限的时间内解决也是考验选手的一点。

最后附上数字识别的数据集还有权重文件:

数字识别训练数据集和权重

电赛F题送药小车程序.zip文章来源地址https://www.toymoban.com/news/detail-621623.html

到了这里,关于21年电赛F 题jetson nano+32F4识别数字(附源码和数据集)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 基于PID算法下STM32控制的坡道行驶电动小车(2020年电赛)

    基于PID算法下STM32控制的坡道行驶电动小车(2020年电赛)

    本题源于2020年TI杯大学生电子设计竞赛C题-----坡道行驶电动小车 由于手上没有MSP430/MSP432 板子,所以本篇采用stm32实现 任务 利用 TI 的 MSP430/MSP432 平台,设计制作一个四轮电动小车。要求小车能沿着指定路线在坡道上自动循迹骑线行驶。小车必须独立运行,车外不能使用任何

    2024年02月16日
    浏览(36)
  • 2018年电赛A题 软件部分 STM32 FFT 时域到频域 STM32cubeMX HAL

    2018年电赛A题 软件部分 STM32 FFT 时域到频域 STM32cubeMX HAL

    题目要求:任意波信号发生器输出非正弦信号时,基波频率范围为50Hz~200Hz,测量电流信号基波频率,频率测量精度优于1%;测量基波及各次谐波分量的幅度(振幅值),电流谐波测量频率不超过1kHz,测量精度优于5% 。 实现方式:利用STM32单片机内置ADC对待测信号进行采集,

    2024年02月15日
    浏览(12)
  • 使用jetson nano的串口与stm32进行通信

    使用jetson nano的串口与stm32进行通信

    首先, jetson nano可以跑python, 那就简单了: 端口就是: GND, 8, 10, 分别接到我STM32F4最小系统板子的UART2: 板子为了方便观察, 就用uart2接收, 用uart1发送, 为啥不用同一个串口呢? 嗯…我乐意… STM32的代码就如上面的, 随便写写就好了. 把UART1的TX接到usb串口上, 然后在jetson上用python运行上

    2024年02月12日
    浏览(23)
  • Jetson nano (4GB B01) 系统安装,官方Demo测试 (目标检测、手势识别)

    Jetson nano (4GB B01) 系统安装,官方Demo测试 (目标检测、手势识别)

    此文确保你可以正确搭建jetson nano环境,并跑通官方”hello AI world” demo. 核心的步骤都来自一手官方教程,如果访问不了可以使用代理或者把com域名修改为cn域名: Getting Started With Jetson Nano Developer Kit 注意:官方”hello AI world“ demo 来自jetson-inference这个API仓库,它没有deepstream复

    2024年02月04日
    浏览(12)
  • 【电赛训练】非接触物体尺寸形态测量 2020年电赛G题

    【电赛训练】非接触物体尺寸形态测量 2020年电赛G题

    一、题目要求 具体内容详见非接触物体尺寸形态测量(G 题)——行走的皮卡丘 设计并制作一个非接触式物体形状和尺寸自动测量装置,装置的布置图如图 1所示,测量装置放置在图中所示的测量装置区内,被测目标放置在图中被测目标放置区内,装置能测量被测目标的形状

    2024年02月16日
    浏览(9)
  • 2021电赛F题数字识别和巡线部分

    2021电赛F题数字识别和巡线部分

    文章之前12月发了一次,但是我后来申请的免毕设后,用到了一些文字,所以删了这篇文章,但是还是查重了,于是我把一些程序讲解先删了,等毕设结束后再编辑加上。 这次电赛我没有准备多少东西,只提前准备了图像识别和坐标计算一类的。在20年的省赛帮过雪地调过k

    2024年02月07日
    浏览(7)
  • 【2023年电赛国一必备】E题报告模板--可直接使用

    【2023年电赛国一必备】E题报告模板--可直接使用

    通过百度网盘分享的文件:https://pan.baidu.com/s/1aXzYwLMLx_b59abvplUiYw?pwd=dn71  提取码:dn71 复制这段内容打开「百度网盘APP 即可获取」 图1 任务内容  图2 基本要求内容  图3 发挥部分内容    图4 说明内容   图5 评分内容         本文使用K210芯片设计了一个运动目标控制与自

    2024年02月14日
    浏览(12)
  • 2019年电赛D题《简易电路特性测试仪》全过程

    2019年电赛D题《简易电路特性测试仪》全过程

    本人为团队中负责硬件部分,为了准备2022年电赛,本队伍已经制作2019年和2021年电赛信号题,本次主要讲解为2019年电赛D题硬件部分,少部分为软件需要做的部分。后续会对整个硬件进行优化和整理。   题目的硬件所确定的部分为一个分压式放大电路,其中利用的9013 npn来进

    2023年04月08日
    浏览(14)
  • 【2023年电赛】运动目标控制与自动追踪系统(E 题)最简单实现

    【2023年电赛】运动目标控制与自动追踪系统(E 题)最简单实现

    本方案的思路是最简单的不涉及复杂算法:识别矩形框,标记矩形框,输出坐标和中心点,计算长度,控制舵机移动固定长度!仅供完成基础功能参考,不喜勿喷! # 实现运动目标控制与自动追踪系统 ## 任务概述 本文将介绍如何使用OpenMV开发板和舵机构建一个运动目标控制

    2024年02月14日
    浏览(14)
  • 2023年电赛---运动目标控制与自动追踪系统(E题)OpenMV方案

    2023年电赛---运动目标控制与自动追踪系统(E题)OpenMV方案

    如果有嵌入式企业需要招聘校园大使,湖南区域的日常实习,任何区域的暑假Linux驱动实习岗位,可C站直接私聊,或者邮件:zhangyixu02@gmail.com,此消息至2025年1月1日前均有效 (1)废话少说,很多人可能无法访问GitHub,所以我直接贴出可能要用的代码。 此博客还会进行更新,

    2024年02月14日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包