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

图像的读取与保存

图像是由一个个像素点组成,像素点就是颜色点,而颜色最简单的方式就是用RGB或RGBA表示

图像保存

图像将像素信息按照 一定格式,一定顺序(即编码) 存在硬盘上的 二进制文件 中

保存图像需要以下必要信息:

1. 文件名和路径

2. 文件格式

3. 压缩参数(jpeg图像的压缩质量等)

图像读取

将而二进制文件还原为 像素排布

图像编码

目的:压缩 (有损压缩,无损压缩)减小数据大小

有损压缩: 解压缩后的数据与压缩前的数据不一致.在压缩的过程中要丢失一些人眼和人耳所不敏感的图像或音频信息,而且丢失的信息不可恢复。

无损压缩: 压缩前和解压缩后的数据完全一致。优化数据的排列等。

补充:【端到端指的是直接输入原始数据,让模型自己去学习特征,最后输出结果

非端到端呢,简单来说,就是我们的输入数据首先经过人工处理,在喂给模型去训练】

常见编码:PNG 无损压缩,BMG 无损压缩,JPEG 有损压缩

PNG

PNG图像格式文件(或者称为数据流)由一个8字节的PNG文件署名(PNG file signature)域和按照特定结构组织的3个以上的数据块(chunk)组成。

PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是必需的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。

Critical Chunk(关键数据块),有四种类型:

IHDR,header chunk,包含有图像基本信息,作为第一个出现的数据块并且只出现一次。

PLTE,palette chunk,调色板数据块,必须存放在图像数据块之前。

IDAT,image data chunk,存储实际的图像数据。PNG数据包允许包含多个连续的图像数据块。

IEND,image trailer chunk,图像结束数据,表示PNG数据流结束。

其中ihdr的结构为:4字节为chunk length,4字节为chunk type

剩下13字节的ihdr为:

宽(无符号整,4字节)

高(无符号整,4字节)

bit deep位深(无符号char,1字节)

颜色类型(无符号char,1字节)

压缩方法/滤波方法/隔行扫描法(都是unsigned char 1字节)

https://www.jb51.net/article/199586.htm

# 首先读取二进制文件
f = open("E:/DeepLearning/计算机视觉/cv101-master/dataset/lena.png", 'rb')
print(f)
# <_io.BufferedReader name='E:/DeepLearning/计算机视觉/cv101-master/dataset/lena.png'># head
file_sign = f.read(4)
print("head:", file_sign)
#换行符文件结束符
sign1 = f.read(4)
print("换行符和文件结束符:", sign1)
#head: b'\x89PNG'
#换行符和文件结束符: b'\r\n\x1a\n'length = struct.unpack('I', f.read(4))
print(length)
type = f.read(4)
print(type)
#(218103808,)
#b'IHDR'width = struct.unpack('I', f.read(4))
print("宽度:", width)
height = struct.unpack('I', f.read(4))
print("高度:", height)
# 感觉有点问题
#宽度: (131072,)
#高度: (131072,)
bit = struct.unpack('B',f.read(1))
print("位深:", bit)
color = struct.unpack('B',f.read(1)) 
print("颜色:", color)
#位深: (8,)
#颜色: (2,)a = struct.unpack('B',f.read(1))
b = struct.unpack('B',f.read(1))
c = struct.unpack('B',f.read(1))
print("a,b,c: ",a,b,c)
# a,b,c:  (0,) (0,) (0,)

BMP

-- 文件头:文件类型、文件大小、位图数据的起始位置

-- 位图信息头:图像尺寸、位深图、压缩方式

-- 调色板: 存储位深小于8的像素点信息

-- 位图数据:存储图像中每个像素点的颜色信息

位深的概念

BMP格式中,每个像素点的颜色信息可以使用不同的位深度表示,如1位(单色)、4位(16色)、8位(256色)、16位、24位(真彩色)和32位等。其中,1位表示每个像素点只有黑和白两种颜色;4位表示每个像素点可以有16种颜色;8位(0~255)表示每个像素点可以有256种颜色;16位、24位和32位则表示每个像素点的颜色可以用不同的颜色通道(如红、绿、蓝)进行表示

基本规则如下:

