【香橙派 Orange pi AIpro】| 搭建部署基于Yolov5的车牌识别系统

【香橙派 Orange pi AIpro】| 搭建部署基于Yolov5的车牌识别系统

  • 一、香橙派 Orange pi AIpro 开发板介绍及实物开箱
    • 1.1 开发板介绍
    • 1.2 产品详情图
    • 1.3 开箱实物
  • 二、开发部署预先准备
    • 2.1 镜像介绍与烧录
    • 2.2 启动开发板
    • 2.3 连接开发板
  • 三、基于Yolov5的车牌识别系统
    • 3.1 项目介绍
    • 3.2 拉取项目
    • 3.3 部分核心代码
    • 3.4 关键点分析
    • 3.5 车牌检测模型训练
    • 3.6 车牌识别模型训练
    • 3.7 图片识别测试
    • 3.8 视频识别测试
  • 四. 踩坑问题
  • 五. 使用体验与总结

最近刚好想研究一下嵌入式方面的知识就看到了香橙派新出的板子 Orange pi AIpro,果断搞来研究一下

在这里插入图片描述

一、香橙派 Orange pi AIpro 开发板介绍及实物开箱

1.1 开发板介绍

昇腾AI技术路线:高性能,低功耗 4核64位处理器 + AI处理器,速度更快,功耗更低,可为各类AI应用场景带来卓越的性能表现。

多通道输出,支持多屏异显:支持双HDMI视频输出,支持双4K高清输出,支持一个MIPI DSI屏输出,支持两个MIPI接口摄像头输入。

丰富接口,易于扩展:汇聚了MIPI DSI、MIPI CSI、USB 3.0、Type-C 3.0、HDMI 2.0、千兆以太网、支持SATA/NVMe SSD 2280的M.2插槽等各类流行的接口,可应用于外部设备控制和扩展。

应用场景广泛 覆盖 AIoT各行各业:可广泛适用于AI教学实训、AI算法验证、智能小车、机械臂、边缘计算、无人机、人工智能、云计算、AR/VR、智能安防、智能家居、智能交通等领域。

可运行openEuler系统:高效、稳定、安全。可运行openEuler系统,支持多种硬件架构和虚拟化技术,可广泛应用于企业级云计算、边缘计算场景等。

在这里插入图片描述

1.2 产品详情图

正面
在这里插入图片描述
背面
在这里插入图片描述

1.3 开箱实物

物品清单
在这里插入图片描述
正面图
在这里插入图片描述

背面图
在这里插入图片描述

在提交申请后,也是很快就收到了快递包裹,开箱后,有一个快充头和数据线,板子同标准的盒子装着,同时用两块薄海绵包裹着,可以预防静电对板子造成损害
实物颜值非常高,且已经自带了一块32G的TF卡,里面也已经烧录了openeuler镜像系统

二、开发部署预先准备

2.1 镜像介绍与烧录

开发板默认支持 ubuntu系统和 openeuler系统,由于 TF卡中已经预先烧录好了 openeuler系统,所以下面我就直接使用该系统进行搭建和部署了,熟悉和习惯 ubuntu系统的用户也可以格式化,重新烧录一个 ubuntu系统。

在这里插入图片描述

官方也提供了烧录工具
在这里插入图片描述

2.2 启动开发板

连接电源后,开发板会自动启动
在这里插入图片描述

2.3 连接开发板

由于手边没有 HDMI 线,我就直接用远程连接的方式连接吧

  1. 拿到开发板的 ip
    在这里插入图片描述

  2. 使用 MobaXterm 远程连接
    在这里插入图片描述

三、基于Yolov5的车牌识别系统

3.1 项目介绍

该项目是一个基于深度学习与yolov5 的车牌检测 、车牌识别、中文车牌识别与检测、支持12种中文车牌、支持双层车牌的目标识别系统。
项目开源地址:Chinese_license_plate_detection_recognition

3.2 拉取项目

  1. 先创建一个文件夹用来存放我们的项目
mkdir yolov5

在这里插入图片描述

  1. 开发板系统中已经预先安装好了 git,我们直接使用 git 将项目拉取下来就可以了
git clone https://github.com/we0091234/Chinese_license_plate_detection_recognition.git

在这里插入图片描述

  1. 进入到刚刚拉取的项目中
cd Chinese_license_plate_detection_recognition

在这里插入图片描述

  1. 刚刚拉取的项目,需要众多的依赖,这里需要下载一下,使用下面的命令下载就可以了
pip install -r ./requirements.txt -i https://mirrors.aliyun.com/pypi/simple

需要下载的依赖比较多,这里可能需要多等待一下

