尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
基于YOLOv5与Flask的钢材表面缺陷检测完整落地指南
简介基于Yolov5与Flask的钢材缺陷检测系统完整方案面向计算机视觉方向的毕业设计、课程设计以及软件工程实践者。项目整合深度学习目标检测与Web服务可完成裂缝、腐蚀、变形等缺陷的实时识别与可视化展示。压缩包共2000个文件主要包含1930个txt标签与标注文件、38个Python源码、19个YAML模型配置、少量Markdown说明和Shell脚本整体约38.63MB目录结构清晰便于训练、推理和二次开发。目前已有225人学习下载。通过该资源可掌握Yolov5模型训练与优化、Flask后端接口封装、数据集预处理及性能评估等关键环节并可直接获得可运行的工程模板与标注数据适合作为课题参考或项目起点。1. 钢材缺陷检测的完整落地方案yolov5做视觉flask做产线接口钢材表面的麻点、划伤、氧化铁皮压入传统机器视觉靠阈值分割和形态学处理很难稳定检出因为缺陷边缘不规则、光照不均匀同一个类别在亮场和暗场下的灰度分布完全不同。yolov5这类单阶段检测器用数据驱动的方式绕开了特征设计把缺陷检测变成目标检测问题而flask的作用是把训练好的*.pt模型变成产线能直接调用的HTTP接口。这个标题里的源码数据集结构本质上是告诉你两件事离线训练靠yolov5在线推理靠flask两者通过模型文件和一套接口协议连接起来。适合正在做毕业设计、刚接手视觉落地方案、或手里有零散缺陷样本需要快速出Demo的工程师。接下来按「数据集准备 → 模型训练 → flask部署 → 性能优化」这条线讲清楚整个闭环。2. 钢材缺陷数据集的准备从原始图片到yolov5能消费的labels目录2.1 钢材表面缺陷的类别划分与标注陷阱工业缺陷检测和通用目标检测有一个本质差别通用场景里类别边界清晰而钢材表面缺陷往往是同一块区域上同时存在多种纹理异常。如果按钢材表面缺陷最常用的六分类来组织数据一般对应裂纹crazing、夹杂物inclusion、麻点patches、氧化铁皮压入rolled-in_scale、点蚀pitted_surface和划伤scratches。实际做数据整理时先看图片里到底有哪些类别再决定是否合并不要照搬公开数据集的类名。类别视觉特征标注时的常见问题crazing网状细裂纹分布分散容易把砂轮机磨痕标成裂纹inclusion条状/块状深色异物与氧化皮压入难以区分patches片状暗区域边缘模糊边界难以确定框容易过大rolled-in_scale鱼鳞状压入物有金属光泽与夹杂物混淆率高pitted_surface密集细小凹坑每个坑太小容易漏标scratches细长条状方向一致长宽比极大anchor需要调整标注时有一个容易被忽略的坑labelme里用多边形画缺陷但yolov5训练需要的是外接矩形框。划伤这类细长缺陷如果直接取多边形顶点的min/max生成矩形框框里会包含大量正常表面背景模型学到的是「这个位置有划伤」而不是「划伤的边界在哪里」。工业场景下我一般会在标注规范里要求能用一个矩形框住的缺陷就用矩形标实在需要用多边形的时候将外接矩形面积与多边形实际面积做比值检查比值过低就提示重标。2.2 把labelme的JSON转换成yolov5的txt标签yolov5期望的标签格式是每个图片对应一个同名.txt文件每一行是class x_center y_center width height坐标全部归一化到0到1。下面的脚本把labelme生成的JSON批量转换并在转换过程中完成两个过滤丢弃宽度或高度小于3像素的小目标通常是标注噪声以及过滤掉面积占比过低的异常框。import json import os import glob import numpy as np from pathlib import Path def convert_labelme_json(json_path, out_dir, img_width, img_height, min_side3): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_name Path(json_path).stem out_txt os.path.join(out_dir, img_name .txt) lines [] for shape in data[shapes]: label shape[label] if label not in class_map: continue pts np.array(shape[points], dtypenp.float32) x_min, y_min pts[:, 0].min(), pts[:, 1].min() x_max, y_max pts[:, 0].max(), pts[:, 1].max() box_w, box_h x_max - x_min, y_max - y_min if box_w min_side or box_h min_side: continue # 归一化到yolov5格式 x_center (x_min x_max) / 2.0 / img_width y_center (y_min y_max) / 2.0 / img_height w box_w / img_width h box_h / img_height lines.append(f{class_map[label]} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_txt, w, encodingutf-8) as f: f.write(\n.join(lines)) class_map {crazing: 0, inclusion: 1, patches: 2, rolled-in_scale: 3, pitted_surface: 4, scratches: 5} if __name__ __main__: os.makedirs(labels/train, exist_okTrue) for jf in glob.glob(labelme_json/train/*.json): # 这里假设每张图是1280x960实际项目中图片尺寸要读原图获取 convert_labelme_json(jf, labels/train, 1280, 960)逻辑说明脚本遍历labelme_json/train目录下的所有标注文件逐条提取矩形框。min_side3是过滤超小目标的阈值如果漏标严重可以放松到2。代码里写死图片尺寸是1280x960在实际使用中不要这么做应当用cv2.imread或PIL读取对应原图获取宽高否则批量处理时一旦图片尺寸不统一归一化坐标全部出错训练时loss会异常高。转换完成后还需要把数据集切成train和val。工业缺陷检测有一个特点正样本占比低而且同一个批次的钢材缺陷特征相似如果不加处理地随机切分验证集会非常接近训练集mAP虚高。常见做法是先按文件名前缀分组同一个钢板批次归到同一组再对组做随机划分保证同一批次的图片不会同时出现在训练集和验证集里。2.3 让yolov5高效读取小样本数据钢材缺陷样本往往只有几百到几千张yolov5官方默认的rect和mosaic增强对它来说不是越强越好。样本量少的时候直接上全强度的mosaic会把过多无关背景拼在一起模型很难学到「缺陷是附着在钢板表面上」的上下文。我一般会根据数据规模调整增强策略样本量低于2000张时关闭hsv_h和hsv_s的大幅扰动保留亮度扰动hsv_v因为钢材表面差异主要体现在明暗上而不是颜色上。# steel.yaml train: ./datasets/steel/images/train val: ./datasets/steel/images/val nc: 6 names: [crazing, inclusion, patches, rolled-in_scale, pitted_surface, scratches]这一段data.yaml是yolov5训练的入口配置train和val指向图片目录标签目录默认与图片目录同级且把images换成labels。如果你的数据目录不是这种结构会直接报AssertionError: Label not found这一点比模型选型更容易绊住第一次跑起来的人。3. yolov5训练钢材缺陷模型迁移学习、超参数与收敛判断3.1 训练启动用COCO预训练权重还是从头训练钢材表面缺陷和通用物体在纹理特征上差异很大直接冻住backbone效果并不好但完全不迁移又需要更多数据。实际工程里我会选择yolov5s.pt的COCO预训练权重作为起点然后在训练初期冻结backbone内部的前10层让模型先适应钢材数据的分布每5轮解冻一部分最后20轮全部解冻。这样做的好处是浅层特征边缘、纹理基元在COCO上已经学得足够好不需要用有限的钢材样本重学一遍而深层的语义特征需要针对缺陷类别重新拟合。python train.py \ --data steel.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --patience 20 \ --cache ram \ --project runs/train_steel \ --name v1参数说明--img 640是训练输入分辨率钢材缺陷里的点蚀类目标很小如果硬件允许建议用--img 1280观察小目标召回率是否提升--batch 16在8GB显存的卡上比较稳显存不够降到8并把--cache ram去掉--patience 20表示验证集指标连续20轮无改善就早停工业数据集噪声大不建议把patience设得太小网络波动导致的mAP抖动很容易误触早停--cache ram把图片预加载进内存省去每轮epoch的磁盘IO时间数据量在1万张以内都值得开。3.2 影响缺陷检测效果的三个超参数yolov5的超参数在data/hyps/hyp.scratch-low.yaml里定义工业缺陷检测场景我重点关注三个参数默认值场景设定建议调参理由lr00.010.005钢材数据量少初始学习率过高会让冻结层解冻时loss震荡mosaic1.00.5或按epoch关闭mosaic对密集小缺陷不利模型容易学到拼接缝fl_gamma0.00.5 ~ 1.0正负样本极端不平衡时focal loss让模型聚焦难分缺陷在train.py启动前可以修改hyp文件或用--hyp指定自定义yaml。调参的原则不是追求验证集mAP最高而是观察训练集和验证集之间的gapgap持续变大就是过拟合信号这时候需要用更强的增强或降低模型复杂度而不是继续调loss权重。3.3 从训练产物里读出问题所在训练结束后runs/train_steel/v1/目录下最值得看的不是results.png而是confusion_matrix.png和labels_correlogram.jpg。labels_correlogram显示所有标注框中心点的分布如果中心点密集聚集在图片正中央说明标注阶段有人为把缺陷放在画面中央的偏好模型学到的位置先验会污染部署时的泛化能力。confusion_matrix则告诉你在测试集上哪两个类别互相打架最常见的就是inclusion和rolled-in_scale混淆这类问题靠改进网络没用得回到标注阶段去定义更严格的类别边界。如果发现召回率明显低于精确率先检查hyp里的loss_box再看NMS阈值。yolov5验证阶段默认conf_thres0.25工业场景漏检的代价高于误检用验证脚本单独测几轮把阈值降到0.1到0.15只用于评估不要一上来就改训练配置。3.4 断点续训与导出ONNX训练中途断掉是常态。重新跑一遍完整训练成本太高使用--resume直接从最后一个last.pt续训python train.py --resume runs/train_steel/v1/weights/last.pt续训时原来的data.yaml、hyp等配置会自动读取不需要重新指定。训练完成后导出ONNX用于后续flask部署python export.py --weights runs/train_steel/v1/weights/best.pt --include onnx --img 640导出后检查ONNX模型的输入输出节点确认输入是1x3x640x640输出是1x25200x(5nc)的形状其中25200是yolov5在640分辨率下三个尺度的anchor预测总数。这里要特别留意export.py默认把nms非极大值抑制排除在模型外推理时nms需要自己在flask服务里做后面会讲到。4. 用flask把检测模型包成可用的质检服务4.1 常驻模型、线程池与请求排队flask部署深度学习模型最常见的错误是每个请求都重新加载权重。yolov5的torch.hub加载方式会在每次调用时检查文件变化延迟极高生产环境必须把模型加载写在全局变量里进程启动时加载一次之后所有请求复用。同时用线程池限制并发推理数量避免多个请求同时进入模型前向传播导致显存溢出。import torch import cv2 import numpy as np from flask import Flask, request, jsonify from concurrent.futures import ThreadPoolExecutor app Flask(__name__) model None executor ThreadPoolExecutor(max_workers1) def load_model(): global model # 直接加载训练好的pt文件不经过hub减少启动路径 model torch.hub.load(yolov5, custom, pathruns/train_steel/v1/weights/best.pt, sourcelocal) model.conf 0.25 model.iou 0.45 model.eval() app.route(/predict, methods[POST]) def predict(): if model is None: load_model() if image not in request.files: return jsonify({error: no image field}), 400 file request.files[image] img_bytes np.frombuffer(file.read(), np.uint8) img cv2.imdecode(img_bytes, cv2.IMREAD_COLOR) if img is None: return jsonify({error: invalid image}), 400 future executor.submit(run_inference, img) result future.result(timeout5) return jsonify(result)初始化load_model()放在全局模型为None的判断里保证本地flask run和gunicorn多worker启动时都能正确加载。ThreadPoolExecutor(max_workers1)是关键限制工业现场相机是固定节拍触发一个推理线程足够多余的并发只会争抢GPU资源和内存。如果产线确实需要更多吞吐优先考虑升级batch推理而不是开更多线程。4.2 letterbox前处理与坐标映射回原图yolov5的推理前处理不是简单的cv2.resize而是等比例缩放后用灰色填充这个过程叫letterbox。如果先用普通resize把896x896的图压成640x640细长划伤的宽高比会变形检测框位置也会偏移。推理完成后所有坐标需要减去letterbox的padding偏移量再除以缩放比例才能映射回原图。def run_inference(img): # letterbox预处理 h, w img.shape[:2] target_size 640 ratio min(target_size / w, target_size / h) new_w, new_h int(w * ratio), int(h * ratio) resized cv2.resize(img, (new_w, new_h), interpolationcv2.INTER_LINEAR) canvas np.full((target_size, target_size, 3), 114, dtypenp.uint8) dw, dh (target_size - new_w) // 2, (target_size - new_h) // 2 canvas[dh:dh new_h, dw:dw new_w] resized # 张量转换 blob canvas[:, :, ::-1].transpose(2, 0, 1)[None] / 255.0 blob torch.from_numpy(blob).float() with torch.no_grad(): pred model(blob)[0] # yolo输出的原始预测 # NMS已经在model内部完成torch.hub custom模式 boxes pred.cpu().numpy() results [] for det in boxes: if det.shape[0] 0: continue for x1, y1, x2, y2, conf, cls in det: # 坐标映射回原图 x1 (x1 - dw) / ratio y1 (y1 - dh) / ratio x2 (x2 - dw) / ratio y2 (y2 - dh) / ratio results.append({ class: int(cls), confidence: float(conf), bbox: [float(x1), float(y1), float(x2), float(y2)] }) return {count: len(results), boxes: results}参数说明dw和dh是letterbox填充的左上角偏移量坐标映射必须在NMS之后做如果在NMS之前映射anchors计算出的预测框会全部偏移类间抑制效果失效。model(blob)[0]的输出形状是[1, num_detections, 6]6个值依次是x1, y1, x2, y2, confidence, class_id这是yolov5custom模式加载best.pt时的最终输出格式不再需要额外解码。4.3 接口参数与产线摄像头采集端参数类型必填说明imagefile是单张图片支持jpg/png大小限制在10MB内响应字段类型说明countint检测到的目标数量boxesarray每个目标的类别、置信度和原图坐标errorstring请求失败时的错误描述摄像头采集端把单帧推给flask服务拿到检测结果后叠加画框再显示周期在100ms以内可以接受。下面的客户端代码适合接入产线工位机import requests import cv2 cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break _, buf cv2.imencode(.jpg, frame, [cv2.IMWRITE_JPEG_QUALITY, 85]) resp requests.post( http://127.0.0.1:5000/predict, files{image: (frame.jpg, buf.tobytes(), image/jpeg)}, timeout3, ) if resp.status_code 200: boxes resp.json()[boxes] for box in boxes: x1, y1, x2, y2 [int(v) for v in box[bbox]] cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imshow(inspect, frame) if cv2.waitKey(1) 0xFF ord(q): break这段代码里cv2.imencode的JPEG质量设成85是为了减少网络传输字节数。质量过高时单帧会到几百KB局域网内延迟不明显但如果是通过无线网络传输到质检终端帧率会急剧下降。帧率瓶颈通常不在模型推理而在图片编码和HTTP序列化这一点在对接产线时最容易忽略。5. 模型提速与数据回灌让检测服务跟上产线节拍5.1 导出TensorRT引擎替代PyTorch推理PyTorch的GPU推理在长尾延迟上表现不稳定工业现场要求的是稳定的p95延迟而不是平均延迟。将这个模型通过TensorRT导出成engine文件在持续运行的产线环境下是更稳妥的做法。先用onnx导出再通过trtexec转换trtexec --onnxbest.onnx --saveEnginebest_fp16.engine --fp16FP16精度损失对六类钢材缺陷的mAP影响一般小于0.5%但延迟可以降低40%以上。INT8在钢材表面这种纹理细密的任务上掉点风险较高不建议上来就用先跑FP16。优化手段p95延迟(ms)mAP0.5变化实施难度PyTorch直接推理42基准无FP16 TensorRT23-0.2%低一条命令INT8 TensorRT18-1.5% ~ -3%中需要校准集批量推理batch438/4张-0.1%低需改服务代码验证加速效果用一段采样代码连续推200张真实产线图import time import numpy as np latencies [] for i in range(200): t0 time.time() # 调用上面的run_inference result run_inference(images[i]) latencies.append((time.time() - t0) * 1000) p95 np.percentile(latencies, 95) p99 np.percentile(latencies, 99) print(fp95: {p95:.1f}ms, p99: {p99:.1f}ms)注意测试数据不能用训练集或验证集必须用从产线新采集、模型从未见过的图片否则延迟数据会偏乐观。5.2 高置信度框自动回灌标注集模型上线运行后每天会产生大量带有预测框的图片其中置信度高于0.9的框有较高概率是正确标注。让质检员只复核这些自动生成的标签修正错误框后追加到原始训练集再跑一轮增量训练是成本最低的数据迭代方式。常见做法是把所有预测结果存成JSON格式标注工具打开图片时自动加载这些矩形框人工只做确认和微调保存时再转成yolov5的txt格式。回灌训练时降低学习率并关闭mosaic增强避免老数据被新数据淹没python train.py --data steel_round2.yaml --weights runs/train_steel/v1/weights/best.pt --hyp hyp.finetune.yaml --epochs 30本文还有配套的精品资源点击获取
RELATED

