当前位置: 首页 > news >正文

VS2015 + OpenCV + OnnxRuntime-Cpp + YOLOv8 部署

  • 近期有个工作需求是进行 YOLOv8 模型的 C++ 部署,部署环境如下
    1. 系统:Windows
    2. IDE:VS2015
    3. 语言:C++
    4. OpenCV 4.5.0
    5. OnnxRuntime 1.15.1

0. 预训练模型保存为 .onnx 格式

  • 假设已经有使用 ultralytics 库训练并保存为 .pt 格式的 YOLOv8 模型,将其转换为 .onnx 格式是简单的
    import os
    import sys
    base_path = os.path.abspath(os.path.join(os.path.dirname(__file__),))
    sys.path.append(base_path)from ultralytics import YOLO# Load a YOLOv8 model
    model = YOLO(f"{base_path}/model/output/best.pt")# Export the model
    model.export(format="onnx", opset=9, simplify=True, dynamic=False, imgsz=640)
    

    注意导出时设置了 opset=9,这个版本可以和 OnnxRuntime 1.15.1 匹配

  • 除了 .onnx 模型文件以外,还需要准备数据集的 .yaml 文件和用于测试的图片

1. 依赖下载

1.1 OpenCV

  • 在 window 上用 Cmake 从源码编译 OpenCV 很麻烦,直接下载 release 库
  • 下载地址:OpenCV-4.5.0
    在这里插入图片描述
    下载后得到 opencv-4.5.0-vc14_vc15.exe,双击解压。把 C:\Users…\opencv\build\x64\vc14\bin 添加到环境变量。其中 vc14 对应 vs2015
  • 提取的文件中,以下是我们之后需要的
    1. 头文件:C:\Users…\opencv\build\include\opencv2
    2. 动态库:C:\Users…\opencv\build\x64\vc14\bin\opencv_world450.dll
    3. 静态库:C:\Users…\opencv\build\x64\vc14\lib\opencv_world450.lib & opencv_world450d.lib

      opencv_world450.lib 用于 vs release 模式;opencv_world450d.lib 用于 vs debug 模式

1.2 OnnxRuntime

  • 下载地址:ONNX Runtime v1.15.1,下载 onnxruntime-win-x64-1.15.1.zip,下载后直接解压。
  • 提取的文件中,以下是我们之后需要的
    1. 头文件:C:\Users…\onnxruntime-win-x64-1.15.1\include
    2. 动态库:C:\Users…\onnxruntime-win-x64-1.15.1\lib 下的所有 .dll 文件
    3. 静态库:C:\Users…\onnxruntime-win-x64-1.15.1\lib 下的所有 .lib 文件

1.3 Cpp 源码

  • 下载地址:YOLOv8 OnnxRuntime C++。这是 ultralytics 提供的官方案例,注意其依赖
    在这里插入图片描述
    由于 vs2015 无法设置 C++17 标准,后续会修改源码,去掉其中使用的 filesystem 库,由于仅部署 CPU 版本,无需 Cuda 和 cuDNN。另外这个 readme 还提到了 Cmake 编译,我们不需要做这步,直接用它的源码就行了

2. VS2015 工程配置

2.1 创建项目

  • 首先新建 Win32 控制台项目,选择空项目。我这里项目路径为 YOLOv8-Test,项目名为 Test。打开工程根目录,新建 bin、lib、include 三个目录
    在这里插入图片描述
    • 在 bin 中粘贴 1.2 和 1.3 节提到的所有动态库文件
      在这里插入图片描述
    • 在 lib 中粘贴 1.2 和 1.3 节提到的所有静态库文件
      在这里插入图片描述
    • 在 include 中粘贴 1.2 和 1.3 节提到的所有头文件目录
      在这里插入图片描述
      其中 onnxruntime-win-x64 就是 C:\Users…\onnxruntime-win-x64-1.15.1\include 文件夹
  • 把源码粘贴到根目录,并添加到项目中
    在这里插入图片描述

2.2 配置项目属性

  • 在解决方案名 Test 处右键,点最下面属性,打开项目属性页。首先配置 Release 属性,平台选择 x64
    在这里插入图片描述
    • VC++目录 -> 包含目录,编辑增加以下路径
      在这里插入图片描述

    • VC++目录 -> 库目录,编辑增加以下路径
      在这里插入图片描述

    • C/C++ -> 常规 -> 附加包含目录,编辑增加以下路径。并关闭 SDL 检查
      在这里插入图片描述

    • 链接器 -> 附加库目录,编辑增加以下路径
      在这里插入图片描述

    • 链接器 -> 输入 -> 附加依赖项,编辑增加以下文件名(主要这里是Release版本所以用 opencv_world450.lib)
      在这里插入图片描述

    • 类似地配置 Debug 属性,区别仅在于最后一步链接附加依赖项写入 opencv_world450d.lib

  • 由于 1.3 节没有对源码进行 Cmake 安装,还需要将 onnxruntime.dll 复制粘贴到编译运行后 .exe 文件的生成目录下,如 C:…\YOLOv8-Test\Test\x64\Release,以免出现链接错误
    在这里插入图片描述
    如果不想在每次编译都粘贴,可以直接把它粘贴到 C:\Windows\System32 和 C:\Windows\SysWOW64