在这里插入图片描述
出现绿色的 Successfully 就代表依赖下载成功了

  1. 到此为止,项目就算拉取成功了,我们看一下,项目的目录文件结构

在这里插入图片描述
可以看到文件还是很多的

3.3 部分核心代码

# -*- coding: UTF-8 -*-
import argparse
import time
from pathlib import Path
import os
import cv2
import torch
import torch.backends.cudnn as cudnn
from numpy import random
import copy
import numpy as np
from models.experimental import attempt_load
from utils.datasets import letterbox
from utils.general import check_img_size, non_max_suppression_face, apply_classifier, scale_coords, xyxy2xywh, \
    strip_optimizer, set_logging, increment_path
from utils.plots import plot_one_box
from utils.torch_utils import select_device, load_classifier, time_synchronized
from utils.cv_puttext import cv2ImgAddText
from plate_recognition.plate_rec import get_plate_result,allFilePath,init_model,cv_imread
# from plate_recognition.plate_cls import cv_imread
from plate_recognition.double_plate_split_merge import get_split_merge

clors = [(255,0,0),(0,255,0),(0,0,255),(255,255,0),(0,255,255)]
danger=['危','险']
def order_points(pts):                   #四个点按照左上 右上 右下 左下排列
    rect = np.zeros((4, 2), dtype = "float32")
    s = pts.sum(axis = 1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect


def four_point_transform(image, pts):                       #透视变换得到车牌小图
    # rect = order_points(pts)
    rect = pts.astype('float32')
    (tl, tr, br, bl) = rect
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype = "float32")
    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    return warped

def load_model(weights, device):   #加载检测模型
    model = attempt_load(weights, map_location=device)  # load FP32 model
    return model

def scale_coords_landmarks(img1_shape, coords, img0_shape, ratio_pad=None):  #返回到原图坐标
    # Rescale coords (xyxy) from img1_shape to img0_shape
    if ratio_pad is None:  # calculate from img0_shape
        gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])  # gain  = old / new
        pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2  # wh padding
    else:
        gain = ratio_pad[0][0]
        pad = ratio_pad[1]

    coords[:, [0, 2, 4, 6]] -= pad[0]  # x padding
    coords[:, [1, 3, 5, 7]] -= pad[1]  # y padding
    coords[:, :8] /= gain
    #clip_coords(coords, img0_shape)
    coords[:, 0].clamp_(0, img0_shape[1])  # x1
    coords[:, 1].clamp_(0, img0_shape[0])  # y1
    coords[:, 2].clamp_(0, img0_shape[1])  # x2
    coords[:, 3].clamp_(0, img0_shape[0])  # y2
    coords[:, 4].clamp_(0, img0_shape[1])  # x3
    coords[:, 5].clamp_(0, img0_shape[0])  # y3
    coords[:, 6].clamp_(0, img0_shape[1])  # x4
    coords[:, 7].clamp_(0, img0_shape[0])  # y4
    # coords[:, 8].clamp_(0, img0_shape[1])  # x5
    # coords[:, 9].clamp_(0, img0_shape[0])  # y5
    return coords


def get_plate_rec_landmark(img, xyxy, conf, landmarks, class_num,device,plate_rec_model,is_color=False):  #获取车牌坐标以及四个角点坐标并获取车牌号
    h,w,c = img.shape
    result_dict={}
    tl = 1 or round(0.002 * (h + w) / 2) + 1  # line/font thickness

    x1 = int(xyxy[0])
    y1 = int(xyxy[1])
    x2 = int(xyxy[2])
    y2 = int(xyxy[3])
    height=y2-y1
    landmarks_np=np.zeros((4,2))
    rect=[x1,y1,x2,y2]
    for i in range(4):
        point_x = int(landmarks[2 * i])
        point_y = int(landmarks[2 * i + 1])
        landmarks_np[i]=np.array([point_x,point_y])

    class_label= int(class_num)  #车牌的的类型0代表单牌,1代表双层车牌
    roi_img = four_point_transform(img,landmarks_np)   #透视变换得到车牌小图
    if class_label:        #判断是否是双层车牌,是双牌的话进行分割后然后拼接
        roi_img=get_split_merge(roi_img)
    if not is_color:
        plate_number,rec_prob = get_plate_result(roi_img,device,plate_rec_model,is_color=is_color)                 #对车牌小图进行识别
    else:
        plate_number,rec_prob,plate_color,color_conf=get_plate_result(roi_img,device,plate_rec_model,is_color=is_color) 
    # cv2.imwrite("roi.jpg",roi_img)
    result_dict['rect']=rect                      #车牌roi区域
    result_dict['detect_conf']=conf              #检测区域得分
    result_dict['landmarks']=landmarks_np.tolist() #车牌角点坐标
    result_dict['plate_no']=plate_number   #车牌号
    result_dict['rec_conf']=rec_prob   #每个字符的概率
    result_dict['roi_height']=roi_img.shape[0]  #车牌高度
    result_dict['plate_color']=""
    if is_color:
        result_dict['plate_color']=plate_color   #车牌颜色
        result_dict['color_conf']=color_conf    #颜色得分
    result_dict['plate_type']=class_label   #单双层 0单层 1双层
    
    return result_dict



