前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >YOLOv3使用笔记

YOLOv3使用笔记

作者头像
小锋学长生活大爆炸
发布2022-05-09 16:05:46
1K0
发布2022-05-09 16:05:46
举报

目录

使用免费的DL环境

Google Cloud Platform (GCP) 深度学习虚拟机 (VM)(推荐!)

Google Colab Notebook

Amazon Web Services

数据集标注工具

Roboflow(推荐!)

CVAT

labelimg

训练可视化

wandb(推荐!)

tensorboardX

YOLOv3安装与使用

自定义训练YOLOv3

OpenCV与YOLOv3的结合

其他YOLOv3_C++使用方法

别人的开源代码

使用免费的DL环境

Google Cloud Platform (GCP) 深度学习虚拟机 (VM)(推荐!)

可以免费获得300美元的额度

教程:GCP Quickstart · ultralytics/yolov5 Wiki · GitHub

Google Colab Notebook

免费使用,提供GPU

教程:https://colab.research.google.com/github/ultralytics/yolov5/blob/master/tutorial.ipynb

Amazon Web Services

可以免费获得试用额度

链接:亚马逊AWS海外区域账户免费套餐_免费云服务-AWS云服务

数据集标注工具

Roboflow(推荐!)

官网:Overview - Roboflow

教程:How to Train YOLOv5 On a Custom Dataset

CVAT

官网:Computer Vision Annotation Tool

教程:How to use CVAT for computer vision [2022 updates]

labelimg

官网:GitHub - tzutalin/labelImg: 🖍️ LabelImg is a graphical image annotation tool and label object bounding boxes in images

教程:LabelImg for computer vision annotation

训练可视化

wandb(推荐!)

官网:Weights & Biases

tensorboardX

官网:GitHub - lanpa/tensorboardX: tensorboard for pytorch (and chainer, mxnet, numpy, ...)

YOLOv3安装与使用

官方网站:YOLO: Real-Time Object Detection 官方Github:GitHub - ultralytics/yolov3: YOLOv3 in PyTorch > ONNX > CoreML > TFLite 官方文档:YOLOv5 Documentation 官方论文:https://arxiv.org/abs/1804.02767v1

自定义训练YOLOv3

教程:Training YOLOv3 : Deep Learning based Custom Object Detector | LearnOpenCV #

使用Darknet框架训练模型,该框架为C语言编写。

1、下载并编译

cd ~
git clone https://github.com/pjreddie/darknet
cd darknet
# 使用nproc可以看可用核心数
make -j4

2、准备数据集

下载数据集,并拆分为训练集(70%~90%)和测试集(10%~30%)。

数据集拆分脚本splitTrainAndTest.py示例:

import random
import os
import subprocess
import sys

def split_data_set(image_dir):
    f_val = open("test.txt", 'w')
    f_train = open("train.txt", 'w')
    
    path, dirs, files = next(os.walk(image_dir))
    data_size = len(files)

    ind = 0
    data_test_size = int(0.1 * data_size)
    test_array = random.sample(range(data_size), k=data_test_size)
    
    for f in os.listdir(image_dir):
        if(f.split(".")[1] == "jpg"):
            ind += 1
            
            if ind in test_array:
                f_val.write(image_dir+'/'+f+'\n')
            else:
                f_train.write(image_dir+'/'+f+'\n')

split_data_set(sys.argv[1])

用法:

python3 splitTrainAndTest.py ./path/JPEGImages/

3、标注数据集

使用软件对数据集进行标注。其中标签文件中的每一行条目代表图像中的单个边界框,并包含有关该框的以下信息:

<object-class-id> <center-x> <center-y> <width> <height>
  • object-class-id是一个整数,表示对象的类别。它的范围从 0 到(类数 - 1)。在我们当前的例子中,因为我们只有一个类别,所以它总是设置为 0。
  • center-xcenter-y分别是边界框中心的 x 和 y 坐标(以像素为单位),分别由图像宽度和高度归一化。
  • widthheight分别是边界框的宽度和高度(以像素为单位),再次分别由图像宽度和高度归一化。

