YOLOv8-Cls推理详解及部署实现

目录

    • 前言
    • 一、YOLOv8-Cls推理(Python)
      • 1. YOLOv8-Cls预测
      • 2. YOLOv8-Cls预处理
      • 3. YOLOv8-Cls推理
    • 二、YOLOv8-Cls推理(C++)
      • 1. ONNX导出
      • 2. YOLOv8-Cls预处理
      • 3. YOLOv8-Cls推理
    • 三、YOLOv8-Cls部署
      • 1. 源码下载
      • 2. 环境配置
        • 2.1 配置CMakeLists.txt
        • 2.2 配置Makefile
      • 3. ONNX导出
      • 4. 源码修改
    • 结语
    • 下载链接
    • 参考

前言

梳理下 YOLOv8-Cls 的预处理流程,顺便让 tensorRT_Pro 支持 YOLOv8-Cls

参考:https://github.com/shouxieai/tensorRT_Pro

实现:https://github.com/Melody-Zhou/tensorRT_Pro-YOLOv8

一、YOLOv8-Cls推理(Python)

1. YOLOv8-Cls预测

我们先尝试利用官方预训练权重来推理一张图片,看能否成功

在 YOLOv8 主目录下新建 predict-cls.py 预测文件,其内容如下:

import cv2
from ultralytics import YOLOif __name__ == "__main__":model = YOLO("yolov8s-cls.pt")img = cv2.imread("ultralytics/assets/bus.jpg")result = model(img)[0]names  = result.namestop1_label = result.probs.top1top5_label = result.probs.top5top1_conf  = result.probs.top1conftop5_conf  = result.probs.top5conftop1_name  = names[top1_label]print(f"The model predicted category is {top1_name}, label = {top1_label}, confidence = {top1_conf:.4f}")

在上述代码中我们通过 opencv 读取了一张图像,并送入模型中推理得到 results,results 中保存着不同任务的结果,我们这里是分类任务,因此只需要拿到对应 1000 个类别中最高置信度的类别标签即可。

模型推理的结果如下所示:

在这里插入图片描述

2. YOLOv8-Cls预处理

模型预测成功后我们就需要自己动手来写下 YOLOv8-Cls 的预处理,方便后续在 C++ 上的实现

经过我们的调试分析可知 YOLOv8-Cls 的预处理过程在 ultralytics/data/augment.py 文件中,可以参考:augment.py#L1059

class CenterCrop:"""YOLOv8 CenterCrop class for image preprocessing, designed to be part of a transformation pipeline, e.g.,T.Compose([CenterCrop(size), ToTensor()])."""def __init__(self, size=640):"""Converts an image from numpy array to PyTorch tensor."""super().__init__()self.h, self.w = (size, size) if isinstance(size, int) else sizedef __call__(self, im):"""Resizes and crops the center of the image using a letterbox method.Args:im (numpy.ndarray): The input image as a numpy array of shape HWC.Returns:(numpy.ndarray): The center-cropped and resized image as a numpy array."""imh, imw = im.shape[:2]m = min(imh, imw)  # min dimensiontop, left = (imh - m) // 2, (imw - m) // 2return cv2.resize(im[top:top + m, left:left + m], (self.w, self.h), interpolation=cv2.INTER_LINEAR)class ToTensor:"""YOLOv8 ToTensor class for image preprocessing, i.e., T.Compose([LetterBox(size), ToTensor()])."""def __init__(self, half=False):"""Initialize YOLOv8 ToTensor object with optional half-precision support."""super().__init__()self.half = halfdef __call__(self, im):"""Transforms an image from a numpy array to a PyTorch tensor, applying optional half-precision and normalization.Args:im (numpy.ndarray): Input image as a numpy array with shape (H, W, C) in BGR order.Returns:(torch.Tensor): The transformed image as a PyTorch tensor in float32 or float16, normalized to [0, 1]."""im = np.ascontiguousarray(im.transpose((2, 0, 1))[::-1])  # HWC to CHW -> BGR to RGB -> contiguousim = torch.from_numpy(im)  # to torchim = im.half() if self.half else im.float()  # uint8 to fp16/32im /= 255.0  # 0-255 to 0.0-1.0return im

它包含如下步骤:

  • im[top:top +m, left:left + m]:中心裁剪
  • cv2.resize:缩放到 224x224
  • transpose(2, 0, 1)[::-1]:HWC → CHW,BGR → RGB
  • torch.from_numpy:to Tensor
  • im /= 255.0:除以 255.0,归一化

