Python实现多个圆和圆中圆的检测
主要思想是先检测外边圆和圆心
然后再外圆内检测小圆,计算小圆圆心与外圆圆心的距离判断是不是有问题
或者可以计算两圆圆心的距离
# coding:utf-8 import math import cv2 import numpy as np import os def findNeedlePoints(img): gray_src= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) minThreshValue = 50 _, gray = cv2.threshold(gray_src, minThreshValue, 255, cv2.THRESH_BINARY) erosion_size = 3 # element = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2 * erosion_size + 1, 2 * erosion_size + 1), # (erosion_size, erosion_size)) element = cv2.getStructuringElement(cv2.MORPH_ERODE, (2 * erosion_size + 1, 2 * erosion_size + 1), (erosion_size, erosion_size)) # MORPH_ELLIPSE 不同的测试一下 erosion_gray = cv2.erode(gray, element, 3) cv2.imshow("erosion_gray", erosion_gray) paramsIn = cv2.SimpleBlobDetector_Params() paramsIn.filterByArea = True # 不同图片应该调节的参数 paramsIn.minArea = 80 paramsIn.maxArea = 1000 paramsIn.minDistBetweenBlobs = 80 paramsIn.filterByColor = True paramsIn.filterByConvexity = False paramsIn.minThreshold = 100*2 paramsIn.maxThreshold = 1000 # 图像取反 needleGray = 255 - erosion_gray.copy() # 中值滤波和腐蚀去噪 needleGray = cv2.medianBlur(needleGray, 3) # cv2.imshow('needleGray', needleGray) erosion_size = 2 element = cv2.getStructuringElement(cv2.MORPH_RECT, (2 * erosion_size + 1, 2 * erosion_size + 1), (erosion_size, erosion_size)) needlePoints = cv2.erode(needleGray, element, 1) cv2.imshow('needle=Points', needlePoints) detector2 = cv2.SimpleBlobDetector_create(paramsIn) needleKeypoints = detector2.detect(needlePoints) # opencv needle_keypoints = cv2.drawKeypoints(needlePoints, needleKeypoints, np.array([]), (255, 0, 0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) allNeedlePoints = [] if needleKeypoints is not None: for i in range(len(needleKeypoints)): allNeedlePoints.append(needleKeypoints[i].pt) color_img = cv2.cvtColor(needle_keypoints, cv2.COLOR_BGR2RGB) # needle_img = cv2.cvtColor(im_with_keypoints, cv2.COLOR_BGR2RGB) cv2.imshow('holeShow', color_img) # cv2.imshow('needleShow', needle_img) cv2.waitKey() def innerHoughCicle(hsv_image, src_image, rect): # 霍夫变换圆检测 gray_src = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2RGB) gray_src = cv2.cvtColor(gray_src, cv2.COLOR_RGB2GRAY) minThreshValue = 100 _, gray = cv2.threshold(gray_src, minThreshValue, 255, cv2.THRESH_BINARY) kernel1 = np.ones((3, 3), dtype=np.uint8) kernel2 = np.ones((3, 3), dtype=np.uint8) gray = cv2.erode(gray, kernel2, 2) gray = cv2.dilate(gray, kernel1, 2) # 1:迭代次数,也就是执行几次膨胀操作 # cv2.namedWindow("gray", 2) # cv2.imshow("gray", gray) # cv2.waitKey() circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 2, 100, param1=100, param2=60, minRadius=10, maxRadius=100) # 如果没检测到会报错 # 这种判断方式过于简单 if circles is None: print("没有检测到连接器外圆") else: for circle in circles[0]: # 圆的基本信息 # print(circle[2]) # 坐标行列-圆心坐标 out_x = int(circle[0]) out_y = int(circle[1]) # 半径 r = int(circle[2]) # # 在原图用指定颜色标记出圆的边界 cv2.circle(hsv_image, (out_x, out_y), r, (0, 0, 255), 2) # # 画出圆的圆心 cv2.circle(hsv_image, (out_x, out_y), 3, (0, 0, 255), -1) cv2.namedWindow("hsv_circle", 2) cv2.imshow("hsv_circle",hsv_image) cv2.waitKey() def outHoughCicle(hsv_image, src_image, rect): # 霍夫变换圆检测 gray_src = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2RGB) gray_src = cv2.cvtColor(gray_src, cv2.COLOR_RGB2GRAY) minThreshValue = 50 _, gray = cv2.threshold(gray_src, minThreshValue, 255, cv2.THRESH_BINARY) kernel1 = np.ones((3, 3), dtype=np.uint8) kernel2 = np.ones((3, 3), dtype=np.uint8) gray = cv2.erode(gray, kernel2, 2) gray = cv2.dilate(gray, kernel1, 2) # 1:迭代次数,也就是执行几次膨胀操作 cv2.namedWindow("gray", 2) cv2.imshow("gray", gray) cv2.waitKey() circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 10e10, param1=100, param2=60, minRadius=500, maxRadius=10000) # 如果没检测到会报错 # 这种判断方式过于简单 if circles is None: print("没有检测到连接器外圆") else: for circle in circles[0]: # 圆的基本信息 # print(circle[2]) # 坐标行列-圆心坐标 out_x = int(circle[0]) out_y = int(circle[1]) # 半径 r = int(circle[2]) # # 在原图用指定颜色标记出圆的边界 cv2.circle(hsv_image, (out_x, out_y), r, (0, 0, 255), 2) # # 画出圆的圆心 cv2.circle(hsv_image, (out_x, out_y), 3, (0, 0, 255), -1) # 画在原图上 cv2.circle(src_image, (out_x + rect[0], out_y + rect[1]), r, (0, 0, 255), 2) # # 画出圆的圆心 cv2.circle(src_image, (out_x + rect[0], out_y+ rect[1]), 3, (0, 0, 255), -1) cv2.namedWindow("hsv_circle", 2) cv2.imshow("hsv_circle",hsv_image) cv2.namedWindow("src_image", 2) cv2.imshow("src_image",src_image) cv2.waitKey() # 检测针脚位置 def needelCenter_detect(img): params = cv2.SimpleBlobDetector_Params() # Setup SimpleBlobDetector parameters. # print('params') # print(params) # print(type(params)) # Filter by Area. params.filterByArea = True params.minArea = 100 params.maxArea = 10e3 params.minDistBetweenBlobs = 50 # params.filterByColor = True params.filterByConvexity = False # tweak these as you see fit # Filter by Circularity params.filterByCircularity = False params.minCircularity = 0.2 # params.blobColor = 0 # # # Filter by Convexity # params.filterByConvexity = True # params.minConvexity = 0.87 # Filter by Inertia # params.filterByInertia = True # params.filterByInertia = False # params.minInertiaRatio = 0.01 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Detect blobs. minThreshValue = 100 _, gray = cv2.threshold(gray, minThreshValue, 255, cv2.THRESH_BINARY) erosion_size = 1 # element = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2 * erosion_size + 1, 2 * erosion_size + 1), # (erosion_size, erosion_size)) element = cv2.getStructuringElement(cv2.MORPH_ERODE, (2 * erosion_size + 1, 2 * erosion_size + 1), (erosion_size, erosion_size)) dilate_gray = cv2.dilate(gray, element, 1) # cv2.namedWindow("gray", 2) # cv2.imshow("gray",dilate_gray) # cv2.waitKey() detector = cv2.SimpleBlobDetector_create(params) keypoints = detector.detect(dilate_gray) # print(len(keypoints)) # print(keypoints[0].pt[0]) # 如果这儿没检测到可能会出错 if len(keypoints) == 0: print("没有检测到针角坐标,可能需要调整针角斑点检测参数") print(keypoints) return keypoints else: print("检测到孔的数量", len(keypoints)) # im_with_keypoints = cv2.drawKeypoints(img, keypoints, np.array([]), (255, 0, 0), # cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # # color_img = cv2.cvtColor(im_with_keypoints, cv2.COLOR_BGR2RGB) # 画出圆的圆心 # for kp in keypoints: # cv2.circle(img, (int(kp.pt[0]), int(kp.pt[1])), 3, (0, 0, 255), -1) # # cv2.namedWindow("color_img", 2) # cv2.imshow("color_img",img) # # cv2.waitKey() return keypoints # 检测外部区域针或孔的位置 def out_circle_detect(rect_hole_info, src): # 灰度化 circle_img = rect_hole_info gray = cv2.cvtColor(circle_img, cv2.COLOR_HSV2RGB) gray = cv2.cvtColor(gray, cv2.COLOR_RGB2GRAY) # 输出图像大小,方便根据图像大小调节minRadius和maxRadius # print(image.shape) # 进行中值滤波 img = cv2.medianBlur(gray, 3) erosion_size = 3 # element = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2 * erosion_size + 1, 2 * erosion_size + 1), # (erosion_size, erosion_size)) element = cv2.getStructuringElement(cv2.MORPH_ERODE, (2 * erosion_size + 1, 2 * erosion_size + 1), (erosion_size, erosion_size)) dilate_gray = cv2.dilate(img, element, 1) # cv2.namedWindow("dilate_gray", 2) # cv2.imshow("dilate_gray", dilate_gray) # cv2.waitKey() # 针角圆心坐标 out_x, out_y, r = 0, 0, 0 # 霍夫变换检测最大圆 circles = cv2.HoughCircles(dilate_gray, cv2.HOUGH_GRADIENT, 1, 1000, param1=100, param2=30, minRadius=500, maxRadius=1000) # 如果没检测到会报错 # 这种判断方式过于简单 if circles is None: print("没有检测到连接器外圆") return 0, 0, 0 else: for circle in circles[0]: # 圆的基本信息 # print(circle[2]) # 坐标行列-圆心坐标 out_x = int(circle[0]) out_y = int(circle[1]) # 将检测到的坐标保存 # 半径 r = int(circle[2]) # print(r) # # # 在原图用指定颜色标记出圆的边界 cv2.circle(circle_img, (out_x, out_y), r, (0, 0, 255), 2) # # 画出圆的圆心 cv2.circle(circle_img, (out_x, out_y), 5, (0, 0, 255), -1) cv2.namedWindow("circle_imgs", 2) cv2.imshow("circle_imgs", circle_img) cv2.waitKey() return out_x, out_y, r # 检测内部区域针或孔的位置 def inner_circle_detect(rect_hole_info, src): # 灰度化 circle_img = rect_hole_info gray = cv2.cvtColor(circle_img, cv2.COLOR_HSV2RGB) gray = cv2.cvtColor(gray, cv2.COLOR_RGB2GRAY) # 输出图像大小,方便根据图像大小调节minRadius和maxRadius # print(image.shape) # 进行中值滤波 img = cv2.medianBlur(gray, 3) erosion_size = 3 # element = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2 * erosion_size + 1, 2 * erosion_size + 1), # (erosion_size, erosion_size)) element = cv2.getStructuringElement(cv2.MORPH_ERODE, (2 * erosion_size + 1, 2 * erosion_size + 1), (erosion_size, erosion_size)) dilate_gray = cv2.dilate(img, element, 1) # cv2.namedWindow("dilate_gray", 2) # cv2.imshow("dilate_gray", dilate_gray) # cv2.waitKey() # 针角圆心坐标 out_x_p = [] out_y_p = [] rudis = [] # 霍夫变换检测最大圆 circles = cv2.HoughCircles(dilate_gray, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=30, minRadius=20, maxRadius=100) # 如果没检测到会报错 # 这种判断方式过于简单 if circles is None: print("没有检测到连接器外圆") return out_x_p, out_y_p else: for circle in circles[0]: # 圆的基本信息 # print(circle[2]) # 坐标行列-圆心坐标 out_x = int(circle[0]) out_y = int(circle[1]) # 将检测到的坐标保存 out_x_p.append(out_x) out_y_p.append(out_y) # 半径 r = int(circle[2]) rudis.append(r) # print(r) # # # 在原图用指定颜色标记出圆的边界 cv2.circle(circle_img, (out_x, out_y), r, (0, 0, 255), 2) # # 画出圆的圆心 cv2.circle(circle_img, (out_x, out_y), 5, (0, 0, 255), -1) cv2.namedWindow("circle_img", 2) cv2.imshow("circle_img",circle_img) cv2.waitKey() # 记录外圆坐标 out_xpoints = out_x_p.copy() out_ypoints = out_y_p.copy() out_rudis = rudis.copy() # print("out_xpoints",out_xpoints) # print("out_ypoints",out_ypoints) # 只框出单个针角的位置区域 step_center = 25 step_rect = 50 # 遍历所有的孔的位置 # 记录孔的位置 in_x_p = [] in_y_p = [] for i in range(0, len(out_xpoints)): out_x_begin = out_xpoints[i] - step_center out_y_begin = out_ypoints[i] - step_center needleRect = circle_img[out_y_begin: out_y_begin + step_rect, out_x_begin: out_x_begin + step_rect] # cv2.namedWindow("needleRect", 2) # cv2.imshow("needleRect", needleRect) # cv2.waitKey() # 根据检测到的圆形连接器中心找针角位置 centerPoint = needelCenter_detect(needleRect) # print(len(centerPoint)) if len(centerPoint) == 0: out_x_p.remove(out_xpoints[i]) out_y_p.remove(out_ypoints[i]) rudis.remove(out_rudis[i]) print("调整位置") else: for cp in centerPoint: # 将针角的坐标原还至原图 in_x = int(cp.pt[0]) in_y = int(cp.pt[1]) in_x += out_x_begin in_y += out_y_begin in_x_p.append(in_x) in_y_p.append(in_y) # # # 画出中心孔的圆心 # cv2.circle(circle_img, (in_x, in_y), 4, (0, 255, 0), -1) # # 画出外孔的圆心 # cv2.circle(circle_img, (out_xpoints[i], out_ypoints[i]), 4, (0, 0, 255), -1) # # 计算两者的距离 # # 假设通过标定其一个像素代表0.0056mm # DPI = 0.0198 # dis = math.sqrt(math.pow(out_xpoints[i] - in_x,2) + math.pow(out_ypoints[i] - in_y,2)) # print("两者相互之间的距离为(mm):", dis*DPI) return in_x_p,in_y_p # cv2.namedWindow("image", 2) # cv2.imshow("image",circle_img) # cv2.waitKey() # if len(out_x_p) == 0: # print("没检测到,需要调整位置") # else: # for j in range(0,len(out_x_p)): # # 画出外孔的圆心 # cv2.circle(circle_img, (out_x_p[j], out_y_p[j]), rudis[j], (0, 0, 255), 3) # cv2.circle(circle_img, (out_x_p[j], out_y_p[j]), 3, (0, 0, 255), -1) # # # cv2.circle(circle_img, (in_x_p[j], in_y_p[j]), 3, (0, 255, 0), -1) # # cv2.namedWindow("image", 2) # cv2.imshow("image",circle_img) # cv2.waitKey() def j599_4_holes_dectWX(imagePath, templatePath): # templatePath需要用户手动框获取ROI img = cv2.imread(imagePath) img_roi = cv2.imread(templatePath) if img_roi is None: print("no image") # HSV二值化 img_roi = cv2.medianBlur(img_roi, 5) # 中值滤波 outx, outy, outR = out_circle_detect(img_roi, img) print(outx, outy, outR ) inx, iny = inner_circle_detect(img_roi, img) if len(inx) == 0 or outx == 0: print("没检测到位置") return "没检测到对象", -1 else: cv2.circle(img_roi, (outx, outy), outR, (0, 0, 255), 3) is_ok = [] for k in range(0, len(inx)): # 计算两者的距离 # 假设通过标定其一个像素代表0.0056mm # 两者相互之间的距离为(mm): 9.311053946788194 # 两者相互之间的距离为(mm): 9.163550379629067 # 两者相互之间的距离为(mm): 8.95984457900917 # 两者相互之间的距离为(mm): 8.977940966613671 # 平均值为 9.103 所以其阈值为9.103 + 0.5 DPI = 0.0198 dis = math.sqrt(math.pow(outx - inx[k], 2) + math.pow(outy - iny[k], 2)) dis *= DPI # print("两者相互之间的距离为(mm):", dis) if dis < 9.603: cv2.circle(img_roi, (inx[k], iny[k]), 8, (0, 255, 0), -1) # print("没有插针歪斜,产品合格") is_ok.append(1) else: cv2.circle(img_roi, (inx[k], iny[k]), 20, (0, 0, 255), 3) # print("有插针歪斜,不合格") is_ok.append(0) # cv2.namedWindow("image", 2) # cv2.imshow("image",img_roi) # cv2.waitKey() isExists = os.path.exists("./runs/J599/") if not isExists: os.makedirs("./runs/J599/") cv2.imwrite("./runs/J599/result.jpg", img_roi) if 0 in is_ok: print("有插针歪斜,不合格") return "有插针歪斜,不合格" else: print("没有插针歪斜,产品合格") return "没有插针歪斜,产品合格" if __name__ == "__main__": reslut = j599_4_holes_dectWX("images/Final/E_0_8.jpg","J599-4holes_template.jpg") print(reslut) # # # # # 4holes # img = cv2.imread("images/Final/E_0_8.jpg", 1) # # img_roi = img[973:2027, 1713:2751] # # img_roi = img[852:2224, 1515:2940] # img_roi = img[842:2234, 1480:2950] # cv2.imwrite("J599-4holes_template.jpg",img_roi) # # # cv2.namedWindow("img_roi",2) # # cv2.imshow("img_roi", img_roi) # # cv2.waitKey() # if img_roi is None: # print("no image") # else: # # HSV二值化 # img_roi = cv2.medianBlur(img_roi, 5) # 中值滤波 # outx, outy, outR = out_circle_detect(img_roi, img) # print(outx, outy, outR ) # inx, iny = inner_circle_detect(img_roi, img) # if len(inx) == 0 or outx == 0: # print("没检测到位置") # else: # cv2.circle(img_roi, (outx, outy), outR, (0, 0, 255), 3) # # for k in range(0, len(inx)): # # 计算两者的距离 # # 假设通过标定其一个像素代表0.0056mm # # 两者相互之间的距离为(mm): 9.311053946788194 # # 两者相互之间的距离为(mm): 9.163550379629067 # # 两者相互之间的距离为(mm): 8.95984457900917 # # 两者相互之间的距离为(mm): 8.977940966613671 # # 平均值为 9.103 所以其阈值为9.103 + 0.5 # DPI = 0.0198 # dis = math.sqrt(math.pow(outx - inx[k], 2) + math.pow(outy - iny[k], 2)) # dis *= DPI # # print("两者相互之间的距离为(mm):", dis) # if dis > 9.603: # cv2.circle(img_roi, (inx[k], iny[k]), 20, (0, 0, 255), 3) # print("有插针歪斜,不合格") # else: # cv2.circle(img_roi, (inx[k], iny[k]), 8, (0, 255, 0), -1) # print("没有插针歪斜,产品合格") # # cv2.namedWindow("image", 2) # cv2.imshow("image",img_roi) # cv2.waitKey()
到此这篇关于Python实现多个圆和圆中圆的检测的文章就介绍到这了,更多相关Python检测圆内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
赞 (0)