jetson AGC orin 配置pytorch和cuda使用、yolov8 TensorRt测试

文章目录

  • 1、安装环境
    • 1.1、检查系统环境
    • 1.2、下载安装pytorch
    • 1.3、下载安装torchvision
    • 1.3、测试安装是否成功
  • 2、yolov8测试
    • 2.1、官方python脚本测试
    • 2.2、tensorrt 模型转换
    • 2.3、tensorrt c++ 测试

1、安装环境

1.1、检查系统环境

检查系统环境、安装jetpack版本,执行 cat /etc/nv_tegra_release sudo apt-cache show nvidia-jetpack 查看。

$  cat /etc/nv_tegra_release
# R35 (release), REVISION: 4.1, GCID: 33958178, BOARD: t186ref, EABI: aarch64, DATE: Tue Aug  1 19:57:35 UTC 2023$ sudo apt-cache show nvidia-jetpack
Package: nvidia-jetpack
Version: 5.1.2-b104
Architecture: arm64
Maintainer: NVIDIA Corporation
Installed-Size: 194
Depends: nvidia-jetpack-runtime (= 5.1.2-b104), nvidia-jetpack-dev (= 5.1.2-b104)
Homepage: http://developer.nvidia.com/jetson
Priority: standard
Section: metapackages
Filename: pool/main/n/nvidia-jetpack/nvidia-jetpack_5.1.2-b104_arm64.deb
Size: 29304
SHA256: fda2eed24747319ccd9fee9a8548c0e5dd52812363877ebe90e223b5a6e7e827
SHA1: 78c7d9e02490f96f8fbd5a091c8bef280b03ae84
MD5sum: 6be522b5542ab2af5dcf62837b34a5f0
Description: NVIDIA Jetpack Meta Package
Description-md5: ad1462289bdbc54909ae109d1d32c0a8

1.2、下载安装pytorch

根据官网提供链接安装适配的 pytorch-gpu版本(cpu直接pip install pytorch即可)。例如本机使用的 jetpack 5.1.2,选择安装 PyTorch v2.1.0 版本即可。
在这里插入图片描述
下载 whl 文件,之后pip install 即可。

$ wget https://developer.download.nvidia.cn/compute/redist/jp/v512/pytorch/torch-2.1.0a0+41361538.nv23.06-cp38-cp38-linux_aarch64.whl$ pip install torch-2.1.0a0+41361538.nv23.06-cp38-cp38-linux_aarch64.whl

安装后,在python中执行

import torch

可能出现的错误,和解决办法

  • ImportError: libopenblas.so.0: cannot open shared object file: No such file or directory
    sudo apt-get install libopenblas-base
    

1.3、下载安装torchvision

需要便于安装对应版本torchvision,查看 官网链接 ,要求PyTorch v2.1.0 安装 0.16 版本
在这里插入图片描述
这里选择 0.16.1 版本,下载指定源码进行编译安装


$ git clone --branch v0.16.1 https://github.com/pytorch/vision torchvision`
$ export BUILD_VERSION=0.16.1
$ python setup.py install --user

编译中出现依赖,根据情况安装

# sudo apt-get install libjpeg-dev zlib1g-dev libpython3-dev libopenblas-dev libavcodec-dev libavformat-dev libswscale-dev

编译后验证,

import torchvision

可能的错误,

  • /home/hard_disk/downloads/torchvision/torchvision/io/image.py:13: UserWarning: Failed to load image Python extension: ''If you don’t plan on using image functionality from torchvision.io, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have libjpeg or libpng installed before building torchvision from source?

    安装 sudo apt-get install libjpeg-dev zlib1g-dev 之后,删除所有缓存和编译零时文件,再重新编译安装即可。

1.3、测试安装是否成功

测试安装是否成功,

