基于Yolv5s的口罩检测

1.Yolov5算法原理和网络结构

        YOLOv5按照网络深度和网络宽度的大小,可以分为YO-LOv5s、YOLOv5m、YOLOv5l、YOLOv5x。本文使用YOLOv5s,它的网络结构最为小巧,同时图像推理速度最快达0.007s。YO-LOv5的网络结构主要由四部分组成,分别是Input、Backbone、Neck、Head,其网络结构图如图所示。

Yolov5网络结构图

1.1Input端

        Input使用了Mosaic数据增强、自适应锚框计算、图片尺寸处理。Mosaic数据增强把4张图片,采用随机缩放、随机裁剪、随机排布的方式进行拼接,极大地丰富了检测数据集,尤其是增加了很多小目标,让网络结构的鲁棒性更好。在YOLOv5算法中,不同的数据集,会设定不同初始长宽的锚框,在训练数据的时候,在初始锚框的基础上得到预测框,把它和真实框比较,算出两者差距,反向更新,迭代更新网络结构参数,自适应锚框计算可以得到最佳锚框值。在目标检测算法中,要训练图片的尺寸都不相同,要把原始图片统一缩放到一个固定尺寸,再输入到网络中进行训练,本文图片的尺寸为608×608×3。

1.2Backone

        Backbone包含Focus、CSP和SPP。Focus不存在于其他YOLO算法中,主要是用来进行切片操作,例如608×608×3的图像在Focus结构中进行切片操作后,变成304×304×12大小,在进行32个卷集核的卷积操作,成为304×304×32的特征图。YOLOv4中只有一种CSP结构,而YOLOv5中有两种,CSP1_x和CSP2_x,它们分别应用于Backbone和Neck中,YOLOv4的CSP结构只存在Backbone中,CSP结构如图1所示,其中CSP1_x的x表示CSP1中有x个Resunit(残差组件),CSP2_x的x表示CSP2中有2x个CBL,x影响着网络结构的深度。在Backbone中,采用SPP(空间向量金字塔池化),对特征图做最大池化,将不同尺度的特征图拼接在一起。

(1)Focus结构

        Focus结构中关键的是切片操作,切片操作演示过程,将4×4×3的特征图经过切片处理,变成2×2×12的特征图。将608×608×3的三通道图像输进Focus结构,经过切片操作,先变成304×304×12的特征图,之后,经过使用32个卷积核的卷积操作,最终变成304×304×32的特征图。需要注意的是,YOLOv5s网络结构中的Focus结构使用了32个卷积核,进行卷积操作,而其他三种网络结构,使用的卷积核数量有所增加。

Focus结构图

(2)CSP结构

        YOLOv5中有两种结构的CSP,CSP1_X结构在Backbone主干网络中,另一种CSP2_X结构在Neck中。对于Backbone的主干网络结构,CSP模块中的卷积核大小都是3*3,步进值为2,假如输入的图像尺寸是608*608,那么它的特征图变化的规律是:608*608->304*304->152*152->76*76->38*38->19*19,最终得到了一个19*19大小的特征图。

        使用CSP模块的优点:1.增强网络的学习能力,使得训练出来的模型既能保持轻量化,又能有较高的准确性。2.降低计算瓶颈。3.降低内存成本。

CSP结构图

(3)SPP结构

        SPP结构详细介绍:https://www.cnblogs.com/zongfa/p/9076311.html

SPP结构图

1.3Neck

        Neck中采用了FPN+PAN的结构,FPN是自上而下的,利用上采样的方式对信息进行传递融合,获得预测的特征图。PAN采用自底向上的特征金字塔。具体结构如图所示。

FPN+PAN结构图 

1.4Prediction

        Prediction包括Bounding box损失函数和非极大值抑制(NMS)。YOLOv5中使用GIOU_Loss作为损失函数,有效解决了边界框不重合时问题。在目标检测预测结果处理阶段,针对出现的众多目标框的筛选,采用加权NMS操作,获得最优目标框。

  1. GIOU_Loss损失函数

        目标检测算法的损失函数一般由Classificition Loss(分类损失函数)以及Bounding Box Regeression Loss(回归损失函数)两大部分组成。回归损失函数在近几年的发展过程是:Smooth L1 Loss->IOU_Loss(2016)->GIOU_Loss(2019)->DIOU_Loss(2020)->CIOU_Loss(2020)。