3. 修改源码

  • 由于 vs2015 无法使用 C++17 特征,修改 main.cpp 去掉其中对 filesystem 库的依赖,如下

    #include <iostream>
    #include <iomanip>
    #include "inference.h"
    #include <fstream>
    #include <random>
    #include <vector>
    #include <string>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <opencv2/opencv.hpp>void Detector(YOLO_V8*& p) {std::string current_path = ".";std::string imgs_path = current_path + "/images";DIR* dir;struct dirent* ent;if ((dir = opendir(imgs_path.c_str())) != NULL) {while ((ent = readdir(dir)) != NULL) {std::string file_name = ent->d_name;if (file_name.find(".jpg") != std::string::npos || file_name.find(".png") != std::string::npos || file_name.find(".jpeg") != std::string::npos) {std::string img_path = imgs_path + "/" + file_name;cv::Mat img = cv::imread(img_path);std::vector<DL_RESULT> res;p->RunSession(img, res);for (auto& re : res) {cv::RNG rng(cv::getTickCount());cv::Scalar color(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));cv::rectangle(img, re.box, color, 3);float confidence = floor(100 * re.confidence) / 100;std::cout << std::fixed << std::setprecision(2);std::string label = p->classes[re.classId] + " " +std::to_string(confidence).substr(0, std::to_string(confidence).size() - 4);cv::rectangle(img,cv::Point(re.box.x, re.box.y - 25),cv::Point(re.box.x + label.length() * 15, re.box.y),color,cv::FILLED);cv::putText(img,label,cv::Point(re.box.x, re.box.y - 5),cv::FONT_HERSHEY_SIMPLEX,0.75,cv::Scalar(0, 0, 0),2);std::replace(label.begin(), label.end(), '\r', ' ');std::cout << "Target Type:   " << label << std::endl;std::cout << "Loc (x,y,w,h): " << "(" << re.box.x << "," << re.box.y << "," << re.box.width << "," << re.box.height << ")" << std::endl;}cv::Mat resized_img; double scale_factor = 5.0; // 放大倍数 cv::resize(img, resized_img, cv::Size(), scale_factor, scale_factor, cv::INTER_LINEAR); cv::imshow("Result of Detection", resized_img); std::cout << "Press any key to exit" << std::endl;//cv::imshow("Result of Detection", img);cv::waitKey(0);cv::destroyAllWindows();}}closedir(dir);}
    }void Classifier(YOLO_V8*& p) {std::string current_path = ".";std::string imgs_path = current_path;std::random_device rd;std::mt19937 gen(rd());std::uniform_int_distribution<int> dis(0, 255);DIR* dir;struct dirent* ent;if ((dir = opendir(imgs_path.c_str())) != NULL) {while ((ent = readdir(dir)) != NULL) {std::string file_name = ent->d_name;if (file_name.find(".jpg") != std::string::npos || file_name.find(".png") != std::string::npos) {std::string img_path = imgs_path + "/" + file_name;cv::Mat img = cv::imread(img_path);std::vector<DL_RESULT> res;char* ret = p->RunSession(img, res);float positionY = 50;for (int i = 0; i < res.size(); i++) {int r = dis(gen);int g = dis(gen);int b = dis(gen);cv::putText(img, std::to_string(i) + ":", cv::Point(10, positionY), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(b, g, r), 2);cv::putText(img, std::to_string(res.at(i).confidence), cv::Point(70, positionY), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(b, g, r), 2);positionY += 50;}cv::imshow("TEST_CLS", img);cv::waitKey(0);cv::destroyAllWindows();}}closedir(dir);}
    }int ReadPlaneYaml(YOLO_V8*& p) {// Open the YAML filestd::ifstream file("./cfg/plane.yaml");if (!file.is_open()) {std::cerr << "Failed to open file" << std::endl;return 1;}// Read the file line by linestd::string line;std::vector<std::string> lines;while (std::getline(file, line)) {lines.push_back(line);}// Find the start and end of the names sectionstd::size_t start = 0;std::size_t end = 0;for (std::size_t i = 0; i < lines.size(); i++) {if (lines[i].find("names:") != std::string::npos) {start = i + 1;} else if (start > 0 && lines[i].find(':') == std::string::npos) {end = i;break;}}// Extract the namesstd::vector<std::string> names;for (std::size_t i = start; i < end; i++) {std::stringstream ss(lines[i]);std::string name;std::getline(ss, name, ':'); // Extract the number before the delimiterstd::getline(ss, name); // Extract the string after the delimiternames.push_back(name);}p->classes = names;return 0;
    }void DetectTest() {YOLO_V8* yoloDetector = new YOLO_V8;ReadPlaneYaml(yoloDetector);DL_INIT_PARAM params;params.rectConfidenceThreshold = 0.1;params.iouThreshold = 0.5;params.modelPath = "./model/best.onnx";params.imgSize = { 640, 640 };
    #ifdef USE_CUDAparams.cudaEnable = true;// GPU FP32 inferenceparams.modelType = YOLO_DETECT_V8;// GPU FP16 inference//Note: change fp16 onnx model//params.modelType = YOLO_DETECT_V8_HALF;#else// CPU inferenceparams.modelType = YOLO_DETECT_V8;params.cudaEnable = false;#endifyoloDetector->CreateSession(params);Detector(yoloDetector);
    }// void ClsTest() {
    //     YOLO_V8* yoloDetector = new YOLO_V8;
    //     std::string model_path = "cls.onnx";
    //     ReadPlaneYaml(yoloDetector);
    //     DL_INIT_PARAM params{ model_path, YOLO_CLS, {224, 224} };
    //     yoloDetector->CreateSession(params);
    //     Classifier(yoloDetector);
    // }int main() {DetectTest();//ClsTest();
    }
  • 以上代码使用了 dirent.h 中封装的 windows 文件读写方法,如果 vs 报错找不到这个头文件,则自己创建该文件,放置于 vs 安装路径,我这是 D:\Programmer\Microsoft Visual Studio 14.0\VC\include

    /** Dirent interface for Microsoft Visual Studio** Copyright (C) 1998-2019 Toni Ronkko* This file is part of dirent.  Dirent may be freely distributed* under the MIT license.  For all details and documentation, see* https://github.com/tronkko/dirent*/
    #ifndef DIRENT_H
    #define DIRENT_H/* Hide warnings about unreferenced local functions */
    #if defined(__clang__)
    #   pragma clang diagnostic ignored "-Wunused-function"
    #elif defined(_MSC_VER)
    #   pragma warning(disable:4505)
    #elif defined(__GNUC__)
    #   pragma GCC diagnostic ignored "-Wunused-function"
    #endif/** Include windows.h without Windows Sockets 1.1 to prevent conflicts with* Windows Sockets 2.0.*/
    #ifndef WIN32_LEAN_AND_MEAN
    #   define WIN32_LEAN_AND_MEAN
    #endif
    #include <windows.h>#include <stdio.h>
    #include <stdarg.h>
    #include <wchar.h>
    #include <string.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <errno.h>/* Indicates that d_type field is available in dirent structure */
    #define _DIRENT_HAVE_D_TYPE/* Indicates that d_namlen field is available in dirent structure */
    #define _DIRENT_HAVE_D_NAMLEN/* Entries missing from MSVC 6.0 */
    #if !defined(FILE_ATTRIBUTE_DEVICE)
    #   define FILE_ATTRIBUTE_DEVICE 0x40
    #endif/* File type and permission flags for stat(), general mask */
    #if !defined(S_IFMT)
    #   define S_IFMT _S_IFMT
    #endif/* Directory bit */
    #if !defined(S_IFDIR)
    #   define S_IFDIR _S_IFDIR
    #endif/* Character device bit */
    #if !defined(S_IFCHR)
    #   define S_IFCHR _S_IFCHR
    #endif/* Pipe bit */
    #if !defined(S_IFFIFO)
    #   define S_IFFIFO _S_IFFIFO
    #endif/* Regular file bit */
    #if !defined(S_IFREG)
    #   define S_IFREG _S_IFREG
    #endif/* Read permission */
    #if !defined(S_IREAD)
    #   define S_IREAD _S_IREAD
    #endif/* Write permission */
    #if !defined(S_IWRITE)
    #   define S_IWRITE _S_IWRITE
    #endif/* Execute permission */
    #if !defined(S_IEXEC)
    #   define S_IEXEC _S_IEXEC
    #endif/* Pipe */
    #if !defined(S_IFIFO)
    #   define S_IFIFO _S_IFIFO
    #endif/* Block device */
    #if !defined(S_IFBLK)
    #   define S_IFBLK 0
    #endif/* Link */
    #if !defined(S_IFLNK)
    #   define S_IFLNK 0
    #endif/* Socket */
    #if !defined(S_IFSOCK)
    #   define S_IFSOCK 0
    #endif/* Read user permission */
    #if !defined(S_IRUSR)
    #   define S_IRUSR S_IREAD
    #endif/* Write user permission */
    #if !defined(S_IWUSR)
    #   define S_IWUSR S_IWRITE
    #endif/* Execute user permission */
    #if !defined(S_IXUSR)
    #   define S_IXUSR 0
    #endif/* Read group permission */
    #if !defined(S_IRGRP)
    #   define S_IRGRP 0
    #endif/* Write group permission */
    #if !defined(S_IWGRP)
    #   define S_IWGRP 0
    #endif/* Execute group permission */
    #if !defined(S_IXGRP)
    #   define S_IXGRP 0
    #endif/* Read others permission */
    #if !defined(S_IROTH)
    #   define S_IROTH 0
    #endif/* Write others permission */
    #if !defined(S_IWOTH)
    #   define S_IWOTH 0
    #endif/* Execute others permission */
    #if !defined(S_IXOTH)
    #   define S_IXOTH 0
    #endif/* Maximum length of file name */
    #if !defined(PATH_MAX)
    #   define PATH_MAX MAX_PATH
    #endif
    #if !defined(FILENAME_MAX)
    #   define FILENAME_MAX MAX_PATH
    #endif
    #if !defined(NAME_MAX)
    #   define NAME_MAX FILENAME_MAX
    #endif/* File type flags for d_type */
    #define DT_UNKNOWN 0
    #define DT_REG S_IFREG
    #define DT_DIR S_IFDIR
    #define DT_FIFO S_IFIFO
    #define DT_SOCK S_IFSOCK
    #define DT_CHR S_IFCHR
    #define DT_BLK S_IFBLK
    #define DT_LNK S_IFLNK/* Macros for converting between st_mode and d_type */
    #define IFTODT(mode) ((mode) & S_IFMT)
    #define DTTOIF(type) (type)/** File type macros.  Note that block devices, sockets and links cannot be* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are* only defined for compatibility.  These macros should always return false* on Windows.*/
    #if !defined(S_ISFIFO)
    #   define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
    #endif
    #if !defined(S_ISDIR)
    #   define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
    #endif
    #if !defined(S_ISREG)
    #   define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
    #endif
    #if !defined(S_ISLNK)
    #   define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
    #endif
    #if !defined(S_ISSOCK)
    #   define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
    #endif
    #if !defined(S_ISCHR)
    #   define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
    #endif
    #if !defined(S_ISBLK)
    #   define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
    #endif/* Return the exact length of the file name without zero terminator */
    #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)/* Return the maximum size of a file name */
    #define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)#ifdef __cplusplus
    extern "C" {
    #endif/* Wide-character version */
    struct _wdirent {/* Always zero */long d_ino;/* File position within stream */long d_off;/* Structure size */unsigned short d_reclen;/* Length of name without \0 */size_t d_namlen;/* File type */int d_type;/* File name */wchar_t d_name[PATH_MAX+1];
    };
    typedef struct _wdirent _wdirent;struct _WDIR {/* Current directory entry */struct _wdirent ent;/* Private file data */WIN32_FIND_DATAW data;/* True if data is valid */int cached;/* Win32 search handle */HANDLE handle;/* Initial directory name */wchar_t *patt;
    };
    typedef struct _WDIR _WDIR;/* Multi-byte character version */
    struct dirent {/* Always zero */long d_ino;/* File position within stream */long d_off;/* Structure size */unsigned short d_reclen;/* Length of name without \0 */size_t d_namlen;/* File type */int d_type;/* File name */char d_name[PATH_MAX+1];
    };
    typedef struct dirent dirent;struct DIR {struct dirent ent;struct _WDIR *wdirp;
    };
    typedef struct DIR DIR;/* Dirent functions */
    static DIR *opendir (const char *dirname);
    static _WDIR *_wopendir (const wchar_t *dirname);static struct dirent *readdir (DIR *dirp);
    static struct _wdirent *_wreaddir (_WDIR *dirp);static int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
    static int _wreaddir_r(_WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);static int closedir (DIR *dirp);
    static int _wclosedir (_WDIR *dirp);static void rewinddir (DIR* dirp);
    static void _wrewinddir (_WDIR* dirp);static int scandir (const char *dirname, struct dirent ***namelist,int (*filter)(const struct dirent*),int (*compare)(const struct dirent**, const struct dirent**));static int alphasort (const struct dirent **a, const struct dirent **b);static int versionsort (const struct dirent **a, const struct dirent **b);/* For compatibility with Symbian */
    #define wdirent _wdirent
    #define WDIR _WDIR
    #define wopendir _wopendir
    #define wreaddir _wreaddir
    #define wclosedir _wclosedir
    #define wrewinddir _wrewinddir/* Internal utility functions */
    static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
    static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);static int dirent_mbstowcs_s(size_t *pReturnValue,wchar_t *wcstr,size_t sizeInWords,const char *mbstr,size_t count);static int dirent_wcstombs_s(size_t *pReturnValue,char *mbstr,size_t sizeInBytes,const wchar_t *wcstr,size_t count);static void dirent_set_errno (int error);/** Open directory stream DIRNAME for read and return a pointer to the* internal working area that is used to retrieve individual directory* entries.*/
    static _WDIR*
    _wopendir(const wchar_t *dirname)
    {_WDIR *dirp;DWORD n;wchar_t *p;/* Must have directory name */if (dirname == NULL  ||  dirname[0] == '\0') {dirent_set_errno (ENOENT);return NULL;}/* Allocate new _WDIR structure */dirp = (_WDIR*) malloc (sizeof (struct _WDIR));if (!dirp) {return NULL;}/* Reset _WDIR structure */dirp->handle = INVALID_HANDLE_VALUE;dirp->patt = NULL;dirp->cached = 0;/** Compute the length of full path plus zero terminator** Note that on WinRT there's no way to convert relative paths* into absolute paths, so just assume it is an absolute path.*/
    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)/* Desktop */n = GetFullPathNameW (dirname, 0, NULL, NULL);
    #else/* WinRT */n = wcslen (dirname);
    #endif/* Allocate room for absolute directory name and search pattern */dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);if (dirp->patt == NULL) {goto exit_closedir;}/** Convert relative directory name to an absolute one.  This* allows rewinddir() to function correctly even when current* working directory is changed between opendir() and rewinddir().** Note that on WinRT there's no way to convert relative paths* into absolute paths, so just assume it is an absolute path.*/
    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)/* Desktop */n = GetFullPathNameW (dirname, n, dirp->patt, NULL);if (n <= 0) {goto exit_closedir;}
    #else/* WinRT */wcsncpy_s (dirp->patt, n+1, dirname, n);
    #endif/* Append search pattern \* to the directory name */p = dirp->patt + n;switch (p[-1]) {case '\\':case '/':case ':':/* Directory ends in path separator, e.g. c:\temp\ *//*NOP*/;break;default:/* Directory name doesn't end in path separator */*p++ = '\\';}*p++ = '*';*p = '\0';/* Open directory stream and retrieve the first entry */if (!dirent_first (dirp)) {goto exit_closedir;}/* Success */return dirp;/* Failure */
    exit_closedir:_wclosedir (dirp);return NULL;
    }/** Read next directory entry.** Returns pointer to static directory entry which may be overwritten by* subsequent calls to _wreaddir().*/
    static struct _wdirent*
    _wreaddir(_WDIR *dirp)
    {struct _wdirent *entry;/** Read directory entry to buffer.  We can safely ignore the return value* as entry will be set to NULL in case of error.*/(void) _wreaddir_r (dirp, &dirp->ent, &entry);/* Return pointer to statically allocated directory entry */return entry;
    }/** Read next directory entry.** Returns zero on success.  If end of directory stream is reached, then sets* result to NULL and returns zero.*/
    static int
    _wreaddir_r(_WDIR *dirp,struct _wdirent *entry,struct _wdirent **result)
    {WIN32_FIND_DATAW *datap;/* Read next directory entry */datap = dirent_next (dirp);if (datap) {size_t n;DWORD attr;/** Copy file name as wide-character string.  If the file name is too* long to fit in to the destination buffer, then truncate file name* to PATH_MAX characters and zero-terminate the buffer.*/n = 0;while (n < PATH_MAX  &&  datap->cFileName[n] != 0) {entry->d_name[n] = datap->cFileName[n];n++;}entry->d_name[n] = 0;/* Length of file name excluding zero terminator */entry->d_namlen = n;/* File type */attr = datap->dwFileAttributes;if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {entry->d_type = DT_CHR;} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {entry->d_type = DT_DIR;} else {entry->d_type = DT_REG;}/* Reset dummy fields */entry->d_ino = 0;entry->d_off = 0;entry->d_reclen = sizeof (struct _wdirent);/* Set result address */*result = entry;} else {/* Return NULL to indicate end of directory */*result = NULL;}return /*OK*/0;
    }/** Close directory stream opened by opendir() function.  This invalidates the* DIR structure as well as any directory entry read previously by* _wreaddir().*/
    static int
    _wclosedir(_WDIR *dirp)
    {int ok;if (dirp) {/* Release search handle */if (dirp->handle != INVALID_HANDLE_VALUE) {FindClose (dirp->handle);}/* Release search pattern */free (dirp->patt);/* Release directory structure */free (dirp);ok = /*success*/0;} else {/* Invalid directory stream */dirent_set_errno (EBADF);ok = /*failure*/-1;}return ok;
    }/** Rewind directory stream such that _wreaddir() returns the very first* file name again.*/
    static void
    _wrewinddir(_WDIR* dirp)
    {if (dirp) {/* Release existing search handle */if (dirp->handle != INVALID_HANDLE_VALUE) {FindClose (dirp->handle);}/* Open new search handle */dirent_first (dirp);}
    }/* Get first directory entry (internal) */
    static WIN32_FIND_DATAW*
    dirent_first(_WDIR *dirp)
    {WIN32_FIND_DATAW *datap;DWORD error;/* Open directory and retrieve the first entry */dirp->handle = FindFirstFileExW(dirp->patt, FindExInfoStandard, &dirp->data,FindExSearchNameMatch, NULL, 0);if (dirp->handle != INVALID_HANDLE_VALUE) {/* a directory entry is now waiting in memory */datap = &dirp->data;dirp->cached = 1;} else {/* Failed to open directory: no directory entry in memory */dirp->cached = 0;datap = NULL;/* Set error code */error = GetLastError ();switch (error) {case ERROR_ACCESS_DENIED:/* No read access to directory */dirent_set_errno (EACCES);break;case ERROR_DIRECTORY:/* Directory name is invalid */dirent_set_errno (ENOTDIR);break;case ERROR_PATH_NOT_FOUND:default:/* Cannot find the file */dirent_set_errno (ENOENT);}}return datap;
    }/** Get next directory entry (internal).** Returns*/
    static WIN32_FIND_DATAW*
    dirent_next(_WDIR *dirp)
    {WIN32_FIND_DATAW *p;/* Get next directory entry */if (dirp->cached != 0) {/* A valid directory entry already in memory */p = &dirp->data;dirp->cached = 0;} else if (dirp->handle != INVALID_HANDLE_VALUE) {/* Get the next directory entry from stream */if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {/* Got a file */p = &dirp->data;} else {/* The very last entry has been processed or an error occurred */FindClose (dirp->handle);dirp->handle = INVALID_HANDLE_VALUE;p = NULL;}} else {/* End of directory stream reached */p = NULL;}return p;
    }/** Open directory stream using plain old C-string.*/
    static DIR*
    opendir(const char *dirname)
    {struct DIR *dirp;/* Must have directory name */if (dirname == NULL  ||  dirname[0] == '\0') {dirent_set_errno (ENOENT);return NULL;}/* Allocate memory for DIR structure */dirp = (DIR*) malloc (sizeof (struct DIR));if (!dirp) {return NULL;}{int error;wchar_t wname[PATH_MAX + 1];size_t n;/* Convert directory name to wide-character string */error = dirent_mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);if (error) {/** Cannot convert file name to wide-character string.  This* occurs if the string contains invalid multi-byte sequences or* the output buffer is too small to contain the resulting* string.*/goto exit_free;}/* Open directory stream using wide-character name */dirp->wdirp = _wopendir (wname);if (!dirp->wdirp) {goto exit_free;}}/* Success */return dirp;/* Failure */
    exit_free:free (dirp);return NULL;
    }/** Read next directory entry.*/
    static struct dirent*
    readdir(DIR *dirp)
    {struct dirent *entry;/** Read directory entry to buffer.  We can safely ignore the return value* as entry will be set to NULL in case of error.*/(void) readdir_r (dirp, &dirp->ent, &entry);/* Return pointer to statically allocated directory entry */return entry;
    }/** Read next directory entry into called-allocated buffer.** Returns zero on success.  If the end of directory stream is reached, then* sets result to NULL and returns zero.*/
    static int
    readdir_r(DIR *dirp,struct dirent *entry,struct dirent **result)
    {WIN32_FIND_DATAW *datap;/* Read next directory entry */datap = dirent_next (dirp->wdirp);if (datap) {size_t n;int error;/* Attempt to convert file name to multi-byte string */error = dirent_wcstombs_s(&n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);/** If the file name cannot be represented by a multi-byte string,* then attempt to use old 8+3 file name.  This allows traditional* Unix-code to access some file names despite of unicode* characters, although file names may seem unfamiliar to the user.** Be ware that the code below cannot come up with a short file* name unless the file system provides one.  At least* VirtualBox shared folders fail to do this.*/if (error  &&  datap->cAlternateFileName[0] != '\0') {error = dirent_wcstombs_s(&n, entry->d_name, PATH_MAX + 1,datap->cAlternateFileName, PATH_MAX + 1);}if (!error) {DWORD attr;/* Length of file name excluding zero terminator */entry->d_namlen = n - 1;/* File attributes */attr = datap->dwFileAttributes;if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {entry->d_type = DT_CHR;} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {entry->d_type = DT_DIR;} else {entry->d_type = DT_REG;}/* Reset dummy fields */entry->d_ino = 0;entry->d_off = 0;entry->d_reclen = sizeof (struct dirent);} else {/** Cannot convert file name to multi-byte string so construct* an erroneous directory entry and return that.  Note that* we cannot return NULL as that would stop the processing* of directory entries completely.*/entry->d_name[0] = '?';entry->d_name[1] = '\0';entry->d_namlen = 1;entry->d_type = DT_UNKNOWN;entry->d_ino = 0;entry->d_off = -1;entry->d_reclen = 0;}/* Return pointer to directory entry */*result = entry;} else {/* No more directory entries */*result = NULL;}return /*OK*/0;
    }/** Close directory stream.*/
    static int
    closedir(DIR *dirp)
    {int ok;if (dirp) {/* Close wide-character directory stream */ok = _wclosedir (dirp->wdirp);dirp->wdirp = NULL;/* Release multi-byte character version */free (dirp);} else {/* Invalid directory stream */dirent_set_errno (EBADF);ok = /*failure*/-1;}return ok;
    }/** Rewind directory stream to beginning.*/
    static void
    rewinddir(DIR* dirp)
    {/* Rewind wide-character string directory stream */_wrewinddir (dirp->wdirp);
    }/** Scan directory for entries.*/
    static int
    scandir(const char *dirname,struct dirent ***namelist,int (*filter)(const struct dirent*),int (*compare)(const struct dirent**, const struct dirent**))
    {struct dirent **files = NULL;size_t size = 0;size_t allocated = 0;const size_t init_size = 1;DIR *dir = NULL;struct dirent *entry;struct dirent *tmp = NULL;size_t i;int result = 0;/* Open directory stream */dir = opendir (dirname);if (dir) {/* Read directory entries to memory */while (1) {/* Enlarge pointer table to make room for another pointer */if (size >= allocated) {void *p;size_t num_entries;/* Compute number of entries in the enlarged pointer table */if (size < init_size) {/* Allocate initial pointer table */num_entries = init_size;} else {/* Double the size */num_entries = size * 2;}/* Allocate first pointer table or enlarge existing table */p = realloc (files, sizeof (void*) * num_entries);if (p != NULL) {/* Got the memory */files = (dirent**) p;allocated = num_entries;} else {/* Out of memory */result = -1;break;}}/* Allocate room for temporary directory entry */if (tmp == NULL) {tmp = (struct dirent*) malloc (sizeof (struct dirent));if (tmp == NULL) {/* Cannot allocate temporary directory entry */result = -1;break;}}/* Read directory entry to temporary area */if (readdir_r (dir, tmp, &entry) == /*OK*/0) {/* Did we get an entry? */if (entry != NULL) {int pass;/* Determine whether to include the entry in result */if (filter) {/* Let the filter function decide */pass = filter (tmp);} else {/* No filter function, include everything */pass = 1;}if (pass) {/* Store the temporary entry to pointer table */files[size++] = tmp;tmp = NULL;/* Keep up with the number of files */result++;}} else {/** End of directory stream reached => sort entries and* exit.*/qsort (files, size, sizeof (void*),(int (*) (const void*, const void*)) compare);break;}} else {/* Error reading directory entry */result = /*Error*/ -1;break;}}} else {/* Cannot open directory */result = /*Error*/ -1;}/* Release temporary directory entry */free (tmp);/* Release allocated memory on error */if (result < 0) {for (i = 0; i < size; i++) {free (files[i]);}free (files);files = NULL;}/* Close directory stream */if (dir) {closedir (dir);}/* Pass pointer table to caller */if (namelist) {*namelist = files;}return result;
    }/* Alphabetical sorting */
    static int
    alphasort(const struct dirent **a, const struct dirent **b)
    {return strcoll ((*a)->d_name, (*b)->d_name);
    }/* Sort versions */
    static int
    versionsort(const struct dirent **a, const struct dirent **b)
    {/* FIXME: implement strverscmp and use that */return alphasort (a, b);
    }/* Convert multi-byte string to wide character string */
    static int
    dirent_mbstowcs_s(size_t *pReturnValue,wchar_t *wcstr,size_t sizeInWords,const char *mbstr,size_t count)
    {int error;#if defined(_MSC_VER)  &&  _MSC_VER >= 1400/* Microsoft Visual Studio 2005 or later */error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);#else/* Older Visual Studio or non-Microsoft compiler */size_t n;/* Convert to wide-character string (or count characters) */n = mbstowcs (wcstr, mbstr, sizeInWords);if (!wcstr  ||  n < count) {/* Zero-terminate output buffer */if (wcstr  &&  sizeInWords) {if (n >= sizeInWords) {n = sizeInWords - 1;}wcstr[n] = 0;}/* Length of resulting multi-byte string WITH zero terminator */if (pReturnValue) {*pReturnValue = n + 1;}/* Success */error = 0;} else {/* Could not convert string */error = 1;}#endifreturn error;
    }/* Convert wide-character string to multi-byte string */
    static int
    dirent_wcstombs_s(size_t *pReturnValue,char *mbstr,size_t sizeInBytes, /* max size of mbstr */const wchar_t *wcstr,size_t count)
    {int error;#if defined(_MSC_VER)  &&  _MSC_VER >= 1400/* Microsoft Visual Studio 2005 or later */error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);#else/* Older Visual Studio or non-Microsoft compiler */size_t n;/* Convert to multi-byte string (or count the number of bytes needed) */n = wcstombs (mbstr, wcstr, sizeInBytes);if (!mbstr  ||  n < count) {/* Zero-terminate output buffer */if (mbstr  &&  sizeInBytes) {if (n >= sizeInBytes) {n = sizeInBytes - 1;}mbstr[n] = '\0';}/* Length of resulting multi-bytes string WITH zero-terminator */if (pReturnValue) {*pReturnValue = n + 1;}/* Success */error = 0;} else {/* Cannot convert string */error = 1;}#endifreturn error;
    }/* Set errno variable */
    static void
    dirent_set_errno(int error)
    {
    #if defined(_MSC_VER)  &&  _MSC_VER >= 1400/* Microsoft Visual Studio 2005 and later */_set_errno (error);#else/* Non-Microsoft compiler or older Microsoft compiler */errno = error;#endif
    }#ifdef __cplusplus
    }
    #endif
    #endif /*DIRENT_H*/
  • 注意以上写死了模型路径为 ./model/best.onnx,数据配置文件路径为 ./cfg/plane.yaml,测试图像放在 ./images 路径下。将这些资源放到编译后生成的 C:\Users…\YOLOv8-Test\Test\x64\Release(或Debug) 目录下
    在这里插入图片描述
    现在双击 Test.exe 就能看到 YOLOv8 的识别结果了

  • 最后的问题是,如果在 vscode 里点击运行,还是会报错找不到资源,这是因为工作目录还在根目录,修改属性页->调试 -> 工作目录为 $(OutDir) 即可
    在这里插入图片描述