>>> import torch
>>> print(torch.__version__)
>>> print('CUDA available: ' + str(torch.cuda.is_available()))
>>> print('cuDNN version: ' + str(torch.backends.cudnn.version()))
>>> a = torch.cuda.FloatTensor(2).zero_()
>>> print('Tensor a = ' + str(a))
>>> b = torch.randn(2).cuda()
>>> print('Tensor b = ' + str(b))
>>> c = a + b
>>> print('Tensor c = ' + str(c))>>> import torchvision
>>> print(torchvision.__version__)

若均不报错,且能正常输出说明安装成功,如下图
在这里插入图片描述

2、yolov8测试

使用yolov8m.pt进行测试

2.1、官方python脚本测试

$ yolo predict model=yolov8m.pt source=bus.jpg device=cpu
Ultralytics YOLOv8.0.227 🚀 Python-3.8.18 torch-2.1.0a0+41361538.nv23.06 CPU (ARMv8 Processor rev 1 (v8l))
YOLOv8m summary (fused): 218 layers, 25886080 parameters, 0 gradients, 78.9 GFLOPsimage 1/1 /home/hard_disk/projects/yolov8-ultralytics/bus.jpg: 640x480 4 persons, 1 bus, 1492.5ms
Speed: 12.5ms preprocess, 1492.5ms inference, 9.3ms postprocess per image at shape (1, 3, 640, 480)

使用cpu推理耗时1.5s,gpu耗时0.35s。

s$ yolo predict model=yolov8m.pt source=bus.jpg device=0
Ultralytics YOLOv8.0.227 🚀 Python-3.8.18 torch-2.1.0a0+41361538.nv23.06 CUDA:0 (Orin, 30593MiB)
YOLOv8m summary (fused): 218 layers, 25886080 parameters, 0 gradients, 78.9 GFLOPsimage 1/1 /home/hard_disk/projects/yolov8-ultralytics/bus.jpg: 640x480 4 persons, 1 bus, 349.9ms
Speed: 8.7ms preprocess, 349.9ms inference, 6.8ms postprocess per image at shape (1, 3, 640, 480)

由于gpu推理通常需要预热,拷贝图像(bus.jpg)到文件夹重复多张(以10张为例)即可,重新运行,基本推理耗时28ms

$ yolo predict model=yolov8m.pt source=imgs device=0
Ultralytics YOLOv8.0.227 🚀 Python-3.8.18 torch-2.1.0a0+41361538.nv23.06 CUDA:0 (Orin, 30593MiB)
YOLOv8m summary (fused): 218 layers, 25886080 parameters, 0 gradients, 78.9 GFLOPsimage 1/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus.jpg: 640x480 4 persons, 1 bus, 341.4ms
image 2/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_1.jpg: 640x480 4 persons, 1 bus, 43.2ms
image 3/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_2.jpg: 640x480 4 persons, 1 bus, 37.2ms
image 4/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_3.jpg: 640x480 4 persons, 1 bus, 28.5ms
image 5/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_4.jpg: 640x480 4 persons, 1 bus, 31.1ms
image 6/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_5.jpg: 640x480 4 persons, 1 bus, 28.4ms
image 7/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_6.jpg: 640x480 4 persons, 1 bus, 28.3ms
image 8/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_7.jpg: 640x480 4 persons, 1 bus, 28.8ms
image 9/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_8.jpg: 640x480 4 persons, 1 bus, 28.3ms
image 10/10 /home/hard_disk/projects/yolov8-ultralytics/imgs/bus_9.jpg: 640x480 4 persons, 1 bus, 28.5ms
Speed: 7.9ms preprocess, 62.4ms inference, 5.0ms postprocess per image at shape (1, 3, 640, 480)

2.2、tensorrt 模型转换

默认安装在系统环境中,若在虚拟环境中,可以创建软连接到虚拟环境中

sudo ln -s /usr/lib/python3.8/dist-packages/tensorrt* /home/hard_disk/miniconda3/envs/yolo_pytorch/lib/python3.8/site-packages/
# 验证安装 输出 8.5.2.2
python -c "import tensorrt;  print(tensorrt.__version__);"