IOU_Loss图

 图是IOU_Loss,可以看出黄色框是预测框,蓝色框是真实框。假设预测框和真实框的交集为A,并集为B,IOU定义为交集A除以并集B,IOU的Loss为:

        IOU的Loss比较简单,但存在两个问题。

        问题1:预测框和真实框不相交的情况,如图(a)状态1所示,此时IOU为0,无法反应出预测框和真实框距离的远近,此时损失函数不能求导,IOU_Loss损失函数无法优化预测框和真实框不相交的情况

特殊状态的IOU_Loss图

        问题2:当预测框和真实框大小相同,IOU也可能会相同,如上图(b)(c)的状态2和状态3的情况所示,此时IOU_Loss损失函数也不能区分这两种情况的不同。因此使用GIOU_Loss来进行改进。

GIOU_Loss图

         如上图是GIOU_Loss,黄色框是预测框,蓝色框是真实框,令预测框和真实框的最小外接矩形为集合C,差集定义为集合C和并集B的差,则GIOU_Loss为:

        GIOU_Loss损失函数提高了衡量相交尺度的方式,减少了单纯IOU_Loss时的不足。

2.实验及结果

2.1实验数据集及实验环境

2.1.1数据集

        数据集采用Kaggle上的Face Mask Detection,数据集一共853张图片,划分为三个类,一种是戴口罩的,一种是不戴口罩的,还有一种是没有戴好口罩的。数据集链接:https://www.kaggle.com/andrewmvd/face-mask-detection

        数据集展示:

        下载下来后,这些数据集还不能直接使用。因为yolov5不支持xml文件处理,而是支持txt文件。所以首先将这些数据按照下图这样的目录格式整理好:

        然后运行下面的代码,将该数据集转换成Yolov5能够使用的数据集:

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import random
from shutil import copyfile

classes = ["with_mask", "without_mask","mask_weared_incorrect"]
# classes=["ball"]

TRAIN_RATIO = 80


def clear_hidden_files(path):
    dir_list = os.listdir(path)
    for i in dir_list:
        abspath = os.path.join(os.path.abspath(path), i)
        if os.path.isfile(abspath):
            if i.startswith("._"):
                os.remove(abspath)
        else:
            clear_hidden_files(abspath)


def convert(size, box):
    dw = 1. / size[0]
    dh = 1. / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)


def convert_annotation(image_id):
    in_file = open('VOCdevkit/VOC2007/Annotations/%s.xml' % image_id)
    out_file = open('VOCdevkit/VOC2007/YOLOLabels/%s.txt' % image_id, 'w')
    tree = ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
             float(xmlbox.find('ymax').text))
        bb = convert((w, h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
    in_file.close()
    out_file.close()


wd = os.getcwd()
wd = os.getcwd()
data_base_dir = os.path.join(wd, "VOCdevkit/")
if not os.path.isdir(data_base_dir):
    os.mkdir(data_base_dir)
work_sapce_dir = os.path.join(data_base_dir, "VOC2007/")
if not os.path.isdir(work_sapce_dir):
    os.mkdir(work_sapce_dir)
annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
if not os.path.isdir(annotation_dir):
    os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
if not os.path.isdir(image_dir):
    os.mkdir(image_dir)
clear_hidden_files(image_dir)
yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
if not os.path.isdir(yolo_labels_dir):
    os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)
yolov5_images_dir = os.path.join(data_base_dir, "images/")
if not os.path.isdir(yolov5_images_dir):
    os.mkdir(yolov5_images_dir)
    clear_hidden_files(yolov5_images_dir)
    yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
    if not os.path.isdir(yolov5_labels_dir):
        os.mkdir(yolov5_labels_dir)
    clear_hidden_files(yolov5_labels_dir)
    yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
    if not os.path.isdir(yolov5_images_train_dir):
        os.mkdir(yolov5_images_train_dir)
    clear_hidden_files(yolov5_images_train_dir)
    yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
    if not os.path.isdir(yolov5_images_test_dir):
        os.mkdir(yolov5_images_test_dir)
    clear_hidden_files(yolov5_images_test_dir)
    yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
    if not os.path.isdir(yolov5_labels_train_dir):
        os.mkdir(yolov5_labels_train_dir)
    clear_hidden_files(yolov5_labels_train_dir)
    yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
    if not os.path.isdir(yolov5_labels_test_dir):
        os.mkdir(yolov5_labels_test_dir)
    clear_hidden_files(yolov5_labels_test_dir)

    train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
    test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
    train_file.close()
    test_file.close()
    train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
    test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
    list_imgs = os.listdir(image_dir)  # list image files
    prob = random.randint(1, 100)
    print("Probability: %d" % prob)
    for i in range(0, len(list_imgs)):
        path = os.path.join(image_dir, list_imgs[i])
        if os.path.isfile(path):
            image_path = image_dir + list_imgs[i]
            voc_path = list_imgs[i]
            (nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))
            (voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))
            annotation_name = nameWithoutExtention + '.xml'
            annotation_path = os.path.join(annotation_dir, annotation_name)
            label_name = nameWithoutExtention + '.txt'
    label_path = os.path.join(yolo_labels_dir, label_name)
    prob = random.randint(1, 100)
    print("Probability: %d" % prob)
    if (prob < TRAIN_RATIO):  # train dataset
        if os.path.exists(annotation_path):
            train_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention)  # convert label
            copyfile(image_path, yolov5_images_train_dir + voc_path)
            copyfile(label_path, yolov5_labels_train_dir + label_name)
    else:  # test dataset
        if os.path.exists(annotation_path):
            test_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention)  # convert label
            copyfile(image_path, yolov5_images_test_dir + voc_path)
            copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()

         运行完上面的代码后,会生成下面的目录格式:

        可以看到通过运行上面的代码,在VOCdevkit目录下生成了images和lables文件夹,这两个文件夹下又有train和val文件夹,这个就是需要的数据集了。其中train对应的就是训练集,val对应的就是测试集。

