深度学习在钢板表面缺陷与字符识别中的应用【附代码】

博主简介:擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导,毕业论文、期刊论文经验交流。

 ✅成品或者定制,扫描文章底部微信二维码。


(1) 基于多尺度感受野与图像重构的钢板表面缺陷分类方法

钢板表面缺陷图像具有类内差异性大、形态复杂多样的特点,同一类型的缺陷在不同的生产条件和拍摄环境下呈现出截然不同的视觉表现,这对缺陷分类算法的特征提取能力提出了严峻挑战。传统的卷积神经网络采用固定尺寸的卷积核提取特征,难以同时捕获缺陷的细微纹理特征和整体形状特征,导致分类精度受限。本研究提出了基于多尺度感受野融合的缺陷分类方法,该方法在特征提取网络中并行使用多个不同尺寸的卷积核,分别提取图像中不同尺度的特征信息。小尺寸卷积核捕获缺陷的局部细节特征,如边缘纹理、微小裂纹等;大尺寸卷积核提取缺陷的整体轮廓特征,如缺陷的形状、大小和分布模式。通过特征融合模块将不同尺度的特征图进行拼接和加权融合,形成具有丰富语义信息的综合特征表示,实现对复杂钢板表面缺陷图像的全面表征。针对钢铁行业缺陷图像与通用图像数据集存在显著域差异的问题,在预训练模型的基础上引入图像重构任务作为辅助训练目标。图像重构模块采用编码器解码器结构,编码器将输入图像编码为紧凑的特征向量,解码器从特征向量重建原始图像。通过最小化重构误差,促使网络学习到适用于钢板表面图像的特征表示,弥合源域和目标域之间的特征分布差异。同时引入基于自编码器的特征降维结构,对高维的底层特征进行压缩,去除冗余信息,保留对分类任务最具判别性的特征成分,提升网络的泛化能力,避免在小样本数据集上出现过拟合现象。实验结果表明,该方法在中厚板和热轧带钢表面缺陷图像分类任务中分别取得了百分之九十八点五和百分之九十五点七的分类精度,相比直接使用预训练模型分别提升了两个百分点以上。

(2) 基于分类优先网络与分组卷积的钢板表面缺陷检测算法

传统的深度学习目标检测算法采用先定位后分类的处理流程,首先通过区域建议网络或锚框机制生成候选区域,然后对候选区域进行分类判断。这种流程在钢板表面缺陷检测中存在召回率低、定位不准确、可解释性差等问题,主要原因是缺陷目标的尺度变化大、形状不规则,区域建议网络难以生成准确的候选框,且分类和定位任务共享特征导致两个任务之间存在冲突。本研究提出了分类优先网络的缺陷检测算法,颠覆了传统的检测流程,首先对输入图像进行类别判断,然后根据分类结果指导边界框的回归预测。分类优先网络的核心是分组卷积分类网络,该网络采用相互独立的卷积层组分别提取不同类别缺陷的特征信息。每组卷积层专门负责一类缺陷的特征学习,不同类别的特征提取过程互不干扰,实现了不同类别缺陷特征的有效分离。这种设计使得网络能够为每类缺陷学习到最具判别性的特征表示,避免了不同类别特征之间的相互影响和混淆。在边界框回归阶段,根据分类网络的预测结果选择相应的特征图组进行回归计算,使得回归任务只关注当前类别缺陷的定位,提高了定位精度。分组卷积分类网络的另一个重要优势是增强了网络的可解释性,每组卷积层输出的特征图与原始图像中的缺陷区域存在明显的空间对应关系,特征响应强的区域对应缺陷存在的位置,这种对应关系使得缺陷检测结果更加直观可信,便于质检人员进行结果验证和分析。实验结果表明,分类优先网络在中厚板和热轧板表面缺陷检测任务中均取得了优异的识别效果,检测精度和召回率均有显著提升。