def detect_Recognition_plate(model, orgimg, device,plate_rec_model,img_size,is_color=False):#获取车牌信息
    # Load model
    # img_size = opt_img_size
    conf_thres = 0.3      #得分阈值
    iou_thres = 0.5       #nms的iou值   
    dict_list=[]
    # orgimg = cv2.imread(image_path)  # BGR
    img0 = copy.deepcopy(orgimg)
    assert orgimg is not None, 'Image Not Found ' 
    h0, w0 = orgimg.shape[:2]  # orig hw
    r = img_size / max(h0, w0)  # resize image to img_size
    if r != 1:  # always resize down, only resize up if training with augmentation
        interp = cv2.INTER_AREA if r < 1  else cv2.INTER_LINEAR
        img0 = cv2.resize(img0, (int(w0 * r), int(h0 * r)), interpolation=interp)

    imgsz = check_img_size(img_size, s=model.stride.max())  # check img_size  

    img = letterbox(img0, new_shape=imgsz)[0]           #检测前处理,图片长宽变为32倍数,比如变为640X640
    # img =process_data(img0)
    # Convert
    img = img[:, :, ::-1].transpose(2, 0, 1).copy()  # BGR to RGB, to 3x416x416  图片的BGR排列转为RGB,然后将图片的H,W,C排列变为C,H,W排列

    # Run inference
    t0 = time.time()

    img = torch.from_numpy(img).to(device)
    img = img.float()  # uint8 to fp16/32
    img /= 255.0  # 0 - 255 to 0.0 - 1.0
    if img.ndimension() == 3:
        img = img.unsqueeze(0)

    # Inference
    # t1 = time_synchronized()/
    pred = model(img)[0]
    # t2=time_synchronized()
    # print(f"infer time is {(t2-t1)*1000} ms")

    # Apply NMS
    pred = non_max_suppression_face(pred, conf_thres, iou_thres)

    # print('img.shape: ', img.shape)
    # print('orgimg.shape: ', orgimg.shape)

    # Process detections
    for i, det in enumerate(pred):  # detections per image
        if len(det):
            # Rescale boxes from img_size to im0 size
            det[:, :4] = scale_coords(img.shape[2:], det[:, :4], orgimg.shape).round()

            # Print results
            for c in det[:, -1].unique():
                n = (det[:, -1] == c).sum()  # detections per class

            det[:, 5:13] = scale_coords_landmarks(img.shape[2:], det[:, 5:13], orgimg.shape).round()

            for j in range(det.size()[0]):
                xyxy = det[j, :4].view(-1).tolist()
                conf = det[j, 4].cpu().numpy()
                landmarks = det[j, 5:13].view(-1).tolist()
                class_num = det[j, 13].cpu().numpy()
                result_dict = get_plate_rec_landmark(orgimg, xyxy, conf, landmarks, class_num,device,plate_rec_model,is_color=is_color)
                dict_list.append(result_dict)
    return dict_list
    # cv2.imwrite('result.jpg', orgimg)

