系列文章
Python 学习之open cv检测pcb板上的螺丝数量
文章目录
- 系列文章
- 前言
- 一、作者心得与代码背景
- 二、代码实现
-
- 1.代码思路
- 2.详细步骤
-
- 2.2.1编写相关的头文件
- 2.2.2导入相关的检测图片
- 2.2.3规定区域的位置设置
- 2.2.4检测图片预处理
- 2.2.5轮廓检测(霍夫圆)
- 2.2.6尾部编写
- 3.完整源代码
- 总结
前言
该文章介绍了如何用python来检测自己的pcb板上螺丝是否有缺失,可以运用到不同的业务场景中,本文用于学术交流,禁止商用与冒用,违者后果自负,谢谢!!!
一、作者心得与代码背景
国家最近几年都在推崇数字化转型,在许多的流水线工厂也跟着响应,那作者在实习的时候,发现了一个业务需求困扰了很多企业。
该需求就是:检测流水作业上的pcb板螺丝是否漏打,如下图中左侧红框中的两颗螺丝。
对此,作者提出了自己的思考方式,通过python与open-cv的编写,来解决该问题。
该方法耗费了作者许多的时间与精力,如果各位看官觉得该文章有用,还请给予一个赞与收藏
二、代码实现
1.代码思路
思路如下:
我们要去检测有无螺丝的漏打情况,就得先去定位螺丝的位置,保证螺丝打在了正确的位置后,才能开始检测。
- 传入我们所需要的检测图片
- 划定检测区域,定位螺丝的位置
- 处理相关部分的图片
- 通过霍夫圆检测来确定螺丝的轮廓,并进行判断是否有螺丝漏打的情况
2.详细步骤
2.2.1编写相关的头文件
代码如下:
import cv2 import numpy as np
2.2.2导入相关的检测图片
代码和图片如下:
#传进来螺丝图片 img = cv2.imread('文件名称')
2.2.3规定区域的位置设置
代码和图片如下:
# 下面是规定区域的位置设置 #第一个框 w1 = 0 h1 = 0 width = 350 height = 300 x1 = int(width / 2 - w1 / 2) y1 = int(height / 2 - h1 / 2 - 100) # print(x1, y1, x1 + w1, y1 + h1) cv2.rectangle(img, (w1, h1), (x1 + width, y1 + height), (0, 255, 0), 2) # 在原视频上绘制矩形框 #第二个框 w2 = 250 h2 = 710 width2 = 300 height2 = 300 # print(x1, y1, x1 + w1, y1 + h1) cv2.rectangle(img, (w2, h2), (w2 + width2, h2 + height2),(0, 255, 0), 2) # 在原视频上绘制矩形框 #绿框截取 x11 = w1 y11 = h1 x22 = x1 + width y22 = y1 + height # y写在前,x写在后,对角坐标 ims1 = img[y11:y22, x11:x22] x21 = w2 y21 = h2 x32 = w2 + width2 y32 = h2 + height2 # y写在前,x写在后,对角坐标 ims2 = img[y21:y32, x21:x32] cv2.imshow("Tailoring1",ims1) cv2.imshow("Tailoring2",ims2)
黄色圈圈为霍夫圆检测的轮廓,该阶段不需要注意
2.2.4检测图片预处理
代码如下:
#设置色域范围 HSV1 = cv2.cvtColor(ims1,cv2.COLOR_BGR2HSV) H, S, V = cv2.split(HSV1) HSV2 = cv2.cvtColor(ims2,cv2.COLOR_BGR2HSV) H, S, V = cv2.split(HSV2) #色域下限 lower_red = np.array([0, 0, 46]) #色域上限 upper_red = np.array([180, 43, 220]) mask1 = cv2.inRange(HSV1, lower_red, upper_red) mask1 = cv2.medianBlur(mask1, 5) maskAnd1 = cv2.bitwise_and(ims1, ims1, mask=mask1) upper_red = np.array([180, 43, 220]) mask2 = cv2.inRange(HSV2, lower_red, upper_red) mask2 = cv2.medianBlur(mask2, 5) maskAnd2 = cv2.bitwise_and(ims2, ims2, mask=mask2) # 找出轮廓 gray1 = cv2.cvtColor(maskAnd1, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray1, 175, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) gray2 = cv2.cvtColor(maskAnd2, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray2, 175, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cv2.imshow('maskAnd99', gray1) cv2.imshow('maskAnd98', gray2)
这样处理完后,我们就只会得到银色部分的图片,接下来我们就可以去取轮廓了
2.2.5轮廓检测(霍夫圆)
代码如下:
# 圆形检测 circles1 = cv2.HoughCircles(gray1, cv2.HOUGH_GRADIENT, dp=1, minDist=50, param1=100, param2=40, minRadius=10,maxRadius=100) circles2 = cv2.HoughCircles(gray2, cv2.HOUGH_GRADIENT, dp=1, minDist=50, param1=100, param2=40, minRadius=10,maxRadius=100) sum = 0 if circles1 is not None: try: for circle in circles1[0]: # 坐标行列-圆心坐标 x = int(circle[0]) y = int(circle[1]) # 半径 r = int(circle[2]) # 在原图用指定颜色标记出圆的边界 cv2.circle(ims1, (x, y), r, (0, 255, 255), 3) # 画出圆的圆心 cv2.circle(gray1, (x, y), r, (0, 255, 255), 3) circles = np.round(circles1[0, :]).astype("int") # 计算圆形的数量 sum += 1 except TypeError: print("一个都没打") if circles2 is not None: try: for circle in circles2[0]: # 坐标行列-圆心坐标 x = int(circle[0]) y = int(circle[1]) # 半径 r = int(circle[2]) # 在原图用指定颜色标记出圆的边界 cv2.circle(ims2, (x, y), r, (0, 255, 255), 3) # 画出圆的圆心 cv2.circle(gray2, (x, y), r, (0, 255, 255), 3) circles = np.round(circles2[0, :]).astype("int") # 计算圆形的数量 sum += 1 except TypeError: print("一个都没打") print('螺丝个数为:', sum) if(sum==2): print("OK") else: print("NG")
至此我们可以的得到两颗螺丝的轮廓,就是图中黄色圈圈标注的内容,同时还进行了螺丝的漏打判断,下面一幅图为只打了一颗螺丝的情况
2.2.6尾部编写
代码如下:
#展示图片 cv2.imshow('maskAnd1', img) cv2.waitKey() cv2.destroyAllWindows()
3.完整源代码
import cv2 import numpy as np #传进来螺丝图片 img = cv2.imread('jc1.jpg') # 下面是规定区域的位置设置 #第一个框 w1 = 0 h1 = 0 width = 350 height = 300 x1 = int(width / 2 - w1 / 2) y1 = int(height / 2 - h1 / 2 - 100) # print(x1, y1, x1 + w1, y1 + h1) cv2.rectangle(img, (w1, h1), (x1 + width, y1 + height), (0, 255, 0), 2) # 在原视频上绘制矩形框 #第二个框 w2 = 250 h2 = 710 width2 = 300 height2 = 300 # print(x1, y1, x1 + w1, y1 + h1) cv2.rectangle(img, (w2, h2), (w2 + width2, h2 + height2),(0, 255, 0), 2) # 在原视频上绘制矩形框 #绿框截取 x11 = w1 y11 = h1 x22 = x1 + width y22 = y1 + height # y写在前,x写在后,对角坐标 ims1 = img[y11:y22, x11:x22] x21 = w2 y21 = h2 x32 = w2 + width2 y32 = h2 + height2 # y写在前,x写在后,对角坐标 ims2 = img[y21:y32, x21:x32] cv2.imshow("Tailoring1",ims1) cv2.imshow("Tailoring2",ims2) #设置色域范围 HSV1 = cv2.cvtColor(ims1,cv2.COLOR_BGR2HSV) H, S, V = cv2.split(HSV1) HSV2 = cv2.cvtColor(ims2,cv2.COLOR_BGR2HSV) H, S, V = cv2.split(HSV2) #色域下限 lower_red = np.array([0, 0, 46]) #色域上限 upper_red = np.array([180, 43, 220]) mask1 = cv2.inRange(HSV1, lower_red, upper_red) mask1 = cv2.medianBlur(mask1, 5) maskAnd1 = cv2.bitwise_and(ims1, ims1, mask=mask1) upper_red = np.array([180, 43, 220]) mask2 = cv2.inRange(HSV2, lower_red, upper_red) mask2 = cv2.medianBlur(mask2, 5) maskAnd2 = cv2.bitwise_and(ims2, ims2, mask=mask2) # 找出轮廓 gray1 = cv2.cvtColor(maskAnd1, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray1, 175, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) gray2 = cv2.cvtColor(maskAnd2, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray2, 175, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cv2.imshow('maskAnd99', gray1) cv2.imshow('maskAnd98', gray2) # 圆形检测 circles1 = cv2.HoughCircles(gray1, cv2.HOUGH_GRADIENT, dp=1, minDist=50, param1=100, param2=40, minRadius=10,maxRadius=100) circles2 = cv2.HoughCircles(gray2, cv2.HOUGH_GRADIENT, dp=1, minDist=50, param1=100, param2=40, minRadius=10,maxRadius=100) sum = 0 if circles1 is not None: try: for circle in circles1[0]: # 坐标行列-圆心坐标 x = int(circle[0]) y = int(circle[1]) # 半径 r = int(circle[2]) # 在原图用指定颜色标记出圆的边界 cv2.circle(ims1, (x, y), r, (0, 255, 255), 3) # 画出圆的圆心 cv2.circle(gray1, (x, y), r, (0, 255, 255), 3) circles = np.round(circles1[0, :]).astype("int") # 计算圆形的数量 sum += 1 except TypeError: print("一个都没打") if circles2 is not None: try: for circle in circles2[0]: # 坐标行列-圆心坐标 x = int(circle[0]) y = int(circle[1]) # 半径 r = int(circle[2]) # 在原图用指定颜色标记出圆的边界 cv2.circle(ims2, (x, y), r, (0, 255, 255), 3) # 画出圆的圆心 cv2.circle(gray2, (x, y), r, (0, 255, 255), 3) circles = np.round(circles2[0, :]).astype("int") # 计算圆形的数量 sum += 1 except TypeError: print("一个都没打") print('螺丝个数为:', sum) if(sum==2): print("OK") else: print("NG") #展示图片 cv2.imshow('maskAnd1', img) cv2.waitKey() cv2.destroyAllWindows()
总结
以上就是今天要讲的内容,本文通过python与open-cv的编写,来解决了螺丝检测的业务需求,感谢您的观看