使用/usr/src/tensorrt/bin/trtexec --onnx=yolov8m.onnx --saveEngine=yolov8m.onnx.trt导出默认的fp32模型,耗时11分钟,40qps,加载测试如下
在这里插入图片描述
使用半精度浮点进行模型转换测试/usr/src/tensorrt/bin/trtexec --onnx=yolov8m.onnx --saveEngine=yolov8m.onnx.trt --fp16,执行耗时32分钟(模型文件大小缩小一半),95qps,,如下
在这里插入图片描述

2.3、tensorrt c++ 测试

先给出 cmake 文件

cmake_minimum_required(VERSION 3.0)
project(yolov8)#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")# opencv
find_package(OpenCV 4.5.4 REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})include_directories("/usr/local/cuda-11.4/include")
link_directories("/usr/local/cuda-11.4/lib64")# tensorrt
include_directories("/usr/include/aarch64-linux-gnu")
link_directories("/usr/lib/aarch64-linux-gnu")# target and lib
add_executable(${PROJECT_NAME} main.cpp)target_link_libraries(${PROJECT_NAME}  ${OpenCV_LIBS}  nvinfernvparserscudartcublascudnn
)

直接给出完整cpp代码

#include "opencv2/opencv.hpp"#include "NvInfer.h"
#include <cuda_runtime_api.h>
#include <random>#include <fstream>
#include <string>#define CHECK(status)                                                                      \do                                                                                     \{                                                                                      \auto ret = (status);                                                               \if (ret != 0)                                                                      \{                                                                                  \std::cerr << "Cuda failure: " << ret << std::endl;                             \abort();                                                                       \}                                                                                  \} while (0)class Logger : public nvinfer1::ILogger
{
public:Logger(Severity severity = Severity::kWARNING) : severity_(severity) {}virtual void log(Severity severity, const char* msg) noexcept override{// suppress info-level messagesif(severity <= severity_)std::cout << msg << std::endl;}nvinfer1::ILogger& getTRTLogger() noexcept{return *this;}
private:Severity severity_;
};struct InferDeleter
{template <typename T>void operator()(T* obj) const{delete obj;}
};template <typename T>
using SampleUniquePtr = std::unique_ptr<T, InferDeleter>;//int build();
int inference();int main(int argc, char** argv)
{return inference();
}void drawPred(int classId, float conf, int left, int top, int right, int bottom, cv::Mat& frame);
void postprocess(cv::Mat& frame, const cv::Mat outs);auto confThreshold = 0.25f;
auto scoreThreshold = 0.45f;
auto nmsThreshold = 0.5f;
auto inpWidth = 640.f;
auto inpHeight = 640.f;
auto classesSize = 80;#include <numeric>
#include <opencv2/dnn.hpp>int inference()
{Logger logger(nvinfer1::ILogger::Severity::kVERBOSE);/*trtexec.exe --onnx=yolov8m.onnx --explicitBatch --fp16 --saveEngine=model.trt*/std::string trtFile = R"(E:\DeepLearning\yolov8-ultralytics/yolov8m.onnx.trt)";//std::string trtFile = "model.test.trt";std::ifstream ifs(trtFile, std::ifstream::binary);if(!ifs) {return false;}ifs.seekg(0, std::ios_base::end);int size = ifs.tellg();ifs.seekg(0, std::ios_base::beg);std::unique_ptr<char> pData(new char[size]);ifs.read(pData.get(), size);ifs.close();// engine模型std::shared_ptr<nvinfer1::ICudaEngine> mEngine;{SampleUniquePtr<nvinfer1::IRuntime> runtime{nvinfer1::createInferRuntime(logger.getTRTLogger())};mEngine = std::shared_ptr<nvinfer1::ICudaEngine>(runtime->deserializeCudaEngine(pData.get(), size), InferDeleter());}auto context = SampleUniquePtr<nvinfer1::IExecutionContext>(mEngine->createExecutionContext());// 显存分配std::vector<void*> bindings(mEngine->getNbBindings());//auto t1 = mEngine->getBindingDataType(0);//auto t2 = mEngine->getBindingDataType(1);//CHECK(cudaMalloc(&bindings[0], sizeof(float) * 1 * 3 * 640 * 640)); // type: float32[1,3,640,640]//CHECK(cudaMalloc(&bindings[1], sizeof(int) * 1 * 84 * 8400));   // type: float32[1,84,8400]for(int i = 0; i < bindings.size(); i++) {nvinfer1::DataType type = mEngine->getBindingDataType(i);nvinfer1::Dims dims = mEngine->getBindingDimensions(i);size_t volume = std::accumulate(dims.d, dims.d + dims.nbDims, 1, std::multiplies<size_t>());switch(type) {case nvinfer1::DataType::kINT32:case nvinfer1::DataType::kFLOAT: volume *= 4; break;  // 明确为类型 floatcase nvinfer1::DataType::kHALF: volume *= 2; break;case nvinfer1::DataType::kBOOL:case nvinfer1::DataType::kINT8:default:break;}CHECK(cudaMalloc(&bindings[i], volume));}// 输入cv::Mat img = cv::imread(R"(E:\DeepLearning\yolov5\data\images\bus.jpg)");cv::Mat blob = cv::dnn::blobFromImage(img, 1 / 255., cv::Size(inpWidth,inpHeight), {0,0,0}, true, false);//blob = blob * 2 - 1;cv::Mat pred(cv::Size(8400, 84), CV_32F, {255,255,255});// 推理CHECK(cudaMemcpy(bindings[0], static_cast<const void*>(blob.data), 1 * 3 * 640 * 640 * sizeof(float), cudaMemcpyHostToDevice));context->executeV2(bindings.data());context->executeV2(bindings.data());context->executeV2(bindings.data());context->executeV2(bindings.data());CHECK(cudaMemcpy(static_cast<void*>(pred.data), bindings[1], 1 * 84 * 8400 * sizeof(int), cudaMemcpyDeviceToHost));auto t1 = cv::getTickCount();CHECK(cudaMemcpy(bindings[0], static_cast<const void*>(blob.data), 1 * 3 * 640 * 640 * sizeof(float), cudaMemcpyHostToDevice));context->executeV2(bindings.data());CHECK(cudaMemcpy(static_cast<void*>(pred.data), bindings[1], 1 * 84 * 8400 * sizeof(int), cudaMemcpyDeviceToHost));auto t2 = cv::getTickCount();std::string label = cv::format("inference time: %.2f ms", (t2 - t1) / cv::getTickFrequency() * 1000);std::cout << label << std::endl;cv::putText(img, label, cv::Point(10, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0));// 后处理cv::Mat tmp = pred.t();postprocess(img, tmp);cv::imshow("res",img);cv::waitKey();// 资源释放cudaFree(bindings[0]);cudaFree(bindings[1]);return 0;
}void postprocess(cv::Mat& frame, const cv::Mat tmp)
{using namespace cv;using namespace cv::dnn;// yolov8 has an output of shape (batchSize, 84, 8400) (box[x,y,w,h] + confidence[c])auto tt1 = cv::getTickCount();auto inputSz = frame.size();float x_factor = inputSz.width / inpWidth;float y_factor = inputSz.height / inpHeight;std::vector<int> class_ids;std::vector<float> confidences;std::vector<cv::Rect> boxes;float* data = (float*)tmp.data;for(int i = 0; i < tmp.rows; ++i) {//float confidence = data[4];//if(confidence >= confThreshold) {float* classes_scores = data + 4;cv::Mat scores(1, classesSize, CV_32FC1, classes_scores);cv::Point class_id;double max_class_score;minMaxLoc(scores, 0, &max_class_score, 0, &class_id);if(max_class_score > scoreThreshold) {confidences.push_back(max_class_score);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 += tmp.cols;}std::vector<int> indices;NMSBoxes(boxes, confidences, scoreThreshold, nmsThreshold, indices);auto tt2 = cv::getTickCount();std::string label = format("postprocess time: %.2f ms", (tt2 - tt1) / cv::getTickFrequency() * 1000);cv::putText(frame, label, Point(10, 30), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));for(size_t i = 0; i < indices.size(); ++i) {int idx = indices[i];Rect box = boxes[idx];drawPred(class_ids[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)
{using namespace cv;rectangle(frame, Point(left, top), Point(right, bottom), Scalar(0, 255, 0));std::string label = format("%d: %.2f", classId, conf);Scalar color(rand(), rand(), rand());int baseLine;Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);top = max(top, labelSize.height);rectangle(frame, Point(left, top - labelSize.height),Point(left + labelSize.width, top + baseLine), color, FILLED);cv::putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.5, Scalar());
}

