• OpenCV-Python实战(4) —— OpenCV 五角星各点在坐标系上面的坐标计算(以重心为原点)


    1. 创建坐标系

    输入图片说明

    2. 角度计算

    注意: AO⊥BE !!!

    2.1 五个角的度数
    ∠GAF = ∠FBG = ∠GCH = ∠HDK = ∠KEG = 36°
    
    • 1
    2.2 五个角对应的原点度数
    ∠GOF = ∠FOG = ∠GOH = ∠HOK = ∠KOG = 360° / 5 = 72°
    
    • 1
    2.3 计算与x轴夹角度数
    ∠AOX = 90°
    ∠GOF = 72°
    ∠FOB = 36°
    ∠BOX = 90° - 72° = 18°
    ∠GOX = ∠KOX = 36° - 18° = 18°
    ∠COX = ∠DOX = 36° + 18° = 54°
    ∠FOX = 36° + 18° = 54°
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3 计算各个线段的长度

    假设 OA = r !!!

    3.1 计算 OF 长度
    因为:
    ∠BOX = 90° - 72° = 18°
    ∠FOA = 36°
    OB = r
    所以:
    pi_val = np.pi / 180
    OF * np.cos(36 * pi_val) = OB * np.sin(18 * pi_val)
    OF = min_r = (r * np.sin(18 * pi_val)) / np.cos(36 * pi_val)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4. 各点坐标表示

    # 外五边形的坐标
    A(0,r)
    B(r * np.cos(18 * pi_val), r * np.sin(18 * pi_val))
    C(r * np.cos(54 * pi_val), - r * np.sin(54 * pi_val))
    D(- r * np.cos(54 * pi_val), - r * np.sin(54 * pi_val))
    E(- r * np.cos(18 * pi_val), r * np.sin(18 * pi_val))
    # 内五边形的坐标
    F(min_r * np.cos(54 * pi_val),min_r * np.sin(54 * pi_val))
    G(min_r * np.cos(18 * pi_val),- min_r * np.sin(18 * pi_val))
    H(0, - min_r)
    K(- min_r * np.cos(18 * pi_val),- min_r * np.sin(18 * pi_val))
    G(- min_r * np.cos(54 * pi_val),min_r * np.sin(54 * pi_val))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5. 根据计算的点绘制上边坐标系

    5.1 实现代码
    import cv2 as cv
    import numpy as np
    
    # 使用 **arrowedLine** 箭头线创建坐标系
    def create_coordinate(mat):
      h,w,c = mat.shape
      half_h = int(h / 2)
      half_w = int(w / 2)
      # 绘制x轴
      ptsx1 = (10, half_h)
      ptsx2 = (w - 10, half_h)
      cv.arrowedLine(mat,ptsx1,ptsx2,(0,0,0),tipLength=0.03)
      cv.putText(mat,'x',(w - 25, half_h + 25), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,0))
      # 绘制y轴
      ptsy1 = (half_w, h - 10)
      ptsy2 = (half_w, 10)
      cv.arrowedLine(mat,ptsy1,ptsy2,(0,0,0),tipLength=0.03)
      cv.putText(mat,'y',(half_w + 10, 25), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,0))
    
      # 绘制原点和坐标
      cv.putText(mat,'O(0,0)',(half_w, half_h - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      return mat
    
    # 以五角星的重心为原点,计算各点坐标
    def get_star_point(r = 100):
      # 计算没一份的度数和内五边形的r
      pi_val = np.pi / 180
      min_r = r * np.sin(18 * pi_val) / np.cos(36 * pi_val)
      # 外五边形的坐标
      a = [0,r]
      b = [r * np.cos(18 * pi_val), r * np.sin(18 * pi_val)]
      c = [r * np.cos(54 * pi_val), - r * np.sin(54 * pi_val)]
      d = [- r * np.cos(54 * pi_val), - r * np.sin(54 * pi_val)]
      e = [- r * np.cos(18 * pi_val), r * np.sin(18 * pi_val)]
      # 内五边形的坐标
      in_a = [min_r * np.cos(54 * pi_val),min_r * np.sin(54 * pi_val)]
      in_b = [min_r * np.cos(18 * pi_val),- min_r * np.sin(18 * pi_val)]
      in_c = [0, - min_r]
      in_d = [- min_r * np.cos(18 * pi_val),- min_r * np.sin(18 * pi_val)]
      in_e = [- min_r * np.cos(54 * pi_val),min_r * np.sin(54 * pi_val)]
      return {
        "out": [a, b, c, d, e],
        "in": [in_a, in_b, in_c, in_d, in_e]
      }
    
    def tagging_points(img):
      # 获取五角星各个坐标点
      points = get_star_point()
      # 获取内外五边形的各点坐标
      [a,b,c,d,e] = list(map(lambda items: [int(items[0]),-int(items[1])], points.get("out")))
      [in_a,in_b,in_c,in_d,in_e] = list(map(lambda items: [int(items[0]),-int(items[1])], points.get("in")))
      cv.putText(img,f'A',(a[0] + 200, a[1] + 200), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'B',(b[0] + 200, b[1] + 200 - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'C',(c[0] + 200, c[1] + 200 + 10), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'D',(d[0] + 200, d[1] + 200 + 10), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'E',(e[0] + 200, e[1] + 200 - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'F',(in_a[0] + 200, in_a[1] + 200 - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'G',(in_b[0] + 200, in_b[1] + 200 - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'H',(in_c[0] + 200, in_c[1] + 200 - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'K',(in_d[0] + 200, in_d[1] + 200 - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      cv.putText(img,f'G',(in_e[0] + 200, in_e[1] + 200 - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))
      return img
    
    # 绘制五角星
    def create_star(img):
      # 获取五角星各个坐标点
      points = get_star_point()
      # 获取内外五边形的各点坐标
      [a,b,c,d,e] = list(map(lambda items: [int(items[0]),-int(items[1])], points.get("out")))
      [in_a,in_b,in_c,in_d,in_e] = list(map(lambda items: [int(items[0]),-int(items[1])], points.get("in")))
      # 设置原点坐标
      o = [0,0]
      # 设置多边形点
      pts = np.array([o,a,in_a,o,in_a,b,o,b,in_b,o,in_b,c,o,c,in_c,o,in_c,d,o,d,in_d,o,in_d,e,o,e,in_e,o,in_e,a,o])
      # 由于图片宽度400,设置原点(200,200)
      pts[:,:] += 200
      cv.polylines(img, [pts], True, (0,0,0),1)
      return img
    
    def create_demo():
      img = np.ones((400,400,3),np.uint8)*255
    
      # 绘制坐标系
      img = create_coordinate(img)
    
      # 绘制五角星
      img = create_star(img)
    
      # 标注各点
      img = tagging_points(img)
    
      cv.imshow("coordinate", img)
      cv.waitKey(0)
      cv.destroyAllWindows()
    
    if __name__ == "__main__":
      create_demo()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    5.2 结果

    输入图片说明

    6. 注意

    1. 数学坐标系和OpenCV的坐标系的Y轴相反,因此计算获得坐标点需要将Y轴取反;
    2. 计算坐标点是以五角星重心为原点,因此绘制时须根据实际情况移动原点。
  • 相关阅读:
    牛客刷题总结——Python入门06:元组、字典
    Find My资讯|新系统苹果Find My不再显示AirTag电池电量
    Python的数据分析包Pandas?示例文章完成版来啦~
    “回车”、“换行”浅谈
    jQuery中遍历元素each
    MQ系列7:消息通信,追求极致性能
    文本处理方式方法
    线性回归与逻辑回归 (logistic regression and linear regression)
    Java中等题-交错字符串(力扣)
    MySQL存储引擎
  • 原文地址:https://blog.csdn.net/m0_38082783/article/details/127682226