您现在的位置是:首页 >技术杂谈 >opencv场景识别网站首页技术杂谈

opencv场景识别

CaCu999 2023-07-18 12:00:02
简介opencv场景识别

opencv场景识别

一、需求

1、现状

​ 现在有一个ppt插入软件,可以根据图片的名字,将对应的图片插入到ppt中去。

​ 但是,既然都简化了,拍完的照片还需要挑选然后重命名,实际上也是一个麻烦且琐碎的活,于是试图简化这一步骤。

2、设想

​ 将拍好的图片分类重命名

二、模型使用

1、opencv dnn支持的功能

​ Opencv Dnn可以对图像和视频完成基于深度学习的计算机视觉推理。opencv DNN支持的功能:

  • 图像分类
  • 目标检测
  • 图像分割
  • 文字检测和识别
  • 姿态估计
  • 深度估计
  • 人脸验证和检测
  • 人体重新识别

2、ANN_MLP相关知识

  1. 介绍

    人工神经网络——多层感知器

    先创建一个model,所有的权重都设置为0。

    网络训练层使用一层输入和输出的向量,训练过程可以重复重复不止一次,权重可以基于新的训练数据调整权重

  2. 一些函数

    • create():创建一个model

    • setLayerSizes():指定每层中神经元的数量,包括输入和输出层。第一个元素指定输入图层中的元素数。最后一个元素-输出图层中的元素数

      例子的数量要和标签的数量相同。第一项为图片的像素数,最后一项 为训练的种类数

       Mat layerSizes = (Mat_<int>(1, 4) << image_rows*image_cols, int(image_rows*image_cols / 2), int(image_rows*image_cols / 2), class_num);
       bp->setLayerSizes(layerSizes);
      
    • setActivationFunction():设置激活函数

      setActivationFunction(int type, double param1 = 0, double param2 = 0)

      type含义
      IDENTITY f ( x ) = x f(x) = x f(x)=x
      SIGMOID_SYM f ( x ) = β ∗ 1 − e α x 1 + e − α x f(x) = eta * frac{1 - e^{alpha x}}{1+e^{-alpha x}} f(x)=β1+eαx1eαx
      GAUSSIAN f ( x ) = β e − α x ∗ x f(x) = eta e^{-alpha x*x} f(x)=βeαxx
      RELU f ( x ) = m a x ( 0 , x ) f(x) = max(0,x) f(x)=max(0,x)
      LEAKYRELU对于x>0, f ( x ) = x f(x) = x f(x)=x;对于x<0, f ( x ) = α x f(x) = alpha x f(x)=αx
      bp->setActivationFunction(ANN_MLP::SIGMOID_SYM, 1, 1);
      
    • setTrainMethod()

      训练方式/传播方式

      cv::ml::ANN_MLP::setTrainMethod(int method,double param1 = 0,double param2 = 0 )

      method函数
      BACKPROP反向传播算法
      RPROP弹性反向传播
      ANNEAL模拟退火算法
    • setTermCriteria

      设置迭代算法终止的判断条件

      TermCriteria:迭代算法终止的判断条件

      class CV_EXPORTS TermCriteria {
      public:
          enum Type{
              COUNT = 1;
              MAX_ITER=COUNT;
              EPS=2;
          }
          TermCriteria(int type, int maxCount, double epsilon);
          int type;
          int maxCount;
          double epsilon;
      }
      

      类变量有三个参数:类型、迭代的 最大次数、特定的阈值

    • 加载分类器

      Ptr<ANN_MLP> bp = StatModel::load<ANN_MLP>("*.xml");
      Ptr<ANN_MLP> bp = ANN_MLP::load<ANN_MLP>("*.xml");
      Ptr<ANN_MLP> bp = Algorithm::load<ANN_MLP>("*.xml");
      
    • predict函数

      float predict( InputArray samples, OutputArray results=noArray(), int flags=0 )

      最终的预测结果 应该是第二个参数OutputArray results

3、MLP图像分类模型训练学习

​ 没试过相关的模型训练,先尝试一下,参考:https://blog.csdn.net/qq_15985873/article/details/125087166

#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
using namespace ml;