运行命令行截图如
在这里插入图片描述

前向推理耗时12.68ms,NMS耗时2.7ms,检测结果显示如下

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux操作系统基础(12):Linux的Shell解释器

1. Shell的介绍 在Linux中&#xff0c;Shell 是一种命令行解释器&#xff0c;它是用户与操作系统内核之间的接口&#xff0c;它负责解释用户输入的命令&#xff0c;并将其转换成系统调用或其他操作系统能够执行的指令。 Shell 提供了一种交互式的方式来与操作系统进行通信&am…

内核线程创建-kthread_create

文章参考Linux内核线程kernel thread详解 - 知乎 大概意思就是早期创建内核线程&#xff0c;是交由内核处理&#xff0c;由内核自己完成&#xff08;感觉好像也不太对呢&#xff09;&#xff0c;创建一个内核线程比较麻烦&#xff0c;会导致内核阻塞。因此就诞生了工作队列以及…

Linux 目录结构及其说明

Linux 操作系统遵循一种标准的目录结构&#xff0c;称为 Filesystem Hierarchy Standard&#xff08;文件系统层次结构标准&#xff09;&#xff0c;其定义了不同目录的用途和内容。 浅蓝色文字 /&#xff08;根目录&#xff09;&#xff1a; /根目录是整个文件系统的起点&…

