00 - 前言
欢迎学习《基于 AI 图像处理的铝板缺陷检测》实验。在本实验中,你将深入了解如何运用计算机视觉(CV)领域的 AI 模型,搭建一个高效精准的铝板缺陷检测系统,并利用开源数据集和昇腾 AI 芯片对模型效果加以验证。
学习目标
在本课程中,您将学习一些与使用 AI 图像处理技术实现铝板缺陷检测有关的重要概念,包括:
- 铝板图像数据的预处理方法
- 采用计算机视觉检测铝板各类缺陷的方法
- 目标检测后处理的方法
- 端到端深度学习工作流
目录
本实验分为四个核心部分。第一部分主要介绍案例的应用场景,阐述铝板缺陷检测的重要性及意义;第二部分会详细阐述端到端的解决方案,搭建起技术实现的整体框架;第三部分会手把手指导您完成代码编写与实现;最后一部分给出测试题,帮助您巩固学习内容。 1. 场景介绍 2. 解决方案 3. 代码实战 4. 课后测试
JupyterLab
在本实操实验中,我们将使用 JupyterLab 管理我们的环境。JupyterLab 界面是一个控制面板,可供您访问交互式 iPython Notebook、所用环境的文件夹结构,以及用于进入 Ubuntu 操作系统的终端窗口,只需要点击菜单栏的小三角就可以运行代码。
尝试执行下方单元中的一条简单的 print(打印)语句。
# DO NOT CHANGE THIS CELL # activate this cell by selecting it with the mouse or arrow keys then use the keyboard shortcut [Shift+Enter] to execute print('This is just a simple print statement') This is just a simple print statement
01 场景介绍
在铝板的生产制造以及后续使用过程中,铝板的质量把控至关重要。然而,由于生产工艺、原材料质量、存储环境等诸多因素影响,铝板表面可能会出现各种各样的缺陷,例如 non_conduct(不导电)、abrasion_mark(磨损痕迹)、corner_leak(边角泄漏)、orange_peel(橘皮)、leak(泄漏)、jet_flow(喷射流)、paint_bubble(漆泡)、pit(凹坑)、motley(杂色)、dirty_spot(脏污)等。这些缺陷的存在,不仅会影响铝板的外观品质,更可能严重削弱铝板的物理性能和使用寿命,在一些对铝板质量要求严苛的应用场景中,如航空航天、电子设备制造等领域,哪怕是微小的缺陷都可能导致整个产品出现故障甚至报废,给企业带来巨大的经济损失以及潜在的安全隐患。
传统的铝板缺陷检测方法多依赖人工目视检查或者借助一些简单的量具进行测量,这类方式效率低下,而且极易受到检测人员主观因素影响,长时间检测还容易出现疲劳导致漏检、误检等情况。随着人工智能技术,尤其是 AI 图像处理技术与深度学习的发展,铝板缺陷检测有了全新的、高效且精准的解决方案。借助先进的 AI 模型对铝板表面图像进行分析,能够快速、准确地识别出各种类型的缺陷,实现自动化的质量检测,大幅提高检测效率和准确性,保障铝板产品的质量,满足不同行业对铝板质量的严格要求。
02 解决方案
一个完整的铝板缺陷检测方案主要涵盖以下几个核心模块:
2.1 图像预处理模块
该模块负责接收来自铝板生产线上的摄像头或者专门用于采集铝板图像的设备所传输的图像数据。由于采集环境的复杂性以及设备自身的特性,原始图像往往存在诸多问题,像是图像中存在噪声干扰、亮度不均匀、对比度欠佳等,并且图像的尺寸、分辨率以及像素值范围等通常与后续要使用的 AI 模型输入要求并不匹配。所以,图像预处理模块需要对这些原始图像开展一系列的预处理操作,包括但不限于降噪处理,去除图像中的噪点,使图像更加清晰;进行图像增强,调整亮度、对比度等参数,突出铝板表面的特征信息;按照模型要求对图像尺寸进行调整,可能涉及到 resize、transpose、padding 等操作,以此提升图像质量,剔除干扰信息,为后续模型的准确处理奠定良好的基础。同时,为了能够实现对铝板的实时、连续检测,还需要构建一个高效稳定的图像流管理器,确保源源不断的图像数据可以有序、快速地输送给 AI 模型。
2.2 缺陷检测模型
本实验选用在目标检测领域表现卓越的 YOLOv5 模型来检测铝板缺陷,具体为 YOLOv5_s 版本。YOLOv5 模型经历了不断的发展和优化,它的主干网络采用 CSPDarknet53 结构,这种结构能够高效地提取图像多尺度特征,无论是铝板上较大面积的 orange_peel 缺陷,还是相对微小的 pit 缺陷等,都能从中捕捉到关键特征信息。在模型的 Neck 部分,引入了特征金字塔网络(FPN)与 PAN(Path Aggregation Network)结构,通过这两个结构可以巧妙地融合不同层次的特征图,极大地增强了模型对不同大小目标物体的检测能力,保证各种尺度的铝板缺陷都能被检测出来。而 Head 部分则负责最终的分类与边界框回归任务,它依据 Neck 传来的融合特征图,能够精准输出缺陷的具体类别、所在位置以及对应的置信度信息。选用 YOLOv5 模型用于铝板缺陷检测具备诸多优势,例如它经过大量的数据训练优化后,对铝板各类缺陷的定位和分类准确性很高;具有出色的实时性能,完全可以满足铝板生产线上实时监控的需求;拥有很强的多尺度检测能力,能够适配不同距离、不同大小的铝板缺陷目标;而且模型整体结构紧凑,便于在实际生产环境中进行部署与进一步优化。
2.3 目标检测后处理模块
由于目标检测模型输出的原始结果中,往往会包含数量众多的重复检测框,这些冗余信息会给后续的结果分析和缺陷判断带来很大困扰。为了获取清晰、准确且便于分析的检测结果,我们需要对这些目标检测结果进行去重处理,在本方案中,主要运用 non_max_suppression 算法来实现这一目的。通过该算法,可以筛选出最具代表性、可信度最高的检测框,去除那些因模型的敏感度或者其他因素导致的重复、冗余的框,让最终呈现的铝板缺陷检测结果更加直观、可靠。
03 动手实验
3.1 实验准备
数据集准备
实验所用的图像数据源自公开的铝板缺陷检测数据集,该数据集包含了100多张带有不同类型缺陷的铝板图像,并且每一张图像都精准标注了缺陷的类别以及具体位置信息,数据丰富且准确,为我们的模型训练和验证提供了有力支撑。本实验把数据集下载后取样存放于当前目录下的 ./test_images
目录中,方便后续代码进行读取和处理。
模型权重
本实验采用的 YOLOv5_s 模型权重需要从这个链接下载,该权重已经基于大量数据进行了训练,检测精度足够好。
3.2 构建图像处理类
首先,我们要从测试图片目录中读取图像,并构建 Python 类来封装图像预处理流程,这样做的好处是可以实现代码复用,同时便于对整个预处理过程进行高效管理。 第一步,导入所需的三方库:
import cv2 import glob import numpy as np from pathlib import Path
接着,创建图像预处理类 LoadImages:
class LoadImages: def __init__(self, path, img_size=640, stride=32, auto=True): """ Initializes YOLOv5 loader for images, supporting directories. Args: path (str): Directory path containing images. img_size (int): Image size for resizing. stride (int): Stride for resizing. auto (bool): Automatic image resizing. """ self.img_size = img_size self.stride = stride self.auto = auto self.files = sorted(glob.glob(str(Path(path).resolve()) + '/*.*')) # directory self.nf = len(self.files) # number of files assert self.nf > 0, f"No images found in {path}. Supported formats are: {IMG_FORMATS}" def __iter__(self): """Initializes iterator by resetting count and returns the iterator object itself.""" self.count = 0 return self def __next__(self): """Advances to the next file in the dataset, raising StopIteration if at the end.""" if self.count == self.nf: raise StopIteration path = self.files[self.count] self.count += 1 im0 = cv2.imread(path) # BGR assert im0 is not None, f"Image Not Found {path}" # Padded resize im = letterbox(im0, self.img_size, stride=self.stride, auto=self.auto)[0] # padded resize im = im.transpose((2, 0, 1))[::-1] # HWC to CHW, BGR to RGB im = np.ascontiguousarray(im) # contiguous return path, im, im0
其中,letterbox 函数用于对图像进行填充等相关操作,以满足模型输入对于图像尺寸等方面的要求,其代码实现如下:
def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleFill=False, scaleup=True, stride=32): """Resizes and pads image to new_shape with stride-multiple constraints, returns resized image, ratio, padding.""" shape = im.shape[:2] # current shape [height, width] if isinstance(new_shape, int): new_shape = (new_shape, new_shape) # Scale ratio (new / old) r = min(new_shape[0] / shape[0], new_shape[1] / shape[1]) if not scaleup: # only scale down, do not scale up (for better val mAP) r = min(r, 1.0) # Compute padding ratio = r, r # width, height ratios new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r)) dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding if auto: # minimum rectangle dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding elif scaleFill: # stretch dw, dh = 0.0, 0.0 new_unpad = (new_shape[1], new_shape[0]) ratio = new_shape[1] / shape[1], new_shape[0] / shape[0] # width, height ratios dw /= 2 # divide padding into 2 sides dh /= 2 if shape[::-1] != new_unpad: # resize im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR) top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1)) left, right = int(round(dw - 0.1)), int(round(dw + 0.1)) im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border return im, ratio, (dw, dh)
完成数据类的定义后,我们可以对其进行测试,读取并预处理图像:
source = "./test_images/" dataset = LoadImages(source) count = 0 for path, im, im0 in dataset: print(im.shape) if count > 5: break count += 1 (3, 480, 640) (3, 480, 640) (3, 480, 640) (3, 480, 640) (3, 480, 640) (3, 480, 640) (3, 480, 640)
3.3 使用 YOLOv5 模型检测铝板缺陷
依据前面所介绍的相关知识,我们将使用 YOLOv5_s 模型来精准定位铝板上的各类缺陷。 首先,需要在设备的工作目录克隆 yolov5 模型代码,并且把代码仓路径添加到 python 环境中,这样才能方便我们后续顺利地调用模型,操作如下:
# git clone https://github.com/ultralytics/yolov5 # export PYTHONPATH="./yolov5/:$PYTHONPATH"
此外,还要把3.1章节下载的 YOLOv5_s 权重文件 best.pt
放到工作目录下。 准备好权重文件后,接下来测试一下模型的推理功能:
from models.common import DetectMultiBackend # 导入 yolov5_s 模型 import torch import torch_npu # 使用昇腾硬件推理 from torch_npu.contrib import transfer_to_npu # 使用昇腾硬件推理 import warnings warnings.filterwarnings('ignore') # 屏蔽warnings model = DetectMultiBackend("./best.pt") # 实例化模型 img_loader = LoadImages('./test_images') for path, im, im0s in img_loader: im = torch.from_numpy(im) im = im.half() if model.fp16 else im.float() # uint8 to fp16/32 im /= 255 # 把像素范围转成(0, 1) if len(im.shape) == 3: im = im[None] # expand for batch dim pred = model(im)[0] # 调用yolo进行推理 print(pred.shape) break Fusing layers... YOLOv5m summary: 290 layers, 20889303 parameters, 0 gradients, 48.0 GFLOPs torch.Size([1, 18900, 15])
3.4 后处理函数
正如前面提到的,模型输出的检测框可能存在大量重复的情况,所以我们需要实现 non_max_suppression 算法及其相关的支撑函数,来对这些结果进行过滤和优化。 在实现 non_max_suppression
之前,我们需要先实现2个依赖函数,xywh2xyxy
用来把检测框的 [x, y, w, h]
坐标转成 [x1, y1, x2, y2]
坐标,box_iou
用来计算检测框之间的重合度。
# 把检测框的[x, y, w, h]坐标转成[x1, y1, x2, y2]坐标 def xywh2xyxy(x): """[x, y, w, h] to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-right.""" y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x) y[..., 0] = x[..., 0] - x[..., 2] / 2 # top left x y[..., 1] = x[..., 1] - x[..., 3] / 2 # top left y y[..., 2] = x[..., 0] + x[..., 2] / 2 # bottom right x y[..., 3] = x[..., 1] + x[..., 3] / 2 # bottom right y return y # 计算检测框之前的重合度(Intersection over Union) def box_iou(box1, box2, eps=1e-7): # https://github.com/pytorch/vision/blob/master/torchvision/ops/boxes.py """ Return intersection-over-union (Jaccard index) of boxes. Both sets of boxes are expected to be in (x1, y1, x2, y2) format. Arguments: box1 (Tensor[N, 4]) box2 (Tensor[M, 4]) Returns: iou (Tensor[N, M]): the NxM matrix containing the pairwise IoU values for every element in boxes1 and boxes2 """ # inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2) (a1, a2), (b1, b2) = box1.unsqueeze(1).chunk(2, 2), box2.unsqueeze(0).chunk(2, 2) inter = (torch.min(a2, b2) - torch.max(a1, b1)).clamp(0).prod(2) # IoU = inter / (area1 + area2 - inter) return inter / ((a2 - a1).prod(2) + (b2 - b1).prod(2) - inter + eps)
接下来,我们就可以实现非极大抑制算法了。这个算法的步骤如下:
- 置信度排序: 对于每个图像,NMS算法首先根据检测到的对象的置信度(confidence)进行排序。置信度通常是指模型对于检测到的对象属于某个类别的概率。
- 选择最佳边界框: 选择置信度最高的边界框,将其作为参考框(reference box)。
- 计算交并比(IoU): 计算参考框与其他所有边界框的交并比(Intersection over Union,IoU)。IoU是一个衡量两个边界框重叠程度的指标,计算公式为两个边界框交集面积与并集面积的比值。
- 抑制重叠边界框: 如果某个边界框与参考框的IoU超过了预设的阈值(iou_thres),则认为这两个边界框重叠过多,将该边界框抑制(即从候选列表中移除)。
- 迭代处理: 在移除所有与当前参考框重叠过多的边界框后,选择置信度次高的边界框作为新的参考框,重复步骤3和4,直到所有边界框都被处理。
- 输出结果: 经过NMS处理后,剩下的边界框即为最终的检测结果。
代码实现如下:
# 非极大抑制去除重复框 def non_max_suppression( prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, multi_label=True, labels=(), max_det=300, nm=0, # 掩码的数量 ): """ 在推理结果上执行非最大抑制(NMS)以拒绝重叠的检测结果。 返回: 检测结果的列表,每个图像对应一个(n,6)张量 [x1, y1, x2, y2, conf, cls] """ # 入参检查 assert 0 <= conf_thres <= 1, f"置信度阈值 {conf_thres} 无效,有效值应在0.0和1.0之间" assert 0 <= iou_thres <= 1, f"IoU {iou_thres} 无效,有效值应在0.0和1.0之间" if isinstance(prediction, (list, tuple)): # YOLOv5模型在验证模型中,输出 = (推理输出, 损失输出) prediction = prediction[0] # 仅选择推理输出 bs = prediction.shape[0] # 批量大小 nc = prediction.shape[2] - nm - 5 # 类别数量 xc = prediction[..., 4] > conf_thres # 候选框 # 设置超参 max_wh = 7680 # (像素)最大框宽和高 max_nms = 30000 # 传入torchvision.ops.nms()的最大框数 time_limit = 0.5 + 0.05 * bs # 超时时间 redundant = True # 需要冗余检测 multi_label &= nc > 1 # 每个框多个标签(增加0.5ms/图像) merge = False # 不使用合并NMS t = time.time() mi = 5 + nc # 掩码起始索引 output = [torch.zeros((0, 6 + nm), device=prediction.device)] * bs # 初始化输出检测框 for xi, x in enumerate(prediction): # 遍历推理检测结果 x = x[xc[xi]] # 获取置信度 # 如果自动标记,则添加先验标签 if labels and len(labels[xi]): lb = labels[xi] v = torch.zeros((len(lb), nc + nm + 5), device=x.device) v[:, :4] = lb[:, 1:5] # 框 v[:, 4] = 1.0 # 置信度 v[range(len(lb)), lb[:, 0].long() + 5] = 1.0 # 类别 x = torch.cat((x, v), 0) # 如果没有剩余的处理下一张图像 if not x.shape[0]: continue # 计算置信度 x[:, 5:] *= x[:, 4:5] # 置信度 = 目标置信度 * 类别置信度 # 框/掩码 box = xywh2xyxy(x[:, :4]) # (中心x, 中心y, 宽度, 高度) 转换为 (x1, y1, x2, y2) mask = x[:, mi:] # 如果没有掩码则为零列 # 检测矩阵 nx6 (xyxy, conf, cls) if multi_label: i, j = (x[:, 5:mi] > conf_thres).nonzero(as_tuple=False).T x = torch.cat((box[i], x[i, 5 + j, None], j[:, None].float(), mask[i]), 1) else: # 仅最佳类别 conf, j = x[:, 5:mi].max(1, keepdim=True) x = torch.cat((box, conf, j.float(), mask), 1)[conf.view(-1) > conf_thres] # 按类别过滤 if classes is not None: x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)] # 检查形状 n = x.shape[0] # 框的数量 if not n: # 没有框 continue x = x[x[:, 4].argsort(descending=True)[:max_nms]] # 按置信度排序并移除多余的框 # 批量NMS c = x[:, 5:6] * (0 if agnostic else max_wh) # 类别 boxes, scores = x[:, :4] + c, x[:, 4] # 框(按类别偏移), 得分 # 调用torchvision封装好的NMS接口 i = torchvision.ops.nms(boxes, scores, iou_thres) # NMS i = i[:max_det] # 限制检测数量 if merge and (1 < n < 3e3): # 合并NMS(使用加权平均合并框) # 更新框为 boxes(i,4) = weights(i,n) * boxes(n,4) iou = box_iou(boxes[i], boxes) > iou_thres # IoU矩阵 weights = iou * scores[None] # 框权重 x[i, :4] = torch.mm(weights, x[:, :4]).float() / weights.sum(1, keepdim=True) # 合并框 if redundant: i = i[iou.sum(1) > 1] # 需要冗余 output[xi] = x[i] if (time.time() - t) > time_limit: LOGGER.warning(f"警告 ⚠️ NMS 时间限制 {time_limit:.3f}s 超过") break # 时间限制超过 return output
3.5 整合代码实现端到端检测
为了能够实现对铝板缺陷的实时、准确检测,我们需要将前面所编写的图像预处理、缺陷检测以及后处理等环节的代码进行有机整合,封装成一个完整的端到端检测流程。 在此之前,我们还需要设计一个函数对检测框的坐标进行缩放,原因是我们在推理时为了让图片能够被AI模型处理,对它的形状进行了改变。检测框坐标缩放函数 scale_boxes
及其支撑函数 clip_boxes
的实现如下:
def clip_boxes(boxes, shape): """Clips bounding box coordinates (xyxy) to fit within the specified image shape (height, width).""" if isinstance(boxes, torch.Tensor): # faster individually boxes[..., 0].clamp_(0, shape[1]) # x1 boxes[..., 1].clamp_(0, shape[0]) # y1 boxes[..., 2].clamp_(0, shape[1]) # x2 boxes[..., 3].clamp_(0, shape[0]) # y2 else: # np.array (faster grouped) boxes[..., [0, 2]] = boxes[..., [0, 2]].clip(0, shape[1]) # x1, x2 boxes[..., [1, 3]] = boxes[..., [1, 3]].clip(0, shape[0]) # y1, y2 def scale_boxes(img1_shape, boxes, img0_shape, ratio_pad=None): """Rescales (xyxy) bounding boxes from img1_shape to img0_shape, optionally using provided `ratio_pad`.""" if ratio_pad is None: # calculate from img0_shape gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1]) # gain = old / new pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2 # wh padding else: gain = ratio_pad[0][0] pad = ratio_pad[1] boxes[..., [0, 2]] -= pad[0] # x padding boxes[..., [1, 3]] -= pad[1] # y padding boxes[..., :4] /= gain clip_boxes(boxes, img0_shape) return boxes
接下来,我们设置一些检测过程中需要用到的参数:
conf_thres=0.25 # 置信度阈值 iou_thres=0.45 # NMS IOU 阈值 max_det=1000 # 最大的检测框数量 imgsz=(640, 640) # 图片目标形状 save_dir = "./detect_imgs/" # 检测结果保存目录
然后,运行推理过程:
import time import torchvision from ultralytics.utils.plotting import Annotator, colors model = DetectMultiBackend("./best.pt") names = model.names print("classification names: ", names) img_loader = LoadImages('./test_images') # Run inference for path, im, im0s in img_loader: # 把输入处理成AI模型的输入格式 im = torch.from_numpy(im) im = im.half() if model.fp16 else im.float() # uint8 to fp16/32 im /= 255 # 0 - 255 to 0.0 - 1.0 if len(im.shape) == 3: im = im[None] # expand for batch dim # 执行推理 pred = model(im)[0] # NMS 后处理 pred = non_max_suppression(pred, conf_thres, iou_thres, classes=None, agnostic=False, max_det=max_det) print("%s defects were found in the aluminum plate." % pred[0].shape[0]) # 把检测结果画在原图上 for i, det in enumerate(pred): # per image annotator = Annotator(im0s, line_width=8, example=str(names)) if len(det): # Rescale boxes from img_size to im0 size det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0s.shape).round() # Print results for *xyxy, conf, cls in reversed(det): c = int(cls) # integer class label = f'{names[c]} {conf:.2f}' annotator.box_label(xyxy, label, color=colors(c, True)) # 保存检测结果 print("save_path: ", save_dir + path.split("/")[-1]) cv2.imwrite(str(save_dir + path.split("/")[-1]), im0s) Fusing layers... YOLOv5m summary: 290 layers, 20889303 parameters, 0 gradients, 48.0 GFLOPs classification names: {0: 'non_conduct', 1: 'abrasion_mark', 2: 'corner_leak', 3: 'orange_peel', 4: 'leak', 5: 'jet_flow', 6: 'paint_bubble', 7: 'pit', 8: 'motley', 9: 'dirty_spot'} 1 defects were found in the aluminum plate. save_path: ./detect_imgs/000015.jpg 1 defects were found in the aluminum plate. save_path: ./detect_imgs/000427.jpg 1 defects were found in the aluminum plate. save_path: ./detect_imgs/000467.jpg 1 defects were found in the aluminum plate. save_path: ./detect_imgs/000490.jpg 1 defects were found in the aluminum plate. save_path: ./detect_imgs/000978.jpg 2 defects were found in the aluminum plate. save_path: ./detect_imgs/001178.jpg 1 defects were found in the aluminum plate. save_path: ./detect_imgs/002026.jpg
通过以上步骤,我们就能够实现对铝板缺陷的端到端检测,得到带有缺陷标注的铝板图像,并可以根据实际需求进一步对检测结果进行分析和处理,例如统计各类缺陷的数量、面积等信息,以便更好地评估铝板的质量情况。以下是几种典型的缺陷:
恭喜你!至此,你已经成功完成了基于 AI 图像处理的铝板缺陷检测的全部实验流程,希望你能够熟练掌握这套技术方案,并将其应用到实际的铝板生产质量检测或者其他相关的工业检测场景中,为提高产品质量和生产效率贡献力量。
3.6 软件依赖
本实验的依赖软件版本信息如下:
- Python:为了方便开发者进行学习,本课程采用Python代码实现,您可以在服务器上安装一个Conda,用于创建Python环境,本实验使用的是
python 3.10
; - ultralytics:AI视觉模型三方库,提供了多种CV模型的调用接口,内置了模型的前后处理,方便用户调用模型,本实验使用的是
8.3.48
版本; - opencv-python:opencv-python 是 OpenCV 库的 Python 接口,它提供了对 OpenCV 功能的访问,包括图像处理、视频分析、计算机视觉算法和实时图像处理等,使得开发者能够在 Python 环境中轻松实现复杂的视觉任务,本实验使用的是
4.10.0.84
版本; - numpy: 开源的Python科学计算库,用于进行大规模数值和矩阵运算,本实验使用的是
1.26.4
版本; - torch:AI计算框架,本实验使用的是
2.1.0
版本; - torch_npu:torch在昇腾硬件上的适配插件,可以让torch在昇腾硬件上执行,本实验使用的是
2.1.0.post6
版本; - torchvision:提供了处理图像和视频的常用工具和预训练模型,本实验使用的是
0.16.0
版本; - CANN(Compute Architecture for Neural Networks):Ascend芯片的使能软件,本实验使用的是
="https://www.hiascend.com/developer/download/community/result?module=cann&cann=8.0.RC2.alpha002">8.0.rc2 版本。
04 课后测试
- 尝试调整模型的置信度阈值(conf_thres)和 NMS IOU 阈值(iou_thres),观察对检测结果的影响,并分析原因。
- 如何对检测到的铝板缺陷进行分类统计?请给出实现思路和代码示例。