相关文章:

VS2015 + OpenCV + OnnxRuntime-Cpp + YOLOv8 部署

近期有个工作需求是进行 YOLOv8 模型的 C 部署&#xff0c;部署环境如下 系统&#xff1a;WindowsIDE&#xff1a;VS2015语言&#xff1a;COpenCV 4.5.0OnnxRuntime 1.15.1 0. 预训练模型保存为 .onnx 格式 假设已经有使用 ultralytics 库训练并保存为 .pt 格式的 YOLOv8 模型…...

1.两数之和--力扣

给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你可以按任意顺序返回答案。 示例 1…...

MySQL库表的操作

目录 一、库的操作 1.1库的创建 1.2字符集和校验规则 1.2.1 查看系统默认字符集以及校验规则 1.2.2 查看数据库支持的字符集 1.2.3 查看数据库支持的字符集校验规则 1.2.4 校验规则对数据库的影响 1.3操纵数据库 1.3.1显示库 1.3.2显示创建语句 1.3.3修改数据库 1.3…...

【强化学习】深度确定性策略梯度算法(DDPG)详解(附代码)

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…...

单片机实物成品-011 火灾监测

火灾监测&#xff08;20个版本&#xff09; 版本20&#xff1a; oled显示温湿度烟雾浓度火焰传感器天然气浓度窗户风扇水泵排气系统声光报警语音播报按键WIFI模块 ----------------------------------------------------------------------------- https://www.bilibili.com…...

