空洞卷积或完全卷积

发布时间:2025-06-24 18:17:05  作者:北方职教升学中心  阅读量:293


3.9 正则化技术的探索

在面对小规模数据集时,ENet通过空间Dropout技术有效地防止了过拟合。

3.6 信息保存维度的创新

ENet在信息保存维度上采用了创新的策略,通过并行执行池化和卷积操作,并连接结果特征图,显著提高了模型的推理速度。为了平衡这两个方面,ENet借鉴了SegNet的策略,通过索引保存和稀疏上采样技术,有效地减少了内存消耗,同时尽可能地保留了空间细节。
在这里插入图片描述
论文地址:https://arxiv.org/abs/1606.02147
训练代码:https://download.csdn.net/download/matt45m/89113606
🔥计算机视觉、
在这些卷积层之间,使用批量归一化(Batch Normalization, BN)和PReLU激活函数。ENet可以实时处理图像,比嵌入式平台上的SegNet快近20倍。在复杂的视觉场景中,如道路环境中的行人和骑行者识别,空洞卷积使得模型能够更好地理解对象与其周围环境的关系。这一策略的成功实施,为后续的特征提取和上采样操作奠定了坚实的基础。1. 主卷积层:这是模块的核心,可以是标准卷积、这一点在需要处理大量高分辨率图像的数据中心级应用中尤为重要,因为ENet能够以更快、毕业辅导、一方面,降低分辨率可以减少计算负担,提高处理速度;另一方面,这可能导致空间信息的损失,影响分割的精确度。PReLU允许每个特征图独立学习非线性斜率,提供了更大的灵活性和适应性。更高效的方式执行大规模的计算任务,从而可能为企业节省大量的成本。这种跨平台的高效性能,使得ENet能够适应各种不同的应用场景,从移动设备到数据中心,都能提供准确、

4.数据集处理

数据集的标注用labelme,使用的数据是书本,为了提取书本边缘:
在这里插入图片描述
在这里插入图片描述

5.模型训练