def draw_result(orgimg,dict_list,is_color=False):   # 车牌结果画出来
    result_str =""
    for result in dict_list:
        rect_area = result['rect']
        
        x,y,w,h = rect_area[0],rect_area[1],rect_area[2]-rect_area[0],rect_area[3]-rect_area[1]
        padding_w = 0.05*w
        padding_h = 0.11*h
        rect_area[0]=max(0,int(x-padding_w))
        rect_area[1]=max(0,int(y-padding_h))
        rect_area[2]=min(orgimg.shape[1],int(rect_area[2]+padding_w))
        rect_area[3]=min(orgimg.shape[0],int(rect_area[3]+padding_h))

        height_area = result['roi_height']
        landmarks=result['landmarks']
        result_p = result['plate_no']
        if result['plate_type']==0:#单层
            result_p+=" "+result['plate_color']
        else:                             #双层
            result_p+=" "+result['plate_color']+"双层"
        result_str+=result_p+" "
        for i in range(4):  #关键点
            cv2.circle(orgimg, (int(landmarks[i][0]), int(landmarks[i][1])), 5, clors[i], -1)
        cv2.rectangle(orgimg,(rect_area[0],rect_area[1]),(rect_area[2],rect_area[3]),(0,0,255),2) #画框
        
        labelSize = cv2.getTextSize(result_p,cv2.FONT_HERSHEY_SIMPLEX,0.5,1) #获得字体的大小
        if rect_area[0]+labelSize[0][0]>orgimg.shape[1]:                 #防止显示的文字越界
            rect_area[0]=int(orgimg.shape[1]-labelSize[0][0])
        orgimg=cv2.rectangle(orgimg,(rect_area[0],int(rect_area[1]-round(1.6*labelSize[0][1]))),(int(rect_area[0]+round(1.2*labelSize[0][0])),rect_area[1]+labelSize[1]),(255,255,255),cv2.FILLED)#画文字框,背景白色
        
        if len(result)>=1:
            orgimg=cv2ImgAddText(orgimg,result_p,rect_area[0],int(rect_area[1]-round(1.6*labelSize[0][1])),(0,0,0),21)
            # orgimg=cv2ImgAddText(orgimg,result_p,rect_area[0]-height_area,rect_area[1]-height_area-10,(0,255,0),height_area)
               
    print(result_str)
    return orgimg



def get_second(capture):
    if capture.isOpened():
        rate = capture.get(5)   # 帧速率
        FrameNumber = capture.get(7)  # 视频文件的帧数
        duration = FrameNumber/rate  # 帧速率/视频总帧数 是时间,除以60之后单位是分钟
        return int(rate),int(FrameNumber),int(duration)    


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--detect_model', nargs='+', type=str, default='weights/plate_detect.pt', help='model.pt path(s)')  #检测模型
    parser.add_argument('--rec_model', type=str, default='weights/plate_rec_color.pth', help='model.pt path(s)')#车牌识别+颜色识别模型
    parser.add_argument('--is_color',type=bool,default=True,help='plate color')      #是否识别颜色
    parser.add_argument('--image_path', type=str, default='imgs', help='source')     #图片路径
    parser.add_argument('--img_size', type=int, default=640, help='inference size (pixels)')  #网络输入图片大小
    parser.add_argument('--output', type=str, default='result', help='source')               #图片结果保存的位置
    parser.add_argument('--video', type=str, default='', help='source')                       #视频的路径
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")                     #使用gpu还是cpu进行识别
    # device =torch.device("cpu")
    opt = parser.parse_args()
    print(opt)
    save_path = opt.output                
    count=0
    if not os.path.exists(save_path): 
        os.mkdir(save_path)

    detect_model = load_model(opt.detect_model, device)  #初始化检测模型
    plate_rec_model=init_model(device,opt.rec_model,is_color=opt.is_color)      #初始化识别模型
    #算参数量
    total = sum(p.numel() for p in detect_model.parameters())
    total_1 = sum(p.numel() for p in plate_rec_model.parameters())
    print("detect params: %.2fM,rec params: %.2fM" % (total/1e6,total_1/1e6))
    
    # plate_color_model =init_color_model(opt.color_model,device)
    time_all = 0
    time_begin=time.time()
    if not opt.video:     #处理图片
        if not os.path.isfile(opt.image_path):            #目录
            file_list=[]
            allFilePath(opt.image_path,file_list)  #将这个目录下的所有图片文件路径读取到file_list里面
            for img_path in file_list:             #遍历图片文件
                
                print(count,img_path,end=" ")
                time_b = time.time()               #开始时间
                img =cv_imread(img_path)           #opencv 读取图片
                
                if img is None:                   
                    continue
                if img.shape[-1]==4:               #图片如果是4个通道的,将其转为3个通道
                    img=cv2.cvtColor(img,cv2.COLOR_BGRA2BGR)
                # detect_one(model,img_path,device)
                dict_list=detect_Recognition_plate(detect_model, img, device,plate_rec_model,opt.img_size,is_color=opt.is_color)#检测以及识别车牌
                ori_img=draw_result(img,dict_list)  #将结果画在图上
                img_name = os.path.basename(img_path)  
                save_img_path = os.path.join(save_path,img_name)  #图片保存的路径
                time_e=time.time()
                time_gap = time_e-time_b                         #计算单个图片识别耗时
                if count:
                    time_all+=time_gap 
                cv2.imwrite(save_img_path,ori_img)               #opencv将识别的图片保存
                count+=1
            print(f"sumTime time is {time.time()-time_begin} s, average pic time is {time_all/(len(file_list)-1)}")
        else:                                          #单个图片
                print(count,opt.image_path,end=" ")
                img =cv_imread(opt.image_path)
                if img.shape[-1]==4:
                    img=cv2.cvtColor(img,cv2.COLOR_BGRA2BGR)
                # detect_one(model,img_path,device)
                dict_list=detect_Recognition_plate(detect_model, img, device,plate_rec_model,opt.img_size,is_color=opt.is_color)
                ori_img=draw_result(img,dict_list)
                img_name = os.path.basename(opt.image_path)
                save_img_path = os.path.join(save_path,img_name)
                cv2.imwrite(save_img_path,ori_img)  
        
        
    else:    #处理视频
        video_name = opt.video
        capture=cv2.VideoCapture(video_name)
        fourcc = cv2.VideoWriter_fourcc(*'MP4V') 
        fps = capture.get(cv2.CAP_PROP_FPS)  # 帧数
        width, height = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 宽高
        out = cv2.VideoWriter('result.mp4', fourcc, fps, (width, height))  # 写入视频
        frame_count = 0
        fps_all=0
        rate,FrameNumber,duration=get_second(capture)
        if capture.isOpened():
            while True:
                t1 = cv2.getTickCount()
                frame_count+=1
                print(f"第{frame_count} 帧",end=" ")
                ret,img=capture.read()
                if not ret:
                    break
                # if frame_count%rate==0:
                img0 = copy.deepcopy(img)
                dict_list=detect_Recognition_plate(detect_model, img, device,plate_rec_model,opt.img_size,is_color=opt.is_color)
                ori_img=draw_result(img,dict_list)
                t2 =cv2.getTickCount()
                infer_time =(t2-t1)/cv2.getTickFrequency()
                fps=1.0/infer_time
                fps_all+=fps
                str_fps = f'fps:{fps:.4f}'
                
                cv2.putText(ori_img,str_fps,(20,20),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2)
                # cv2.imshow("haha",ori_img)
                # cv2.waitKey(1)
                out.write(ori_img)

                # current_time = int(frame_count/FrameNumber*duration)
                # sec = current_time%60
                # minute = current_time//60
                # for result_ in result_list:
                #     plate_no = result_['plate_no']
                #     if not is_car_number(pattern_str,plate_no):
                #         continue
                #     print(f'车牌号:{plate_no},时间:{minute}分{sec}秒')
                #     time_str =f'{minute}分{sec}秒'
                #     writer.writerow({"车牌":plate_no,"时间":time_str})
                # out.write(ori_img)
                
                
        else:
            print("失败")
        capture.release()
        out.release()
        cv2.destroyAllWindows()
        print(f"all frame is {frame_count},average fps is {fps_all/frame_count} fps")