相关推荐

第30讲:可验证交付的全流程落地方法论

第30讲:可验证交付的全流程落地方法论

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/14 7:40:45
QT四轴上位机实战:串口通信、姿态绘图与指令控制

QT四轴上位机实战:串口通信、姿态绘图与指令控制

简介:面向QT与无人机开发初学者,这份资源提供了四轴飞行器上位机软件的初级版本。内容涵盖基于Qt的GUI控制面板、串口通信模块、下位机协议解析以及简单的实时数据显示逻辑,适合希望上手无人机地面站基础开发、理解上位机与飞控交互流程的读者…

📅 2026/9/14 7:40:45
开发者注意力管理:从科学原理到工程实践

开发者注意力管理:从科学原理到工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/14 7:40:45
MORE NEWS

更多资讯

📰

深入剖析 ScyllaDB Commitlog 段文件格式:从文件头到碎片化条目的逐字节解析

深入剖析 ScyllaDB Commitlog 段文件格式:从文件头到碎片化条目的逐字节解析 【免费下载链接】scylladb NoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB 项目地址: https://gitcode.com/GitHub_Trending/s…

📰

数据驱动MPC与机组组合优化:预测、滚动求解与Matlab实现

简介:针对电力系统机组组合与模型预测控制交叉方向,这份Matlab项目案例提供了完整可运行的代码框架,适合自动化、电气工程、人工智能等相关专业学生与研究人员用于学习或二次开发。资源共29个文件,核心为16个.mat数据文件与11个.m…

