通过拟合椭圆,区分开内外两组点,然后计算两两的距离
from Ransac_Process import RANSAC
import cv2
import numpy as np
import math
from operator import *
def calu_neighbor_dis(src, centerPoints, tolerance, DPI, standard_dis):
img = np.zeros((300, 300, 3), np.uint8)
h,w = img.shape[:2]
# 拟合时坐标为整数
for item in centerPoints:
item[0] = math.ceil(item[0])*30 + int(w/2)
item[1] = math.ceil(item[1])*30 + int(h/2)
cv2.circle(img, (item[0], item[1]), 5, (0, 255, 0), -1) # 画圆心
points_data = np.array(centerPoints)
# 拟合椭圆
# # 随机采样一致性拟合
# Ransac = RANSAC(data=points_data, threshold=0.5, P=.98, S=0.5, N=10)
#
# ellipse_values = Ransac.execute_ransac()
# # # 检测到轮廓里数量太少(<5)则无法拟合椭圆
# # if ellipse_values is None:
# # return 0, 0
#
# (x, y), (LAxis, SAxis), Angle = ellipse_values
# a = SAxis
# # print( (X, Y), (LAxis, SAxis))
# # # 拟合圆
#
# cv2.ellipse(img, ((x, y), (LAxis, SAxis), Angle), (0, 0, 255), 1, cv2.LINE_AA) # 画圆
# cv2.circle(img, (int(x), int(y)), 3, (0, 0, 255), -1) # 画圆心
# cv2.imshow("image", img)
# cv2.waitKey()
# 直接拟合椭圆
if len(points_data) < 4:
# 点集不够拟合椭圆
return []
rrt = cv2.fitEllipse(points_data) # x, y)代表椭圆中心点的位置(a, b)代表长短轴长度,应注意a、b为长短轴的直径,而非半径,angle 代表了中心旋转的角度
# print("rrt", rrt)
cv2.ellipse(img, rrt, (0, 0, 255), 1, cv2.LINE_AA) # 画圆
x, y = rrt[0]
cv2.circle(img, (int(x), int(y)), 3, (0, 0, 255), -1) # 画圆心
a, b = rrt[1] # ab分别为短长轴
# 内外侧圆心点集
in_center_points = []
out_center_points = []
for point in points_data:
dis_inner = math.sqrt(math.pow(point[0] - x, 2) + math.pow(point[1] - y, 2))
if dis_inner < (a/2)*0.618:
in_center_points.append(point)
cv2.circle(img, (int(point[0]), int(point[1])), 3, (255, 255, 255), -1) # 画圆心
elif dis_inner > (a/2)*0.8 and dis_inner < 1.15*(b/2):
out_center_points.append(point)
cv2.circle(img, (int(point[0]), int(point[1])), 4, (255, 0, 0), -1) # 画圆心
# print(in_center_points)
standard_in, standard_out = standard_dis
defect = []
# 2.1求外侧一圈两两之间的距离
dis_out_all = []
for k in range(len(out_center_points) -1):
between_dis_out = math.sqrt(math.pow(out_center_points[k][0] - out_center_points[k+1][0], 2) +
math.pow(out_center_points[k][1] - out_center_points[k+1][1], 2))
between_dis_out *= DPI
dis_out_all.append(between_dis_out)
if abs(between_dis_out - standard_out ) > tolerance:
print(abs(between_dis_out - standard_out ))
defect.append(1)
print("外侧针有歪斜,产品不合格")
else:
defect.append(-1)
# print("between_dis_out", between_dis_out)
#2.2计算第一个和最后一个之间的距离
between_dis_fl = math.sqrt(math.pow(out_center_points[0][0] - out_center_points[-1][0], 2) +
math.pow(out_center_points[0][1] - out_center_points[-1][1], 2))
between_dis_fl *= DPI
dis_out_all.append(between_dis_fl)
if abs(between_dis_fl -standard_out ) > tolerance:
defect.append(1)
print("外侧针fl有歪斜,产品不合格")
else:
defect.append(-1)
# print(np.mean(dis_out_all))
# print("between_dis_fl", between_dis_fl)
# 2.3求中间的三个元素求两两的距离
dis_in_all = []
for i in range(len(in_center_points)-1):
for j in range(i + 1, len(in_center_points)):
between_dis_inner = math.sqrt(math.pow(in_center_points[i][0] - in_center_points[j][0], 2) +
math.pow(in_center_points[i][1] - in_center_points[j][1], 2))
between_dis_inner *= DPI
dis_in_all.append(between_dis_inner)
if abs(between_dis_inner - standard_in) > tolerance:
defect.append(0)
print("内侧针有歪斜,产品不合格")
else:
defect.append(-1)
# print("between_dis_inner", between_dis_inner)
# print(np.mean(dis_in_all))
cv2.imshow("image", img)
cv2.waitKey()
return defect
def decide_quality(src, centerPoints, tolerance, DPI, standard_dis):
defect = calu_neighbor_dis(src, centerPoints, tolerance, DPI, standard_dis)
if defect is None:
print("外侧椭圆拟合失败")
return "检测失败"
if 0 in defect or 1 in defect:
return "产品不合格"
else:
return "产品合格"
if __name__ == "__main__":
tolerance = 0.5*2
DPI = 0.0103
# 第一个内侧个针之间的标准距离,第二个元素为外侧两针之间的标准距离
standard_dis = [0.83, 1]
# centerPoints = [[3.71,0],[3, 2.16], [1.14, 3.51],[-1.14, 3.51], [-3.71, 0],
# [-3, 2.16], [-1.14, -3.51], [-3, -2.16], [1.14, -3.51],
# [3, -2.16], [1.42, 0], [-0.89, -1.24],[-0.89,1.14]]
centerPoints = [[3.71,0],[3, 2.16], [1.14, 3.51],[-1.14, 3.51], [-3.71, 0],
[-3, 2.16], [-1.14, -3.51], [-3, -2.16], [1.14, -3.51],
[3, -2.16], [1.42, 0], [-0.89, -1.24],[-0.89,1.14]]
src = "imread image"
defect = calu_neighbor_dis(src, centerPoints, tolerance, DPI, standard_dis)
if defect is None:
print("外侧椭圆拟合失败")
# return "检测失败"
if 0 in defect or 1 in defect:
print("产品不合格")
# return "产品不合格"
else:
print("产品合格")
# return "产品合格"