(3) 基于卷积自编码器与半监督对抗生成网络的缺陷分类方法

钢铁生产线上每天产生海量的钢板表面图像,但由于人工标注成本高昂,只有少量图像具有缺陷类别标签,大量无标签图像未能得到有效利用。在有标签样本不足的情况下,传统的监督学习方法难以训练出高性能的分类模型。本研究提出了基于卷积自编码器与半监督对抗生成网络相结合的缺陷分类方法,充分利用大量无标签图像进行无监督特征学习,提升有标签样本的分类精度。方法分为两个阶段,第一阶段在大规模无标签缺陷图像上训练卷积自编码器,自编码器由编码器和解码器两部分组成,编码器将输入图像压缩为低维的潜在特征向量,解码器从潜在向量重建原始图像。通过最小化重建误差,编码器学习到能够有效表征缺陷图像的特征提取能力,这一过程不需要任何标签信息,完全依靠图像自身的结构特性进行无监督学习。第二阶段构建半监督对抗生成网络,将第一阶段训练好的编码器作为判别器的主体结构,修改判别器的输出层,使其同时预测输入样本的真假属性和类别属性。生成器网络负责生成逼真的缺陷图像样本,判别器需要区分真实样本和生成样本,并对真实样本进行类别分类。在训练过程中,无标签样本参与真假判断任务,帮助判别器学习数据的整体分布特征;有标签样本同时参与真假判断和类别分类任务,提供监督信号指导分类器的学习。

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
from torchvision import models