2.2.2数据集标注

        因为数据集中已经给定了标注好的xml文件,这里就不再进行标注。数据集标注主要是通过labelimg进行标注。

2.2.3实验环境

       实验环境采用Ubuntu 20.04.2+双路Intel 4110CPU+64G内存+RTX2080Ti显卡+Anaconda3进行实验。

2.2Yolov5网络训练

       一般为了缩短网络的训练时间,并达到更好的精度,我们一般加载预训练权重进行网络的训练。而yolov5的5.0版本给我们提供了几个预训练权重,我们可以对应我们不同的需求选择不同的版本的预训练权重。通过如下的图可以获得权重的名字和大小信息,可以预料的到,预训练权重越大,训练出来的精度就会相对来说越高,但是其检测的速度就会越慢。预训练权重可以通过这个网址进行下载,本次训练自己的数据集用的预训练权重为yolov5s.pt。

        我们先将Yolov5通过git将代码pull到本地,可以看到如下的目录格式:

        然后我们将下载好的Yolov5.pt模型文件放在Yolov5的根目录下。将数据集文件也放在Yolov5根目录下:

        现在来对代码的整体目录做一个介绍:

├── data:主要是存放一些超参数的配置文件(这些文件(yaml文件)是用来配置训练集和测试集还有验证集的路径的,其中还包括目标检测的种类数和种类的名称);还有一些官方提供测试的图片。如果是训练自己的数据集的话,那么就需要修改其中的yaml文件。但是自己的数据集不建议放在这个路径下面,而是建议把数据集放到yolov5项目的同级目录下面。

├── models:里面主要是一些网络构建的配置文件和函数,其中包含了该项目的四个不同的版本,分别为是s、m、l、x。从名字就可以看出,这几个版本的大小。他们的检测测度分别都是从快到慢,但是精确度分别是从低到高。这就是所谓的鱼和熊掌不可兼得。如果训练自己的数据集的话,就需要修改这里面相对应的yaml文件来训练自己模型。

├── utils:存放的是工具类的函数,里面有loss函数,metrics函数,plots函数等等。

├── weights:放置训练好的权重参数。

├── detect.py:利用训练好的权重参数进行目标检测,可以进行图像、视频和摄像头的检测。

├── train.py:训练自己的数据集的函数。

├── test.py:测试训练的结果的函数。

├──requirements.txt:这是一个文本文件,里面写着使用yolov5项目的环境依赖包的一些版本,可以利用该文本导入相应版本的包。

        然后我们修改models/yolov5s.yaml文件将nc改成3,因为我们是个3分类问题。并且在data目录下创建一个biaoqing.yaml文件,其内容为:

train: Mask_Datas/images/train  # train images (relative to 'path') 128 images
val: Mask_Datas/images/val  # val images (relative to 'path') 128 images


