小工具知识网

当前位置: 首页 > 行业知识 > 【Yolov8 Opencv C++系列保姆教程】Yolov8 opencv c++ 版本保姆教程,Yolov8训练自己的数据集,实现红绿灯识别及红绿灯故障检测 ,红绿灯故障识别。

行业知识

【Yolov8 Opencv C++系列保姆教程】Yolov8 opencv c++ 版本保姆教程,Yolov8训练自己的数据集,实现红绿灯识别及红绿灯故障检测 ,红绿灯故障识别。

2026-11-10 06:54:43 来源:互联网转载

目录

一、Yolov8简介

1、yolov8 源码地址:

2、官方文档:

3、预训练模型百度网盘地址:

二、模型训练

1、标定红绿灯数据:

2、训练环境:

3、数据转化:

4、构造训练数据:

5、训练样本:

三、验证模型:

1、图像测试:

2、视频测试:

四、导出ONNX

五、Opencv实现Yolov8 C++ 识别

1、开发环境:

2、main函数代码:

3、yolov8 头文件inference.h代码:

4、yolov8 cpp文件inference.cpp代码:


一、Yolov8简介

1、yolov8 源码地址:

工程链接:https://github.com/ultralytics/ultralytics

2、官方文档:

CLI - Ultralytics YOLOv8 Docs

3、预训练模型百度网盘地址:

训练时需要用到,下载的网址较慢:

如果模型下载不了,加QQ:187100248.

链接: https://pan.baidu.com/s/1YfMxRPGk8LF75a4cbgYxGg 提取码: rd7b

二、模型训练

1、标定红绿灯数据:

         类别为23类,分别为:

红绿灯类别
red_lightgreen_lightyellow_lightoff_lightpart_ry_lightpart_rg_light
part_yg_lightryg_lightcountdown_off_lightcountdown_on_lightshade_lightzero
onetwothreefourfivesix
seveneightninebrokeNumberbrokenLight

        标注工具地址:AI标注工具Labelme和LabelImage Labelme和LabelImage集成工具_labelimage与labelme-CSDN博客

标注后图像格式

2、训练环境:

1)、Ubuntu18.04;

2)、Cuda11.7 + CUDNN8.0.6;

3)、opencv4.5.5;

4)、PyTorch1.8.1-GPU;

5)、python3.9

3、数据转化:

 1)、需要把上面标定的数据集中的.xml文件转换为.txt,转换代码为:

