基于Opencv的缺陷检测实战

发布于:2025-07-13 ⋅ 阅读:(25) ⋅ 点赞:(0)
图像处理与缺陷检测流程
├── 1. 图像读取与预处理
│   ├── 读取原始图像
│   ├── 转换为灰度图
│   └── 调整图像大小
│
├── 2. 阈值处理
│   └── 应用固定阈值转换为二值图像
│
├── 3. 形态学操作
│   ├── 应用腐蚀操作消除小噪点
│   └── 应用反相阈值处理
│
├── 4. 边缘检测
│   └── 应用Canny算法检测图像边缘
│
├── 5. 轮廓提取与分析
│   ├── 查找图像中的所有轮廓
│   ├── 筛选有效轮廓(面积过滤)
│   └── 统计有效轮廓数量
│
├── 6. 结果可视化
│   ├── 创建处理流程拼接图
│   ├── 在原图上标记检测到的缺陷
│   │   ├── 绘制轮廓
│   │   ├── 添加缺陷数量文本
│   │   └── 添加时间戳
│   └── 显示处理结果
│
└── 7. 结果保存
    └── 将标记后的图像保存到指定目录

安装相应包,修改图片路径,以下代码即可直接运行:


#--Invert Threshold Detaiimport os
import cv2
import numpy as np

# 基于OpenCV的简单产品缺陷检测,可直接使用,记得把图片路径改成自己的。

#--variable:变量,控制原图大小。
IMAGE_SIZE = (500,500)

#--Threshold Detail
# THRESHOLD_VALUE:二分值,用于将灰度图像转换为二值图像
#普通阈值操作的分割值。当像素值大于 110时,将被设为MAX_VALUE(白色);否则设为 0(黑色)
THRESHOLD_VALUE = 110
# 普通阈值操作中,超过阈值的像素将被设置为这个值(通常代表白色)。
MAX_VALUE = 255

# 反相阈值操作的分割值。当像素值小于 50时,将被设为INV_MAX_VALUE(白色);否则设为 0(黑色)。
INV_THRESHOLD_VALUE = 50
INV_MAX_VALUE = 255

#--Canny Details,Canny 边缘检测算法的配置项,用于在图像中提取清晰的边缘。
THRESHOLD1 = 70
THRESHOLD2 = 100

#--contour properties,这两个参数用于控制在图像上绘制轮廓的视觉属性
# 轮廓线的颜色,采用 BGR(蓝、绿、红)格式。这里的(0, 0, 255)表示纯红色,常用于在图像中突出显示轮廓。
CON_COLOR = (0, 0, 255)
# 轮廓线的粗细,单位为像素。
CON_THICKNESS = 1
# THICKNESS = -1:填充轮廓内部(常用于可视化分割区域)

#--字体颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
RED = (0, 0, 255)
# 图像堆叠时每个子图像的目标尺寸(宽度 × 高度),用于将多个图像组合成网格显示。
STACK_IMG_SIZE =(200, 200)

#-------
# file = 'images/s1.png',原图图片路径位置!!!
file = r'images/s1.png'
path =  file

#1.读数据
imageOri = cv2.imread(path)
print(imageOri)

#2.灰度图,把 BGR 格式的彩色图像转换为灰度图像
image = cv2.cvtColor(imageOri, cv2.COLOR_BGR2GRAY)
#展示灰度图
#cv2.imshow('image_gray', image)
#cv2.waitKey(0)
#cv2.destroyAllWindows()

#3.resize,将原始图像和灰度图像调整为统一尺寸(IMAGE_SIZE),确保后续处理一致性。
imageOri = cv2.resize(imageOri, IMAGE_SIZE)
image = cv2.resize(image, IMAGE_SIZE)

#4.THRESHOLD操作,将灰度图像转换为二值图像
ret,thresh_basic = cv2.threshold(image, THRESHOLD_VALUE, MAX_VALUE, cv2.THRESH_BINARY)
# cv2.imshow('image_gray', thresh_basic)
# cv2.waitKey(0)
# cv2.destroyAllWindows()

#5.形态学操作
# 功能解析
# 腐蚀操作(Erosion):
# 目的:通过3×3的全 1 内核(kernel)缩小前景物体的边界,消除小噪点或分离相连物体。
# 参数:
# kernel:结构元素,控制腐蚀的范围和形状。
# iterations=1:执行 1 次腐蚀操作。
# 反相阈值(Inverse Threshold):
# 目的:将腐蚀后的图像二值化并反转(前景变背景,背景变前景)。
# 参数:
# INV_THRESHOLD_VALUE=50:低于此值的像素设为INV_MAX_VALUE(通常为 255,白色)。
# INV_MAX_VALUE=255:高于阈值的像素设为 0(黑色)。
kernel = np.ones((3,3), np.uint8)
img_erosion = cv2.erode(thresh_basic, kernel, iterations = 1)

