python基于DeeplabV3Plus开发构建手机屏幕表面缺陷图像分割识别系统

Deeplab是图像分割领域非常强大的模型,在前面的博文中我们也进行过很多相应项目的开发实践,感兴趣的话可以自行移步阅读即可:

《基于DeepLabv3Plus开发构建人脸人像分割系统》

《基于DeepLabV3实践路面、桥梁、基建裂缝裂痕分割》

《基于DeepLabV3Plus实现质检划痕图像分割识别系统》

《基于DeepLabV3Plus实现无人机航拍目标分割识别系统》

《python基于DeepLabv3+开发构建河道分割识别系统》

《基于DeepLabV3Plus实现焊缝分割识别系统》

《python基于DeeplabV3Plus开发构建裂缝分割识别系统,并实现裂缝宽度计算测量》

 《AI助力隧道等洞体类场景下水泥基建缺陷检测,基于DeeplabV3Plus开发构建洞体场景下壁体建筑缺陷分割系统》

本文的核心目的就是想要基于DeepLabV3Plus来开发构建手机屏幕表面缺陷图像智能分割识别系统,助力工业生产流程上的智能化,首先看下实例效果:

在图像分割领域中有不少优秀出色的网络,DeepLab系列就是其中非常经典的分支之一,在之前的很多项目中陆续都已经有接触到了,在处理图像分割中表现出色。

DeepLabV3Plus是一种用于语义分割任务的深度学习模型,它是DeepLab系列模型的一种改进版本。下面详细解释DeepLabV3Plus的原理:

引入空洞卷积(Dilated Convolution):DeepLabV3Plus利用空洞卷积来扩大感受野,以更好地捕捉图像中的上下文信息。传统的卷积操作只关注局部区域,而空洞卷积通过在卷积核中引入间隔(或称为膨胀率),使得卷积核能够跳过一些像素点,从而扩大感受野。

多尺度金字塔池化(Multi-scale Atrous Spatial Pyramid Pooling, ASPP):DeepLabV3Plus使用ASPP模块来处理不同尺度的信息。ASPP模块使用多个并行的空洞卷积分支,每个分支具有不同的膨胀率,以捕捉来自不同感受野的特征。最后,将这些特征进行汇总并进行融合,以生成更丰富的特征表示。

融合低级特征:为了结合低层次的细节特征,DeepLabV3Plus引入了一个编码器-解码器结构。在编码器部分,通过堆叠多个残差块和降采样操作,提取高层次的语义特征。然而,这会导致空间信息的丢失。因此,在解码器部分,使用反卷积(或上采样)操作来恢复特征图的分辨率,并与对应的低级特征进行融合。

融合注意力机制:为了进一步提升融合的效果,DeepLabV3Plus引入了注意力机制。该机制利用辅助监督信号和空间注意力模块,自适应地对不同的特征图进行加权融合。这样可以使网络更加关注重要的特征区域,提升语义分割的准确性。

DeepLabV3Plus通过引入空洞卷积、多尺度金字塔池化、融合低级特征和注意力机制等改进,提升了语义分割任务的性能。它能够准确地标记图像中每个像素的类别,从而在许多计算机视觉领域(如图像分割、自动驾驶等)中发挥着重要作用。

整体网络结构图如下所示:

接下来看下数据集:

共包含:油污、划痕和斑点这三种常见的手机屏幕缺损类型。

DeepLabV3Plus核心实现如下:

import tensorflow as tf
from keras import backend as K
from keras.layers import (
    Activation,
    BatchNormalization,
    Concatenate,
    Conv2D,
    DepthwiseConv2D,
    Dropout,
    GlobalAveragePooling2D,
    Input,
    Lambda,
    Softmax,
    ZeroPadding2D,
)
from keras.models import Model
from modules.mobilenet import mobilenetV2
from modules.Xception import Xception