标注软件:

自动生成的类别信息:

自动生成的标签信息:

4、下载预训练模型

wget https://pjreddie.com/media/files/darknet53.conv.74

5、准备数据文件

在xxx.data文件中,设置好各个文件的路径信息

classes = 1
train  = /home/sxf/Desktop/yolov3/darknet/datasets/train.txt
valid  = /home/sxf/Desktop/yolov3/darknet/datasets/test.txt
names = /home/sxf/Desktop/yolov3/darknet/datasets/classes.names
backup = /home/sxf/Desktop/yolov3/darknet/datasets/weights/

6、YOLO参数配置

使用模型配置文件darknet-yolov3.cfg

7、开始训练

./darknet detector train /home/sxf/Desktop/yolov3/darknet/datasets/darknet.data /home/sxf/Desktop/yolov3/darknet/datasets/darknet-yolov3.cfg ./darknet53.conv.74 > ./train.log

8、测试模型

python3 object_detection_yolo.py --image=image.jpg

OpenCV与YOLOv3的结合

Opencv4.0已经包含DNN相关的库函数,可以非常方便的调用训练好的YOLO3模型使用。OpenCV CPU 版本快9倍

相关结合教程:

OpenCV的安装:

各平台安装OpenCV_小锋学长生活大爆炸的博客-CSDN博客

OpenCV教程合辑:

GitHub - spmallick/learnopencv: Learn OpenCV : C++ and Python Examples

YOLO可能的一些问题:

YOLO相关问题记录_小锋学长生活大爆炸的博客-CSDN博客

Ubuntu升级CMake3.22:

Ubuntu20.04升级CMake3.22(树莓派适用)_小锋学长生活大爆炸的博客-CSDN博客_树莓派更新cmake

权重与模型配置文件下载:

#!/bin/bash
wget "https://raw.githubusercontent.com/spmallick/learnopencv/master/ObjectDetection-YOLO/yolov3.cfg"
wget "https://pjreddie.com/media/files/yolov3.weights"
wget "https://raw.githubusercontent.com/spmallick/learnopencv/master/ObjectDetection-YOLO/coco.names"
wget "https://raw.githubusercontent.com/spmallick/learnopencv/master/ObjectDetection-YOLO/run.mp4"

赋予权限并执行

sudo chmod +x download.sh 
./download.sh

编写C++代码

#include <iostream>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/dnn/all_layers.hpp>
#include <fstream>

using namespace cv;
using namespace std;
using namespace dnn;

vector<string> classes;//储存名字的容器
float confThreshold = 0.5;//置信度阈值
float nmsThreshold = 0.4;//非最大抑制阈值
int inpWidth = 416;//网络输入图片宽度
int inpHeight = 416;//网络输入图片高度
//移除低置信度边界框
void postprocess(cv::Mat& frame,const vector<cv::Mat>& out);
//画出预测边界框
void drawPred(int classId,float conf,int left,int top,int right,int bottom,cv::Mat& frame);
//取得输出层的名字
vector<cv::String> getOutputNames(const cv::dnn::Net& net);

