【项目实战】 Python + Opencv 的工业级机器视觉检测系统

目录

前言

一、系统介绍

1.1 设计目的

1.2 硬件配置

二、程序描述

2.1 视觉检测流程

2.2 程序描述

2.2.1 清空文件夹模块

2.2.2 ROI区域划分模块

2.2.3 黑白占比计算

2.2.4 图像处理模块

三、系统简易展示

3.1 合格展示

3.2 不合格展示

四、系统框架代码


前言

 1. 由于受到软件著作权保护,本视觉检测系统仅提供部分算法设计思路。该系统建议作为一个框架使用,通过调整算法结构,具体参数和文件路径实现视觉检测。
 2. 完整版本已投入工业现场使用。

一、系统介绍

1.1 设计目的


本系统主要针对PCB进行检测,PCB在焊锡过程中可能出现以下问题:

 - (1)焊点缺失
 - (2)焊点粘连

因此提出以下要求:

 - (1)对PCB上的焊点进行检测
 - (2)对所有焊点进行判断是否存在缺陷,有缺陷则报警,无缺陷则显示合格
 - (3)将视觉检测系统与PLC进行通讯,通过三色灯显示检测结果

1.2 硬件配置

名称

型号规格

高清工业相机

AA1300 -90GC

相机镜头

HF1628-6MP

LED面光源

BL120*60

光源控制器

模拟恒流

工控机

CV-A6-08128

IO控制器

DAM0808D

二、程序描述

2.1 视觉检测流程

检测思路:

  1. 当系统启动时,首先判断寄存文件夹的文件数量,当文件数量不为1时,删除除了最新图片外的所有图片,然后进行图片读取。当文件数量为1时直接进行图片读取。
  2. 在读取到图片后对图片通过掩膜进行裁剪,然后进行图像处理,消除图片噪声,提取有用的特征。
  3. 用黑白像素的占比计算来作为合格条件进行判断,当白像素超出阈值时为不合格,通过与PLC通讯使得三色灯亮,低于阈值时三色灯绿灯亮,最终显示OK/NG结果,系统结束。

2.2 程序描述

2.2.1 清空文件夹模块

 

模块介绍:

    1.通过python内置的os库来进行文件读取,获得目标文件夹长度list,通过len(list)计算文件夹长度。

    2.当目标文件夹长度不为1时,显示长度(文件夹内图片数量),通过for循环递增文件夹长度的倒数第二个位置,用os.Remove()将图片删除,剩下最后一张即最新的图片。

    3.当目标文件夹长度为1时,说明相机驱动软件MVS采集到最新图片,直接pass进入下一模块。

2.2.2 ROI区域划分模块

 

模块介绍:

    1.图片在计算机中以数组形式显示,相机分辨率为1280*1024,受限于焦距和光圈限制,不能完全覆盖PCB大小,因此需要把 1280*1024的原图裁剪成 和PCB大小相同的 300*350 的图片。PCB板的焊锡分布为上面五个,中间三个,下面三个,生成目标区域的掩膜mask,并且将掩膜像素全置为255,三个mask区域大小分别为:

    2.通过位操作cv.bitwise_and将图像和掩膜进行合并,分别提取出三个目标区域,最后通多cv.add()将区域相加,使得原本图像只剩下三个目标区域:

2.2.3 黑白占比计算

模块介绍:

    用black-pixel和white-pixel两个变量储存黑白像素点的数量,通过遍历1280*1024即13,107,200个像素,使用PLI包内的Image模块,image.size()用于读取PIL方式image.open()打开的图片,该模式下读取图片的宽和长,将值返回到width和height两个变量中。通过image.getpixel()获取某点处像素,统计图片画幅中的像素点数量,当遍历完所有像素后,计算黑白占比并显示,流程结束。

2.2.4 图像处理模块

    图像处理模块是一个线性流程,其中的图像处理算法为灰度处理 - 形态学处理(腐蚀 - 膨胀 - 开运算)- 高斯滤波 - 轮廓提取,分别使用到以下函数:

表2 — 图像处理函数表

类型

函数名称

结构元大小

腐蚀

cv.erode()

(5,5)

膨胀

cv.dilate()

(3,3)

开运算

cv.morphologyEx()

(7,7)

高斯滤波