- 文件头(14b):

- 表示符:BM(2b)

- 文件大小 (4b)

- 保留量 (4b)

- 偏移量 (4b)

- 位图头 (40b)

- 字节头大小 4b

- 宽 4b

- 高 4b

- 颜色通道数 2b

- 位深 2b

- 位图数据

- 从左到右,从上到下

- 所占空间为宽乘以高乘以位数除以8

- 补齐4字节

读取一张BMP图片全过程

# 以bmp为例
# 首先读取二进制文件
f = open("E:/DeepLearning/计算机视觉/cv101-master/dataset/lena.bmp", 'rb')
print(f)
#<_io.BufferedReader name='E:/DeepLearning/计算机视觉/cv101-master/dataset/lena.bmp'># 先读取头文件
# 2字节标识符
file_sign = f.read(2)
print("标识符:", file_sign)
#标识符: b'BM'# 4字节文件大小
file_size_byte = f.read(4)
# 需要解码
import struct
file_size = struct.unpack("i", file_size_byte)
print("文件大小:", file_size)
#文件大小: (786486,)# 4字节保留
f.read(4)
# 4字节数据偏移量
offset = struct.unpack("i", f.read(4))[0]
print("偏移量:", offset)
#偏移量: 54# 位图头读取
# 字节头解码
bm_header_size = struct.unpack('i', f.read(4))
print("字节头大小:", bm_header_size)
width = struct.unpack('i', f.read(4))
print("宽度:", width)
height = struct.unpack('i', f.read(4))
print("高度:", height)
channels = struct.unpack('<H', f.read(2))
print("通道:", channels)
color_bit = struct.unpack('<H', f.read(2))  # 2字节解码,低位字节在前
print("位深:", color_bit)
#字节头大小: (40,)
#宽度: (512,)
#高度: (512,)
#通道: (1,)
#位深: (24,)# 读取像素
f.seek(offset)
data = f.read()
# print(data[0], data[1], data[2])
print("总像素值数量为:", len(data))
print("像素点个数为:", len(data) // (color_bit[0] // 8))
print("长(512)*宽(512)= ", 512 * 512)
#总像素值数量为: 786432
#像素点个数为: 262144
#长(512)*宽(512)=  262144# 解码数据
# 一个像素占用的字节:24位深,一个像素三个数字表示rgb通道数值,用三个字节表示;8位深用1个字节表示(灰度图像);1位深用1个比特来存储(二值图像)
# 因此,计算方式为:int(位深/8)
pixel_bit = int(color_bit[0] / 8)
print("一个像素占用%d字节" % pixel_bit)
row_bit = pixel_bit * width[0]
print("一行占用%d字节" % row_bit)
#一个像素占用3字节
#一行占用1536字节# 建立一个空矩阵用于存储像素
import numpy as np
img = np.zeros((height[0], width[0], 3), dtype=np.uint8)
# 依次填充像素值
for i in range(height[0]):for j in range(width[0]):index = i * height[0] * 3 + j * 3img[i, j, 2] = data[index]img[i, j, 1] = data[index + 1]img[i, j, 0] = data[index + 2]
# 展示结果
import matplotlib.pyplot as plt
plt.imshow(img, origin='lower')
plt.show()

JPEG

-- joint photographic experts group

-- 有损压缩格式

-- DCT和量化实现

-- 具体步骤:

1. 预处理:rgb->YCbCr

2. DCT变换:

- 图像划分成8*8的patch

- 每个patch做DCT变换

3. 量化:

- 量化频域信号

- 舍弃高频信号

4. 编码:

- 熵编码技术对DCT信号编码

- 保留主分量,舍去噪声分量

- 常见的两种实现方式:

* baseline jpeg:常规方式,编码顺序为从左至右从上至下

* progressive jpeg:内容从模糊到清晰,将图像分为多个扫描,每个扫描中先编码大致轮廓,然后在后续扫描中添加细节

图像读取和保存的第三方库

PIL

安装:pip install pillow

读写使用

from PIL import Image
# 读取图像
img = Image.open('E:/DeepLearning/计算机视觉/cv101-master/dataset/lena.bmp')
plt.imshow(img)
plt.show()# 查看图像大小
print('image shape:', img.size)
# 查看图像格式
print('format:', img.format)
# 查看图像通道数
print('mode:', img.mode)# 获取像素值
# 通常是将其转换为其他格式来使用像素值,例如
import numpy as np
img_array = np.asarray(img)
print(img_array[:3, :3, 0])

输出:

image shape: (512, 512)

format: BMP

mode: RGB

[[226 226 223]

[226 226 223]

[226 226 223]]

保存

# PIL提供了保存图像的方法,即
img.save('../../dataset/pil_lena.bmp')

opencv

安装:pip install python-opencv

读取使用:默认读取bgr需转化为rgb

import cv2
img = cv2.imread('E:/dataset/lena.bmp')#路径中不能有中文!!!plt.imshow(img)
plt.show()#读取默认bgr
img = cv2.imread('E:/notebook/lena.bmp')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)plt.imshow(img)
plt.show()
# 在读取图像时,imread还有个隐藏参数,可以直接将彩色图像转化为灰度图像
img = cv2.imread('E:/notebook/lena.bmp', 0)
img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)plt.imshow(img)
plt.show()

