Python實(shí)現(xiàn)多個(gè)圓和圓中圓的檢測
主要思想是先檢測外邊圓和圓心
然后再外圓內(nèi)檢測小圓,計(jì)算小圓圓心與外圓圓心的距離判斷是不是有問題
或者可以計(jì)算兩圓圓心的距離
# 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
# 不同圖片應(yīng)該調(diào)節(jié)的參數(shù)
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:迭代次數(shù),也就是執(zhí)行幾次膨脹操作
# 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)
# 如果沒檢測到會報(bào)錯
# 這種判斷方式過于簡單
if circles is None:
print("沒有檢測到連接器外圓")
else:
for circle in circles[0]:
# 圓的基本信息
# print(circle[2])
# 坐標(biāo)行列-圓心坐標(biāo)
out_x = int(circle[0])
out_y = int(circle[1])
# 半徑
r = int(circle[2])
# # 在原圖用指定顏色標(biāo)記出圓的邊界
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:迭代次數(shù),也就是執(zhí)行幾次膨脹操作
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)
# 如果沒檢測到會報(bào)錯
# 這種判斷方式過于簡單
if circles is None:
print("沒有檢測到連接器外圓")
else:
for circle in circles[0]:
# 圓的基本信息
# print(circle[2])
# 坐標(biāo)行列-圓心坐標(biāo)
out_x = int(circle[0])
out_y = int(circle[1])
# 半徑
r = int(circle[2])
# # 在原圖用指定顏色標(biāo)記出圓的邊界
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("沒有檢測到針角坐標(biāo),可能需要調(diào)整針角斑點(diǎn)檢測參數(shù)")
print(keypoints)
return keypoints
else:
print("檢測到孔的數(shù)量", 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
# 檢測外部區(qū)域針或孔的位置
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)
# 輸出圖像大小,方便根據(jù)圖像大小調(diào)節(jié)minRadius和maxRadius
# print(image.shape)
# 進(jìn)行中值濾波
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()
# 針角圓心坐標(biāo)
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)
# 如果沒檢測到會報(bào)錯
# 這種判斷方式過于簡單
if circles is None:
print("沒有檢測到連接器外圓")
return 0, 0, 0
else:
for circle in circles[0]:
# 圓的基本信息
# print(circle[2])
# 坐標(biāo)行列-圓心坐標(biāo)
out_x = int(circle[0])
out_y = int(circle[1])
# 將檢測到的坐標(biāo)保存
# 半徑
r = int(circle[2])
# print(r)
# # # 在原圖用指定顏色標(biāo)記出圓的邊界
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
# 檢測內(nèi)部區(qū)域針或孔的位置
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)
# 輸出圖像大小,方便根據(jù)圖像大小調(diào)節(jié)minRadius和maxRadius
# print(image.shape)
# 進(jìn)行中值濾波
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()
# 針角圓心坐標(biāo)
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)
# 如果沒檢測到會報(bào)錯
# 這種判斷方式過于簡單
if circles is None:
print("沒有檢測到連接器外圓")
return out_x_p, out_y_p
else:
for circle in circles[0]:
# 圓的基本信息
# print(circle[2])
# 坐標(biāo)行列-圓心坐標(biāo)
out_x = int(circle[0])
out_y = int(circle[1])
# 將檢測到的坐標(biāo)保存
out_x_p.append(out_x)
out_y_p.append(out_y)
# 半徑
r = int(circle[2])
rudis.append(r)
# print(r)
# # # 在原圖用指定顏色標(biāo)記出圓的邊界
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()
# 記錄外圓坐標(biāo)
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)
# 只框出單個(gè)針角的位置區(qū)域
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()
# 根據(jù)檢測到的圓形連接器中心找針角位置
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("調(diào)整位置")
else:
for cp in centerPoint:
# 將針角的坐標(biāo)原還至原圖
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)
# # 計(jì)算兩者的距離
# # 假設(shè)通過標(biāo)定其一個(gè)像素代表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("沒檢測到,需要調(diào)整位置")
# 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)):
# 計(jì)算兩者的距離
# 假設(shè)通過標(biāo)定其一個(gè)像素代表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("沒有插針歪斜,產(chǎn)品合格")
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("沒有插針歪斜,產(chǎn)品合格")
return "沒有插針歪斜,產(chǎn)品合格"
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)):
# # 計(jì)算兩者的距離
# # 假設(shè)通過標(biāo)定其一個(gè)像素代表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("沒有插針歪斜,產(chǎn)品合格")
#
# cv2.namedWindow("image", 2)
# cv2.imshow("image",img_roi)
# cv2.waitKey()
到此這篇關(guān)于Python實(shí)現(xiàn)多個(gè)圓和圓中圓的檢測的文章就介紹到這了,更多相關(guān)Python檢測圓內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一個(gè)基于flask的web應(yīng)用誕生 bootstrap框架美化(3)
一個(gè)基于flask的web應(yīng)用誕生第三篇,這篇文章主要介紹了前端框架bootstrap與flask框架進(jìn)行整合,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
pyinstaller打包exe程序的步驟和添加依賴文件的實(shí)現(xiàn)
這篇文章主要介紹了pyinstaller打包exe程序的步驟和添加依賴文件的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
Caffe卷積神經(jīng)網(wǎng)絡(luò)視覺層Vision?Layers及參數(shù)詳解
這篇文章主要為大家介紹了Caffe卷積神經(jīng)網(wǎng)絡(luò)視覺層Vision?Layers及參數(shù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Python numpy線性代數(shù)用法實(shí)例解析
這篇文章主要介紹了Python numpy線性代數(shù)用法實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
django實(shí)現(xiàn)用戶注冊實(shí)例講解
在本篇文章里小編給大家整理的是關(guān)于django用戶注冊的相關(guān)實(shí)例內(nèi)容,有興趣的朋友們學(xué)習(xí)下。2019-10-10
Keras 切換后端方式(Theano和TensorFlow)
這篇文章主要介紹了Keras 切換后端方式(Theano和TensorFlow),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06
Python pywifi ERROR Open handle fai
這篇文章主要介紹了Python pywifi ERROR Open handle failed問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06