牛客网刷题 ——C语言初阶(6指针)——BC106 上三角矩阵判定

1. 题目描述——BC106 上三角矩阵判定 牛客网OJ题链接 描述 KiKi想知道一个n阶方矩是否为上三角矩阵&#xff0c;请帮他编程判定。上三角矩阵即主对角线以下的元素都为0的矩阵&#xff0c;主对角线为从矩阵的左上角至右下角的连线。 示例 输入&#xff1a; 3 1 2 3 0 4 5 0 0…...

Mysql--重点篇--索引(索引分类,Hash和B-tree索引,聚簇和非聚簇索引,回表查询,覆盖索引,索引工作原理,索引失效,索引创建原则等)

索引是数据库中用于加速查询操作的重要机制。通过索引&#xff0c;MySQL可以快速定位到满足查询条件的数据行&#xff0c;而不需要扫描整个表。合理的索引设计可以显著提高查询性能&#xff0c;但不合理的索引可能会导致性能下降和磁盘空间浪费。因此&#xff0c;理解索引的工作…...

Vue3框架核心功能点响应式数据reactive、组合式API setup、computed、组件通信、路由导航,状态管理vuex、pinia等的实战示例代码

记录几个Vue3框架核心功能点&#xff0c;例如响应式数据reactive、组合式API setup、computed、组件通信、路由导航&#xff0c;状态管理vuex、pinia……等实战示例代码&#xff1a; 一、响应式数据&#xff08;Reactive Data&#xff09; 创建响应式对象 使用reactive函数创建…...