3.4 关键点分析

  1. 初始化参数
  • 从输入图像img获取其高度h、宽度w和通道数c。
  • 初始化一个空字典 result_dict 用于存储结果。
  • 计算线条/字体粗细tl,这里基于图像尺寸动态计算。
  1. 解析车牌位置和角点坐标
  • 从xyxy(车牌边界框的坐标,格式为[x1, y1, x2, y2])中提取车牌的左上角和右下角坐标。
  • 初始化一个 NumPy 数组 landmarks_np 用于存储车牌的四个角点坐标。
  • 遍历 landmarks(车牌角点坐标列表),将每个角点坐标(x, y)存入 landmarks_np
  1. 获取车牌类型
  • class_num 获取车牌类型(0代表单牌,1代表双层车牌)。
  1. 透视变换获取车牌小图
  • 使用 four_point_transform 函数(需要预先定义或导入)对车牌区域进行透视变换,得到车牌的正面视图 roi_img
  1. 处理双层车牌
  • 如果车牌类型为双层( class_label 为1),则调用 get_split_merge 函数(需要预先定义或导入)对车牌小图进行分割和合并处理。
  1. 车牌识别
  • 根据 is_color 参数决定是否需要识别车牌颜色。
  • 调用 get_plate_result 函数(需要预先定义或导入)对车牌小图roi_img进行识别,获取车牌号 plate_number 、识别概率 rec_prob ,以及(如果 is_colorTrue )车牌颜色 plate_color 和颜色置信度 color_conf
  1. 构建结果字典
  • 将车牌的边界框rect、检测置信度conf、角点坐标landmarks、车牌号 plate_number 、识别概率 rec_prob 、车牌高度 roi_img.shape[0]、车牌颜色(如果 is_color 为True)以及车牌类型 class_label 等信息存入result_dict。
  1. 返回结果
  • 返回包含车牌识别结果的字典 result_dict

3.5 车牌检测模型训练

  1. 下载一定量的数据集

需要下载一定量的数据集,项目的作者有提供,需要的可以联系项目作者,格式为 yolov5 格式