5.1 环境安装
conda create --name enet python=3.7source activate enetconda install pytorch torchvision cudatoolkit=10.2 -c pytorchpip install cython matplotlib tqdm opencv-python scipy pillow
5.2 数据处理
import osimport sysimport globimport jsonimport mathimport uuidimport randomimport numpy as npimport PIL.Imageimport PIL.ImageDrawfrom tqdm import tqdmdef shape_to_mask(img_shape, points, shape_type=None,                  line_width=10, point_size=5):    mask = np.zeros(img_shape[:2], dtype=np.uint8)    mask = PIL.Image.fromarray(mask)    draw = PIL.ImageDraw.Draw(mask)    xy = [tuple(point) for point in points]    if shape_type == 'circle':        assert len(xy) == 2, 'Shape of shape_type=circle must have 2 points'        (cx, cy), (px, py) = xy        d = math.sqrt((cx - px) ** 2 + (cy - py) ** 2)        draw.ellipse([cx - d, cy - d, cx + d, cy + d], outline=1, fill=1)    elif shape_type == 'rectangle':        assert len(xy) == 2, 'Shape of shape_type=rectangle must have 2 points'        draw.rectangle(xy, outline=1, fill=1)    elif shape_type == 'line':        assert len(xy) == 2, 'Shape of shape_type=line must have 2 points'        draw.line(xy=xy, fill=1, width=line_width)    elif shape_type == 'linestrip':        draw.line(xy=xy, fill=1, width=line_width)    elif shape_type == 'point':        assert len(xy) == 1, 'Shape of shape_type=point must have 1 points'        cx, cy = xy[0]        r = point_size        draw.ellipse([cx - r, cy - r, cx + r, cy + r], outline=1, fill=1)    else:        assert len(xy) > 2, 'Polygon must have points more than 2'        draw.polygon(xy=xy, outline=1, fill=1)    mask = np.array(mask, dtype=bool)    return maskdef shapes_to_label(img_shape, shapes, label_name_to_value):    cls = np.zeros(img_shape[:2], dtype=np.int32)    ins = np.zeros_like(cls)    instances = []    for shape in shapes:        points = shape['points']        label = shape['label']        group_id = shape.get('group_id')        if group_id is None:            group_id = uuid.uuid1()        shape_type = shape.get('shape_type', None)        cls_name = label        instance = (cls_name, group_id)        if instance not in instances:            instances.append(instance)        ins_id = instances.index(instance) + 1        cls_id = 1        # cls_id = label_name_to_value[cls_name]        mask = shape_to_mask(img_shape[:2], points, shape_type)        cls[mask] = cls_id        ins[mask] = ins_id    return cls, insdef lblsave(filename, lbl):    if os.path.splitext(filename)[1] != '.png':        filename += '.png'    # Assume label ranses [-1, 254] for int32,    # and [0, 255] for uint8 as VOC.    if lbl.min() >= 0 and lbl.max() <= 255:        lbl_pil = PIL.Image.fromarray(lbl.astype(np.uint8), mode='L')        lbl_pil.save(filename)    else:        raise ValueError(            '[%s] Cannot save the pixel-wise class label as PNG. '            'Please consider using the .npy format.' % filename        )if __name__ == '__main__':    data_path = sys.argv[1]    out_path = sys.argv[2]    if not os.path.exists(out_path):        os.makedirs(out_path)    label_name_to_value = {        '_background_': 0,        'a': 1,    }    json_fns = glob.glob(os.path.join(data_path, '**/*.json'), recursive=True)    out_lst = []    for json_fn in tqdm(json_fns):        with open(json_fn, 'r') as f:            data = json.load(f)        img_shape = (data['imageHeight'], data['imageWidth'])        lbl, _ = shapes_to_label(img_shape, data['shapes'], label_name_to_value)        image_fn = json_fn.replace('.json', '.jpg')        label_fn = json_fn.replace('.json', '_label.png')        if not os.path.exists(image_fn):            print(image_fn + ' not exists')            continue        else:            img = PIL.Image.open(image_fn)            mask = PIL.Image.open(label_fn)            if img.size != mask.size:                print(image_fn, img.size, mask.size)                continue        lblsave(label_fn, lbl)        out_lst.append(image_fn + ',' + label_fn)    random.shuffle(out_lst)    trn_num = int(len(out_lst) * 0.9)    with open(os.path.join(out_path, 'train.txt'), 'w') as f:        f.write('\n'.join(out_lst[:trn_num]))    with open(os.path.join(out_path, 'val.txt'), 'w') as f:        f.write('\n'.join(out_lst[trn_num:]))

执行以下命令:

python generate_label.py /path/to/ datasets

结果将在datasets目录下生成train.txt和val.txt,分别表示训练集和验证集。在原始论文中,这些卷积层被描述为具有3×3卷积核的conv操作。

ENet在NVIDIA TX1硬件平台上的应用展示了其实时、这一指标综合考虑了所有类别的分割结果,提供了模型整体性能的一个全面评估。

3.8 空洞卷积的性能提升

空洞卷积在不增加计算负担的情况下,显著提高了模型的感受野。空洞卷积或完全卷积。

3.4 编码器与解码器的结构优化

ENet的编码器-解码器架构经过精心设计,以确保编码器能够充分提取图像特征,而解码器则专注于恢复这些特征以实现精确的像素级预测。这种分解策略不仅提高了模型的运行速度,还通过增加非线性层,增强了模型的表达能力。iIoU(实例间交叉验证)以及整体类别IoU方面均优于SegNet。

2.3 编码器和解码器
2.4 特殊设计
2.5 性能优化

3.设计选择

3.1 特征图分辨率的权衡

在语义分割任务中,特征图分辨率的调整是一个双刃剑。快速的语义分割服务。1. 1×1扩展卷积:这个卷积层用于将通道数目扩展回原来的大小,以便于与其他特征图进行合并。它的设计考虑了计算效率和内存使用,同时保持了优秀的分割性能。

最后,整体类别IoU的提升进一步证实了ENet在整体分割性能上的优势。代码获取,远程协助,代码定制,私聊会回复!
✍🏻作者简介:机器学习,深度学习,卷积神经网络处理,图像处理
🚀B站项目实战:https://space.bilibili.com/364224477
😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+
🤵‍♂代做需求:@个人主页


在这里插入图片描述

2.2 Bottleneck模块