Gitlab-Runner配置

原理 Gitlab-Runner是一个非常强大的CI/CD工具。它可以帮助我们自动化执行各种任务&#xff0c;如构建、测试和部署等。Gitlab-Runner和Gitlab通过API通信&#xff0c;接收作业并提交到执行队列&#xff0c;Gitlab-Runner从队列中获取作业&#xff0c;并允许在不同环境下进行作…...

多台PC共用同一套鼠标键盘

当环境中有多个桌面 pc 需要操作的时候&#xff0c;在 多台 pc 之间切换会造成很多的不方便 可以通过远程进行连接&#xff0c;但是有一个更好的方案是让多台机器之间共用同一套键盘鼠标 常用的解决方案 synergy 和 sharemouse&#xff0c;通过移动光标在不同的 pc 间切换 s…...

学会使用computed计算属性与watch监听(小白学习笔记)

1. 使用不同方法实现 姓名案例 需求: 根据data中 firstName 和 lastName 的值 来动态地展示全名 1.1. 插值语法 如果只使用学过的插值语法 那可以在模板中直接使用两个变量 . 但是如果需要对数据进行计算等处理 就需要在插值语法里写复杂的js表达式. 这样就违背了vue风格指…...

atoi函数的概念和使用案例

atoi 函数是 C 语言标准库中的一个函数&#xff0c;它用于将字符串转换为整数。atoi 的名称是 “ASCII to integer” 的缩写。该函数定义在 <stdlib.h> 头文件中。 概念 atoi 函数会从字符串的开始位置开始转换&#xff0c;直到遇到第一个非数字字符或遇到字符串结束符…...