cv.GaussianBlur()

(1,1)

二值化

cv.threshold()

发现轮廓

cv.findContours()

绘制轮廓

cv.drawContours()

具体函数的使用如下:

三、系统简易展示

处理前图片为PCB板,因涉及专利设计保护,因此使用SW模型代替。

3.1 合格展示

  

图1 处理前图片                                                      图2 处理后图片

 

图3 检测结果显示

3.2 不合格展示

  

 图4 处理前图片                                         图5 处理后图片

 

 图6 处理前图片   

四、系统框架代码

import os
import time
import cv2 as cv
import numpy as np
from PIL import Image
from appdirs import unicode

'''
算法设计:
(1)形态学处理 -- 1、(腐蚀5*5,膨胀3*3,开运算7*7,均为矩形结构元) 2、高斯滤波
(2)blob筛选 -- 提取并绘制轮廓,减少图片噪声
'''

'''
检测流程:
(1)从文件夹内读取RGB图片
(2)对RGB图片进行灰度处理,形态学处理,高斯滤波和轮廓提取,其中灰度处理后需要进行掩膜处理,提取目标区域.
(3)对处理完的图片进行黑白占比计算,焊锡点缺失会导致焊锡处反光,导致亮度过高.当白色占比超过阈值,判断为焊锡缺失
(4)输出合格与不合格后,与PLC通过modbus通讯
'''

def cut(cut):
    '''
    主要功能:把 1024*1280 的原图 裁剪成 PCB大小的 300*350 的图片
            然后将三个焊锡区域提取出来并合并
    '''
    img = cut[350:650, 500:850]  # 把 1280*1024 的原图 裁剪成 PCB大小的 300*350 的图片

    # 分割区域1 -- 上面五个焊锡点
    mask1 = np.zeros(img.shape[:2], np.uint8)
    mask1[10:60, 10:330] = 255
    mask1_img = cv.bitwise_and(img, img, mask=mask1)
    # cv.imshow('mask1',mask1_img)

    # 分割区域2 -- 中间三个焊锡点
    mask2 = np.zeros(img.shape[:2], np.uint8)
    mask2[80:130, 70:270] = 255
    mask2_img = cv.bitwise_and(img, img, mask=mask2)
    # cv.imshow('mask2',mask2_img)

    # 分割区域3 -- 下面三个焊锡点
    mask3 = np.zeros(img.shape[:2], np.uint8)
    mask3[240:290, 70:270] = 255
    mask3_img = cv.bitwise_and(img, img, mask=mask3)
    # cv.imshow('mask3',mask3_img)

    pic1 = cv.add(mask1_img, mask2_img)  # 区域1+区域2
    pic = cv.add(pic1, mask3_img)  # 区域(1+2)+区域3

    return pic

def remove():
    '''
       主要功能:保证文件夹内只有最新的那一张图片
    '''
    # 时间在0.01以内,因此不记录时间
    path = r'C:\Users\-libr\Desktop\PCB\PCB input_dir'
    file = unicode(path)
    files = os.listdir(file)  # 创建由文件名组成的列表
    #print('filelist:', files)

    if len(os.listdir(path)) > 1:
        print(f"图片数量为:{len(os.listdir(path))}")
        for i in range(len(os.listdir(path))-1):
            #设置 len(os.listdir(path))-1 是为了保证i递增到倒数第二,留下最新的图片
            i += 1
            #print(i)
            os.remove(os.path.join(path, f'PCB{i}.jpg'))

    elif len(os.listdir(path)) == 1:
        print(f"图片数量为:1 ")
        #文件夹内只有最新的那张图片
        pass

def count(image):
        '''
           主要功能;输入单张图片图片,计算并输出'黑白占比的计算结果'和'计算一次的时间'
        '''

        start = time.time()
        white_pixel = 0
        black_pixel = 0

        width, height = image.size
        for i in range(width):
                for j in range(height):
                        if image.getpixel((i,j)):
                                white_pixel += 1
                        else:
                                black_pixel += 1

        black = black_pixel / (width * height)
        white = white_pixel / (width * height)

        end = time.time()
        cost = end - start

        print('黑白检测时间:%s'%cost)
        print('黑色占比:%s\n白色占比:%s'%(black,white))

        #判断黑白占比阈值,输出检验结果
        if black > 0.99:
                return(print('合格\n'))
        else:
                return(print('不合格\n'))