因此我们不难写出对应的预处理代码,如下所示:

def preprocess(img, dst_width=224, dst_height=224):imh, imw = img.shape[:2]m = min(imh, imw)top, left = (imh - m) // 2, (imw - m) // 2img_pre = img[top:top+m, left:left+m]img_pre = cv2.resize(img_pre, (dst_width, dst_height), interpolation=cv2.INTER_LINEAR)img_pre = (img_pre[...,::-1] / 255.0).astype(np.float32)img_pre = img_pre.transpose(2, 0, 1)[None]img_pre = torch.from_numpy(img_pre)return img_pre

经过中心裁剪并 resize 后的图片如下所示:

在这里插入图片描述

3. YOLOv8-Cls推理

由于我们经过 softmax 后直接得到的是每个类别的概率值,因此没有后处理一说,YOLOv8-Cls 的推理包括图像预处理、模型推理,其中预处理主要是 中心裁剪和缩放

完整的推理代码如下:

import cv2
import torch
import numpy as np
from ultralytics.nn.autobackend import AutoBackenddef preprocess(img, dst_width=224, dst_height=224):imh, imw = img.shape[:2]m = min(imh, imw)top, left = (imh - m) // 2, (imw - m) // 2img_pre = img[top:top+m, left:left+m]img_pre = cv2.resize(img_pre, (dst_width, dst_height), interpolation=cv2.INTER_LINEAR)img_pre = (img_pre[...,::-1] / 255.0).astype(np.float32)img_pre = img_pre.transpose(2, 0, 1)[None]img_pre = torch.from_numpy(img_pre)return img_preif __name__ == "__main__":img = cv2.imread("ultralytics/assets/bus.jpg")img_pre = preprocess(img)model = AutoBackend(weights="yolov8s-cls.pt")names = model.namesprobs = model(img_pre)[0]top1_label = int(probs.argmax())top5_label = (-probs).argsort(0)[:5].tolist()top1_conf  = probs[top1_label]top5_conf  = probs[top5_label]top1name = names[top1_label]print(f"The model predicted category is {top1name}, label = {top1_label}, confidence = {top1_conf:.4f}")

推理结果如下所示:

在这里插入图片描述

至此,我们在 Python 上面完成了 YOLOv8-Cls 的整个推理过程,下面我们去 C++ 上实现。

二、YOLOv8-Cls推理(C++)

C++ 上的实现我们使用的 repo 依旧是 tensorRT_Pro,现在我们就基于 tensorRT_Pro 完成 YOLOv8-Cls 在 C++ 上的推理。

1. ONNX导出

首先我们需要将 YOLOv8-Cls 模型导出为 ONNX,为了适配 tensorRT_Pro 我们需要做一些修改,主要有以下几点:

  • 修改输出节点名 output
  • 输入输出只让 batch 维度动态,宽高不动态

具体修改如下:

1. 在 ultralytics/engine/exporter.py 文件中改动一处

  • 323 行:输出节点名修改为 output
  • 326 行:输入只让 batch 维度动态,宽高不动态
  • 331 行:输出只让 batch 维度动态,宽高不动态
# ========== exporter.py ==========# ultralytics/engine/exporter.py第323行
# output_names = ['output0', 'output1'] if isinstance(self.model, SegmentationModel) else ['output0']
# dynamic = self.args.dynamic
# if dynamic:
#     dynamic = {'images': {0: 'batch', 2: 'height', 3: 'width'}}  # shape(1,3,640,640)
#     if isinstance(self.model, SegmentationModel):
#         dynamic['output0'] = {0: 'batch', 2: 'anchors'}  # shape(1, 116, 8400)
#         dynamic['output1'] = {0: 'batch', 2: 'mask_height', 3: 'mask_width'}  # shape(1,32,160,160)
#     elif isinstance(self.model, DetectionModel):
#         dynamic['output0'] = {0: 'batch', 2: 'anchors'}  # shape(1, 84, 8400)
# 修改为:output_names = ['output0', 'output1'] if isinstance(self.model, SegmentationModel) else ['output']
dynamic = self.args.dynamic
if dynamic:dynamic = {'images': {0: 'batch'}}  # shape(1,3,640,640)dynamic['output'] = {0: 'batch'}if isinstance(self.model, SegmentationModel):dynamic['output0'] = {0: 'batch', 2: 'anchors'}  # shape(1, 116, 8400)dynamic['output1'] = {0: 'batch', 2: 'mask_height', 3: 'mask_width'}  # shape(1,32,160,160)elif isinstance(self.model, DetectionModel):dynamic['output'] = {0: 'batch'}  # shape(1, 84, 8400)