label x y w h  pt1x pt1y pt2x pt2y pt3x pt3y pt4x pt4y

自己的数据集可以通过lablme 软件,create polygons标注车牌四个点即可,然后通过json2yolo.py 将数据集转为yolo格式,也可进行训练

  1. 修改 data/widerface.yaml trainval 路径,换成你的数据路径
train: /your/train/path #修改成你的训练集路径
val: /your/val/path     #修改成你的验证集路径
# number of classes
nc: 2                 #这里用的是2分类,0 单层车牌 1 双层车牌

# class names
names: [ 'single','double']
  1. 训练命令
python3 train.py --data data/widerface.yaml --cfg models/yolov5n-0.5.yaml --weights weights/plate_detect.pt --epoch 120

3.6 车牌识别模型训练

  1. 下载数据集
    数据集可以自己收集,或者找项目作者提供

  2. 数据集打上标签,生成train.txt和val.txt
    在这里插入图片描述

图片命名如上图:车牌号_序号.jpg 然后执行如下命令,得到 train.txtval.txt

python plateLabel.py --image_path your/train/img/path/ --label_file datasets/train.txt
python plateLabel.py --image_path your/val/img/path/ --label_file datasets/val.txt

数据格式如下:

train.txt

/mnt/Gu/trainData/plate/new_git_train/CCPD_CRPD_ALL/冀BAJ731_3.jpg 5 53 52 60 49 45 43 
/mnt/Gu/trainData/plate/new_git_train/CCPD_CRPD_ALL/冀BD387U_2454.jpg 5 53 55 45 50 49 70 
/mnt/Gu/trainData/plate/new_git_train/CCPD_CRPD_ALL/冀BG150C_3.jpg 5 53 58 43 47 42 54 
/mnt/Gu/trainData/plate/new_git_train/CCPD_CRPD_OTHER_ALL/皖A656V3_8090.jpg 13 52 48 47 48 71 45 
/mnt/Gu/trainData/plate/new_git_train/CCPD_CRPD_OTHER_ALL/皖C91546_7979.jpg 13 54 51 43 47 46 48 
/mnt/Gu/trainData/plate/new_git_train/CCPD_CRPD_OTHER_ALL/皖G88950_1540.jpg 13 58 50 50 51 47 42 
/mnt/Gu/trainData/plate/new_git_train/CCPD_CRPD_OTHER_ALL/皖GX9Y56_2113.jpg 13 58 73 51 74 47 48 
  1. train.txt val.txt 路径写入 lib/config/360CC_config.yaml
DATASET:
  DATASET: 360CC
  ROOT: ""
  CHAR_FILE: 'lib/dataset/txt/plate2.txt'
  JSON_FILE: {'train': 'datasets/train.txt', 'val': 'datasets/val.txt'}
  1. 执行训练命令
python train.py --cfg lib/config/360CC_config.yaml

3.7 图片识别测试

  1. 项目基础图片集
    在这里插入图片描述
    项目中已经预先存放了一些车牌图片,我们可以使用这些图片来测试一下

  2. 执行图片检测命令

python detect_plate.py --detect_model weights/plate_detect.pt  --rec_model weights/plate_rec_color.pth --image_path imgs --output result

输入完命令后,大约在3秒后,程序持续输出识别结果,可以看到程序的启动速度还是挺快了,总共的识别时间在8.5秒左右,平均一张图片的识别速度在0.5秒左右,这速度已经是相当的快了

在这里插入图片描述

  1. 图片识别结果

在这里插入图片描述

3.8 视频识别测试

  1. 项目基础识别视频
    视频:

yolov2车牌识别视频

视频截图:
在这里插入图片描述
视频时间长度在 54 秒左右,视频类型为 mp4,视频内容主要是以行驶中的车尾视角拍摄马路上的车辆。

  1. 上传视频到项目文件中
    我连接软件用的 MobaXterm,不知道为什么,上传文件总是会卡住,没办法,只能用 Xftp 再连接一次然后上传视频了
    在这里插入图片描述

  2. 执行视频检测命令

python detect_plate.py --detect_model weights/plate_detect.pt  --rec_model weights/plate_rec_color.pth --video 2.mp4

输入执行命令后,系统大约在 5 秒后启动了,然后将视频分帧处理
在这里插入图片描述
处理过程中ing
在这里插入图片描述
视频的后半部分就已经没有车了,处理显示的也都是空帧,就没有任何意义了,这里就不进行展示了。
在这里插入图片描述
可以看到,54 秒的视频,共划分了 1501 帧,香橙派 Orange pi AIpro 这块板子,处理速度在 2.7 fps 左右,相对比其他开发板子来说,速度已经可以了。

