HSG金属表面缺陷检测

HSG金属表面缺陷检测

  • 1. 项目背景
    • 1.1 项目简述
    • 1.2 项目目标
  • 2. 解决方案
  • 3. 数据集
    • 3.1 收集各种缺陷的图片
    • 3.2 利用有限图片创造更多可能
    • 3.3 分割图像
    • 3.4 打标签
  • 4. 部分代码
    • 4.1 数据集划分
    • 4.2图像分割
    • 4.3 训练模型
    • 4.4 预测
  • 5. 预测结果

1. 项目背景

1.1 项目简述

  • iPad HSG 的材质是带有磨砂质感的金属框,在生产或搬运过程中,会产生一些缺陷。比如:长度不等的黑线,面积不定的亮印,亮度不同的吐酸酸蚀,以及HSG在搬运过程中经常出现的刮伤或磕伤。
  • 常见的4种缺陷类型:
    • 划伤
      在这里插入图片描述

    • 吐酸
      在这里插入图片描述

    • 黑线
      在这里插入图片描述

    • 亮印
      在这里插入图片描述

1.2 项目目标

  • 使用多组相机对HSG进行拍照取像,通过对图像的分析,完成以上四种缺陷的检测。
  • 技术要求:明显缺陷要求 100% 检出,不明显缺陷检出率超过 95%。

2. 解决方案

  • 该项目遇到的问题属于检测类问题,最终选择使用 YOLOv8 Detect 模块完成。

3. 数据集

3.1 收集各种缺陷的图片

  • 自动化领域的缺陷样品收集起来并不容易,因为带有缺陷的样品往往当天或者第二天就会被返工或做报废处理,工程师到达现场时只能拿到当天的一小部分缺陷样品。在打样阶段产品本来就少,这给我们的工作带来不少麻烦。

3.2 利用有限图片创造更多可能

  • 能拿到的样品少,就只能在实验室制造更多可能了。
  • 改变拍摄的位置和角度,光源亮度,拍摄更多的图片。
  • 也可以通过图像处理(旋转、翻转等)生成更多的图片。

3.3 分割图像

  • 项目使用的是 1200W 彩色相机,缺陷相较于整张图像来说比较小,所以采取了图像分割的方法。将原有的大图像分割为小图,再进行标注。
  • 这里采用 5 × 4 分割。

3.4 打标签

  • 标注工具使用的是 lableImg
  • calsses
    • acid
    • bright
    • black
    • scratch

4. 部分代码

4.1 数据集划分

import cv2
import matplotlib.pyplot as plt
import numpy as np
import random
from tqdm import tqdm
import shutil
import osdef CollateDataset(image_dir,label_dir):"""功能:数据集划分(训练集、验证集、测试集):param image_dir: 图片路径:param label_dir: 标签路径:return:"""# 创建一个空列表来存储有效图片的路径valid_images = []# 创建一个空列表来存储有效 label 的路径valid_labels = []# 遍历 images 文件夹下的所有图片for image_name in os.listdir(image_dir):# 获取图片的完整路径image_path = os.path.join(image_dir, image_name)# 获取图片文件的扩展名ext = os.path.splitext(image_name)[-1]# 根据扩展名替换成对应的 label 文件名label_name = image_name.replace(ext, ".txt")# 获取对应 label 的完整路径label_path = os.path.join(label_dir, label_name)# 判断 label 是否存在if not os.path.exists(label_path):# # 删除图片# os.remove(image_path)print("there is no:", label_path)else:# 将图片路径添加到列表中valid_images.append(image_path)# 将 label 路径添加到列表中valid_labels.append(label_path)# 遍历每个有效图片路径for i in tqdm(range(len(valid_images))):image_path = valid_images[i]label_path = valid_labels[i]# 随机生成一个概率r = random.random()# 判断图片应该移动到哪个文件夹# train:valid:test = 8:2:0if r < 0.0:# 移动到 test 文件夹destination = "./dataset/test"elif r < 0.2:# 移动到 valid 文件夹destination = "./dataset/valid"else:# 移动到 train 文件夹destination = "./dataset/train"# 创建目标文件夹中 images 和 labels 子文件夹os.makedirs(os.path.join(destination, "images"), exist_ok=True)os.makedirs(os.path.join(destination, "labels"), exist_ok=True)# 生成目标文件夹中图片的新路径image_destination_path = os.path.join(destination, "images", os.path.basename(image_path))# 移动图片到目标文件夹shutil.copy(image_path, image_destination_path)# 生成目标文件夹中 label 的新路径label_destination_path = os.path.join(destination, "labels", os.path.basename(label_path))# 移动 label 到目标文件夹shutil.copy(label_path, label_destination_path)if __name__ == '__main__':CollateDataset("./images","./labels")