unittest VS pytest

以下是 unittest 和 pytest 框架的对比表格&#xff1a; 特性unittestpytest设计理念基于类的设计&#xff0c;类似于 Java 的 JUnit更简洁&#xff0c;基于函数式编程设计&#xff0c;支持类和函数两种方式测试编写需要继承 unittest.TestCase 类&#xff0c;方法以 test_ 开…...

B2C API安全警示:爬虫之外,潜藏更大风险挑战

在数字化时代&#xff0c;B2C&#xff08;Business-to-Consumer&#xff09;电子商务模式已成为企业连接消费者、推动业务增长的重要桥梁。而B2C API&#xff08;应用程序编程接口&#xff09;作为企业与消费者之间数据交互的桥梁&#xff0c;其安全性更是至关重要。然而&#…...

大型语言模型(LLM)中的tokens是什么

大型语言模型(LLM)中的tokens是什么 在大型语言模型(LLM)中,tokens是文本处理的基本单位,它可以是一个单词、一个字符、一个标点符号,或者是一个特殊的标记。以下是关于tokens的详细介绍及举例: 一、tokens的定义和作用 定义:tokens是将文本分割成的一个个有意义的…...

自动驾驶---E2E架构演进

1 背景 模型最早应用的自动驾驶模块就是感知层面&#xff0c;随着技术的发展&#xff0c;逐渐开始应用到决策规划等其它模块。端到端自动驾驶架构是一种基于深层神经网络模型和方法的自动驾驶技术模式。目前一段式端到端系统只有在英伟达早期所做的demo中实现&#xff0c;再者就…...