def SepConv_BN(
    x,
    filters,
    prefix,
    stride=1,
    kernel_size=3,
    rate=1,
    depth_activation=False,
    epsilon=1e-3,
):
    if stride == 1:
        depth_padding = "same"
    else:
        kernel_size_effective = kernel_size + (kernel_size - 1) * (rate - 1)
        pad_total = kernel_size_effective - 1
        pad_beg = pad_total // 2
        pad_end = pad_total - pad_beg
        x = ZeroPadding2D((pad_beg, pad_end))(x)
        depth_padding = "valid"
    if not depth_activation:
        x = Activation("relu")(x)
    x = DepthwiseConv2D(
        (kernel_size, kernel_size),
        strides=(stride, stride),
        dilation_rate=(rate, rate),
        padding=depth_padding,
        use_bias=False,
    )(x)
    x = BatchNormalization(epsilon=epsilon)(x)
    if depth_activation:
        x = Activation("relu")(x)
    x = Conv2D(
        filters, (1, 1), padding="same", use_bias=False
    )(x)
    x = BatchNormalization(epsilon=epsilon)(x)
    if depth_activation:
        x = Activation("relu")(x)
    return x


def Deeplabv3(
    input_shape, num_classes, alpha=1.0, backbone="mobilenet", downsample_factor=16
):
    img_input = Input(shape=input_shape)
    x, atrous_rates, skip1 = MobileNet(
        img_input, alpha, downsample_factor=downsample_factor
    )
    size_before = tf.keras.backend.int_shape(x)
    b0 = Conv2D(256, (1, 1), padding="same", use_bias=False)(x)
    b0 = BatchNormalization(epsilon=1e-5)(b0)
    b0 = Activation("relu")(b0)
    b1 = SepConv_BN(
        x, 256, "A!", rate=atrous_rates[0], depth_activation=True, epsilon=1e-5
    )
    b2 = SepConv_BN(
        x, 256, "A2", rate=atrous_rates[1], depth_activation=True, epsilon=1e-5
    )
    b3 = SepConv_BN(
        x, 256, "A3", rate=atrous_rates[2], depth_activation=True, epsilon=1e-5
    )
    b4 = GlobalAveragePooling2D()(x)
    b4 = Lambda(lambda x: K.expand_dims(x, 1))(b4)
    b4 = Lambda(lambda x: K.expand_dims(x, 1))(b4)
    b4 = Conv2D(256, (1, 1), padding="same", use_bias=False)(b4)
    b4 = BatchNormalization(epsilon=1e-5)(b4)
    b4 = Activation("relu")(b4)
    b4 = Lambda(
        lambda x: tf.image.resize_images(x, size_before[1:3], align_corners=True)
    )(b4)
    x = Concatenate()([b4, b0, b1, b2, b3])
    x = Conv2D(256, (1, 1), padding="same", use_bias=False)(x)
    x = BatchNormalization(epsilon=1e-5)(x)
    x = Activation("relu")(x)
    x = Dropout(0.1)(x)
    skip_size = tf.keras.backend.int_shape(skip1)
    x = Lambda(
        lambda xx: tf.image.resize_images(xx, skip_size[1:3], align_corners=True)
    )(x)
    dec_skip1 = Conv2D(
        48, (1, 1), padding="same", use_bias=False
    )(skip1)
    dec_skip1 = BatchNormalization(epsilon=1e-5)(
        dec_skip1
    )
    dec_skip1 = Activation(tf.nn.relu)(dec_skip1)
    x = Concatenate()([x, dec_skip1])
    x = SepConv_BN(x, 256, "DC0", depth_activation=True, epsilon=1e-5)
    x = SepConv_BN(x, 256, "DC1", depth_activation=True, epsilon=1e-5)
    size_before3 = tf.keras.backend.int_shape(img_input)
    x = Conv2D(num_classes, (1, 1), padding="same")(x)
    x = Lambda(
        lambda xx: tf.image.resize_images(xx, size_before3[1:3], align_corners=True)
    )(x)
    x = Softmax()(x)
    model = Model(img_input, x)
    return model

基于轻量级的MobileNet作为骨干网络来实现特征的提取,即使是在算力较弱的设备下也可以完成训练。在自己的项目中也可以直接整合集成使用。