4.2图像分割

import cv2
import os
import pathlibsource_path = "D:/images"
target_path = "D:/images_split"def mkdir(path):path = path.strip()path = path.rstrip("\\")isExists = os.path.exists(path)if not isExists:os.makedirs(path)print(path + ' 创建成功')return Trueelse:print(path + ' 目录已存在')return Falsedef split_img2(img_file):img = cv2.imread(img_file)img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img_h = img.shape[0]  # 高度img_w = img.shape[1]  # 宽度# h1_half = int(img_h / 2)# w1_half = int(img_w / 2)h1_half = img_h // 2w1_half = img_w // 2img_name = os.path.basename(img_file)for i in range(4):img1 = img[int(i / 2) * h1_half: h1_half * (int(i / 2) + 1), int(i % 2) * w1_half: (int(i % 2) + 1) * w1_half]img1_path = os.path.join(target_path, f"{img_name[:-4]}_{i}.jpg")print("spilt img:", img1_path)cv2.imwrite(img1_path, img1)def split_img(img_file,wp = 2, hp = 2):img = cv2.imread(img_file)img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img_h = img.shape[0]  # 高度img_w = img.shape[1]  # 宽度# h1_half = int(img_h / 2)# w1_half = int(img_w / 2)h1_half = img_h // hpw1_half = img_w // wpwh_sum = wp * hpprint(wh_sum)img_name = os.path.basename(img_file)for i in range(wh_sum):img1 = img[int(i / wp) * h1_half: h1_half * (int(i / wp) + 1), int(i % hp) * w1_half: (int(i % hp) + 1) * w1_half]img1_path = os.path.join(target_path, f"{img_name[:-wh_sum]}_{i}.jpg")print("spilt img:", img1_path)cv2.imwrite(img1_path, img1)if __name__ == '__main__':mkdir(target_path)for file in pathlib.Path(source_path).glob('**/*'):str = pathlib.Path(source_path)print(str)split_img(os.path.join(source_path, file),5,4)

4.3 训练模型

def train():"""训练模型:return:"""# model = YOLO("./ultralytics/cfg/models/v8/mtyolov8.yaml")model = YOLO("./yolov8n.pt")model.train(data="./ultralytics/cfg/datasets/coco8_HSG.yaml", epochs=400)result = model.val()

4.4 预测

import random
import time
from tqdm import tqdm
from ultralytics import YOLO
import torch
import cv2
import matplotlib.pyplot as plt
import os
import numpy as np
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'def load_train_model():"""加载训练好的模型:return:"""global modelmodel = YOLO("./best.pt")def load_image(image_path):"""加载图像:return: 图像"""print(image_path)if not os.path.exists(image_path):returnelse:return cv2.imread(image_path)def save_image(image):"""保存图像:return:"""# 创建目标文件夹中 images 和 labels 子文件夹os.makedirs(os.path.join("./", "predict_result"), exist_ok=True)# 移动图片到目标文件夹image_name = time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime(time.time())) + ".jpg"image_path = "./predict_result/" + image_namecv2.imwrite(image_path, image)def get_images_path(image_path):"""获得文件加下所有图片的路径:return: 列表"""# 创建一个空列表来存储有效图片的路径images_path = []# 遍历 images 文件夹下的所有图片for image_name in os.listdir(image_path):# 获取图片的完整路径path = os.path.join(image_path, image_name)# 将图片路径添加到列表中images_path.append(path)return images_pathdef load_image_random(images_path):"""功能:在文件夹中随机加载一张图像:param image_path: 文件夹路径:return:"""pathname = random.choices(images_path)[0]image = load_image(pathname)return imagedef load_image_order(images_path):"""功能:在文件夹中按照先后顺序加载图片:param image_path: 文件夹路径:return:"""for pathname in images_path:image = load_image(pathname)yield imagedef train():"""训练模型:return:"""# model = YOLO("./ultralytics/cfg/models/v8/mtyolov8.yaml")model = YOLO("./yolov8n.pt")model.train(data="./ultralytics/cfg/datasets/coco8_HSG.yaml", epochs=400)result = model.val()def predict(pre_image):# 定义分割参数segment_width = 819segment_height = 750stride_w = 820  # w步长stride_h = 750  # h步长color_map = {'bright': (255, 0, 0),'acid': (0, 255, 0)# 其他类别的颜色可以根据需要添加}for y in range(0, pre_image.shape[0], stride_h):for x in range(0, pre_image.shape[1], stride_w):# 提取分割区域segment = pre_image[y:y + segment_height, x:x + segment_width]# 对分割区域进行目标检测results = model.predict(segment,conf=0.3)for result in results:boxes = result.boxesnames = result.namesnum = len(boxes.cls.cpu().numpy().astype(int))if num >= 1:for i in range(num):xyxy = boxes.xyxy.cpu().numpy().astype(int)[i]cls = boxes.cls.cpu().numpy().astype(int)[i]conf = boxes.conf.cpu().numpy()[i]color = color_map.get(names.get(cls), (0, 255, 0))  # 默认绿色# 将RGB格式的颜色转换为BGR格式color = (color[2], color[1], color[0])offset = 15x1 = xyxy[0] + x - offsety1 = xyxy[1] + y - offsetx2 = xyxy[2] + x + offsety2 = xyxy[3] + y + offsetcv2.rectangle(pre_image, (x1, y1), (x2, y2), color, 4)cv2.putText(pre_image, f"{names.get(cls)} {conf:.2f}", (x1, y1 - 15),cv2.FONT_HERSHEY_SIMPLEX, 1.5, color, 4)#cv2.imwrite("./result1.jpg",pre_image)#plt.title('Pre')#plt.imshow(cv2.cvtColor(pre_image, cv2.COLOR_BGR2RGB))#plt.show()return pre_image