以上就是为了适配 tensorRT_Pro 而做出的代码修改,修改好以后,将预训练权重 yolov8-cls.pt 放在 ultralytics-main 主目录下,新建导出文件 export.py,内容如下:

from ultralytics import YOLOmodel = YOLO("yolov8s-cls.pt")success = model.export(format="onnx", dynamic=True, simplify=True)

在终端执行如下指令即可完成 onnx 导出:

python export.py

导出过程如下图所示:

在这里插入图片描述

可以看到导出的 pytorch 模型的输入 shape 是 1x3x224x224,输出 shape 是 1x1000,符合我们的预期。

导出成功后会在当前目录下生成 yolov8s-cls.onnx 模型,我们可以使用 Netron 可视化工具查看,如下图所示:

在这里插入图片描述

可以看到输入节点名是 images,维度是 batchx3x224x224,保证只有 batch 维度动态,输出节点名是 output,维度是 batchx1000,保证只有 batch 维度动态,符合 tensorRT_Pro 的格式。

2. YOLOv8-Cls预处理

之前有提到过 YOLOv8-Cls 的预处理部分主要是中心裁剪加缩放,而在 tensorRT_Pro 中有提供 resize 的实现,我们只需要添加中心裁剪即可。

因此我们不难写出 YOLOv8-Cls 的预处理代码,如下所示:

__global__ void crop_resize_bilinear_and_normalize_kernel(uint8_t* src, int src_line_size, int src_width, int src_height, float* dst, int dst_width, int dst_height,int crop_x, int crop_y, float sx, float sy, Norm norm, int edge
){int position = blockDim.x * blockIdx.x + threadIdx.x;if (position >= edge) return;int dx      = position % dst_width;int dy      = position / dst_width;float src_x = (dx + 0.5f) * sx - 0.5f + crop_x;float src_y = (dy + 0.5f) * sy - 0.5f + crop_y;float c0, c1, c2;int y_low = floorf(src_y);int x_low = floorf(src_x);int y_high = limit(y_low + 1, 0, src_height - 1);int x_high = limit(x_low + 1, 0, src_width - 1);y_low = limit(y_low, 0, src_height - 1);x_low = limit(x_low, 0, src_width - 1);int ly    = rint((src_y - y_low) * INTER_RESIZE_COEF_SCALE);int lx    = rint((src_x - x_low) * INTER_RESIZE_COEF_SCALE);int hy    = INTER_RESIZE_COEF_SCALE - ly;int hx    = INTER_RESIZE_COEF_SCALE - lx;int w1    = hy * hx, w2 = hy * lx, w3 = ly * hx, w4 = ly * lx;float* pdst = dst + dy * dst_width + dx * 3;uint8_t* v1 = src + y_low * src_line_size + x_low * 3;uint8_t* v2 = src + y_low * src_line_size + x_high * 3;uint8_t* v3 = src + y_high * src_line_size + x_low * 3;uint8_t* v4 = src + y_high * src_line_size + x_high * 3;c0 = resize_cast(w1 * v1[0] + w2 * v2[0] + w3 * v3[0] + w4 * v4[0]);c1 = resize_cast(w1 * v1[1] + w2 * v2[1] + w3 * v3[1] + w4 * v4[1]);c2 = resize_cast(w1 * v1[2] + w2 * v2[2] + w3 * v3[2] + w4 * v4[2]);if(norm.channel_type == ChannelType::Invert){float t = c2;c2 = c0;  c0 = t;}if(norm.type == NormType::MeanStd){c0 = (c0 * norm.alpha - norm.mean[0]) / norm.std[0];c1 = (c1 * norm.alpha - norm.mean[1]) / norm.std[1];c2 = (c2 * norm.alpha - norm.mean[2]) / norm.std[2];}else if(norm.type == NormType::AlphaBeta){c0 = c0 * norm.alpha + norm.beta;c1 = c1 * norm.alpha + norm.beta;c2 = c2 * norm.alpha + norm.beta;}int area = dst_width * dst_height;float* pdst_c0 = dst + dy * dst_width + dx;float* pdst_c1 = pdst_c0 + area;float* pdst_c2 = pdst_c1 + area;*pdst_c0 = c0;*pdst_c1 = c1;*pdst_c2 = c2;
}

相比于 resize 的实现就多了一个偏移,主要是为了做中心裁剪,具体代码可以参考:preprocess_kernel.cu#L49