力扣2807.在链表中插入最大公约数

思路&#xff1a;遍历链表&#xff0c;对于每一个结点求出它与下一个结点的最大公约数并插入到俩个结点之间 代码&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}…

【数据库系统概念】第7-14章集合

文章目录 第七章 数据库设计和E-R模型&#xff08;重点&#xff01;&#xff01;&#xff01;&#xff09;~~7.1 设计过程概览&#xff08;了解&#xff09;~~7.1.1 设计阶段7.1.2 设计选择 7.2 实体-联系模型&#xff08;重点掌握&#xff09;7.2.1 实体集7.2.2 联系集联系集的…

BLE Mesh蓝牙组网技术详细解析之Model Layer模型层(八)

目录 一、什么是BLE Mesh Model Layer模型层&#xff1f; 二、SIG Model 2.1 模型概念 2.2 消息格式 2.3 开关模型 四、资料获取 一、什么是BLE Mesh Model Layer模型层&#xff1f; Models Layer的作用是定义了一些通用的或特定的模型&#xff0c;用于实现网络节点设备…

Beauty algorithm(四)眼影

一、skills 前瞻 略 二、目标区域定位 1、 眼影区域 1、眼部关键点 左侧:36,37,38,39,40,41 右侧:42,43,44,45,46,47 2、计算roi区域的w,h,center 目的调整mask的比列。 FaceRegion left_es, right_es; left_es.w = landmarks.at(39).x - landmarks.at(36).x; left_es.…

书生·浦语大模型实战营第一次课堂笔记