5. 预测结果

  • 测试集中明显缺陷已经可以检出,不明显的缺陷还需要继续优化。随着项目的推进,会有更多的缺陷图像补充进来,这样会极大提高模型的检测精度。

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【NLP学习路线的总结】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步! 目录 0. 👉前言1. 👉前置知识👉基础数学知识👉编程语言👉…

LabVIEW干涉仪测向系统

开发了一套基于LabVIEW的软件系统&#xff0c;结合硬件设备&#xff0c;构建一个干涉仪测向实验教学平台。该平台应用于信号处理课程&#xff0c;帮助学生将理论知识与实际应用相结合&#xff0c;深化对信号处理核心概念的理解和应用。 项目背景&#xff1a; 当前信号处理教学…

初识c++(命名空间,缺省参数,函数重载)

一、命名空间 1、namespace的意义 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全 局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c;以避免命名 冲突…

路径规划 | 基于蜣螂优化算法的栅格地图机器人路径规划(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 路径规划 | 基于蜣螂优化算法的栅格地图机器人路径规划&#xff08;Matlab&#xff09; 1.利用蜣螂算法DBO优化栅格地图机器人路径规划&#xff0c;效果如图所示&#xff0c;包括迭代曲线图、栅格地图等等&#xff5e…

【智能算法改进】多策略改进的蜣螂优化算法

目录 1.算法原理2.改进点3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】蜣螂优化算法&#xff08;DBO&#xff09;原理及实现 2.改进点 混沌反向学习初始化 采用 Pwlcm 分段混沌映射&#xff0c;由于 Pwlcm 在其定义区间上具有均匀的密度函数&#xff0c;在特定的…

PyCharm中如何将某个文件设置为默认运行文件

之前在使用JetBrain公司的另一款软件IDEA的时候&#xff0c;如果在选中static main函数后按键altenter可以默认以后运行Main类的main函数。最近在使用PyCharm学习Python&#xff0c;既然同为一家公司的产品而且二者的风格如此之像&#xff0c;所以我怀疑PyCharm中肯定也有类似的…

day01:项目概述,环境搭建

文章目录 软件开发整体介绍软件开发流程角色分工软件环境 外卖平台项目介绍项目介绍定位功能架构 产品原型技术选型 开发环境搭建整体结构&#xff1a;前后端分离开发前后端混合开发缺点前后端分离开发 前端环境搭建Nginx 后端环境搭建熟悉项目结构使用Git进行版本控制数据库环…

【Mathematical14.0最新进阶教学】-1-基础计算拓展

我在真正使用Mathematica后&#xff0c;才发觉这个软件的神奇&#xff0c;但是又有对于不知道如何使用这个神奇软件&#xff0c;因此我将我学习《The Student’s Introduction to Mathematica and the Wolfram Language (Bruce F. Torrence, Eve A. Torrence) 》的一些心得进行…

【AI大模型】驱动的未来:穿戴设备如何革新血液、皮肤检测与营养健康管理

文章目录 1. 引言2. 现状与挑战3. AI大模型与穿戴设备概述4. 数据采集与预处理4.1 数据集成与增强4.2 数据清洗与异常检测 5. 模型架构与训练5.1 高级模型架构5.2 模型训练与调优 6. 个性化营养建议系统6.1 营养建议生成优化6.2 用户反馈与系统优化 7. 关键血液成分与健康状况评…

Appium Inspector介绍和使用

一、什么是Appium Inspector 官方介绍&#xff1a;Overview - Appium Inspector 检查器的主要目的是提供应用程序页面源代码的检查功能。它主要用于测试自动化开发&#xff0c;但也可用于应用程序开发 - 或者如果只是想查看应用程序的页面源代码&#xff01; 从本质上讲&…

谈大语言模型动态思维流程编排

尽管大语言模型已经呈现出了强大的威力&#xff0c;但是如何让它完美地完成一个大的问题&#xff0c;仍然是一个巨大的挑战。 需要精心地给予大模型许多的提示&#xff08;Prompt&#xff09;。对于一个复杂的应用场景&#xff0c;编写一套完整的&#xff0c;准确无误的提示&am…

力扣hot100-普通数组

文章目录 题目&#xff1a;最大子数组和方法1 动态规划方法2 题目&#xff1a;合并区间题解 题目&#xff1a;轮转数组方法1-使用额外的数组方法2-三次反转数组 题目&#xff1a;除自身以外数组的乘积方法1-用到了除法方法2-前后缀乘积法 题目&#xff1a;最大子数组和 原题链…

MICCAI 2024Centerline Boundary Dice Loss for Vascular Segmentation

MICCAI 2024 Centerline Boundary Dice Loss for Vascular Segmentation MICCAI 2024Centerline Boundary Dice Loss for Vascular Segmentation中心线边界Dice损失用于血管分割**摘要**:1. 引言相关工作&#xff1a; 2. 方法预备知识Dice的变化 3 实验3.1 数据集3.2 设置3.3 结…

虚拟机使用

1、安装 如何安装虚拟机&#xff1f;保姆级安装教程&#xff01; - 知乎 (zhihu.com) 2、使用 2.1 快照 作用&#xff1a;保留当前系统信息为快照&#xff0c;随时可以恢复&#xff0c;以防未来系统被你玩坏&#xff0c;就好比游戏中的归档&#xff01;每配置好一个就可以保…

C++ 类和对象 拷贝构造函数

一 拷贝构造函数的概念&#xff1a; 拷贝构造函数是一种特殊的构造函数&#xff0c;用于创建一个对象是另一个对象的副本。当需要用一个已存在的对象来初始化一个新对象时&#xff0c;或者将对象传递给函数或从函数返回对象时&#xff0c;会调用拷贝构造函数。 二 拷贝构造函…

【TB作品】51单片机 Proteus仿真00016 乒乓球游戏机

课题任务 本课题任务 (联机乒乓球游戏)如下图所示: 同步显示 oo 8个LED ooooo oo ooooo 8个LED 单片机 单片机 按键 主机 从机 按键 设计题目:两机联机乒乓球游戏 图1课题任务示意图 具体说明: 共有两个单片机,每个单片机接8个LED和1 个按键,两个单片机使用串口连接。 (2)单片机…

pygame 音乐粒子特效

代码 import pygame import numpy as np import pymunk from pymunk import Vec2d import random import librosa import pydub# 初始化pygame pygame.init()# 创建屏幕 screen pygame.display.set_mode((1920*2-10, 1080*2-10)) clock pygame.time.Clock()# 加载音乐文件 a…

CentOS 离线安装部署 MySQL 8详细教程

1、简介 MySQL是一个流行的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它基于SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;进行操作。MySQL最初由瑞典的MySQL AB公司开发&#xff0c;后来被Sun Microsystems公司…

若依前后端分离 前端路由登录页 如何进行跳转

路由守卫&#xff0c;看这篇文章 http://t.csdnimg.cn/HkypThttp://t.csdnimg.cn/HkypT

从nginx返回404来看http1.0和http1.1的区别

序言 什么样的人可以称之为有智慧的人呢&#xff1f;如果下一个定义&#xff0c;你会如何来定义&#xff1f; 所谓智慧&#xff0c;就是能区分自己能改变的部分&#xff0c;自己无法改变的部分&#xff0c;努力去做自己能改变的&#xff0c;而不要天天想着那些无法改变的东西&a…