#define ROW 45
#define COL 30
#define TYPE_NUM 5
#define SUM 100
// string fruits[5] = {"apple", "cabbage", "carrot", "cucumber", "pear"};
string fruits[5] = {"apple", "cabbage", "carrot", "banana", "pear"};
Mat Label = Mat::eye(5, 5, CV_32FC1);

void fruitAnnPrePro(Mat &src, Mat &dst) {
    src.convertTo(src, CV_32FC1);
    resize(src, src, Size(ROW, COL));
    dst.push_back(src.reshape(0,1));
}

void trainChar(string &root_path, string &model_path) {
    vector<string> dir_path;
    for(string s : fruits)
        dir_path.push_back(root_path + s +"\");
    Mat trainDataMat,trainLabelMat;
    
    vector<vector<string>> files(TYPE_NUM, vector<string>());
    for(int i = 0; i < dir_path.size(); i++) {
        glob(dir_path[i], files[i], false);
    }
    for(int i = 0; i < dir_path.size(); i++) {
        printf("%d  size   %d
", i, files[i].size() );
    }
    for(int i = 0; i < files.size(); i++) {
        for(int j = 0; j < files[i].size(); j++) {
            Mat src = imread(files[i][j], IMREAD_GRAYSCALE);
            if(src.empty()){
                break;
            }
            fruitAnnPrePro(src, trainDataMat);
            trainLabelMat.push_back(Label.row(i));
        }
    }
    imshow("trainData", trainDataMat);
    waitKey(0);
    cout << trainDataMat.size() << endl;
    cout << trainLabelMat.size() << endl;
    Ptr<ANN_MLP> model = ANN_MLP::create();

    Mat labelSizes = (Mat_<int>(1,5) << 1350, 1350, 1350, 10, TYPE_NUM);
    model->setLayerSizes(labelSizes);
    model->setActivationFunction(ANN_MLP::SIGMOID_SYM, 1, 1);
    model->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 300,0.95));
    model->setTrainMethod(ANN_MLP::BACKPROP, 0, 1);

    Ptr<TrainData> trainData = TrainData::create(trainDataMat, ROW_SAMPLE, trainLabelMat);
    printf("开始训练!
");
    model->train(trainData);

    // //保存模型
    model->save(model_path);
    printf("+++++++++++++++++++++++++++训练完成+++++++++++++++++++++++++++

");
}

void useModel(string imgPath, string &model_path) {
    Mat src = imread(imgPath, IMREAD_GRAYSCALE);
    Mat testDataMat;
    fruitAnnPrePro(src, testDataMat);

    Ptr<ANN_MLP> model = ANN_MLP::create();
    model = Algorithm::load<ANN_MLP>(model_path);
    Mat res;
    double maxVal;
    Point maxLoc;
    for(int i = 0; i < testDataMat.rows; i++) {
        model->predict(testDataMat.row(i), res);
        cout << format(res, Formatter::FMT_NUMPY) << endl;
        minMaxLoc(res, NULL, &maxVal, NULL, &maxLoc);
        printf("测试结果:%s 置信度: %f% 
", fruits[maxLoc.x].c_str(), maxVal * 100);
    }
}

int main() {
    // string rootpath = "cpp\opencv\fruitClassify\img\";
    string rootpath = "C:\Users\CaCu999\Pictures\img\";
    string modelpath = "cpp\opencv\fruitClassify\model\fruitModel.xml";
    trainChar(rootpath, modelpath);
    // string imgpath = "cpp\opencv\fruitClassify\img\apple\r1_304.jpg";
    string imgpath = "C:\Users\CaCu999\Pictures\img\banana\10.jpg";
    useModel(imgpath, modelpath);
    return 0;
}

三、更换方向

1、目标检测模型

  1. 知识了解

    仔细想想,我需要的不是图像的分类,而是内部的物体的识别。所以需要的是目标检测

    https://blog.csdn.net/virobotics/article/details/124008160

  2. 物体识别的概念

    需要解决的问题是目标在哪里以及其状态

    秒检测用的比较多的主要是RCNN,spp-net,fast-rcnn;yolo系列(yolov3和yolov4);还有SSD,ResNet等

  3. YOLO算法概述

    对出入的图片,将图片分为mxm个方格。当某个物体的中心点落在了某个方格中,该方格负责预测该物体。每个方格会被预测物体产生n个候选框并生成每个框的置信度。最后选区置信度比较高的方框作为结果

2、darknet网络介绍

  1. darknet,yolo和Opencv

    • Darknet

      一种几乎全用c写的框架或者说是工具,用于计算机视觉。可以用来训练神经网络也可以用这些这些审计忘了读照片或者视频。

    • YOLO

      darknet使用的众多配置文件的一种。这些配置文件定义了神经网络如何创建和运行。配置文件中有些快但不精准,也有些精准但要花很久,当然有些取中间值。

      每个配置文件有不同的可能和置信度

    • YOLOv4

      YOLO的最新版本。YOLOv4-tiny是个比YOLOv4更轻量级的版本(小/快)。

      YOLOv4-tiny-3l是3层网络,介于YOLOv4和YOLOv4-tiny之间

    • what is neural network from this stack: Darknet, Yolov, OpenCV.

      • Darknet是训练和使用神经网络的工具
      • 神经网络本质是用来找事物中模式(特征?)的软件。以darknet举例,神经网络创建一个"weights"文件,用以找在图片中的特征。
      • Opencv是一款intel软件库,常被开发者用以处理图片。它能让你对图片进行一些处理(找到边界用以进行物体检测)。opencv支持运行已生成的神经网络。所以可以用opencv加载训练好的网络
      • 在创建网络的过程中,opencv不是必须的。但有opencv的参与,训练和推导都能更快
  2. 哪些软件参与这些工作

    • Darknet

      最少也要下载并编译darknet。darknet包含了很多YOLO的配置文件。可以让训练新网络并运行推导照片和视频帧

      原作者是Joseph Redmon,但他的pjreddie在很多年前就被弃用了。自2016年就没有什么重大更新。AlexeyAB现在维护的这个分支被认为是Darknet的最新版本。后面构建的也是该版本

    • Opencv

      处理图像的开源库。

    • CUDA

      一个NVIDIA的可选择的闭源库。仅在电脑有NVIDIA配置的GPU时才能生效,训练不用他明显会更慢

    • CUDNN

      一个NVIDIA的可选择闭源库。它提供了神经网络可以用来加速的功能。与CUDA类似,这需要在您的计算机中安装nvidia品牌的GPU。

    • DarkHelp

      DarkHelp是可选的开源c++ API包装器和用于Darknet的CLI。

    • DarkMark

      一个可选的开源GUI工具。DarkMark需要Linux,尽管它在使用WSL 2或Linux虚拟机时也可以在Windows中运行。

  3. 使用什么配置文件

    • 多数人建议使用Yolo-tiny。“tiny”代表这个配置有两层而不是三层忘了。特别是刚开始建立一个新的神经网络,或追求一个快点的结果,用tiny更好。到2022年, Stéphane仍然锐减YOLOv4-tiny
    • 如果有很多类,并且相近,那就尝试用yolov4-tiny-3l.cfg,3l代表三层yolo,会比YOLOv4-tiny大且慢
    • 最后,最大最复杂的是完整的yolov4.cfg和yolov7.cfg,自己自定义的神经网络基本不太用
  4. 储存要求

    默认的网络要求的通常是416x416 或 608x608,实际上要求:

    • 宽和高可以被32整除
    • 必须有足够的空间

    尺寸按照自己需要的就可以,但是有些限制

    • 尺寸增加,训练和推导速度会慢,且需要更多的GPU空间
    • 尺寸减小,训练和推导速度增加,但找到小的物体就更难

    有3种相关的尺寸必须考虑:

    • 图像尺寸
    • 网络维度
    • 图像中每个对象的大小
  5. 标签规则

    • 照片中的每个物体都需要背标签
    • 准确标签。
    • 如果希望Darknet找到特定场景下,在确定光源下,在特定角度和以特定大小的物体,则训练图片必须覆盖这些场景
    • 不要忘了负样本

四、opencv调用darknet模型

1、darknet模型获取

  • 文件

    • cfg文件:模型描述文件
    • weights文件:模型权重文件
  • yolov3

    https://github.com/pjreddie/darknet/blob/master/cfg/yolov3.cfg
    https://pjreddie.com/media/files/yolov3.weights

    https://github.com/pjreddie/darknet/blob/master/data/coco.names

  • yolov4

    https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.cfg
    https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights

2、python调用darknet模型

直接粘贴并稍微修改一下以后的实现

import cv2
cv=cv2
import numpy as np
import time

#读取模型
net = cv2.dnn.readNetFromDarknet("cpp\opencv\ObjectDetection\model\yolov3.cfg", 
                                 "cpp\opencv\ObjectDetection\model\yolov3.weights")
#gpu计算之类的……
# net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
# net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
#阈值
confThreshold = 0.5  #Confidence threshold
nmsThreshold = 0.4   #Non-maximum suppression threshold
#读取图片
frame=cv2.imread("cpp\opencv\ObjectDetection\img\20221122_110416.jpg")
#等比例缩小
frame = cv2.resize(frame,((int)(frame.shape[1]/10),(int)(frame.shape[0]/10)))
print(frame.shape[0] * frame.shape[1] / 100)
#标签文件并读取所有的标签
classesFile = "cpp\opencv\ObjectDetection\model\coco.names";
classes = None
with open(classesFile, 'rt') as f:
    classes = f.read().rstrip('
').split('
')

#读取网络名字
def getOutputsNames(net):
    # Get the names of all the layers in the network
    layersNames = net.getLayerNames()
    # Get the names of the output layers, i.e. the layers with unconnected outputs
    return [layersNames[i - 1] for i in net.getUnconnectedOutLayers()]
print(getOutputsNames(net))
# Remove the bounding boxes with low confidence using non-maxima suppression

def postprocess(frame, outs):
    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]
    # Scan through all the bounding boxes output from the network and keep only the
    # ones with high confidence scores. Assign the box's class label as the class with the highest score.
    classIds = []
    confidences = []
    boxes = []
    # 解析结果
    for out in outs:
        print(out.shape)
        for detection in out:
            scores = detection[5:]
            classId = np.argmax(scores)
            confidence = scores[classId]
            if confidence > confThreshold:
                center_x = int(detection[0] * frameWidth)
                center_y = int(detection[1] * frameHeight)
                width = int(detection[2] * frameWidth)
                height = int(detection[3] * frameHeight)
                left = int(center_x - width / 2)
                top = int(center_y - height / 2)
                classIds.append(classId)
                confidences.append(float(confidence))
                boxes.append([left, top, width, height])
 
    # Perform non maximum suppression to eliminate redundant overlapping boxes with
    # lower confidences.
    print(boxes)
    print(confidences)  
    indices = cv2.dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold) 
    for i in indices:
        #print(i)
        #i = i[0]
        box = boxes[i]
        left = box[0]
        top = box[1]
        width = box[2]
        height = box[3]
        drawPred(classIds[i], confidences[i], left, top, left + width, top + height)

    # Draw the predicted bounding box
def drawPred(classId, conf, left, top, right, bottom):
    # Draw a bounding box.
    cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255))
    label = '%.2f' % conf    
    # Get the label for the class name and its confidence
    if classes:
        assert(classId < len(classes))
        label = '%s:%s' % (classes[classId], label)
    #Display the label at the top of the bounding box
    labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
    top = max(top, labelSize[1])
    cv2.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255))