四. 踩坑问题

  1. 烧录报错
    在这里插入图片描述
    错误提示

出了点问题。如果源镜像曾被压缩过,请检查它是否已损坏。
The writer process ended unexpectedly

直接点击跳过即可
在这里插入图片描述

  1. ping 命令不能使用
    在这里插入图片描述
    解决办法:
sudo setcap cap_net_raw+p /bin/ping

在这里插入图片描述
成功解决
在这里插入图片描述

五. 使用体验与总结

使用下来体验感还挺好的,板子在通电启动后,5秒内散热风扇的噪音还是比较大的,5秒后,声音就变的很小了,后续即使在跑项目的时候,声音也没有较大的变化,散热做的也非常的好,整体体验下来板子的温度一直维持在一个正常的温度,没有出现温度过高的情况。

除了个人体验外,OrangePi AIpro 凭借其卓越的即插即用特性,极大地加速了开发进程。通过简单的配置步骤,省去了繁琐的硬件调试环节。在软件生态方面,香橙派社区构建了一个资源丰富、文档详尽的生态系统,对初学者来说可以轻松访问并选用适合的文字识别模型和框架,通过直观易懂的指南,快速部署至开发板上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/802558.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端pc和小程序接入快递100(跳转方式和api方式)====实时查询接口

文章目录 跳转方式微信小程序&#xff08;我以uniapp为例&#xff09;pc api接入说明关于签名计算成功示例 跳转方式 没有任何开发成本&#xff0c;直接一键接入 可以直接看官方文档 https://www.kuaidi100.com/openapi/api_wxmp.shtml 微信小程序&#xff08;我以uniapp为例…

知识图谱与 LLM:微调与检索增强生成

Midjourney 的知识图谱聊天机器人的想法。 大型语言模型 (LLM) 的第一波炒作来自 ChatGPT 和类似的基于网络的聊天机器人&#xff0c;这些模型在理解和生成文本方面非常出色&#xff0c;这让人们&#xff08;包括我自己&#xff09;感到震惊。 我们中的许多人登录并测试了它写…

大数据信用查询有哪些问题值得注意呢?

随着大数据技术的不断发展&#xff0c;大数据信用报告成为一种新型的信用风险检测工具&#xff0c;被很多的银行和机构广泛用于信用风险评估&#xff0c;那大数据信用查询有哪些问题值得注意呢?本文就带大家一起去了解一下&#xff0c;希望对你有一定的帮助。 大数据信用查询这…

数据结构——单链表详解(超详细)(2)

前言&#xff1a; 上一篇文章小编简单的介绍了单链表的概念和一些函数的实现&#xff0c;不过为了保证文章的简洁&#xff0c;小编把它分成了两篇来写&#xff0c;这一篇小编紧接上一篇文章继续写单链表函数功能的实现&#xff1a; 目录&#xff1a; 1.单链表剩余函数的编写 1.…

使用Windows Linux 子系统安装 Tensorflow,并使用GPU环境

在Microsoft Store商店安装Ubuntu 20.04 使用 nvidia-smi 命令查看GPU信息&#xff0c;查看支持的CUDA版本&#xff0c;这里最高支持11.7 安装cuda工具集 进入官网&#xff1a;CUDA Toolkit Archive | NVIDIA Developer&#xff0c;现在对应版本&#xff0c;点击 配置平台&…

【Django+Vue3 线上教育平台项目实战】登录功能模块之短信登录与钉钉三方登录

文章目录 前言一、几个关键概念1.HTTP无状态性2.Session机制3.Token认证4.JWT 二、通过手机号验证码登录1.前端短信登录界面2.发送短信接口与短信登录接口3.Vue 设置interceptors拦截器4. 服务端验证采用自定义中间件方式实现5. 操作流程及效果图如下&#xff1a; 三、通过第三…

对某根域的一次渗透测试

前言 两个月之前的一个渗透测试项目是基于某网站根域进行渗透测试&#xff0c;发现该项目其实挺好搞的&#xff0c;就纯粹的没有任何防御措施与安全意识所以该项目完成的挺快&#xff0c;但是并没有完成的很好&#xff0c;因为有好几处文件上传没有绕过&#xff08;虽然从一个…

【Java】数据类型及类型转换

数据类型 Java语言的数据类型分为两大类&#xff1a; 基础数据类型引用数据类型 基础数据类型 基础数据类型包括以下8种&#xff1a; 类型名称关键字占用内存取值范围区间描述字节型byte1 字节-128~127-27~27-1短整型short2 字节-32768~32767-215~215-1整型int4 字节-2147…

nftables(7)集合(SETS)

