在这里插入图片描述

很多想入行工业视觉的朋友都会问我:“我需要把Python学到什么程度才能开始做工业视觉?”

我的答案永远是:不需要精通Python,掌握50%的核心语法就足够了

我见过太多人陷入了"先把Python学透再开始做项目"的误区,花了几个月时间学了面向对象、多线程、装饰器、生成器这些高级特性,结果到了工业视觉项目中发现90%都用不上。反而最基础的列表操作、循环、函数这些内容掌握得不够扎实。

同样,OpenCV有几百个函数,但工业视觉中90%的需求只需要用到不到20个核心函数。只要掌握了这些核心操作,你就能解决80%以上的工业图像处理问题。

本文是我专门为工业视觉初学者准备的速成指南,只讲工业视觉中最常用、最实用的Python语法和OpenCV操作,没有任何废话。看完这篇文章,你就能写出第一个工业缺陷检测程序。

一、工业视觉必备Python基础语法

Python是工业视觉开发的首选语言,它语法简单、库丰富、开发速度快。下面我会列出工业视觉开发中必须掌握的Python语法,每个知识点都配有工业场景的实际例子。

1.1 变量与数据类型

工业视觉中最常用的数据类型只有4种:整数、浮点数、字符串和布尔值。

# 整数:用于计数、坐标、像素值
defect_count = 5  # 缺陷数量
x = 100  # 缺陷x坐标
y = 200  # 缺陷y坐标

# 浮点数:用于精度、置信度、尺寸
confidence = 0.85  # 检测置信度
defect_length = 12.5  # 缺陷长度(mm)

# 字符串:用于文件路径、日志信息
image_path = "D:/images/pcb_001.jpg"  # 图像路径
log_message = "检测到5个缺陷"  # 日志信息

# 布尔值:用于判断
has_defect = True  # 是否有缺陷
is_running = False  # 程序是否运行

1.2 列表与字典

列表和字典是工业视觉中最重要的数据结构,几乎所有的检测结果都会用它们来存储。

列表:用于存储多个相同类型的数据,比如多个缺陷的坐标。

# 存储多个缺陷的坐标
defect_coordinates = [(100, 200), (300, 400), (500, 600)]

# 列表常用操作
defect_coordinates.append((700, 800))  # 添加一个缺陷
print(f"缺陷数量: {len(defect_coordinates)}")  # 获取缺陷数量
print(f"第一个缺陷坐标: {defect_coordinates[0]}")  # 访问第一个元素

# 遍历列表
for coord in defect_coordinates:
    print(f"缺陷坐标: x={coord[0]}, y={coord[1]}")

字典:用于存储一个对象的多个属性,比如一个缺陷的详细信息。

# 存储一个缺陷的详细信息
defect = {
    "id": 1,
    "type": "划痕",
    "x": 100,
    "y": 200,
    "length": 12.5,
    "confidence": 0.85
}

# 字典常用操作
print(f"缺陷类型: {defect['type']}")  # 访问属性
defect["area"] = 25.0  # 添加新属性
print(f"缺陷信息: {defect}")  # 打印完整信息

1.3 条件与循环

条件判断和循环是程序的基本控制结构,工业视觉中最常用的就是if-else判断和for循环。

# 条件判断:根据缺陷数量决定是否报警
defect_count = 5

if defect_count == 0:
    print("产品合格")
elif defect_count <= 3:
    print("产品合格,存在轻微缺陷")
else:
    print("产品不合格,存在严重缺陷")
    # 触发报警信号
    trigger_alarm()

# for循环:处理多张图片
image_paths = ["pcb_001.jpg", "pcb_002.jpg", "pcb_003.jpg"]

for path in image_paths:
    print(f"正在处理: {path}")
    # 读取图像
    image = cv2.imread(path)
    # 进行缺陷检测
    result = detect_defect(image)
    # 保存结果
    save_result(result)

1.4 函数

函数可以将重复的代码封装起来,提高代码的可读性和复用性。在工业视觉项目中,我们通常会把每个功能都封装成一个函数。

def calculate_defect_area(contour):
    """计算缺陷的面积"""
    area = cv2.contourArea(contour)
    return area

def is_valid_defect(area, min_area=10, max_area=1000):
    """判断是否为有效缺陷"""
    return min_area < area < max_area