#读取图片,改为416*416的大小
blob = cv2.dnn.blobFromImage(frame, 1/255, (416, 416), [0,0,0], 1, crop=False)
t1=time.time()
#设置输入的图片获取结果
net.setInput(blob)
#使用模型
outs = net.forward(getOutputsNames(net))
print(time.time()-t1)
postprocess(frame, outs)
t, _ = net.getPerfProfile()
label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency())
cv2.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255))
print(frame.shape)
cv2.imshow("result",frame)
cv2.waitKey(0)

3、遇到的一些问题

  • blobFromImage(frame, (double)1/255, Size(416, 416),Scalar(0,0,0), true);需要注意这里的收缩比例以及需要转为double

  • net.forward的输出结果

    一共80个label,输出结果为n*85。第1和2个是方框中心点(x,y)的位置的比例。第3和4个是宽和高的比例。第五个不知道。后面的80个是这个区域的每个标签的可能性

    所以针对这个结果,需要做的是:从后面80个结果里面获取最大值和索引。这个索引也就是label的索引。如果这个最大值大于置信度的阈值,就获取前面的选框区域

4、c++调用darknet进行物体识别

#include <iostream>
#include <opencv2/opencv.hpp>
#include <fstream>

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

void readClasses(vector<string> &classes, string classFile) {
    ifstream readFile;
    readFile.open(classFile);
    if(readFile.is_open()) {
        // printf("文件打开成功!
开始读取内容……
");
        string label;
        while(getline(readFile, label)) {
            // printf("%s
", label.c_str());
            classes.push_back(label);
        }
        // printf("读取结束,一共%d个标签
", classes.size());
    } else {
        cerr << "文件打开失败" << endl;
    }
    readFile.close();
}