w~自动驾驶~合集16

我自己的原文哦~ https://blog.51cto.com/whaosoft/12765612 #SIMPL 用于自动驾驶的简单高效的多智能体运动预测基准 原标题&#xff1a;SIMPL: A Simple and Efficient Multi-agent Motion Prediction Baseline for Autonomous Driving 论文链接&#xff1a;https://ar…...

python学opencv|读取图像(三十)使用cv2.getAffineTransform()函数倾斜拉伸图像

【1】引言 前序已经学习了如何平移和旋转缩放图像&#xff0c;相关文章链接为&#xff1a; python学opencv|读取图像&#xff08;二十七&#xff09;使用cv2.warpAffine&#xff08;&#xff09;函数平移图像-CSDN博客 python学opencv|读取图像&#xff08;二十八&#xff0…...

Java异常处理

1.异常是程序运行过程中出现的非正常现象&#xff0c;例如输入错误、需要处理的文件不存在&#xff0c;在网络上传输数据但是网络没有连接等2.在java中我们把异常分为&#xff1a;错误&#xff08;Error&#xff09;和异常&#xff08;Exception&#xff09;Exception类有自己的…...

STM32-DMA数据转运

注&#xff1a;DMA对应的库函数文件讲解 DMA_GetITStatus(uint32_t DMAy_IT) 是一个用于检查DMA&#xff08;直接存储器访问&#xff09;中断状态的库函数。它通常在使用STM32系列微控制器及其标准外设库时被调用。此函数的主要作用是返回指定DMA通道的特定中断标志的状态&…...

ASP.NET Core 实现微服务 - Elastic APM

这次要给大家介绍的是Elastic APM &#xff0c;一款应用程序性能监控组件。APM 监控围绕对应用、服务、容器的健康监控&#xff0c;对接口的调用链、性能进行监控。在我们实施微服务后&#xff0c;由于复杂的业务逻辑&#xff0c;服务之间的调用会像蜘蛛网一样复杂。有了调用链…...

Stable Diffusion本地部署教程(附安装包)

想使用Stable Diffusion需要的环境有哪些呢? python3.10.11(至少也得3.10.6以上):依赖python环境NVIDIA:GPUgit:从github上下载包(可选,由于我已提供安装包,你可以不用git)Stable Diffusion安装包工具包: NVIDIA:https://developer.nvidia.com/cuda-toolkit-archiv…...

图片和短信验证码(头条项目-06)

1 图形验证码接口设计 将后端⽣成的图⽚验证码存储在redis数据库2号库。 结构&#xff1a; {img_uuid:0594} 1.1 创建验证码⼦应⽤ $ cd apps $ python ../../manage.py startapp verifications # 注册新应⽤ INSTALLED_APPS [django.contrib.admin,django.contrib.auth,…...

天气app的收获

天气app的收获 无论如何&#xff0c;是基于MVC模式&#xff0c;但都是从UI页面开始设计&#xff0c;然后根据输入的城市名称&#xff0c;将其传入到model层&#xff0c;进行相对应的处理。 对于controler层&#xff0c;需要通过一些协议完成一些输入的反馈&#xff0c;例如输…...

软件自动定时启动器

点击添加软件&#xff0c;可以添加可执行文件软件&#xff0c;设置启动的时间&#xff0c;也可以设置关闭的时间 注意&#xff0c;时间为00&#xff1a;00&#xff1a;00 等于没设置&#xff0c;这个时间不在设置范围&#xff0c;其他任何时间都可以 1.1更新 1&#xff1a;修复…...

k8s部署rocketmq踩坑笔记

给团队部署一个rocketmq4.8.0. k8s上部署的broker&#xff0c;注册到nameserver上是自己的pod ip&#xff0c;导致本机连接到的broker的pod ip&#xff0c;这个ip k8s集群外的机器是无法联通的。 nameserver上注册的是这个pod ipv4 尝试将broker的配置brokerIP1修改为注册到na…...

从项目代码看 React:State 和 Props 的区别及应用场景实例讲解

在 React 中&#xff0c;state 和 props 是组件的两个重要概念&#xff0c;它们有不同的作用和应用场景。理解它们之间的区别对于开发 React 应用至关重要。 1. state 和 props 的区别 props (属性)&#xff1a; props 是由父组件传递给子组件的数据或函数。props 是只读的&am…...

深度学习中的优化算法

深度学习中的优化算法&#xff0c;是模型训练期间微调神经网络参数的关键元素。其主要作用是最小化模型的误差或损失&#xff0c;从而提高性能。各种优化算法(称为优化器)采用不同的策略来收敛到最佳参数值&#xff0c;从而有效地提高预测效果。 在深度学习的背景下&#xff0c…...

python3GUI--大屏可视化-传染病督导平台 By:PyQt5

文章目录 一&#xff0e;前言二&#xff0e;预览三&#xff0e;软件组成&开发心得1.样式&使用方法2.左侧表格实现3.设计4.学习5.体验效果 四&#xff0e;代码分享1.环形渐变进度组件2.自定义图片的背景组件 五&#xff0e;总结 大小&#xff1a;60.9 M&#xff0c;软件…...

设计模式——单例模式

单例模式 实现单例模式的方法前置条件懒汉式&#xff08;Lazy Initialization&#xff09;饿汉式&#xff08;Eager Initialization&#xff09;双重锁式&#xff08;Double-Checked Locking&#xff09;静态内部类式&#xff08;Static Inner Class&#xff09;枚举式&#xf…...

【01】AE特效开发制作特技-Adobe After Effects-AE特效制作快速入门-制作飞机,子弹,爆炸特效以及导出png序列图-优雅草央千澈

【01】AE特效开发制作特技-Adobe After Effects-AE特效制作快速入门-制作飞机&#xff0c;子弹&#xff0c;爆炸特效以及导出png序列图-优雅草央千澈 开发背景 优雅草央千澈所有的合集&#xff0c;系列文章可能是不太适合完全初学者的&#xff0c;因为课程不会非常细致的系统…...

docker一键安装脚本(docker安装)