int main() {
    string device = "cpu";
    string bastPath = "/home/sxf/Desktop/yolov3/project/";

    //将类名存进容器
    string classesFile = bastPath+"model/coco.names";//coco.names包含80种不同的类名
    ifstream ifs(classesFile.c_str());
    string line;
    while(getline(ifs,line)) classes.push_back(line);

    //取得模型的配置和权重文件
    cv::String modelConfiguration = bastPath+"model/yolov3.cfg";
    cv::String modelWeights = bastPath+"model/yolov3.weights";

    //加载网络
    cv::dnn::Net net = cv::dnn::readNetFromDarknet(modelConfiguration, modelWeights);
    if (device == "cpu")
    {
        cout << "Using CPU device" << endl;
        net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
        net.setPreferableBackend(cv::dnn::DNN_TARGET_CPU);
    }
    else if (device == "gpu")
    {
        cout << "Using GPU device" << endl;
        net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
        net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
    }


    //打开视频文件或者图形文件或者相机数据流
    cv::VideoCapture cap(bastPath+"model/run.mp4");
    //开启摄像头
    //cv::VideoCapture cap(1);
    cv::VideoWriter video;
    string str, outputFile;
    cv::Mat frame, blob;

    //创建窗口
    static const string kWinName = "Deep learning object detection in OpenCV";
    cv::namedWindow(kWinName,cv::WINDOW_AUTOSIZE);

    //处理每帧
    while(cv::waitKey(1)<0){
        //取每帧图像
        cap>>frame;
        //如果视频播放完则停止程序
        if(frame.empty()){
            break;
        }
        //在dnn中从磁盘加载图片
        cv::dnn::blobFromImage(frame,blob,1/255.0,cv::Size(inpWidth,inpHeight));
        //设置输入网络
        net.setInput(blob);
        //设置输出层
        vector<cv::Mat> outs;//储存识别结果
        net.forward(outs,getOutputNames(net));
        //移除低置信度边界框
        postprocess(frame,outs);
        //显示s延时信息并绘制
        vector<double> layersTimes;
        double freq = cv::getTickFrequency()/1000;
        double t = net.getPerfProfile(layersTimes)/freq;
        string label = cv::format("Infercence time for a frame:%.2f ms",t);
        cv::putText(frame,label,cv::Point(0,15),cv::FONT_HERSHEY_SIMPLEX,0.5,cv::Scalar(0,255,255));
        //绘制识别框
        cv::Mat detecteFrame;
        frame.convertTo(detecteFrame,CV_8U);
        cv::imshow(kWinName,frame);
    }
    cap.release();

    return 0;
}

//移除低置信度边界框
void postprocess(cv::Mat& frame,const vector<cv::Mat>& outs){
    vector<int> classIds;//储存识别类的索引
    vector<float> confidences;//储存置信度
    vector<cv::Rect> boxes;//储存边框

    for(size_t i=0;i<outs.size();i++){
        //从网络输出中扫描所有边界框
        //保留高置信度选框
        //目标数据data:x,y,w,h为百分比,x,y为目标中心点坐标
        float* data = (float*)outs[i].data;
        for(int j=0;j<outs[i].rows;j++,data+=outs[i].cols){
            cv::Mat scores = outs[i].row(j).colRange(5,outs[i].cols);
            cv::Point classIdPoint;
            double confidence;//置信度
            //取得最大分数值与索引
            cv::minMaxLoc(scores,0,&confidence,0,&classIdPoint);
            if(confidence>confThreshold){
                int centerX = (int)(data[0]*frame.cols);
                int centerY = (int)(data[1]*frame.rows);
                int width = (int)(data[2]*frame.cols);
                int height = (int)(data[3]*frame.rows);
                int left = centerX-width/2;
                int top = centerY-height/2;

                classIds.push_back(classIdPoint.x);
                confidences.push_back((float)confidence);
                boxes.push_back(cv::Rect(left, top, width, height));
            }

        }

    }

    //低置信度
    vector<int> indices;//保存没有重叠边框的索引
    //该函数用于抑制重叠边框
    cv::dnn::NMSBoxes(boxes,confidences,confThreshold,nmsThreshold,indices);
    for(size_t i=0;i<indices.size();i++){
        int idx = indices[i];
        cv::Rect box = boxes[idx];
        drawPred(classIds[idx],confidences[idx],box.x,box.y,
                 box.x+box.width,box.y+box.height,frame);
    }
}