训练完成后对整体进行可视化,核心实现如下:

from matplotlib import pyplot as plt
 
 
with open("train.txt") as f:
    train_list = [float(one) for one in f.readlines() if one.strip()]
with open("val.txt") as f:
    val_list = [float(one) for one in f.readlines() if one.strip()]
print("train_list_length: ", len(train_list))
print("val_list_length: ", len(val_list))
 
 
plt.clf()
plt.figure(figsize=(8, 6))
plt.plot(train_list, label="Train Loss Cruve", c="g")
plt.plot(val_list, label="Val Loss Cruve", c="b")
plt.title("Model Loss Cruve")
plt.savefig("loss.png")

结果如下所示:

这里分为两个阶段进行训练,首先是冷冻训练,主要是基于预训练权重来进行训练,如下:

这一阶段大部分参数被冻结,模型的整体损失比较高,完成预热之后解冻模型参数开启全量训练,如下所示:

这里为了方便使用模型,开发了专用的可视化系统界面,实例推理计算效果如下所示:

直观来看效果还是不错的,有兴趣的话都是可以自己动手实践一下的。

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

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

相关文章

金蝶 Apusic 应用服务器任意文件上传漏洞

声明 本文仅用于技术交流,请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。 1. 产品介绍 金蝶 Apusic 是金蝶集团旗下的一款企业级应用服务器&#…

鸿蒙原生应用/元服务开发-新手入门练习心得

1.先根据案例模仿代码(页面跳转案例) 点击next后跳转页面,点击back返回第一个页面 2.模块化层层拆解代码 先创建了row,一行,在这一行里面写代码: 内容都放到Column中 Text内置组件可以直接引用文本 thi…

前端笔记(四)Flex 布局

标准流 标准流也叫文档流,指的是标签在页面中默认的派不规则,例如:块元素独占一行,行内元素可以一行显示多个。 但是很多的网页布局都是块元素在一行中显示的,这时候就需要浮动和 Flex 布局,浮动只需要了解…

地址栏不安全提示

在使用浏览器时访问网站的时候,我们可能会遇到地址栏提示不安全的情况。这种情况通常都是是由于未安装有效SSL证书或者网站SSL证书过期等原因导致的。本文将介绍如何处理地址栏提示不安全的问题,以确保我们的上网安全。 1,缺少SSL证书&#x…

基于Java SSM框架实现超市进销存购物商城管理系统项目【项目源码+论文说明】

基于java的SSM框架实现超市进销存购物商城管理系统演示 摘要 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,社区生活超市管理系统当然也不能排除在外。社区生活超市管理系统…

TQ2440开发板-按键驱动程序设计

目录 按键测试底板原理图核心板原理图使用轮询方式设计按键程序 按键测试底板原理图 TQ2440开发板有4个用户可编程按键,它们直接与CPU的GPIO相连,低电平触发中断,资源占用如下图所示: 核心板原理图 使用轮询方式设计按键程序 按…

使用FFMPEG转码,转单声道,转标准WAV,转PCM

本文为使用FFMPEG命令行的方式处理音频,来获取想要得到的音频文件。 零、使用命令行查看编码封装信息 格式:ffprobe.exe -show_format inputfile 例子:ffprobe.exe -show_format .\stereo_44_16bit.wav 运行结果为下图: 如图可…

HNU计算机结构体系-实验2:CPU动态指令调度Tomasulo

文章目录 实验2 CPU动态指令调度Tomasulo一、实验目的二、实验说明三、实验内容问题1:问题2:问题3:问题4:问题5: 四、思考题问题1:问题2: 五、实验总结 实验2 CPU动态指令调度Tomasulo 一、实验…

前端canvas的基础使用

一、介绍 前端中的 Canvas 是一种用于在网页上绘制图形的 HTML 元素。它提供了一个可以通过 JavaScript 进行绘制的 2D 绘图环境。使用 Canvas,您可以绘制图形,包括线条、矩形、圆形、文本和图像。Canvas 为开发人员提供了灵活自由的绘图能力&#xff0…