简介 在nftables中&#xff0c;集合&#xff08;sets&#xff09;是一个非常有用的特性&#xff0c;它允许你以集合的形式管理IP地址、端口号等网络元素&#xff0c;从而简化规则的配置和管理。 nftables提供了两种类型的集合&#xff1a;匿名集合和命名集合。 匿名集合&…

高职院校人工智能人才培养成果导向系统构建、实施要点与评量方法

一、引言 近年来&#xff0c;人工智能技术在全球范围内迅速发展&#xff0c;对各行各业产生了深远的影响。高职院校作为培养高技能人才的重要基地&#xff0c;肩负着培养人工智能领域专业人才的重任。为了适应社会对人工智能人才的需求&#xff0c;高职院校需要构建一套科学、…

大模型产品琳琅满目,企业应该如何选择?

AI 和大模型方兴未艾&#xff0c;我们每天都在看到和尝试不同版本、不同品牌的大模型产品&#xff0c;它们的能力各不相同。无论是个人还是企业&#xff0c;都在思考如何尽早地参与进来到大模型的浪潮当中来。 目前&#xff0c;一些先锋企业已经将 AI 和大模型融入到他们的日常…

C#学习

C#学习 1.B站丑萌气质狗C#的循环-判断泛型错误处理面向对象static的使用定义showInfo类和Hero类 在这里插入图片描述 然后在该解决方案add新建一个类库&#xff0c;点击rebuild&#xff0c;会在bin文件夹下生成.dll文件 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direc…

无人机之图传距离的决定因素

一、发射功率&#xff1a;图传设备的发射功率越大&#xff0c;信号能够传播的距离就越远 二、工作频段&#xff1a;不同频段具有不同的传播特性&#xff0c;一些频段在相同条件下可能具有更远的传输距离。 三、天线性能&#xff1a;优质的天线可以增强信号的发送和接收能力&a…

php相关

php相关 ​ 借鉴了小迪安全以及各位大佬的博客&#xff0c;如果一切顺利&#xff0c;会不定期更新。 如果感觉不妥&#xff0c;可以私信删除。 默认有php基础。 文章目录 php相关1. php 缺陷函数1. 与2. MD53. intval()4. preg_match() 2. php特性1. php字符串解析特性2. 杂…

jdk22+maven环境配置教程+idea的maven环境配置(Windows系统)

前言 jdk是Java开发必要的编程环境&#xff0c;idea是常用的Java开发工具&#xff0c;这里着重解释一下maven。 maven就是我们经常看见的pom.xml文件&#xff0c;maven有以下三点功能&#xff1a; 1.项目构建&#xff08;可以帮助我们更快速的打包、构建项目&#xff09; 2.依…

<数据集>钢铁缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;1800张 标注数量(xml文件个数)&#xff1a;1800 标注数量(txt文件个数)&#xff1a;1800 标注类别数&#xff1a;6 标注类别名称&#xff1a;[crazing, patches, inclusion, pitted_surface, rolled-in_scale, scr…

Blender使用(二)点线面基本操作

Blender使用之点线面 1.编辑模式 tab键进行切换&#xff0c;为了方便菜单调出&#xff0c;可以设置键位映射为拖动时的饼菜单。 设置好后&#xff0c;按住tab键移动鼠标(注意不要点击鼠标)&#xff0c;即可弹出编辑菜单。 默认是点模式&#xff0c;在左上角可进行点线面的切换…

C++从入门到精通(第2版) 中文电子版

前言 C&#xff08;c plus plus&#xff09;是一种计算机高级程序设计语言&#xff0c;由C语言扩展升级而产生&#xff0c;最早于1979年由本贾尼斯特劳斯特卢普在AT&T贝尔工作室研发。C既可以进行C语言的过程化程序设计&#xff0c;又可以进行以抽象数据类型为特点的基于对…

[C++] 由浅入深理解面向对象思想的组成模块

文章目录 (一) 类的默认成员函数(二) 构造函数构造函数的特征构造函数示例无参构造带参构造 冲突:全缺省参数的构造函数与无参构造函数 &#xff08;三&#xff09;析构函数特性析构函数的析构过程解析 &#xff08;四&#xff09;拷贝构造函数什么是拷贝构造&#xff1f;特性为…

H2数据库启动时,设置非“全零监听”

全零监听 全零监听&#xff08;即将监听地址设置为全零地址&#xff0c;如IPv4中的0.0.0.0或IPv6中的::&#xff09;在网络服务配置中确实存在一定的安全风险。以下是全零监听可能带来的安全风险&#xff1a; 1. 暴露服务到不安全网络 全网段监听&#xff1a;将监听地址设置…