3. YOLOv8-Cls推理

通过上面对 YOLOv8-Cls 的预处理分析之后,整个推理过程就显而易见了。C++ 上 YOLOv8-Cls 的预处理部分将 resize 简单修改即可。

我们在终端执行如下指令即可完成推理(注意!完整流程博主会在后续内容介绍,这边只是简单演示

make yolo_cls

编译图解如下所示:

在这里插入图片描述

至此,我们在 C++ 上面完成了 YOLOv8-Cls 的整个推理过程,下面我们将完整的走一遍流程。

三、YOLOv8-Cls部署

博主新建了一个仓库 tensorRT_Pro-YOLOv8,该仓库基于 shouxieai/tensorRT_Pro,并进行了调整以支持 YOLOv8 的各项任务,目前已支持分类、检测、分割、姿态点估计任务。

下面我们就来具体看看如何利用 tensorRT_Pro-YOLOv8 这个 repo 完成 YOLOv8-Cls 的推理。

1. 源码下载

tensorRT_Pro-YOLOv8 的代码可以直接从 GitHub 官网上下载,源码下载地址是 https://github.com/Melody-Zhou/tensorRT_Pro-YOLOv8,Linux 下代码克隆指令如下:

git clone https://github.com/Melody-Zhou/tensorRT_Pro-YOLOv8.git

也可手动点击下载,点击右上角的 Code 按键,将代码下载下来。至此整个项目就已经准备好了。也可以点击 here 下载博主准备好的源代码(注意代码下载于 2023/11/7 日,若有改动请参考最新

2. 环境配置

需要使用的软件环境有 TensorRT、CUDA、cuDNN、OpenCV、Protobuf,所有软件环境的安装可以参考 Ubuntu20.04软件安装大全,这里不再赘述,需要各位看官自行配置好相关环境😄,外网访问较慢,这里提供下博主安装过程中的软件安装包下载链接 Baidu Drive【pwd:yolo】🚀🚀🚀

tensorRT_Pro-YOLOv8 提供 CMakeLists.txt 和 Makefile 两种方式编译,二者选一即可

2.1 配置CMakeLists.txt

主要修改五处

1. 修改第 13 行,修改 OpenCV 路径

set(OpenCV_DIR   "/usr/local/include/opencv4/")

2. 修改第 15 行,修改 CUDA 路径

set(CUDA_TOOLKIT_ROOT_DIR     "/usr/local/cuda-11.6")

3. 修改第 16 行,修改 cuDNN 路径

set(CUDNN_DIR    "/usr/local/cudnn8.4.0.27-cuda11.6")

4. 修改第 17 行,修改 tensorRT 路径

set(TENSORRT_DIR "/opt/TensorRT-8.4.1.5")

5. 修改第 20 行,修改 protobuf 路径

set(PROTOBUF_DIR "/home/jarvis/protobuf")
2.2 配置Makefile

主要修改五处

1. 修改第 4 行,修改 protobuf 路径

lean_protobuf  := /home/jarvis/protobuf

2. 修改第 5 行,修改 tensorRT 路径

lean_tensor_rt := /opt/TensorRT-8.4.1.5

3. 修改第 6 行,修改 cuDNN 路径

lean_cudnn     := /usr/local/cudnn8.4.0.27-cuda11.6

4. 修改第 7 行,修改 OpenCV 路径

lean_opencv    := /usr/local

5. 修改第 8 行,修改 CUDA 路径

lean_cuda      := /usr/local/cuda-11.6

3. ONNX导出

导出细节可以查看之前的内容,这边不再赘述。记得将导出的 ONNX 模型放在 tensorRT_Pro-YOLOv8/workspace 文件夹下。

4. 源码修改

如果你想推理自己训练的模型还需要修改下源代码,YOLOv8-Cls 模型的推理代码主要在 app_yolo_cls.cpp 文件中,我们就只需要修改这一个文件中的内容即可,源码修改较简单主要有以下几点:

  • 1. app_yolo_cls.cpp 187行,“yolov8s-cls” 修改为你导出的 ONNX 模型名
  • 2. app_yolo_cls.cpp 105行,“imagenet.txt” 修改为你自训练分类模型的类别 txt 文件

具体修改示例如下:

test(TRT::Model::FP32, "best")	// 修改1 187行"yolov8s-cls"改成"best"auto labels = iLogger::split_string(iLogger::load_text_file("custom.txt"), "\n");	// 修改2 105行修改检测类别,为自训练模型的类别名称

OK!源码修改好了,Makefile 编译文件也搞定了,ONNX 模型也准备好了,现在可以编译运行了,直接在终端执行如下指令即可:

make yolo_cls

编译过程如下所示:

在这里插入图片描述

编译运行成功后在 workspace 文件夹下会生成 engine 文件 yolov8s-cls.FP32.trtmodel 用于模型推理,同时在终端还可以看见模型预测的结果。

OK!以上就是使用 tensorRT_Pro-YOLOv8 推理 YOLOv8-Cls 的大致流程,若有问题,欢迎各位看官批评指正。

结语

博主在这里针对 YOLOv8-Cls 的预处理和后处理做了简单分析,同时与大家分享了 C++ 上的实现流程,目的是帮大家理清思路,更好的完成后续的部署工作😄。感谢各位看到最后,创作不易,读后有收获的看官请帮忙点个👍⭐️

最后大家如果觉得 tensorRT_Pro-YOLOv8 这个 repo 对你有帮助的话,不妨点个 ⭐️ 支持一波,这对博主来说非常重要,感谢各位🙏。

下载链接

  • 软件安装包下载链接【提取码:yolo】🚀🚀🚀
  • 源代码、权重下载链接【提取码:yolo】

参考

  • https://github.com/shouxieai/infer
  • https://github.com/ultralytics/ultralytics
  • https://github.com/shouxieai/tensorRT_Pro
  • https://github.com/Melody-Zhou/tensorRT_Pro-YOLOv8
  • YOLOv5推理详解及预处理高性能实现

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

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

相关文章

【解密ChatGPT】:从过去到未来,揭示其发展与变革

🎊专栏【ChatGPT】 🌺每日一句:天行健,君子以自强不息,地势坤,君子以厚德载物 ⭐欢迎并且感谢大家指出我的问题 文章目录 一、ChatGPT的发展历程 二、ChatGPT的技术原理 三、ChatGPT的应用场景 四、ChatGPT的未来趋势 五、总结 引言:随着…

基于指数分布算法的无人机航迹规划-附代码

基于指数分布算法的无人机航迹规划 文章目录 基于指数分布算法的无人机航迹规划1.指数分布搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要:本文主要介绍利用指数分布算法来优化无人机航迹规划。 …

Visual Studio Code将中文写入变量时,中文老是乱码问题

对于这个问题,我也是弄了很久才知道,编码格式的问题 在此之前我们要先下载个插件 照这以上步骤,最后按F6运行即可,按F6是利用我们刚刚下载的插件进行编译,唯一有一点不好就是,用这种插件运行的话&#xff…

MCU测试科普|如何进行MCU芯片测试,具体流程是什么?

MCU芯片测试系统是一种专门用于检测MCU芯片性能和质量的综合性设备。它通常由硬件和软件两部分组成,硬件包括测试仪器、适配器、测试夹具等,用于连接被测MCU芯片和测试机,实现高效高精度的测试。软件部分通常包括测试程序、测试管理软件等&am…

VMware Ubuntu 共享文件夹

VMware Ubuntu 共享文件夹 flyfish 物理机配置 Network Adapter设置 此处设置为NAT Shared Folders设置 虚拟机配置 vmware-hgfsclient sudo vmhgfs-fuse .host:/ /mnt -o nonempty -o allow_other 或者 sudo vmhgfs-fuse .host:/ /mnt/ -o allow_other第一行命令是查看共…

大数据学习之一文学会Spark【Spark知识点总结】

文章目录 什么是SparkSpark的特点Spark vs HadoopSparkHadoopSpark集群安装部署Spark集群安装部署StandaloneON YARN Spark的工作原理什么是RDDRDD的特点Spark架构相关进程Spark架构原理 Spark实战:单词统计Scala代码开发java代码开发任务提交 Transformation与Acti…

vue基础知识十八:说说你对keep-alive的理解是什么?

一、Keep-alive 是什么 keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们 keep-alive可以设置以下props属性&#xff1a…

nanodet训练自己的数据集、NCNN部署到Android

nanodet训练自己的数据集、NCNN部署到Android 一、介绍二、训练自己的数据集1. 运行环境2. 数据集3. 配置文件4. 训练5. 训练可视化6. 测试 三、部署到android1. 使用官方权重文件部署1.1 下载权重文件1.2 使用Android Studio部署apk 2. 部署自己的模型【暂时存在问题】2.1 生成…

目标检测回归损失函数(看情况补...)

文章目录 L1 loss-平均绝对误差(Mean Absolute Error——MAE)L2 loss-均方误差(Mean Square Error——MSE)Smooth L1 LossMAE、MSE、Smooth L1对比IoU LossGIoU LossDIoU Loss、CIoU LossE-IoU Loss、Focal E-IoU LossReferenceL1 loss-平均绝对误差(Mean Absolute Error——…

ASP.NETCore6开启文件服务允许通过url访问附件(图片)

需求背景 最近在做一个工作台的文件上传下载功能,主要想实现上传图片之后,可以通过url直接访问。由于url直接访问文件不安全,所以需要手动开启文件服务。 配置 文件路径如下,其中Files是存放文件的目录: 那么&…

接口测试工具

接口测试的重要性 接口测试: 直接对后端服务的测试,是服务端性能测试的基础,是测试工程师的必备技能。 接口测试的概念 接口:系统之间数据交互的通道 接口测试:校验接口响应数据与预期数据是否一致 接口信息解析 …

缓存-基础理论和Guava Cache介绍

缓存-基础理论和Guava Cache介绍 缓存基础理论 缓存的容量和扩容 缓存初始容量、最大容量,扩容阈值以及相应的扩容实现。 缓存分类 本地缓存:运行于本进程中的缓存, 如Java的 concurrentHashMap, Ehcache,Guava Cache。 分布式缓…

Mac上好用的翻译软件推荐 兼容m

Mac翻译软件可以用在学习,工作,生活当中,一款好用的翻译软件,具有翻译准确,翻译快速等基本特点,能够帮您提高工作效率。Mac上有什么好用的翻译软件呢?今天小编为大家整理了6款好用的Mac翻译软件…

C语言--typedef的使用

前言 在C语言中使用结构体时必须加上struct这个关键字,那有没有办法省略这个呢?要想达到这个目的就 需要用到关键字typedef,顾名思义”类型定义”。 typedef 数据类型 新的别名; 它是用来操作数据类型。其主要作用有两个: 1.给一个较长较复杂的类型取一个简单的别名。 2.给类…

MySQL数据库入门到大牛_03_SQL概述、基本的SELECT语句、显示表结构、过滤数据

文章目录 1. SQL概述1.1 SQL背景知识1.2 SQL语言排行榜1.3 SQL 分类1.4 数据库内容 2. SQL语言的规则与规范2.1 基本规则2.2 SQL大小写规范 (建议遵守)2.3 注 释2.4 命名规则(暂时了解)2.5 数据导入指令2.5.1 source 文件全路径名…

零代码编程:用ChatGPT批量将Mp4视频转为Mp3音频

文件夹中有很多mp4视频文件,如何利用ChatGPT来全部转换为mp3音频呢? 在ChatGPT中输入提示词: 你是一个Python编程专家,要完成一个批量将Mp4视频转为Mp3音频的任务,具体步骤如下: 打开文件夹:…

Springboot中解析JSON字符串(jackson库ObjectMapper解析JSON字符串)

1、ObjectMapper与JSONObject比较 1、ObjectMapper属于jackson库的一部分,JSONObject属于alibaba的fastjson,两者各有优劣,可根据自己的系统环境选择使用哪种技术。 2、目前来看,Jackson社区相对活跃,Spring MVC和Spring Boot都…

IDEA项目下不显示target目录或者target目录不完整没有新添加的资源,idea隐藏target目录

文章目录 一、前言二、idea隐藏target目录2.1、idea隐藏target目录2.2、git提交时隐藏target目录 三、idea下显示target目录3.1、解决idea下不显示target目录问题3.2、target显示目录不完整 一、前言 在idea-2020.1.4版本下讲解idea怎么显示或隐藏target目录。 需要知道:如果…

聊一聊 tcp/ip 在.NET故障分析的重要性

一:背景 1. 讲故事 这段时间分析了几个和网络故障有关的.NET程序之后,真的越来越体会到计算机基础课的重要,比如 计算机网络 课,如果没有对 tcpip协议 的深刻理解,解决这些问题真的很难,因为你只能在高层…

线性代数之 伪逆矩阵

目录 一、伪逆矩阵 ◼ A的伪逆矩阵与SVD ◼ 用Python代码计算A的伪逆矩阵 ◼ 笔算A的伪逆矩阵 一、伪逆矩阵 ◼ A的伪逆矩阵与SVD 逆矩阵并不总是存在,即使是方阵。然而,对于非正方形矩阵,存在一个伪逆矩阵,也叫摩尔-彭罗斯…