FlexRay总线信号译码

我们用虹科Pico汽车示波器捕捉了FlexRay总线信号 ,一定要用专用的高速探头,不能用基本的BNC测试线来测。因为FlexRay的传输信号太快,用基本的BNC测试线来测,信号会失真严重。 专用的高速探头有TA499,如下图&#xff1a…

Vue3-01-创建项目

环境准备 1.需要用到 16.0 以及更高版本的 node.js 2.使用vscode编辑器进行项目开发可以在命令行中查看node的版本号: node -v创建项目 1.准备一个目录 例如,我创建项目的时候是在该目录下进行的;D:\projectsTest\vue3project2.执行创建命令(*&#x…

Nacos 基础篇:Nacos简介、基本概念、基本架构、Standalone单机搭建部署

文章目录 什么是Nacos基本架构逻辑架构及其组件介绍领域模型数据模型服务领域模型配置领域模型 下载目录结构配置启动 什么是Nacos Nacos:(Dynamic) Naming and Configuration Service,动态的服务发现和配置的服务,是一个更易于构建云原生应…

Qt/C++音视频开发58-逐帧播放/上一帧下一帧/切换播放进度/实时解码

一、前言 逐帧播放是近期增加的功能,之前也一直思考过这个功能该如何实现,对于mdk/qtav等内核组件,可以直接用该组件提供的接口实现即可,而对于ffmpeg,需要自己处理,如果有缓存的数据的话,可以…

Linux(17):认识与分析登录档

什么是登录档 【详细而确实的分析以及备份系统的登录文件】是一个系统管理员应该要进行的任务之一。 登录档 就是记录系统活动信息的几个文件,例如:何时、何地(来源IP)、何人(什么服务名称)、做了什么动作(讯息登录啰)。 换句话说就是:记录系…

设置网络发现,合理利用共享,让自己在准确的地方出现或隐藏

本文介绍如何在Windows 11中打开或关闭网络发现。它还解释了网络发现的用途以及你可能想使用(或不使用)它的时间。 如何在Windows 11中切换网络发现 可以在“设置”中打开和关闭网络发现。 1、使用WINI快捷方式打开“设置”或从任务栏中搜索。 2、选…

CAS-ESM设置起始时间不起作用的原因

问题描述: 今天在运行CAS-ESM2.0的时候出现了一个怪事,不论我怎么修改start_ymd,模式总是从1850年,1851 年开始跑。 解决方法: 修改start_type为startup,初始积分。 原因解释: CAS-ESM2.0代码…

Rust的From与Into Trait

Into的本质是调用了From Trait 的方法。 From是底层的方法,把From实现了,Into的实现,编译器会自动根据From Trait生成Into Trait的代码 编译器自动类型推导出Into Trait的U的类型,调用了U类型的From的方法,实现其他类…

JavaSE基础50题:18. 写一个递归方法,输入一个非负整数,返回组成它的数字之和。例如:输入1729,则应该返回1+7+2+9,它的和是19

概述 写一个递归方法&#xff0c;输入一个非负整数&#xff0c;返回组成它的数字之和。例如&#xff1a;输入1729&#xff0c;则应该返回1729&#xff0c;它的和是19。 代码 public class P18 {public static int func(int n) {if (n < 10) {return n;}return n%10 func…

[gRPC实现go调用go]

1什么是RPC RPC&#xff1a;Remote Procedure Call&#xff0c;远程过程调用。简单来说就是两个进程之间的数据交互。正常服务端的接口服务是提供给用户端(在Web开发中就是浏览器)或者自身调用的&#xff0c;也就是本地过程调用。和本地过程调用相对的就是&#xff1a;假如两个…

使用Pytorch实现变分自编码器

使用Pytorch实现变分自编码器 可以结合这篇VAE讲解文章阅读这篇blog post代码。 # Import necessary packages. import os import torch import torch.nn as nn import torch.nn.functional as F import torchvision from torchvision import transforms from torchvision.ut…