每个bottleneck模块由三个卷积层组成:

  1. 1×1投影卷积:这个卷积层用于减小通道数目,为后续的主卷积层做准备。
    参数说明:第一个参数为训练图像目录,第二个参数为输出文件夹

    5.3 训练

    运行以下命令:

    python main.py -m train --save-dir save/ENet_Card --name ENet --dataset card --dataset-dir datasets --epochs 100 --height 512 --width 512 --print-step

    参数说明:
    -- save-dir:训练模型保存路径
    –dataset:训练数据类型
    –dataset-dir:train.txt和val.txt所在路径
    –epochs:训练总epoch数
    –height:输入高度
    –width:输入宽度
    –print-step:是否打印每个step的loss

    5.4 测试

    运行以下命令:

    python demo.py demo_imgs save/ENet_Card/ENet results

    参数说明:
    第一个参数:输入图像路径
    第二个参数: 训练得到的模型
    第三个参数:输出文件夹路径

    5.5 转成onnx

    运行以下命令:

    python convert_to_onnx.py --input save/ENet_Card/ENet --output save/ENet_Card/ENet.onnx

    参数说明:
    –input:训练得到的模型
    –output: 输出onnx模型,可以采用opencv的dnn调用

    6.模型推理

    #include <iostream>#include <string>#include <vector>#include <fstream>#include <sstream>#include <opencv2/opencv.hpp>#include <opencv2/dnn.hpp>void show_img(std::string name, const cv::Mat& img) {	cv::namedWindow(name, 0);	int max_rows = 500;	int max_cols = 600;	if (img.rows >= img.cols) {		cv::resizeWindow(name, cv::Size(img.cols * max_rows / img.rows, max_rows));	}	else {		cv::resizeWindow(name, cv::Size(max_cols, img.rows * max_cols / img.cols));	}	cv::imshow(name, img);}int main(int argc, char* argv[]) {	std::string path = "D:/data/DataSet/book/";	std::vector<std::string> filenames;	cv::glob(path, filenames, false);	for (auto img_name : filenames)	{		cv::Mat img = cv::imread(img_name);		cv::Size reso(512, 512);		cv::Mat blob = cv::dnn::blobFromImage(img, 1.0 / 255, reso,			cv::Scalar(0, 0, 0), false, false);		cv::dnn::Net net = cv::dnn::readNet("model/ENet.onnx");		net.setInput(blob);		auto t0 = cv::getTickCount();		cv::Mat out = net.forward();		std::cout << out << std::endl;		auto t1 = cv::getTickCount();		std::cout << "elapsed time: " << (t1 - t0) * 1000.0 / cv::getTickFrequency() << "ms" << std::endl;		cv::Mat segm = cv::Mat::zeros(out.size[2], out.size[3], CV_8UC1);		for (int i = 0; i < out.size[2] * out.size[3]; ++i)		{			if (out.ptr<float>(0, 0)[i] < out.ptr<float>(0, 1)[i])			{				segm.data[i] = 255;			}		}		cv::resize(segm, segm, img.size(), 0.0, 0.0, cv::INTER_NEAREST);		show_img("img", img);		show_img("out", segm);		cv::waitKey();	}	return 0;}

    在这里插入图片描述
    在这里插入图片描述

    7.实验结果

    推理时间:
    在这里插入图片描述
    硬件要求:
    在这里插入图片描述

    基准测试:
    Cityscapes:
    在这里插入图片描述
    ENet在类别IoU(类别间交叉验证)、代码获取,远程协助,代码定制,私聊会回复!
    ✍🏻作者简介:机器学习,深度学习,卷积神经网络处理,图像处理
    🚀B站项目实战:https://space.bilibili.com/364224477
    😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+
    🤵‍♂代做需求:@个人主页

    2.网络架构

    ENet的网络架构是一个高度优化的结构,旨在实现高效的实时语义分割。

    尺寸方面,ENet的设计注重减少模型的参数数量和计算复杂度。图像处理、这种不对称的结构设计反映了两个部分在任务中的不同重要性,同时也减少了模型的参数数量,提高了整体的运行效率。作业帮助、
    ENet不仅在嵌入式设备上提供了实时语义分割的可能性,而且在高性能计算平台上也展现了其强大的计算能力。SegNet的架构相对对称,包含大量的参数,而ENet则采用了一种大型编码器与小型解码器的组合,这种设计哲学基于一个观点:解码器的主要作用是对编码器的输出进行上采样,并微调细节,而这并不需要一个复杂的结构。这个阶段使用最大池化和卷积层来减少图像的空间维度,同时增加网络的深度。
    在这里插入图片描述
    CamVid:
    在这里插入图片描述
    SUN RGB-D:准确性的差异不应掩盖这两个网络之间巨大的性能差距。图像处理、作业帮助、这种技术的应用使得ENet在保持分辨率的同时,能够捕捉到更广泛的上下文信息,从而提高了分割的精度。因此,ENet的参数数量大幅减少,仅为0.7MB,这使得整个网络可以适配在嵌入式处理器的快速片上内存中,从而显著降低了硬件要求。

    此外,ENet在iIoU方面也展现了更好的结果,这表明ENet在处理实例级别的分割任务时同样表现出色。下面是对ENet网络架构的详细描述:
    在这里插入图片描述

    2.1 Initial模块

    Initial模块是整个网络的起始部分,它接收原始输入图像并开始构建特征图。

    这些性能指标的比较揭示了ENet在语义分割任务的几个关键评估领域中展现出更优的性能。这种正则化方法不仅提高了模型的泛化能力,还通过随机丢弃部分特征图,增加了模型的鲁棒性。便携的嵌入式解决方案的强大实力。实例分割不仅需要识别图像中的不同类别,还需要区分属于同一类别的不同实例,这对于理解复杂场景中的个体对象非常重要。
    🔥计算机视觉、

    3.7 分解卷积的计算优化

    ENet通过将大的卷积核分解为多个小的卷积核,有效地减少了模型的参数数量和计算复杂度。

    8.总结

    ENet所提出的这一创新神经网络架构,专为语义分割任务量身打造,其核心设计理念在于充分发挥嵌入式设备上有限资源的潜力。ENet的实验结果表明,空洞卷积在提高分割精度方面起到了关键作用。

    3.5 非线性激活函数的优化

    在ENet中,传统的ReLU激活函数被PReLU所取代,这一改变基于对网络行为的深入分析。具体来说,ENet在类别IoU方面的表现超过了SegNet,这意味着ENet在识别和分割不同类别的像素时更为准确。这种策略的实施,不仅优化了信息流,还减少了信息的丢失,提高了分割的准确性。

    3.3 早期下采样的策略

    ENet的早期下采样策略体现了对计算资源的精细管理。毕业辅导、

    计算机视觉——实时语义分割ENet算法原理与模型训练

    1.概述

    ENet(Efficient Neural Network)是一种专为实时语义分割任务设计的深度神经网络架构。这一平台的高效性能不仅适用于移动设备,ENet的实验还表明,即使在如NVIDIA Titan X这样的高端GPU上,ENet同样能够发挥出色的效果。在这一目标的指引下,ENet的工作取得了显著的成效,不仅成功实现了与现有技术相比更为高效的计算性能,而且在某些情况下,还实现了与之相匹配甚至更优的结果,即便这些现有技术对计算能力和内存的需求远高于ENet的设计。

    3.2 空洞卷积的应用

    空洞卷积(Dilated Convolution)作为一种能够增大感受野的技术,对于提高模型对上下文信息的捕捉能力至关重要。如果bottleneck模块负责下采样,那么会在主分支上添加一个最大池化层,并且第一个1×1投影卷积会被一个步长为2的2×2卷积替换,以匹配特征图的数量。这使得ENet成为实时语义分割应用中一个非常有力的竞争者,尤其是在需要高精度分割结果的场景中。与SegNet相比,ENet在尺寸和推理时间上都有显著的优势,同时能够提供相当或更好的准确性。这种策略基于一个核心假设:视觉信息在空间上存在高度的冗余性,可以通过更紧凑的表示形式进行编码。

    这些结果表明,ENet在处理语义分割任务时,不仅在单个类别上表现出色,而且在整体分割精度上也超越了SegNet。类别IoU是一个衡量模型在特定类别上分割精度的指标,它通过计算预测的分割区域与真实标注之间的重叠程度来评估模型的性能。通过在网络的初始阶段大幅度减小输入尺寸,ENet有效地降低了后续层的计算负担。这种激活函数的选择不仅提高了模型的表达能力,还有助于在不同的网络层中实现更精细的信息处理。