ret, thresh_inv = cv2.threshold(img_erosion,INV_THRESHOLD_VALUE,INV_MAX_VALUE,cv2.THRESH_BINARY_INV)
# cv2.imshow('image_gray', img_erosion)
# cv2.waitKey(0)
# cv2.destroyAllWindows()

#6.Canny边缘检测
# 功能解析
# 输入:img_erosion(经过腐蚀处理的二值图像)。
# 输出:edged(包含检测到的边缘的二值图像)。
# 参数:
# THRESHOLD1(低阈值):控制弱边缘的保留条件。
# THRESHOLD2(高阈值):控制强边缘的定义标准。
edged = cv2.Canny(img_erosion,THRESHOLD1,THRESHOLD2)
# cv2.imshow('edged', edged)
# cv2.waitKey(0)
# cv2.destroyAllWindows()

#7.轮廓
# 功能解析
# 输入:img_erosion(经过腐蚀处理的二值图像)。
# 输出:
# contours:检测到的轮廓列表,每个轮廓由一系列点组成。
# h(或hierarchy):轮廓的层次结构信息(嵌套关系)。
# 参数:
# cv2.RETR_TREE:检索所有轮廓并重建完整的嵌套层次结构。
# cv2.CHAIN_APPROX_SIMPLE:仅保留轮廓的端点,压缩水平、垂直和对角线方向的冗余点。
contours,h = cv2.findContours(img_erosion,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

#--Image Stack,将上列图像整合到一起然后画出
# 当前功能
# 将各个处理阶段的图像(灰度图、阈值图、腐蚀图、反相阈值图、边缘图)调整为统一尺寸(STACK_IMG_SIZE)。
# 准备用于后续的水平或垂直拼接。
font = cv2.FONT_HERSHEY_SIMPLEX

imageRz = cv2.resize(image, STACK_IMG_SIZE)
thresh_basicRz = cv2.resize(thresh_basic, STACK_IMG_SIZE)
img_erosionRz = cv2.resize(img_erosion, STACK_IMG_SIZE)
thresh_invRz = cv2.resize(thresh_inv, STACK_IMG_SIZE)
edgedRz = cv2.resize(edged, STACK_IMG_SIZE)

#给图片取名写文字
# 当前功能
# 文字标注:在每个图像的左上角添加描述性文字。
# 水平拼接:将所有图像沿水平方向(axis=1)拼接成一个大图像。
imageRz = cv2.putText(imageRz,'GrayScale',(5,15),font,0.5,WHITE,1,cv2.LINE_AA)
thresh_basicRz = cv2.putText(thresh_basicRz,'ThresholdBasic',(5,15),font,
                             0.5,WHITE,1,cv2.LINE_AA)

img_erosionRz = cv2.putText(img_erosionRz,'Morphology-Erosion',(5,15),font,
                            0.5,WHITE,1,cv2.LINE_AA)

thresh_invRz = cv2.putText(thresh_invRz,'Threshold-mode INV',(5,15),font,
                           0.5,BLACK,1,cv2.LINE_AA)

edgedRz = cv2.putText(edgedRz,'Canny Edged',(5,15),font,
                      0.5,WHITE,1,cv2.LINE_AA)

numpy_horizontal_concat = np.concatenate((imageRz,thresh_basicRz,img_erosionRz,
                                          thresh_invRz,edgedRz),axis=1)

# 当前功能
# 显示处理流程:展示包含多个处理步骤的拼接图像。
# 轮廓计数:统计检测到的轮廓数量。
# 缺陷标记:
# 若检测到轮廓,在原图上绘制所有轮廓并标注缺陷数量。
# 若未检测到轮廓,显示 "Unable to detect defect"。
# 优化建议
#画图
cv2.imshow('Filtering...',numpy_horizontal_concat)

#get total contours,找轮廓的返回值,计算
num_of_con = str(len(contours) - 1)
print("Number of Contours found = " + num_of_con)
if len(contours) > 1:
    print('=========================')
    print('=   MARKINGS DETECTED   =')
    print('=========================\n\n')

# show original img
# cv2.imshow('Original Image',imageOri)
# draw contours on original img
if int(num_of_con) != 0:
    for i in range(int(num_of_con)):
        highlighted_img = cv2.drawContours(imageOri,contours,i,CON_COLOR,CON_THICKNESS)

    highlighted_img = cv2.putText(highlighted_img,'Approximately {} defect(s) detected'.
                                  format(num_of_con),(5,15),font,0.5,GREEN,1,cv2.LINE_AA)
else:
    highlighted_img = cv2.putText(imageOri,'Unable to detect defect',(5,15),font,
                                0.5,RED,2,cv2.LINE_AA)

# show markings highlighted img,结果保存:将标记后的图像保存到Output Images文件夹,文件名格式为原图名_DEFECTS_HIGHLIGHTED.png。
cv2.imshow('Highlighted Defect',highlighted_img)
# save image containing highlighted defect
cv2.imwrite('Output Images/{}_DEFECTS_HIGHLIGHTED.png'.format(file.split('.')[0]),highlighted_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

展示效果:


网站公告

今日签到

点亮在社区的每一天
去签到