# 调用函数
contour = [...]  # 轮廓数据
area = calculate_defect_area(contour)
if is_valid_defect(area):
    print("检测到有效缺陷")
else:
    print("噪声,忽略")

1.5 文件操作

工业视觉中经常需要读取图像文件、保存检测结果、写入日志文件。

# 写入检测日志
with open("detection_log.txt", "a", encoding="utf-8") as f:
    f.write("2026-05-16 10:30:00 - 检测到5个缺陷\n")

# 读取配置文件
with open("config.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    for line in lines:
        print(line.strip())

1.6 异常处理

工业设备需要7×24小时连续运行,异常处理至关重要。一个未捕获的异常就可能导致整个产线停机。

try:
    # 尝试读取图像
    image = cv2.imread("pcb_001.jpg")
    if image is None:
        raise Exception("图像读取失败")
    
    # 进行缺陷检测
    result = detect_defect(image)
    
except Exception as e:
    # 捕获所有异常,记录日志
    print(f"发生错误: {e}")
    with open("error_log.txt", "a", encoding="utf-8") as f:
        f.write(f"2026-05-16 10:30:00 - 错误: {e}\n")
    
finally:
    # 无论是否发生错误,都会执行的代码
    release_resources()

二、OpenCV核心操作:工业视觉90%的需求都在这里

OpenCV是最流行的计算机视觉库,工业视觉中几乎所有的图像处理操作都是基于OpenCV实现的。下面我会介绍工业视觉中最常用的10个OpenCV核心操作,每个操作都有明确的工业应用场景。

图像读取

图像预处理

灰度化

滤波去噪

ROI裁剪

阈值处理

边缘检测

轮廓检测

结果绘制

图像保存

2.1 图像读取与显示

这是OpenCV最基础的操作,也是所有图像处理的第一步。

import cv2
import numpy as np

# 读取图像
# 注意:OpenCV默认使用BGR颜色空间,而不是RGB
image = cv2.imread("pcb_001.jpg")

# 检查图像是否读取成功
if image is None:
    print("图像读取失败")
    exit()

# 获取图像信息
height, width, channels = image.shape
print(f"图像尺寸: {width}x{height}, 通道数: {channels}")

# 显示图像
cv2.imshow("Original Image", image)
cv2.waitKey(0)  # 等待按键输入
cv2.destroyAllWindows()  # 关闭所有窗口

踩坑提醒:OpenCV读取中文路径会报错,解决方法是用cv2.imdecode

# 读取中文路径图像
image = cv2.imdecode(np.fromfile("PCB板001.jpg", dtype=np.uint8), cv2.IMREAD_COLOR)

2.2 图像基本操作

工业视觉中最常用的图像基本操作包括:裁剪、缩放、旋转和翻转。

# 1. 裁剪ROI区域(最重要!工业中只关心产品所在的区域)
# ROI: Region of Interest,感兴趣区域
# 格式: image[y1:y2, x1:x2]
roi = image[100:500, 200:600]  # 裁剪x从200到600,y从100到500的区域

# 2. 缩放图像
# 缩小到原来的一半
resized = cv2.resize(image, (width//2, height//2))
# 缩放到指定尺寸640x480
resized = cv2.resize(image, (640, 480))

# 3. 旋转图像
# 旋转90度
rotated = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)
# 旋转180度
rotated = cv2.rotate(image, cv2.ROTATE_180)

# 4. 翻转图像
# 水平翻转
flipped = cv2.flip(image, 1)
# 垂直翻转
flipped = cv2.flip(image, 0)

2.3 颜色空间转换

工业视觉中最常用的颜色空间转换是BGR转灰度,因为大多数图像处理算法都是基于灰度图像的。

# BGR转灰度图像(最常用)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# BGR转HSV(用于颜色检测)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# 显示灰度图像
cv2.imshow("Gray Image", gray)
cv2.waitKey(0)

2.4 图像滤波

滤波的主要目的是去除图像中的噪声,这是缺陷检测前必不可少的预处理步骤。

# 高斯滤波(最常用,对高斯噪声效果好)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)

# 中值滤波(对椒盐噪声效果好,适合去除金属表面的亮点)
median_blurred = cv2.medianBlur(gray, 5)

# 双边滤波(去噪的同时保留边缘)
bilateral_blurred = cv2.bilateralFilter(gray, 9, 75, 75)

2.5 阈值处理

阈值处理可以将灰度图像转换为二值图像,将目标和背景分离开,这是缺陷检测中最核心的步骤之一。

# 1. 全局阈值处理(适用于光照均匀的场景)
# 像素值大于127的设为255(白色),小于的设为0(黑色)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 2. 自适应阈值处理(适用于光照不均匀的场景,工业中最常用)
binary = cv2.adaptiveThreshold(
    gray, 
    255, 
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
    cv2.THRESH_BINARY_INV, 
    11, 
    2
)

# 3. OTSU阈值处理(自动计算最佳阈值)
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

2.6 边缘检测

边缘检测可以找到图像中物体的边界,常用于尺寸测量和缺陷定位。

# Canny边缘检测(最常用)
edges = cv2.Canny(blurred, 50, 150)

# 显示边缘图像
cv2.imshow("Edges", edges)
cv2.waitKey(0)

2.7 轮廓检测

轮廓检测可以找到图像中所有连通区域的边界,是工业缺陷检测中最常用的技术之一。通过分析轮廓的面积、周长、形状等特征,我们可以判断是否存在缺陷。

# 查找轮廓
contours, hierarchy = cv2.findContours(
    binary, 
    cv2.RETR_EXTERNAL,  # 只检测最外层轮廓
    cv2.CHAIN_APPROX_SIMPLE  # 压缩轮廓点
)

print(f"找到{len(contours)}个轮廓")

# 遍历所有轮廓
for contour in contours:
    # 计算轮廓面积
    area = cv2.contourArea(contour)
    
    # 面积过滤,去除噪声
    if area < 10 or area > 1000:
        continue
    
    # 计算轮廓的外接矩形
    x, y, w, h = cv2.boundingRect(contour)
    
    print(f"有效缺陷: 位置({x},{y}), 尺寸{w}x{h}, 面积{area}")

2.8 绘制图形与文字

检测到缺陷后,我们需要在图像上绘制矩形框和文字,直观地显示检测结果。

# 创建一个原始图像的副本,用于绘制
result = image.copy()

for contour in contours:
    area = cv2.contourArea(contour)
    if 10 < area < 1000:
        x, y, w, h = cv2.boundingRect(contour)
        
        # 绘制矩形框
        cv2.rectangle(result, (x, y), (x+w, y+h), (0, 0, 255), 2)
        
        # 绘制文字
        cv2.putText(
            result, 
            f"Defect: {area:.1f}", 
            (x, y-10), 
            cv2.FONT_HERSHEY_SIMPLEX, 
            0.5, 
            (0, 0, 255), 
            2
        )

# 显示结果
cv2.imshow("Detection Result", result)
cv2.waitKey(0)

踩坑提醒:OpenCV的putText函数不支持中文,会显示成乱码。如果需要显示中文,可以使用PIL库。

2.9 图像保存

检测完成后,我们需要将结果图像保存下来,用于后续的追溯和分析。

# 保存结果图像
cv2.imwrite("result.jpg", result)

# 保存中文路径图像
cv2.imencode('.jpg', result)[1].tofile("检测结果.jpg")

2.10 视频与相机操作

工业视觉中最常见的是实时处理相机流,而不是处理静态图片。

# 打开USB相机(0表示第一个相机)
cap = cv2.VideoCapture(0)

# 设置相机参数
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap.set(cv2.CAP_PROP_FPS, 30)

# 检查相机是否打开成功
if not cap.isOpened():
    print("无法打开相机")
    exit()

# 实时处理相机流
while True:
    # 读取一帧图像
    ret, frame = cap.read()
    if not ret:
        print("无法读取图像")
        break
    
    # 在这里添加你的图像处理代码
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    ret, binary = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY)
    
    # 显示结果
    cv2.imshow("Live Detection", binary)
    
    # 按q键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

三、综合实战:简单的PCB缺陷检测程序

现在我们把前面学到的所有知识整合起来,写一个完整的PCB缺陷检测程序。这个程序可以检测PCB板上的孔洞缺陷,并在图像上标注出来。

import cv2
import numpy as np

def detect_pcb_defects(image_path):
    """检测PCB板上的孔洞缺陷"""
    # 1. 读取图像
    image = cv2.imread(image_path)
    if image is None:
        print(f"无法读取图像: {image_path}")
        return None
    
    # 2. 预处理
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    
    # 3. 阈值处理
    ret, binary = cv2.threshold(blurred, 100, 255, cv2.THRESH_BINARY_INV)
    
    # 4. 查找轮廓
    contours, hierarchy = cv2.findContours(
        binary, 
        cv2.RETR_EXTERNAL, 
        cv2.CHAIN_APPROX_SIMPLE
    )
    
    # 5. 轮廓过滤与结果绘制
    result = image.copy()
    defect_count = 0
    
    for contour in contours:
        area = cv2.contourArea(contour)
        
        # 过滤掉面积太小和太大的轮廓
        if 20 < area < 200:
            x, y, w, h = cv2.boundingRect(contour)
            
            # 绘制缺陷框
            cv2.rectangle(result, (x, y), (x+w, y+h), (0, 0, 255), 2)
            cv2.putText(
                result, 
                f"Hole: {area:.1f}", 
                (x, y-10), 
                cv2.FONT_HERSHEY_SIMPLEX, 
                0.5, 
                (0, 0, 255), 
                2
            )
            
            defect_count += 1
    
    # 6. 在图像上添加统计信息
    cv2.putText(
        result, 
        f"Defects: {defect_count}", 
        (10, 30), 
        cv2.FONT_HERSHEY_SIMPLEX, 
        1, 
        (0, 255, 0), 
        2
    )
    
    print(f"检测完成,共发现{defect_count}个孔洞缺陷")
    return result, defect_count

# 主程序
if __name__ == "__main__":
    image_path = "pcb_sample.jpg"
    result_image, defect_count = detect_pcb_defects(image_path)
    
    if result_image is not None:
        # 显示结果
        cv2.imshow("PCB Defect Detection", result_image)
        cv2.waitKey(0)
        
        # 保存结果
        cv2.imwrite("pcb_result.jpg", result_image)
        
        # 判断产品是否合格
        if defect_count == 0:
            print("产品合格")
        else:
            print("产品不合格")

四、常见问题与踩坑指南

4.1 OpenCV读取中文路径报错

这是OpenCV最常见的坑,解决方法是使用cv2.imdecodecv2.imencode

# 读取中文路径
image = cv2.imdecode(np.fromfile("中文路径.jpg", dtype=np.uint8), cv2.IMREAD_COLOR)

# 保存中文路径
cv2.imencode('.jpg', image)[1].tofile("中文结果.jpg")

4.2 图像显示不出来或一闪而过

这是因为没有调用cv2.waitKey(0),这个函数会等待用户按键输入,否则窗口会立即关闭。

4.3 中文乱码问题

OpenCV的putText函数不支持中文,解决方法是使用PIL库:

from PIL import Image, ImageDraw, ImageFont

def put_chinese_text(image, text, position, font_size=20, color=(0, 0, 255)):
    """在图像上绘制中文文字"""
    pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(pil_image)
    font = ImageFont.truetype("msyh.ttc", font_size)
    draw.text(position, text, font=font, fill=color)
    return cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)

4.4 相机无法打开

  • 检查相机是否正确连接
  • 检查相机驱动是否安装
  • 尝试更换USB端口
  • 关闭其他可能占用相机的程序

五、总结与下一步

恭喜你!看完这篇文章,你已经掌握了工业视觉开发所需的90%的Python基础语法和OpenCV核心操作。

回顾一下我们学到的内容:

  • Python基础:变量、列表、字典、条件、循环、函数、文件操作、异常处理
  • OpenCV核心:图像读写、裁剪缩放、灰度化、滤波、阈值处理、边缘检测、轮廓检测、绘制结果、相机操作

这些知识足够你解决大多数简单的工业视觉问题了。接下来你可以:

  1. 找一些工业缺陷图片,自己动手写代码进行检测
  2. 学习YOLO算法,用深度学习的方法解决更复杂的缺陷检测问题
  3. 学习工业相机的使用和标定
  4. 学习如何与PLC、机器人等工业设备通信

在后续的文章中,我会详细介绍这些内容,带你一步步成为工业视觉工程师。


👉 点击我的头像进入主页,关注专栏第一时间收到更新提醒,有问题评论区交流,看到都会回。

更多推荐