图片保存

opencv提供函数保存图像,其格式为:

cv2.imwrite(filename, image, [params])

其中,参数分别是: 文件名, 图像数据,可选参数:文件格式

img = cv2.imread('E:/notebook/lena.bmp')
cv2.imwrite('E:/notebook/lena.png', img)
cv2.imwrite('E:/notebook/lena_90.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 90])#压缩质量90kb
cv2.imwrite('E:/notebook/lena_10.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 10])#压缩质量10kb
质量10kb(第一张)和90kb对比

两者区别

cv2直接读取到图像的内容,pil读取图像的区块

cv2支持的图像格式更多,保存图像时能够控制图像质量,需要空间转换

pil适合简单的图像查看应用场景,opencv适合处理计算机视觉任务。

assignment

PNG2JPG

#方法一:使用PIL库
from PIL import Image
img = Image.open('test.jpg')
img.save('testpil.png')
#方法二:使用opencv库
from cv2 import imread, imwrite
image = imread("test.jpg", 1)
imwrite("testcv.png", image)

不使用第三方库怎么做?

def png2jpg(filename, quality_value, save_folder):# 不依赖opencv或者pil库,从二进制文件直接解析png文件,并保存成jpeg格式。# 其中,jpeg格式的压缩参数由输入指定。# # 输入: #     filename: str, png图像路径#     quality_value: 压缩质量参数#     save_folder: 保存的目标路径# # 图像保存文件名:# # 返回值:#    返回0

相关文章:

图像的读取与保存

图像是由一个个像素点组成&#xff0c;像素点就是颜色点&#xff0c;而颜色最简单的方式就是用RGB或RGBA表示图像保存图像将像素信息按照 一定格式&#xff0c;一定顺序&#xff08;即编码&#xff09; 存在硬盘上的 二进制文件 中保存图像需要以下必要信息&#xff1a;1. 文件…...

【蓝桥杯集训·每日一题】AcWing 4074. 铁路与公路

文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴Floyd 算法Spfa 算法一、题目 1、原题链接 4074. 铁路与公路 2、题目描述 某国家有 n 个城市&#xff08;编号 1∼n&#xff09;和 m 条双向铁路。 每条铁路连接两个不同的…...

网络:TCP与UDP相关知识(详细)

目录&#xff1a;1、UDP 和 TCP 的特点与区别2、UDP 、TCP 首部格式3、TCP 的三次握手和四次挥手4、TCP 的三次握手&#xff08;为什么三次&#xff1f;&#xff09;5、TCP 的四次挥手&#xff08;为什么四次&#xff1f;&#xff09;6、TCP 长连接和短连接的区别7、TCP粘包、拆…...

不好!有敌情,遭到XSS攻击【网络安全篇】

XSS&#xff1a;当一个目标的站点&#xff0c;被我们用户去访问&#xff0c;在渲染HTMl的过程中&#xff0c;出现了没有预期到的脚本指令&#xff0c;然后就会执行攻击者用各种方法注入并执行的恶意脚本&#xff0c;这个时候就会产生XSS。 涉及方&#xff1a; 用户&#xff0…...

Mysql中Explain详解及索引的最佳实践

Mysql中Explain详解及索引的最佳实践1.Explan工具的介绍1.1 Explan 分析示例1.2 Explain中的列1.2.1 id1.2.2 select_type1.2.3 table1.2.4 partitions1.2.5 type1.2.6 possible_keys1.2.7 key1.2.8 key_len1.2.9 ref1.2.10 rows1.2.11 filtered1.2.12 Extra1.Explan工具的介绍…...

JavaScript 内的 this 指向

在 javascript 语言中, 有一个奇奇怪怪的 “关键字” 叫做 this为什么说它是 奇奇怪怪 呢, 是因为你写出 100 个 this, 可能有 100 个解释, 完全不挨边&#xff0c;但是, 在你的学习过程中, 搞清楚了 this 这个玩意, 那么会对你的开发生涯有很大帮助的&#xff0c;接下来咱们就…...

Java多种方法实现等待所有子线程完成再继续执行

简介 在现实世界中&#xff0c;我们常常需要等待其它任务完成&#xff0c;才能继续执行下一步。Java实现等待子线程完成再继续执行的方式很多。我们来一一查看一下。 Thread的join方法 该方法是Thread提供的方法&#xff0c;调用join()时&#xff0c;会阻塞主线程&#xff0…...

制造企业数字化工厂建设步骤的建议

随着工业4.0、中国制造2025的深度推进&#xff0c;越来越多的制造企业开始迈入智能制造的领域&#xff0c;那数字工厂要从何入手呢&#xff1f; 数字工厂规划的核心&#xff0c;也正是信息域和物理域这两个维度&#xff0c;那就从这两个维度来进行分析&#xff0c;看如何进行数…...

网上鲜花交易平台,可运行

文章目录项目介绍一、项目功能介绍1、用户模块主要功能包括&#xff1a;2、商家模块主要功能包括&#xff1a;3、管理员模块主要功能包括&#xff1a;二、部分页面展示1、用户模块部分功能页面展示2、商家模块部分功能页面展示3、管理员模块部分功能页面展示三、部分源码四、底…...

【实战】用 Custom Hook + TS泛型实现 useArray

文章目录一、题目二、答案&#xff08;非标准&#xff09;三、关键知识点1.Custom Hook关键点案例useMountuseDebounce2.TS 泛型关键点一、题目 完善自定义 Hook —— useArray &#xff0c;使其能够完成 tryUseArray 组件中测试的功能&#xff1a; 入参&#xff1a;数组返回…...

【LeetCode】剑指 Offer(18)

目录 题目&#xff1a;剑指 Offer 35. 复杂链表的复制 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offer 35. 复杂链…...

Kubernetes节点运行时从Docker切换到Containerd

由于k8s将于1.24版本弃用dockershim&#xff0c;所以最近在升级前把本地的k8s切换到了Containerd运行时&#xff0c;目前我的k8s版本是1.22.5&#xff0c;一个master&#xff0c;二个Node的配置&#xff0c;以下做为一个操作记录日志整理&#xff0c;其它可以参考官网文档。 在…...

【编程基础之Python】12、Python中的语句

【编程基础之Python】12、Python中的语句Python中的语句赋值语句条件语句循环语句for循环while循环continue语句break语句continue与break的区别函数语句pass语句异常处理语句结论Python中的语句 Python是一种高级编程语言&#xff0c;具有简单易学的语法&#xff0c;适用于各…...

android h5餐饮管理系统myeclipse开发mysql数据库编程服务端java计算机程序设计

一、源码特点 android h5餐饮管理系统是一套完善的WEBandroid设计系统&#xff0c;对理解JSP java&#xff0c;安卓app编程开发语言有帮助&#xff08;系统采用web服务端APP端 综合模式进行设计开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要…...

容易混淆的嵌入式(Embedded)术语

因为做嵌入式开发工作虽然跳不出电子行业&#xff0c;但还是能接触到跨度较大的不同行当&#xff0c;身处不同的圈子。诸如医疗&#xff0c;银行&#xff0c;车载&#xff0c;工业&#xff1b;亦或者手机&#xff0c;PC&#xff0c;专用芯片&#xff1b;甚至可能横跨系统开发、…...

Nodejs 中 JSON 和 YAML 互相转换

JSON 转换成 YAML 1. 安装 js-yaml 库: npm install js-yaml2. 在程序中引入依赖库 const yaml require(js-yaml);3. 创建一个 js 对象, 代表 json 数据 const jsonData {name: John,age: 30,city: New York };4. 使用 yaml.dump() 把 js 对象转换成 YAML, 返回 YAML 字符…...

C++入门教程||C++ 修饰符类型||C++ 存储类

C 修饰符类型 C 允许在 char、int 和 double 数据类型前放置修饰符。修饰符用于改变基本类型的含义&#xff0c;所以它更能满足各种情境的需求。 下面列出了数据类型修饰符&#xff1a; signedunsignedlongshort 修饰符 signed、unsigned、long 和 short 可应用于整型&#…...

Android开发面试:Java知识答案精解

目录 Java 集合 集合概述 HashMap ConcurrentHashMap 泛型 反射 注解 IO流 异常、深浅拷贝与Java8新特性 Java异常 深浅拷贝 Java8新特性 并发 线程 线程池 锁 volatile JVM 内存区域 内存模型 类加载机制 垃圾回收机制 如何判断对象已死 Java 集合 …...

Windows上一款特别好用的画图软件

安装 废话不多说&#xff0c;打开windows的应用商店&#xff0c;搜索draw.io&#xff0c;点击获取即可。 画图 draw.io的布局左边是各种图形组件&#xff0c;中间是画布&#xff0c;右边是属性设置&#xff0c;文件扩展名是.drawio。 点击左边列表中的图形可以将它添加到画…...

html--学习

javascrapt交互&#xff0c;网页控制JavaScript&#xff1a;改变 HTML 图像本例会动态地改变 HTML <image> 的来源&#xff08;src&#xff09;&#xff1a;点亮灯泡<script>function changeImage() {elementdocument.getElementById(myimage) #内存变量&#xff0…...

关于递归处理,应该怎么处理,思路是什么?

其实问题很简单&#xff0c;就是想要循环遍历整个data对象&#xff0c;来实现所有name转成label&#xff0c;但是想到里面还有children属性&#xff0c;整个children里面可能还会嵌套很多很多的name&#xff0c;如此循环&#xff0c;很难搞&#xff0c;知道使用递归&#xff0c…...

重磅!牛客笔试客户端可防ChatGPT作弊

上线俩月&#xff0c;月活过亿。爆火的ChatGPT能代写文&#xff0c;撕代码&#xff0c;善玩梗&#xff0c;秒答题&#xff0c;几乎“无所不能”&#xff0c;争议也随之而来。调查显示&#xff0c;截至2023年1月&#xff0c;美国89%的大学生利用ChatGPT应付作业&#xff0c;53%的…...

春季训练营 | 前端+验证直通车-全实操项目实践,履历加成就业无忧

“芯动的offer”是2023年E课网联合企业全新推出集训培优班&#xff08;线下&#xff09;&#xff0c;针对有一定基础&#xff08;linux、verilog、uvm等&#xff09;在校学生以及想要通过短时间的学习进入到IC行业中的转行人士&#xff0c;由资深IC设计工程师带教&#xff0c;通…...

2.详解URL

文章目录视图函数1.1endpoint简介1.2 装饰器注册路由源码浅析1.3 另一种注册路由的方式---app.add_url_rule()1.4 视图函数中添加自定义装饰器2 视图类2.1 视图类的基本写法3 详细讲解注册路由的参数3.1常用的参数3.2不常用的参数(了解)视图函数 1.1endpoint简介 endpint参数…...

Android特别的数据结构(二)ArrayMap源码解析

1. 数据结构 public final class ArrayMap<K,V> implements Map<K,V> 由两个数组组成&#xff0c;一个int[] mHashes用来存放Key的hash值&#xff0c;一个Object[] mArrays用来连续存放成对的Key和ValuemHashes数组按非严格升序排列初始默认容量为0减容&#xff…...

减少if else

1. 三目运算符 可以理解为条件 ?结果1 : 结果2 里面的?号是格式要求。也可以理解为条件是否成立&#xff0c;条件成立为结果1&#xff0c;否则为结果2。 实例&#xff1a; public String handle(int code) {if (code 1) {return "success";} else {return &quo…...

硕士毕业论文常见的排版小技巧

word排版陆续更新吧&#xff0c;更具我所遇到的一些小问题&#xff0c;总结上来 文章目录1.避免题注&#xff08;图或者表的标题&#xff09;与图或表格分不用页注意点&#xff1a;光标移动到表的题注后面2.设置论文的页眉关键点&#xff1a;需要将每一章节末尾&#xff0c;都要…...

JAVA开发(数据类型String和HasMap的实现原理)

在JAVA开发中&#xff0c;使用最多的数据类型恐怕是String 和 HasMap两种数据类型。在开发的过程中我们每天都使用的不亦乐乎。但是相信很多人都没有考虑过String数据类型的实现原理或者说是在数据结构中的存储原理&#xff0c;还有一个就是是HashMap&#xff0c;也很少有人去了…...

Hbase 映射到Hive

目录 一、环境配置修改 关闭掉hbase&#xff0c;zookeeper和hive服务 进入hive312/conf 修改hive-site.xml配置&#xff0c; 在代码最后添加配置 将hbase235的jar包全部拷贝到hive312的lib目录&#xff0c;并且所有的是否覆盖信息全部输入n&#xff0c;不覆盖 查看hive312下…...

14_MySQL视图

1. 常见的数据库对象2. 视图概述2.1 使用视图的好处视图一方面可以帮我们使用表的一部分而不是所有的表&#xff0c;另一方面也可以针对不同的用户制定不同的查询视图。比如&#xff0c;针对一个公司的销售人员&#xff0c;我们只想给他看部分数据&#xff0c;而某些特殊的数据…...

武汉做网站公司哪家好/网络推广竞价是什么

《计算机组装与维护课程设计》——微型计算机基本知识引言&#xff1a;一、课程设计的性质与任务尽管计算机原理和制造技术非常复杂&#xff0c;但计算机的组成却十分简单。学会计算机组装一般维护和维修&#xff0c;并不需要很多的计算机知识。只需要了解当前比较流行的硬件组…...

深圳网站设计价格表/广告投放平台公司

原文&#xff1a;http://blog.csdn.net/qq_30379689/article/details/52411489 &#xff08;为了自己看的懂&#xff0c;自己在原文的基础上略做改动&#xff09; 作为Google开源框架Zxing&#xff0c;里面的文件很大&#xff0c;这里主要讲的是精简ZXing项目后只保留扫描功能的…...

3g网站建设/成人短期培训能学什么

在上一篇文章中介绍了关于C#如何插入Word书签、插入图片或表格到word、删除word书签等内容&#xff0c;本篇文章将继续介绍C#操作word书签的方法。下面的示例中将介绍C# 如何读取Word书签C# 如何替换Word书签工具使用Spire.Doc for .NET 示例代码原文档中的书签内容&#xff1a…...

志愿者网站时长码怎么做/网站推广的常用方法有哪些?

你有没有考虑过&#xff0c;当你辛辛苦苦写了好多代码&#xff0c;最后编译运行的时候&#xff0c;计算机到底经历了什么过程&#xff1f; 如同施了魔法一般&#xff0c;计算机运行的程序实现了我们当初的构想。 而随着计算机技术的不断提高&#xff0c;我们可以利用集成开发…...

营销型网站制作方案/郑州网络营销公司有哪些

<style>.button {width: 50px;height: 50px;border-radius: 5px;-webkit-appearance: none;}</style> <input type"button" value"按钮" class"button">...

wap网页设计/seo网站推广主要目的不包括

前言 微信群机器人&#xff0c;主要用来管理群聊&#xff0c;提供类似天气查询、点歌、机器人聊天等用途。由于微信将web端的协议封杀后&#xff0c;很多基于http协议的群聊机器人都失效了&#xff0c;所以这里使用基于PC端协议的插件来实现。 声明以下过程只用于交流学习&am…...