# Classes
nc: 3  # number of classes
names: ['with_mask', 'without_mask', 'mask_weared_incorrect']  # class names

        里面指定了训练集和测试集的路径,以及分类的内容。

        然后我们修改Yolov5根目录下的train.py文件,修改超参数如下图。其中—weights指定了预训练权重,--cfg指定预训练权重的配置文件,--data指定数据集的配置文件。还有一些参数比如—epochs指定了训练的轮数,默认是300轮,可以根据需要进行修改。还有--batch-size指定一次读取多少张照片,一般都是指定8的倍数张。根据自己的电脑性能进行修改。

        修改完上面的参数后,我们将代码上传到了运行环境如下:

        通过requirements.txt安装了所需要的库。直接运行python train.py即可开始进行训练,下面是训练图

        经过200轮训练后,我们生成了一个best.pt,也就是在这200轮训练得出来的最后的权重文件。

2.3实验结果与分析 

 

        我们查看results.png文件如下图:

训练过程中随着迭代次数增加,各种数值变化,如上图所示,图中各个数值的含义如下:

GIo U:数值越接近0,目标框画的越准确。

Objectness:数值越接近0,对目标检测得越准确。

Classification:数值越接近0,目标分类越准确。

Precision:准确率,即标出的正确目标个数除以标出的目标总个数,越接近1,准确率越高。

Recall:召回率,即标出的正确目标个数除以需要标出的目标总个数,越接近1,准确率越高。

m AP@0.5和m AP@0.5:0.95:AP是用Precision和Recall作为两坐标轴作图后围成的面积,越接近1,准确率越高。

置信度图

                     P-R图

 

混淆矩阵 

 实验效果:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

三天吃透MySQL八股文(2023最新整理)

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

博客系统(界面设计)

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录实现博客列表页预期效果导航栏页面主体左右布局左侧区域右侧区域完整代码实现博客详情页预期效果导航栏 左侧右侧完整代码实现…

全国程序员薪酬大曝光!看完我酸了····

2023年&#xff0c;随着互联网产业的蓬勃发展&#xff0c;程序员作为一个自带“高薪多金”标签的热门群体&#xff0c;被越来越多的人所关注。在过去充满未知的一年中&#xff0c;他们的职场现状发生了一定的改变。那么&#xff0c;程序员岗位的整体薪资水平、婚恋现状、职业方…

认识TomcatMavenServlet第一个Servlet程序

文章目录一、什么是Tomcat、什么是Servlet二、Tomcat的下载与使用关于下载启动欢迎页面查看可能出现的问题博客系统静态页面的部署三、什么是Maven四、第一个servlet程序1.创建Maven项目2.引入依赖3.创建目录结构4.编写程序5.打包程序6.部署程序7.验证小结五、servlet程序简化版…

学习 Python 之 Pygame 开发魂斗罗(四)

学习 Python 之 Pygame 开发魂斗罗&#xff08;四&#xff09;继续编写魂斗罗1. 创建子弹类2. 根据玩家方向和状态设置子弹发射的位置(1). 站立向右发射子弹(2). 站立向左发射子弹(3). 站立朝上发射子弹(4). 蹲下发射子弹(5). 向斜方发射子弹(6). 奔跑时发射子弹(7). 跳跃时发射…

图片的美白与美化

博主简介 博主是一名大二学生&#xff0c;主攻人工智能研究。感谢让我们在CSDN相遇&#xff0c;博主致力于在这里分享关于人工智能&#xff0c;c&#xff0c;Python&#xff0c;爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主&#xff0c;博主会继续更新的&#xff0c…

Python雪花代码

前言 用python画个雪花玩玩&#xff0c;源码在文末公众号哈。 雪花类 class Snow(): #雪花类 def __init__(self): self.r 6 #雪花的半径 self.x ra.randint(-1000,1000) #雪花的横坐标 self.y ra.randint(-500,5…

读书笔记——《富爸爸穷爸爸》

《富爸爸穷爸爸》&#xff0c;以前不屑读这种书。这种书就是那种走进书店放在门口展销位的成功学著作&#xff0c;一眼看上去没什么实在的内容&#xff0c;看上去很不靠谱&#xff0c;感觉就是骗一些社会底层又做着暴富梦的人来买的&#xff0c;但是由于自身原因或环境局限根本…

MySQL基本查询

文章目录表的增删查改Create&#xff08;创建&#xff09;单行数据 全列插入多行数据 指定列插入插入否则更新替换Retrieve&#xff08;读取&#xff09;SELECT列全列查询指定列查询查询字段为表达式查询结果指定别名结果去重WHERE 条件基本比较BETWEEN AND 条件连接OR 条件连…

【面试题】Python软件工程师能力评估试题(一)

