前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV-Python实战(4) —— OpenCV 五角星各点在坐标系上面的坐标计算(以重心为原点)

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

作者头像
Rattenking
发布2022-11-14 17:22:08
1.2K0
发布2022-11-14 17:22:08
举报
文章被收录于专栏:RattenkingRattenking

1. 创建坐标系

输入图片说明
输入图片说明

2. 角度计算

注意: AO⊥BE !!!

2.1 五个角的度数
代码语言:javascript
复制
∠GAF = ∠FBG = ∠GCH = ∠HDK = ∠KEG = 36°
2.2 五个角对应的原点度数
代码语言:javascript
复制
∠GOF = ∠FOG = ∠GOH = ∠HOK = ∠KOG = 360° / 5 = 72°
2.3 计算与x轴夹角度数
代码语言:javascript
复制
∠AOX = 90°
∠GOF = 72°
∠FOB = 36°
∠BOX = 90° - 72° = 18°
∠GOX = ∠KOX = 36° - 18° = 18°
∠COX = ∠DOX = 36° + 18° = 54°
∠FOX = 36° + 18° = 54°

3 计算各个线段的长度

假设 OA = r !!!

3.1 计算 OF 长度
代码语言:javascript
复制
因为:
∠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)

4. 各点坐标表示

代码语言:javascript
复制
# 外五边形的坐标
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))

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

5.1 实现代码
代码语言:javascript
复制
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()
5.2 结果
输入图片说明
输入图片说明

6. 注意

  1. 数学坐标系和OpenCV的坐标系的Y轴相反,因此计算获得坐标点需要将Y轴取反;
  2. 计算坐标点是以五角星重心为原点,因此绘制时须根据实际情况移动原点。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 创建坐标系
  • 2. 角度计算
    • 2.1 五个角的度数
      • 2.2 五个角对应的原点度数
        • 2.3 计算与x轴夹角度数
        • 3 计算各个线段的长度
          • 3.1 计算 OF 长度
          • 4. 各点坐标表示
          • 5. 根据计算的点绘制上边坐标系
            • 5.1 实现代码
              • 5.2 结果
              • 6. 注意
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档