def convert(input_dir, output_dir):
        for filename in os.listdir(input_dir):
                '''
                   主要功能:读取文件夹内的图片,进行图像处理后,并将其保存到指定文件
                '''
                path = input_dir + "/" + filename  # 获取文件路径
                gray_img = cv.imread(path, 0)  # 读取图片,参数0为直接以灰度模式读取

                cut_pic = cut(gray_img)  #提取三个焊锡区域后的图片

                # 腐蚀
                kernel1 = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
                img_erode = cv.erode(cut_pic, kernel1)

                # 膨胀
                kernel2 = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
                img_dilate = cv.dilate(img_erode, kernel2)

                # 开运算
                kernel3 = cv.getStructuringElement(cv.MORPH_RECT, (7, 7))
                img_open = cv.morphologyEx(img_dilate, cv.MORPH_OPEN, kernel3, iterations=1)

                # 高斯滤波
                img_gaussian = cv.GaussianBlur(img_open, (1, 1), 2)

                # 二值化
                ret, img_turn = cv.threshold(img_gaussian, 127, 255, 0)

                # 发现轮廓
                contours, heriachy = cv.findContours(img_turn, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
                for i, contour in enumerate(contours):
                        # 绘制每条轮廓
                        cv.drawContours(img_turn, contours, i, (0, 0, 255), 2)

                cv.imwrite(output_dir + '/' + filename, img_turn)
                cv.imshow("PCB", img_turn)
                cv.waitKey()
                cv.destroyAllWindows()
                # cv.destroyAllWindows(1)
        
def read_path(output_dir):
        for filename in os.listdir(output_dir):
                '''
                   主要功能:定义读取路径的函数,为用PIL打开图片获得
                '''
                path = output_dir + "/" + filename  # 获取文件路径
                image = Image.open(path).convert('L')
                count(image)

if __name__ == '__main__':

        # 输入RGB图片
        input_dir = r'C:\Users\-libr\Desktop\PCB\PCB input_dir'  # 输入文件夹
        output_dir = r'C:\Users\-libr\Desktop\PCB\PCB output_dir'  # 输出文件夹

        #1、保持文件夹内只有最新图片
        remove()

        #2、对图片进行读取,处理和保存
        convert(input_dir, output_dir)

        #3、对图片进行黑白占比计算并判断
        read_path(r'C:\Users\-libr\Desktop\PCB\PCB output_dir')

  • 16
    点赞
  • 136
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,下面是一个使用Python+OpenCV+MediaPipe实现手势识别系统的项目示例: 1. 安装必要的库,包括OpenCV、MediaPipe和NumPy等。 ``` pip install opencv-python mediapipe numpy ``` 2. 导入必要的库和模块: ```python import cv2 import mediapipe as mp import numpy as np ``` 3. 初始化Hand Tracking模块: ```python mp_hands = mp.solutions.hands hands = mp_hands.Hands( static_image_mode=False, max_num_hands=2, min_detection_confidence=0.7, min_tracking_confidence=0.7) ``` 4. 读取摄像头捕获到的图像: ```python cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: continue ``` 5. 对图像中的手部进行跟踪和检测: ```python # 转换图像颜色空间 image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 处理图像 results = hands.process(image) # 将图像颜色空间转换回来 image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) ``` 6. 对检测到的手部进行手势识别,并根据识别结果做出相应的反应: ```python # 检测到手部 if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: # 获取手部关键点坐标 landmarks = np.array([[lmk.x, lmk.y, lmk.z] for lmk in hand_landmarks.landmark]).T # 进行手势识别 gesture = gesture_recognition(landmarks) # 根据手势识别结果做出相应的反应 if gesture == 'Fist': # 做出拳头手势的反应 ... elif gesture == 'Open': # 做出张开手掌的反应 ... else: # 其他手势的反应 ... ``` 7. 释放摄像头和Hand Tracking模块,并关闭窗口: ```python cap.release() hands.close() cv2.destroyAllWindows() ``` 需要注意的是,以上代码只是一个简单的示例,实际的手势识别系统还需要进行模型的训练和优化,以及对不同的手势进行分类和识别。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值