文章目录前言应试者需知&#xff08;一&#xff09;Python 语言基础能力评估1、理解问题并完成代码&#xff1a;2、阅读理解代码&#xff0c;并在空白处补充完整代码&#xff1a;3、编写一个装饰器&#xff1a;exposer4、阅读代码并在空白处补充完整代码&#xff1a;5、自行用P…

嵌入式 串口通信

目录 1、通信的基本概念 1.1 串行通信 1.2 并行通信 2、串行通信的特点 2.1 单工 2.2 半双工 2.3 全双工 3、串口在STM32的引脚 4、STM32的串口的接线 4.1 STM32的串口1和电脑通信的接线方式 4.2 单片机和具备串口的设备连接图 5、串口通信协议 6、串口通信…

linux进程管理

进程管理 进程是启动的可执行程序的一个指令 1、进程简介 &#xff08;1&#xff09;进程的组成部分 已分配内存的地址空间安全属性&#xff0c;包括所有权凭据和特权程序代码的一个或多个执行线程进程状态 &#xff08;2&#xff09;程序和进程的区别 程序是一个静态的二进制…

第十四届蓝桥杯第三期模拟赛 C/C++ B组 原题与详解

文章目录 一、填空题 1、1 找最小全字母十六进制数 1、1、1 题目描述 1、1、2 题解关键思路与解答 1、2 给列命名 1、2、1 题目描述 1、2、2 题解关键思路与解答 1、3 日期相等 1、3、1 题目描述 1、3、2 题解关键思路与解答 1、4 乘积方案数 1、4、1 题目描述 1、4、2 题解关…

28岁小公司程序员,无车无房不敢结婚,要不要转行?

大家好&#xff0c;这里是程序员晚枫&#xff0c;又来分享程序员的职场故事了~ 今天分享的这位朋友叫小青&#xff0c;我认识他2年多了。以前从事的是土木行业&#xff0c;2年前找我咨询转行程序员的学习路线和职业规划后&#xff0c;通过自学加入了一家创业公司&#xff0c;成…

分享几个常用的运维 shell 脚本

今天咸鱼给大家分享几个不错的 Linux 运维脚本&#xff0c;这些脚本中大量使用了 Linux 的文本三剑客&#xff1a; awkgrepsed 建议大家这三个工具都要了解并最好能够较为熟练的使用 根据 PID 显示进程所有信息 根据用户输入的PID&#xff0c;过滤出该PID所有的信息 #! /b…

第十四届蓝桥杯三月真题刷题训练——第 11 天

目录 第 1 题&#xff1a;卡片 题目描述 运行限制 第 2 题&#xff1a;路径_dpgcd 运行限制 第 3 题&#xff1a;字符统计 问题描述 输入格式 输出格式 样例输入 样例输出 评测用例规模与约定 运行限制 第 4 题&#xff1a;费用报销 第 1 题&#xff1a;卡片 题…

我今天要彻底搞懂线程状态的变化

&#x1f497;推荐阅读文章&#x1f497; &#x1f338;JavaSE系列&#x1f338;&#x1f449;1️⃣《JavaSE系列教程》&#x1f33a;MySQL系列&#x1f33a;&#x1f449;2️⃣《MySQL系列教程》&#x1f340;JavaWeb系列&#x1f340;&#x1f449;3️⃣《JavaWeb系列教程》…

MATLAB | 这些花里胡哨的热图怎么画

好早之前写过一个绘制相关系数矩阵的代码&#xff0c;但是会自动求相关系数&#xff0c;而且画出来的热图只能是方形&#xff0c;这里写一款允许nan值出现&#xff0c;任意形状的热图绘制代码&#xff0c;绘制效果如下&#xff1a; 如遇到bug请后台提出&#xff0c;并去gitee下…

出道即封神的ChatGPT,现在怎么样了?

从互联网的普及到智能手机&#xff0c;都让广袤的世界触手而及&#xff0c;如今身在浪潮中的我们&#xff0c;已深知其力。前阵子爆火的ChatGPT&#xff0c;不少人保持观望态度。现如今&#xff0c;国内关于ChatGPT的各大社群讨论&#xff0c;似乎沉寂了不少&#xff0c;现在怎…

Linux IPC:匿名管道 与 命名管道

目录一、管道的理解二、匿名管道三、命名管道四、管道的通信流程五、管道的特性进程间通信方式有多种&#xff0c;本文介绍的是管道&#xff0c;管道分为匿名管道和命名管道。 一、管道的理解 生活中的管道用来传输资源&#xff0c;例如水、石油之类的资源。而进程间通信的管道…