📰

MATLAB计算太阳天顶角:从赤纬、时角公式到完整实现

简介:SolarAngle.MATLAB 是一份面向太阳能工程、气象与环境科学研究者的 MATLAB 计算工具,用于根据地理位置、日期和时间精确求取太阳天顶角、太阳高度角与方位角,为光伏电站朝向优化、建筑采光设计及辐射分析提供基础数据。太阳天顶角与高度…

📰

Matlab实现区域能源系统双层优化与需求响应

1. 项目背景与核心价值区域综合能源系统(RIES)作为能源互联网的重要载体,正在推动传统能源系统向低碳化、智能化转型。这个Matlab复现项目源自核心期刊论文,聚焦"需求响应双层优化"这一前沿方向,其核心价值在…

📰

政府科技管理部门技术转移体系构建与实践

1. 政府科技管理部门推动技术转移的现状与挑战技术转移作为科技创新成果转化为现实生产力的关键环节,一直是政府科技管理部门工作的重点。但在实际操作中,我们常常面临以下典型问题:信息不对称:高校科研院所的研究成果与企业需求之…

📰

用Python手写BP神经网络实现鸢尾花分类:从原理到调参

简介:面向Python初学者的人工智能实践项目,使用BP神经网络对经典鸢尾花数据集进行分类,配套完整源码、数据集和文档说明,可满足期末大作业、课程设计等场景。除BP神经网络两个版本(V1/V2)外,还提…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