vector<string> getOutputsNames(Net net) {
    vector<string> layers = net.getLayerNames();
    cout << layers.size()<< endl;
    //获得末端连接神经网络名字,用于指定forward输出层的名字
    auto idx = net.getUnconnectedOutLayers();
    vector<string> res;
    for(int i = 0; i < idx.size(); i++) {
        res.push_back(layers[idx[i] - 1]);
    }
    for(int i = 0; i < res.size(); i++) {
        cout << res[i] << endl;
    }
    return res;
}

void readAndGetRes(string imgPath,Mat &frame, vector<Mat> &outs) {
    Net net = readNetFromDarknet("cpp\opencv\ObjectDetection\model\yolov3.cfg", 
                                 "cpp\opencv\ObjectDetection\model\yolov3.weights");
    frame = imread(imgPath);
    resize(frame, frame, Size(frame.cols / 10, frame.rows / 10));
    string classFile = "cpp\opencv\ObjectDetection\model\coco.names";

    Mat blob = blobFromImage(frame, (double)1/255, Size(416, 416),Scalar(0,0,0), true);
    time_t startTime;
    time(&startTime);
    net.setInput(blob);
    net.forward(outs, getOutputsNames(net));
}

void postProcess(Mat &frame,vector<Mat> probs) {
    vector<string> classes;
    readClasses(classes, "cpp\opencv\ObjectDetection\model\coco.names");
    int w = frame.cols;
    int h = frame.rows;
    float confThreshold = 0.5;
    float nmxThreshold = 0.4;
    vector<int> classIds;
    vector<float> confidences;
    vector<Rect> boxes;
    for(auto prob: probs) {
        cout << prob.size() << endl;
        for(int i = 0; i < prob.rows; i++) {
            //获取该选框的所有label的可能性
            Mat scores = prob.row(i).colRange(5, prob.cols);
            //获取选框的位置
            vector<float> detect = prob.row(i).colRange(0, 4);
            Point maxLoc;
            double confidence;
            //获取最大可能的可能性以及它的索引
            minMaxLoc(scores, 0, &confidence, 0, &maxLoc);
            if(confidence > confThreshold) {
                printf("confidence   %0.2f, loc %s,  %0.2f  %0.2f  %0.2f  %0.2f %0.2f
",
                confidence, classes[maxLoc.x].c_str(), detect[0], detect[1], detect[2], detect[3], detect[4]);
                int center_x = detect[0] * w;
                int center_y = detect[1] * h;
                int width = detect[2] * w;
                int height = detect[3] * h;
                Rect box = Rect(center_x - width / 2, center_y - height / 2, width, height);
                boxes.push_back(box);
                confidences.push_back(confidence);
                classIds.push_back(maxLoc.x);
            }
        }
    }
    vector<int> indices;
    NMSBoxes(boxes, confidences, confThreshold, nmxThreshold, indices);
    cout << "the res " <<  indices.size() << endl;
    for(int i:indices) {
        cout << i << endl;
        rectangle(frame, boxes[i], Scalar(0, 0, 255));
        string label = format("%s:%0.2f%", classes[classIds[i]].c_str(), confidences[i]*100);
        cout << label << endl;
        putText(frame, label, Point(boxes[i].x,boxes[i].y), FONT_HERSHEY_SIMPLEX,0.5,Scalar(255,255,255));
        cout << label << endl;
    }
    cout << "this is end" << endl;
    imshow("label frame",frame);
    waitKey(0);
}