import osimport shutilimport xml.etree.ElementTree as ETfrom xml.etree.ElementTree import Element, SubElementfrom PIL import Imageimport cv2classes = ['red_light', 'green_light', 'yellow_light', 'off_light', 'part_ry_light', 'part_rg_light', 'part_yg_light', 'ryg_light',           'countdown_off_light', 'countdown_on_light','shade_light','zero','one','two','three','four','five','six','seven',           'eight','nine','brokeNumber','brokenLight']class Xml_make(object):    def __init__(self):        super().__init__()    def __indent(self, elem, level=0):        i = "\n" + level * "\t"        if len(elem):            if not elem.text or not elem.text.strip():                elem.text = i + "\t"            if not elem.tail or not elem.tail.strip():                elem.tail = i            for elem in elem:                self.__indent(elem, level + 1)            if not elem.tail or not elem.tail.strip():                elem.tail = i        else:            if level and (not elem.tail or not elem.tail.strip()):                elem.tail = i    def _imageinfo(self, list_top):        annotation_root = ET.Element('annotation')        annotation_root.set('verified', 'no')        tree = ET.ElementTree(annotation_root)        '''        0:xml_savepath 1:folder,2:filename,3:path        4:checked,5:width,6:height,7:depth        '''        folder_element = ET.Element('folder')        folder_element.text = list_top[1]        annotation_root.append(folder_element)        filename_element = ET.Element('filename')        filename_element.text = list_top[2]        annotation_root.append(filename_element)        path_element = ET.Element('path')        path_element.text = list_top[3]        annotation_root.append(path_element)        # checked_element = ET.Element('checked')        # checked_element.text = list_top[4]        # annotation_root.append(checked_element)        source_element = ET.Element('source')        database_element = SubElement(source_element, 'database')        database_element.text = 'Unknown'        annotation_root.append(source_element)        size_element = ET.Element('size')        width_element = SubElement(size_element, 'width')        width_element.text = str(list_top[5])        height_element = SubElement(size_element, 'height')        height_element.text = str(list_top[6])        depth_element = SubElement(size_element, 'depth')        depth_element.text = str(list_top[7])        annotation_root.append(size_element)        segmented_person_element = ET.Element('segmented')        segmented_person_element.text = '0'        annotation_root.append(segmented_person_element)        return tree, annotation_root    def _bndbox(self, annotation_root, list_bndbox):        for i in range(0, len(list_bndbox), 9):            object_element = ET.Element('object')            name_element = SubElement(object_element, 'name')            name_element.text = list_bndbox[i]            # flag_element = SubElement(object_element, 'flag')            # flag_element.text = list_bndbox[i + 1]            pose_element = SubElement(object_element, 'pose')            pose_element.text = list_bndbox[i + 2]            truncated_element = SubElement(object_element, 'truncated')            truncated_element.text = list_bndbox[i + 3]            difficult_element = SubElement(object_element, 'difficult')            difficult_element.text = list_bndbox[i + 4]            bndbox_element = SubElement(object_element, 'bndbox')            xmin_element = SubElement(bndbox_element, 'xmin')            xmin_element.text = str(list_bndbox[i + 5])            ymin_element = SubElement(bndbox_element, 'ymin')            ymin_element.text = str(list_bndbox[i + 6])            xmax_element = SubElement(bndbox_element, 'xmax')            xmax_element.text = str(list_bndbox[i + 7])            ymax_element = SubElement(bndbox_element, 'ymax')            ymax_element.text = str(list_bndbox[i + 8])            annotation_root.append(object_element)        return annotation_root    def txt_to_xml(self, list_top, list_bndbox):        tree, annotation_root = self._imageinfo(list_top)        annotation_root = self._bndbox(annotation_root, list_bndbox)        self.__indent(annotation_root)        tree.write(list_top[0], encoding='utf-8', xml_declaration=True)def txt_2_xml(source_path, xml_save_dir, jpg_save_dir,txt_dir):    COUNT = 0    for folder_path_tuple, folder_name_list, file_name_list in os.walk(source_path):        for file_name in file_name_list:            file_suffix = os.path.splitext(file_name)[-1]            if file_suffix != '.jpg':                continue            list_top = []            list_bndbox = []            path = os.path.join(folder_path_tuple, file_name)            xml_save_path = os.path.join(xml_save_dir, file_name.replace(file_suffix, '.xml'))            txt_path = os.path.join(txt_dir, file_name.replace(file_suffix, '.txt'))            filename = file_name#os.path.splitext(file_name)[0]            checked = 'NO'            #print(file_name)            im = Image.open(path)            im_w = im.size[0]            im_h = im.size[1]            shutil.copy(path, jpg_save_dir)            if im_w*im_h > 34434015:                print(file_name)            if im_w  im_w - 1:                    xmax = im_w - 1                if ymax > im_h - 1:                    ymax = im_h - 1                if w > 5 and h > 5:                  list_bndbox.extend([name, flag, pose, truncated, difficult,str(xmin), str(ymin), str(xmax), str(ymax)])                if xmin  im_w - 1 or ymin  im_h - 1:                    print(xml_save_path)            Xml_make().txt_to_xml(list_top, list_bndbox)            COUNT += 1            #print(COUNT, xml_save_path)if __name__ == "__main__":    out_xml_path = "/home/TL_TrainData/"  # .xml输出文件存放地址    out_jpg_path = "/home/TL_TrainData/"  # .jpg输出文件存放地址    txt_path = "/home/Data/TrafficLight/trainData"  # yolov3标注.txt和图片文件夹    images_path = "/home/TrafficLight/trainData"  # image文件存放地址    txt_2_xml(images_path, out_xml_path, out_jpg_path, txt_path)

4、构造训练数据:

2)、训练样本数据构造,需要把分成images和labels,images下面放入图片,labels下面放入.txt文件:

分成images和labels images labels

5、训练样本:

 1)、首先安装训练包:

pip install ultralytics

2)、修改训练数据参数coco128_light.yaml文件,这个是自己修改的。

# Ultralytics YOLO , AGPL-3.0 license# COCO128 dataset https://www.kaggle.com/ultralytics/coco128 (first 128 images from COCO train2017) by Ultralytics# Example usage: yolo train data=coco128.yaml# parent# ├── ultralytics# └── datasets#     └── coco128  ← downloads here (7 MB)# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]path: /home/Data/TrafficLight/datasets  # dataset root dirtrain: images  # train images (relative to 'path') 128 imagesval: images  # val images (relative to 'path') 128 imagestest:  # test images (optional)# Parametersnc: 23  # number of classes# Classesnames:  0: red_light  1: green_light  2: yellow_light  3: off_light  4: part_ry_light  5: part_rg_light  6: part_yg_light  7: ryg_light  8: countdown_off_light  9: countdown_on_light  10: shade_light  11: zero  12: one  13: two  14: three  15: four  16: five  17: six  18: seven  19: eight  20: nine  21: brokeNumber  22: brokenLight# Download script/URL (optional)#download: https://ultralytics.com/assets/coco128.zip

