拟合椭圆分开内外两组点集并计算两两之间的距离

 

通过拟合椭圆,区分开内外两组点,然后计算两两的距离


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 "产品合格"


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值