书生浦语大模型全链路开源体系。大模型是发展通用人工智能的重要途径,是人工通用人工智能的一个重要途径。书生浦语大模型覆盖轻量级、重量级、重量级的三种不同大小模型,可用于智能客服、个人助手等领域。还介绍了书生浦语大模型的性能在多个数据集上全面超过了相似量级或相近…

并发(3)

目录 11.Synchronized本质上是通过什么保证线程安全的&#xff1f; 12.Synchronized使得同时只有一个线程可以执行&#xff0c;性能比较差&#xff0c;有什么提升的方法&#xff1f; 13.Synchronized由什么样的缺陷&#xff1f;Java Lock是怎么弥补这些缺陷的&#xff1f; 1…

看了致远OA的表单设计后的思考

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbacheng/n…

通信原理期末复习——计算大题(一)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

交换机04_远程连接

通过远程管理方式连接交换机 1、telnet简介 telnet 是应用层协议 基于传输层TCP协议的&#xff0c;默认端口&#xff1a;23 采用的是明文密码方式 不是很安全&#xff0c;一般用于内网管理。 2、ssh协议简介 ssh 是应用层的协议&#xff0c;基于传输层的TCP协议&#x…

打造清晰的日志管理策略:如何在 NestJS 中集成 winston 高级日志系统

前言 在Web应用程序的开发过程中&#xff0c;日志管理是不可或缺的一部分。日志可以帮助我们了解应用程序的运行状态&#xff0c;监控系统行为&#xff0c;以及在出现问题时快速定位和解决问题。 对于使用NestJS框架的项目来说&#xff0c;集成一个高效、可扩展的日志系统尤为…

面试官:说说接口和抽象类有什么区别

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

Python中的cls语法

在Python中&#xff0c;cls 是一个用于指代类本身的约定性名称&#xff0c;通常用作类方法&#xff08;class method&#xff09;中的第一个参数。cls 类似于 self&#xff0c;它是对类的引用&#xff0c;而不是对实例的引用。cls 通常在类方法中用于访问类级别的属性和方法。举…

LLM Agent之数据分析领域的应用

数据分析&#xff1a;Data-Copilot paper: Data-Copilot: Bridging Billions of Data and Humans with Autonomous Workflow github: https://github.com/zwq2018/Data-Copilot 先介绍下浙大提出的已扩展的数据分析框架&#xff0c;支持多种金融数据类型的查询&#xff0c;数…

论文笔记 Understanding Electricity-Theft Behavior via Multi-Source Data

WWW 2020 oral 1 INTRO 1.1 背景 1.1.1 窃电 窃电&#xff08;electricity theft&#xff09;指用户为了逃避电费而进行非法操作的一种行为 常用的反窃电方法可分为两类&#xff1a; 基于硬件驱动的反窃电方法 ​​​​​​​电表开盖检测、集中器检测。。。。 硬件驱动的…

MySQL之视图案例

目录 一.视图1.1 含义1.2 操作 二.案例三.思维导图 一.视图 1.1 含义 虚拟表&#xff0c;和普通表一样使用 1.2 操作 1.创建视图 create view 视图名 as 查询语句&#xff1b; 2.视图的修改 方式一&#xff1a; create or replace view 视图名 as 查询语句 方式二&#x…

图像分割-Grabcut法(C#)

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 本文的VB版本请访问&#xff1a;图像分割-Grabcut法-CSDN博客 GrabCut是一种基于图像分割的技术&#xff0c;它可以用于将图像中的…

Linux第15步_安装FTP客户端

安装完FTP服务器后&#xff0c;还需要安装FTP客户端&#xff0c;才可以实现Ubuntu系统和Windows系统进行文件互传。 1、在STM32MP157开发板A盘基础资料\03软件中&#xff0c;找到“FileZilla_3.51.0_win64-setup.exe”&#xff0c;双击它&#xff0c;就可以安装。 2、点击“I …