int main() {
    vector<Mat> res;
    Mat img;
    readAndGetRes("cpp\opencv\ObjectDetection\img\20221122_110416.jpg", img, res);
    postProcess(img, res);
    return 0;
}

上述部分参考自:https://blog.csdn.net/virobotics/article/details/124008160

五、darknet编译

1、现状

​ 之前尝试了使用yolo3进行了图像的识别,但是里面的label跟我说需要的不匹配,尝试针对自己的需求进行模型训练

2、下载代码

git clone https://github.com/pjreddie/darknet.git

3、darknet环境准备-win10

  1. 确认训练方式

    如果不使用opencv和gpu的话,打开命令行执行build.ps1

  2. 下载安装CUDA

    参考:https://blog.csdn.net/weixin_43848614/article/details/117221384

    • 下载:https://developer.nvidia.com/cuda-toolkit-archive

    • 安装

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

    • 环境变量

      添加刚刚安装的位置NVIDIA GPU Computing Toolkit的那个

    • 测试

      > nvcc --version
      nvcc: NVIDIA (R) Cuda compiler driver
      Copyright (c) 2005-2020 NVIDIA Corporation
      Built on Tue_Sep_15_19:12:04_Pacific_Daylight_Time_2020
      Cuda compilation tools, release 11.1, V11.1.74
      Build cuda_11.1.relgpu_drvr455TC455_06.29069683_0
      

      windows编译和解编译问题-失败了所以重来

    • 下载cudnn并放到cuda的目录

      配置cudnn
      在这里插入图片描述

  3. 下载Visual Studio

    • 版本:似乎是建议2015-2019

    • 卸载vs
      在这里插入图片描述

    • 下载2019

      https://visualstudio.microsoft.com/zh-hans/vs/older-downloads/

      在这里插入图片描述

    • 安装

      在这里插入图片描述

      在这里插入图片描述

      在这里插入图片描述

    • 一些环境变量的设置

      可能需要mingw放到VS相关环境的下面,不然优先使用的是mingw的c相关编译。mingw和cuda不能一起使用,会产生大量编译问题

      在这里插入图片描述

      在这里插入图片描述