//绘制预测边界框
void drawPred(int classId,float conf,int left,int top,int right,int bottom,cv::Mat& frame){
    //绘制边界框
    cv::rectangle(frame,cv::Point(left,top),cv::Point(right,bottom),cv::Scalar(255,178,50),3);

    string label = cv::format("%.2f",conf);
    if(!classes.empty()){
        CV_Assert(classId < (int)classes.size());
        label = classes[classId]+":"+label;//边框上的类别标签与置信度
    }
    //绘制边界框上的标签
    int baseLine;
    cv::Size labelSize = cv::getTextSize(label,cv::FONT_HERSHEY_SIMPLEX,0.5,1,&baseLine);
    top = max(top,labelSize.height);
    cv::rectangle(frame,cv::Point(left,top-round(1.5*labelSize.height)),cv::Point(left+round(1.5*labelSize.width),top+baseLine),cv::Scalar(255,255,255),cv::FILLED);
    cv::putText(frame, label,cv::Point(left, top), cv::FONT_HERSHEY_SIMPLEX, 0.75,cv::Scalar(0, 0, 0), 1);
}

//从输出层得到名字
vector<cv::String> getOutputNames(const cv::dnn::Net& net){
    static vector<cv::String> names;
    if(names.empty()){
        //取得输出层指标
        vector<int> outLayers = net.getUnconnectedOutLayers();
        vector<cv::String> layersNames = net.getLayerNames();
        //取得输出层名字
        names.resize(outLayers.size());
        for(size_t i =0;i<outLayers.size();i++){
            names[i] = layersNames[outLayers[i]-1];
        }
    }
    return names;
}

CMakeLists文件可参考为:

cmake_minimum_required(VERSION 3.22)
project(project)

set(CMAKE_CXX_STANDARD 17)

find_package(OpenCV REQUIRED)
find_package(Doxygen)

if (NOT APPLE)
    find_package(OpenMP)
endif ()

# ============================================================================ #
# Compilation flags
IF(UNIX)
    SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -O0  -Wall -Wextra -Wunused-variable -DDEBUG -D_DEBUG")
    SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g  -Wall -Wextra -Wunused-variable -DDEBUG -D_DEBUG")
ENDIF(UNIX)

if(OPENMP_FOUND)
    MESSAGE("OpenMP found")
    if(UNIX)
        SET(CMAKE_C_FLAGS_RELEASE "-O3  -Wall -Wextra -Wunused-variable  -g -fPIC -msse2 -msse3 -msse4 -ffast-math")
        SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -Wextra -Wunused-variable -g -fPIC -msse2 -msse3 -msse4 -ffast-math")
    endif(UNIX)
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
else(OPENMP_FOUND)
    MESSAGE("OpenMP not found")
    if(UNIX)
        SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3 -Wall -std=c++0x -Wunused-variable -Wno-unknown-pragmas -g -fPIC -msse2 -msse3 -msse4 -ffast-math")
        SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3 -Wall -std=c++0x -Wno-unknown-pragmas -Wunused-variable -g -fPIC -msse2 -msse3 -msse4 -ffast-math")
    endif(UNIX)
endif(OPENMP_FOUND)

# ============================================================================ #
include_directories( ${OpenCV_INCLUDE_DIRS})


add_executable(project main.cpp)
target_link_libraries(project ${OpenCV_LIBS})

# ============================================================================ #
# Generate Doxygen-based documentation project
if(DOXYGEN_FOUND)
    add_custom_target(akaze_documentation
            ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile
            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
            COMMENT "Generating API documentation with Doxygen" VERBATIM)
endif(DOXYGEN_FOUND)

效果

在此如下配置的电脑上:

YOLOv3:

YOLOv3-tiny:

其他YOLOv3_C++使用方法

别人的开源代码

Github链接:GitHub - zqfang/YOLOv3_CPP: YOLOv3 C++

待续... ...

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用免费的DL环境
    • Google Cloud Platform (GCP) 深度学习虚拟机 (VM)(推荐!)
      • Google Colab Notebook
        • Amazon Web Services
        • 数据集标注工具
          • Roboflow(推荐!)
            • CVAT
              • labelimg
              • 训练可视化
                • wandb(推荐!)
                  • tensorboardX
                  • YOLOv3安装与使用
                  • 自定义训练YOLOv3
                  • OpenCV与YOLOv3的结合
                  • 其他YOLOv3_C++使用方法
                    • 别人的开源代码
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档