class MultiScaleFeatureExtractor(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(MultiScaleFeatureExtractor, self).__init__()
        self.branch1 = nn.Sequential(
            nn.Conv2d(in_channels, out_channels // 4, kernel_size=1),
            nn.BatchNorm2d(out_channels // 4),
            nn.ReLU(inplace=True)
        )
        self.branch2 = nn.Sequential(
            nn.Conv2d(in_channels, out_channels // 4, kernel_size=3, padding=1),
            nn.BatchNorm2d(out_channels // 4),
            nn.ReLU(inplace=True)
        )
        self.branch3 = nn.Sequential(
            nn.Conv2d(in_channels, out_channels // 4, kernel_size=5, padding=2),
            nn.BatchNorm2d(out_channels // 4),
            nn.ReLU(inplace=True)
        )
        self.branch4 = nn.Sequential(
            nn.Conv2d(in_channels, out_channels // 4, kernel_size=7, padding=3),
            nn.BatchNorm2d(out_channels // 4),
            nn.ReLU(inplace=True)
        )
        self.fusion = nn.Conv2d(out_channels, out_channels, kernel_size=1)
    def forward(self, x):
        b1 = self.branch1(x)
        b2 = self.branch2(x)
        b3 = self.branch3(x)
        b4 = self.branch4(x)
        out = torch.cat([b1, b2, b3, b4], dim=1)
        return self.fusion(out)

class ImageReconstructionModule(nn.Module):
    def __init__(self, feature_dim=512, image_size=224):
        super(ImageReconstructionModule, self).__init__()
        self.decoder = nn.Sequential(
            nn.Linear(feature_dim, 1024),
            nn.ReLU(inplace=True),
            nn.Linear(1024, 2048),
            nn.ReLU(inplace=True),
            nn.Linear(2048, 3 * 56 * 56),
            nn.Sigmoid()
        )
        self.upsample = nn.Upsample(size=(image_size, image_size), mode='bilinear', align_corners=True)
    def forward(self, features):
        decoded = self.decoder(features)
        decoded = decoded.view(-1, 3, 56, 56)
        reconstructed = self.upsample(decoded)
        return reconstructed

class FeatureDimensionReducer(nn.Module):
    def __init__(self, input_dim, latent_dim):
        super(FeatureDimensionReducer, self).__init__()
        self.encoder = nn.Sequential(
            nn.Linear(input_dim, 512),
            nn.ReLU(inplace=True),
            nn.Linear(512, latent_dim)
        )
        self.decoder = nn.Sequential(
            nn.Linear(latent_dim, 512),
            nn.ReLU(inplace=True),
            nn.Linear(512, input_dim)
        )
    def forward(self, x):
        latent = self.encoder(x)
        reconstructed = self.decoder(latent)
        return latent, reconstructed

class DefectClassificationNet(nn.Module):
    def __init__(self, num_classes=6):
        super(DefectClassificationNet, self).__init__()
        resnet = models.resnet50(pretrained=True)
        self.backbone = nn.Sequential(*list(resnet.children())[:-2])
        self.multi_scale = MultiScaleFeatureExtractor(2048, 512)
        self.pool = nn.AdaptiveAvgPool2d(1)
        self.reducer = FeatureDimensionReducer(512, 128)
        self.classifier = nn.Linear(128, num_classes)
        self.reconstructor = ImageReconstructionModule(512)
    def forward(self, x, return_reconstruction=False):
        features = self.backbone(x)
        multi_scale_features = self.multi_scale(features)
        pooled = self.pool(multi_scale_features).flatten(1)
        reduced, reconstructed_features = self.reducer(pooled)
        logits = self.classifier(reduced)
        if return_reconstruction:
            reconstructed_image = self.reconstructor(pooled)
            return logits, reconstructed_image
        return logits

class GroupedConvClassifier(nn.Module):
    def __init__(self, in_channels, num_classes):
        super(GroupedConvClassifier, self).__init__()
        self.class_convs = nn.ModuleList()
        for _ in range(num_classes):
            self.class_convs.append(nn.Sequential(
                nn.Conv2d(in_channels, 64, 3, padding=1),
                nn.BatchNorm2d(64),
                nn.ReLU(inplace=True),
                nn.Conv2d(64, 32, 3, padding=1),
                nn.BatchNorm2d(32),
                nn.ReLU(inplace=True),
                nn.AdaptiveAvgPool2d(1)
            ))
        self.fc = nn.Linear(32 * num_classes, num_classes)
    def forward(self, x):
        class_features = []
        class_maps = []
        for conv in self.class_convs:
            feat_map = conv[:-1](x)
            class_maps.append(feat_map)
            feat = conv[-1](feat_map).flatten(1)
            class_features.append(feat)
        combined = torch.cat(class_features, dim=1)
        logits = self.fc(combined)
        return logits, class_maps

class ClassificationFirstDetector(nn.Module):
    def __init__(self, num_classes=6):
        super(ClassificationFirstDetector, self).__init__()
        resnet = models.resnet50(pretrained=True)
        self.backbone = nn.Sequential(*list(resnet.children())[:-2])
        self.grouped_classifier = GroupedConvClassifier(2048, num_classes)
        self.bbox_regressors = nn.ModuleList()
        for _ in range(num_classes):
            self.bbox_regressors.append(nn.Sequential(
                nn.Conv2d(32, 16, 3, padding=1),
                nn.ReLU(inplace=True),
                nn.Conv2d(16, 4, 1)
            ))
    def forward(self, x):
        features = self.backbone(x)
        class_logits, class_maps = self.grouped_classifier(features)
        predicted_class = class_logits.argmax(dim=1)
        batch_bboxes = []
        for i in range(x.size(0)):
            cls_idx = predicted_class[i].item()
            bbox = self.bbox_regressors[cls_idx](class_maps[cls_idx][i:i+1])
            batch_bboxes.append(bbox)
        return class_logits, batch_bboxes

class ConvAutoencoder(nn.Module):
    def __init__(self, latent_dim=256):
        super(ConvAutoencoder, self).__init__()
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 32, 4, stride=2, padding=1),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(32, 64, 4, stride=2, padding=1),
            nn.BatchNorm2d(64),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(64, 128, 4, stride=2, padding=1),
            nn.BatchNorm2d(128),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Conv2d(128, 256, 4, stride=2, padding=1),
            nn.BatchNorm2d(256),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Flatten(),
            nn.Linear(256 * 14 * 14, latent_dim)
        )
        self.decoder = nn.Sequential(
            nn.Linear(latent_dim, 256 * 14 * 14),
            nn.Unflatten(1, (256, 14, 14)),
            nn.ConvTranspose2d(256, 128, 4, stride=2, padding=1),
            nn.BatchNorm2d(128),
            nn.ReLU(inplace=True),
            nn.ConvTranspose2d(128, 64, 4, stride=2, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.ConvTranspose2d(64, 32, 4, stride=2, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True),
            nn.ConvTranspose2d(32, 3, 4, stride=2, padding=1),
            nn.Tanh()
        )
    def forward(self, x):
        latent = self.encoder(x)
        reconstructed = self.decoder(latent)
        return latent, reconstructed

class SemiSupervisedGAN(nn.Module):
    def __init__(self, num_classes=6, latent_dim=256):
        super(SemiSupervisedGAN, self).__init__()
        self.generator = nn.Sequential(
            nn.Linear(100, 256 * 14 * 14),
            nn.Unflatten(1, (256, 14, 14)),
            nn.ConvTranspose2d(256, 128, 4, stride=2, padding=1),
            nn.BatchNorm2d(128),
            nn.ReLU(inplace=True),
            nn.ConvTranspose2d(128, 64, 4, stride=2, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.ConvTranspose2d(64, 32, 4, stride=2, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True),
            nn.ConvTranspose2d(32, 3, 4, stride=2, padding=1),
            nn.Tanh()
        )
        self.discriminator_encoder = ConvAutoencoder(latent_dim).encoder
        self.real_fake_head = nn.Linear(latent_dim, 1)
        self.class_head = nn.Linear(latent_dim, num_classes)
    def discriminate(self, x):
        features = self.discriminator_encoder(x)
        real_fake = torch.sigmoid(self.real_fake_head(features))
        class_logits = self.class_head(features)
        return real_fake, class_logits
    def generate(self, z):
        return self.generator(z)

class ThresholdFocalLoss(nn.Module):
    def __init__(self, alpha=0.25, gamma=2.0, threshold=0.5):
        super(ThresholdFocalLoss, self).__init__()
        self.alpha = alpha
        self.gamma = gamma
        self.threshold = threshold
    def forward(self, predictions, targets):
        ce_loss = F.cross_entropy(predictions, targets, reduction='none')
        pt = torch.exp(-ce_loss)
        focal_weight = torch.where(pt > self.threshold, self.alpha * (1 - pt) ** self.gamma, torch.ones_like(pt))
        return (focal_weight * ce_loss).mean()

class LightweightCharacterRecognizer(nn.Module):
    def __init__(self, num_classes=36):
        super(LightweightCharacterRecognizer, self).__init__()
        mobilenet = models.mobilenet_v2(pretrained=True)
        self.features = mobilenet.features
        self.pool = nn.AdaptiveAvgPool2d(1)
        self.classifier = nn.Sequential(
            nn.Dropout(0.2),
            nn.Linear(1280, num_classes)
        )
    def forward(self, x):
        features = self.features(x)
        pooled = self.pool(features).flatten(1)
        return self.classifier(pooled)

if __name__ == "__main__":
    defect_classifier = DefectClassificationNet(num_classes=6)
    detector = ClassificationFirstDetector(num_classes=6)
    cae_sgan = SemiSupervisedGAN(num_classes=6)
    char_recognizer = LightweightCharacterRecognizer(num_classes=36)
    dummy_input = torch.randn(4, 3, 224, 224)
    class_output = defect_classifier(dummy_input)
    det_output, bboxes = detector(dummy_input)


如有问题,可以直接沟通

👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坷拉博士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值