4、darknet-编译相关准备

  1. tips

    这是在众多尝试的时候进行的一部分感觉有用的修改,实际不确定是否真的有用

  2. Makefile:修改GPU=1

    GPU=1
    CUDNN=1
    OPENCV=1
    OPENMP=0
    DEBUG=0
    
  3. Makefile:修改/usr/local/cuda/include/改成自己的路径

  4. compute_30已经被cuda11放弃使用了,修改Makefile

    ARCH= -gencode arch=compute_30,code=sm_30 
          -gencode arch=compute_35,code=sm_35 
          -gencode arch=compute_50,code=[sm_50,compute_50] 
          -gencode arch=compute_52,code=[sm_52,compute_52]
          
    
    ARCH= -gencode arch=compute_35,code=sm_35 
          -gencode arch=compute_50,code=[sm_50,compute_50] 
          -gencode arch=compute_52,code=[sm_52,compute_52]
    

5、编译darknet-官方建议-build.ps1

  1. 打开PowerShell 管理员,输入Set-ExecutionPolicy RemoteSigned

在这里插入图片描述

  1. 进入darknet目录执行:.uild.ps1
    在这里插入图片描述

    结果

    在这里插入图片描述

    每次尝试的时候,只有上面几个输入全部都不选的情况下,才会有结果,但是那个编译出来的结果不用opencv和gpu,训练特别慢

6、VS编译

参考:https://www.cnblogs.com/taotingz/p/11319410.html

  • 添加包含目录
    在这里插入图片描述
    在这里插入图片描述


  • 在这里插入图片描述

  • 常规设置
    在这里插入图片描述


  • 在这里插入图片描述

  • 直接点击调试,可以在build/darknet目录找到对应的exe文件

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。