3)、执行 train_yolov8x_light.sh,内容为:

yolo detect train data=coco128_light.yaml model=./runs/last.pt epochs=100 imgsz=640 workers=16 batch=32

        开始启动训练:

        

模型训练启动

三、验证模型:

1、图像测试:

from ultralytics import YOLO# Load a model#model = YOLO('yolov8n.pt')  # load an official modelmodel = YOLO('best.pt')  # load a custom model# Predict with the modelresults = model('bus.jpg')  # predict on an image# View resultsfor r in results:    print(r.boxes)  # print the Boxes object containing the detection bounding boxes

2、视频测试:

import cv2from ultralytics import YOLO# Load the YOLOv8 modelmodel = YOLO('best.pt')# Open the video filevideo_path = "test_car_person_1080P.mp4"cap = cv2.VideoCapture(video_path)# Loop through the video frameswhile cap.isOpened():    # Read a frame from the video    success, frame = cap.read()    if success:        # Run YOLOv8 inference on the frame        results = model(frame)        # Visualize the results on the frame        annotated_frame = results[0].plot()        # Display the annotated frame        cv2.imshow("YOLOv8 Inference", annotated_frame)        cv2.waitKey(10)

四、导出ONNX

1、训练输出,经过上面的训练后,得到训练生成文件,weights下生成了best.pt和last.pt:

训练数据生成文件

2、等训练完毕后,利用best.pt生成best.onnx,执行命令如下:

yolo export model=best.pt imgsz=640 format=onnx opset=12

五、Opencv实现Yolov8 C++ 识别

1、开发环境:

1)、win7/win10;

2)、vs2019;

3)、opencv4.7.0;

2、main函数代码:

#include #include #include "opencv2/opencv.hpp"#include "inference.h"#include #include #define socklen_t int#pragma comment (lib, "ws2_32.lib")using namespace std;using namespace cv;int getFiles(std::string path, std::vector& files, std::vector& names){    int i = 0;    intptr_t hFile = 0;    struct _finddata_t c_file;    std::string imageFile = path + "*.*";    if ((hFile = _findfirst(imageFile.c_str(), &c_file)) == -1L)    {        _findclose(hFile);        return -1;    }    else    {        while (true)        {            std::string strname(c_file.name);            if (std::string::npos != strname.find(".jpg") || std::string::npos != strname.find(".png") || std::string::npos != strname.find(".bmp"))            {                std::string fullName = path + c_file.name;                files.push_back(fullName);                std::string cutname = strname.substr(0, strname.rfind("."));                names.push_back(cutname);            }            if (_findnext(hFile, &c_file) != 0)            {                _findclose(hFile);                break;            }        }    }    return 0;}int main(){    std::string projectBasePath = "./"; // Set your ultralytics base path    bool runOnGPU = true;    //    // Pass in either:    //    // "yolov8s.onnx" or "yolov5s.onnx"    //    // To run Inference with yolov8/yolov5 (ONNX)    //    // Note that in this example the classes are hard-coded and 'classes.txt' is a place holder.    Inference inf(projectBasePath + "/best.onnx", cv::Size(640, 640), "classes.txt", runOnGPU);    std::vector files;    std::vector names;    getFiles("./test/", files, names);    //std::vector imageNames;    //imageNames.push_back(projectBasePath + "/test/20221104_8336.jpg");    //imageNames.push_back(projectBasePath + "/test/20221104_8339.jpg");    for (int i = 0; i  modelScoreThreshold)                {                    confidences.push_back(confidence);                    class_ids.push_back(class_id.x);                    float x = data[0];                    float y = data[1];                    float w = data[2];                    float h = data[3];                    int left = int((x - 0.5 * w) * x_factor);                    int top = int((y - 0.5 * h) * y_factor);                    int width = int(w * x_factor);                    int height = int(h * y_factor);                    boxes.push_back(cv::Rect(left, top, width, height));                }            }        }        data += dimensions;    }    std::vector nms_result;    cv::dnn::NMSBoxes(boxes, confidences, modelScoreThreshold, modelNMSThreshold, nms_result);    std::vector detections{};    for (unsigned long i = 0; i 

上一篇:基于单片机的防酒驾检测系统设计研究

下一篇:怎么快速升级服务器驱动?