第一种方法一键安装命令 curl -O --url http://luyuanbo79.south.takin.cc/wenjian/docker_install.sh && chmod x docker_install.sh && ./docker_install.sh 备用方法 curl -O --url https://file.gitcode.com/4555247/releases/untagger_0896d4789937405…...

Python的Matplotlib库应用(超详细教程)

目录 一、环境搭建 1.1 配置matplotlib库 1.2 配置seaborn库 1.3 配置Skimage库 二、二维图像 2.1 曲线&#xff08;直线&#xff09;可视化 2.2 曲线&#xff08;虚线&#xff09;可视化 2.3 直方图 2.4 阶梯图 三、三维图像 3.1 3D曲面图 3.2 3D散点图 3.3 3D散…...

VS Code的设置功能以及多层级的设置方式与解密

VS Code的Settings功能为用户提供了极大的灵活性和便利性&#xff0c;使得用户可以根据自己的需求和偏好来定制编辑器的行为和外观。 Settings 可以实现的具体功能 VS Code的设置项非常丰富&#xff0c;涵盖了各个方面&#xff0c;包括但不限于&#xff1a; 编辑器选项&…...

怎么理解编码器与解码器?

编码器和解码器是在信息处理、通信、多媒体等众多领域中广泛应用的两个概念&#xff0c;它们的作用相反但又紧密相关。下面从多个角度来帮助你理解这两个概念&#xff1a; 定义 编码器&#xff1a;编码器是一种将输入信息&#xff08;如模拟信号、文本、图像、声音等&#xf…...

关于智能个人生活助手的一些想法

我感觉未来计算机发展 会变成钢铁侠的贾维斯那样, 每个人有自己的系统 集成ai和其他功能 助力生活和工作 说一下我为什么有这样的想法: 1.ai发展迅猛: 近些年来ai的发展势头越来越猛,不断破圈,越来越多的人了解到ai的强大,并使用ai改变了自己原有的生活或工作方式,熟练使用…...

FFmpeg音视频流媒体,视频编解码性能优化

你是不是也有过这样一个疑问&#xff1a;视频如何从一个简单的文件变成你手机上快速播放的短片&#xff0c;或者是那种占满大屏幕的超高清大片&#xff1f;它背后的法宝&#xff0c;离不开一个神奇的工具——FFmpeg&#xff01;说它强大&#xff0c;完全不为过&#xff0c;它在…...

页面滚动下拉时,元素变为fixed浮动,上拉到顶部时恢复原状,js代码以视频示例

页面滚动下拉时,元素变为fixed浮动js代码 以视频示例 <style>video{width:100%;height:auto}.div2,#float1{position:fixed;_position:absolute;top:45px;right:0; z-index:250;}button{float:right;display:block;margin:5px} </style><section id"abou…...

Python玩转视频剪辑 - Opencv、Moviepy(附完整案例)

1. 准备工作 1.1 安装Opencv-python、Moviepy pip install opencv-python pip install moviepy 1.2 视频剪辑目标 如图&#xff0c;作者从b站下载了两个视频(仅做代码测试用&#xff0c;不作转载等任何商业用途)&#xff0c;一个是刘初寻的疏远&#xff08;以下简称视频一&a…...

Pulsar客户端如何控制内存使用

Pulsar客户端如何控制内存使用 一、使用场景 在实际应用中&#xff0c;Pulsar客户端的内存使用控制是一个重要的性能优化点。假设有一个搜索类业务需要记录用户搜索请求&#xff0c;以便后续分析搜索热点和优化搜索效果。以下是一个简化的代码示例&#xff1a; PulsarClient…...

接口测试总结(http与rpc)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传…...

Linux:进程概念(二.查看进程、父进程与子进程、进程状态详解)

目录 1. 查看进程 1.1 准备工作 1.2 指令&#xff1a;ps—显示当前系统中运行的进程信息 1.3 查看进程属性 1.4 通过 /proc 系统文件夹看进程 2. 父进程与子进程 2.1 介绍 2.2 getpid() \getppid() 2.3 fork()函数—通过系统调用创建进程 fork()函数疑问 3. 进程状态…...

ubuntu22.04 编译安装libvirt 10.x

环境安装 sudo apt-get update -y sudo apt-get install qemu-system-x86 bridge-utils libyajl-dev -y sudo apt-get install build-essential autoconf automake libtool -y sudo apt-get install libxml2-dev libxslt1-dev libgnutls28-dev libpciaccess-dev libnl-3-de…...

Ubuntu 下载安装 Consul1.17.1

下载 来到 Consul 的下载页面&#xff1a;https://developer.hashicorp.com/consul/install?product_intentconsul 上面标注的地方可以切换你想要的版本&#xff0c;复制下载链接&#xff0c;使用 wget 下载这个文件&#xff1a; wget https://releases.hashicorp.com/consu…...

怎么实现Redis的高可用?

大家好&#xff0c;我是锋哥。今天分享关于【怎么实现Redis的高可用&#xff1f;】面试题。希望对大家有帮助&#xff1b; 怎么实现Redis的高可用&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 为了实现 Redis 的高可用性&#xff0c;我们需要保证在发…...

Domain Adaptation(李宏毅)机器学习 2023 Spring HW11 (Boss Baseline)

1. 领域适配简介 领域适配是一种迁移学习方法,适用于源领域和目标领域数据分布不同但学习任务相同的情况。具体而言,我们在源领域(通常有大量标注数据)训练一个模型,并希望将其应用于目标领域(通常只有少量或没有标注数据)。然而,由于这两个领域的数据分布不同,模型在…...

Chatper 4: mplementing a GPT model from Scratch To Generate Text

4 Implementing a GPT model from Scratch To Generate Text 本章节包含 编写一个类似于GPT的大型语言模型&#xff08;LLM&#xff09;&#xff0c;这个模型可以被训练来生成类似人类的文本。Normalizing layer activations to stabilize neural network training在深度神经网…...

websocket股票行情接口

股票行情区别 交易所出来的数据&#xff0c;不管通过什么渠道&#xff0c;延时一般都不会差太远&#xff0c;估计一般也就几十ms的差别。 但是如果是通过http轮询&#xff0c;不太可能几十ms全部轮询一次。所以&#xff0c;做量化的话&#xff0c;用http协议是最次的选择。 …...

一键部署Netdata系统无需公网IP轻松实现本地服务器的可视化监控

文章目录 前言1.关于Netdata2.本地部署Netdata3.使用Netdata4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定Netdata公网地址 &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。…...

概率图模型01

机器学习中&#xff0c;线性回归、树、集成和概率图都属于典型的统计学习方法&#xff0c;概率图模型会更深入地体现出‘统计’两字 概率图模型的常见算法 概率图模型中的图 概率图模型如图主要分为两种&#xff0c;即贝叶斯网络和马尔可夫网络&#xff0c;有向图与无向图&…...