OpenCV-Python学习(13)—— OpenCV 多边形填充与绘制(cv.fillPoly、cv.polylines)

2022-11-14 17:21:46 浏览数 (1)

1. 知识点

  1. 学习 cv.polylines 函数的使用;
  2. 学习 cv.fillPoly 函数的使用。

2. 绘制折线或多边形 cv.polylines 函数说明

2.1 函数使用
代码语言:javascript复制
cv.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]]) → img
2.2 参数说明

参数

说明

img

表示要在其上绘制矩形的图像的img对象。

pts

表示一个或多个点集。

isClosed

表示标志,决定所绘制的多边形是否闭合。若为 True ,则画若干个闭合多边形;若为 False ,则画一条连接所有点的折线。

color

表示颜色。

thickness

表示线宽,注意:必须大于0。

lineType

表示绘制直线的线性,默认为 LINE_8。

shift

表示坐标精确到小数点后第几位。

2.3 lineType 值说明

描述

cv.LINE_4

表示 4 邻接线型。

cv.LINE_8

表示 8 邻接线型。

cv.LINE_AA

表示抗锯齿线型,图像更平滑。

3. 填充颜色 cv.fillPoly 函数说明

3.1 函数使用
代码语言:javascript复制
cv.fillPoly(img, pts, color[, lineType[, shift[, offset]]]) → img
3.2 参数说明

参数

说明

img

表示要在其上绘制矩形的图像的img对象。

pts

表示一个或多个点集。

color

表示颜色。

lineType

表示绘制直线的线性,默认为 LINE_8。

shift

表示坐标精确到小数点后第几位。

3.3 lineType 值说明

描述

cv.LINE_4

表示 4 邻接线型。

cv.LINE_8

表示 8 邻接线型。

cv.LINE_AA

表示抗锯齿线型,图像更平滑。

4. 注意

  1. thickness 线宽的值必须大于0;
  2. isClosed 闭合标志为 True 时绘制若干个闭合多边形;闭合标志为 False 时绘制一条连接所有点的折线;
  3. pts 点集表示函数 cv.polylines 与 cv.fillPoly 可以绘制或填充一个或多个多边形;
  4. pts 点集参数必须设置dtype=np.uint8。

5. 实例

5.1 实例代码
代码语言:javascript复制
import cv2 as cv
import numpy as np

# 以五角星的重心为原点,计算各点坐标
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 create_pentagon(a,b,c,d,e,isClosed=True,color=(0,0,255),fill=False,fillColor=(255,0,0)):
  img = np.ones((200, 200, 3), np.uint8)*255
  pts = np.array([a,b,c,d,e])
  # 向左上角移动100像素原点
  pts[:,:]  = 100
  cv.polylines(img, [pts], isClosed, color,1)
  # 判断是否填充多边形
  if fill:
    cv.fillPoly(img,[pts],fillColor)
  return img

def create_five_pointed_star(a,b,c,d,e,
isClosed=True,
color=(0,0,255),
fill=False,
fillColor=(255,0,0)):
  img = np.ones((200, 200, 3), np.uint8)*255
  pts = np.array([a,c,e,b,d])
  # 向左上角移动100像素原点
  pts[:,:]  = 100
  cv.polylines(img, [pts], isClosed, color,1)
  # 判断是否填充多边形
  if fill:
    cv.fillPoly(img,[pts],fillColor)
  return img

def create_five_pointed_star_all(
  a,b,c,d,e,
  in_a,in_b,in_c,in_d,in_e,
  isClosed=True,
  color=(0,0,255),
  fill=False,
  fillColor=(255,0,0)):
  img = np.ones((200, 200, 3), np.uint8)*255
  pts = np.array([a,in_a,b,in_b,c,in_c,d,in_d,e,in_e])
  # 向左上角移动100像素原点
  pts[:,:]  = 100
  cv.polylines(img, [pts], isClosed, color,1)
  # 判断是否填充多边形
  if fill:
    cv.fillPoly(img,[pts],fillColor)
  return img

def create_demo():
  # 以五角星长轴半径计算各点坐标,注意计算坐标需要倒转
  star_points = get_star_point(60)
  [a,b,c,d,e] = list(map(lambda items: list(map(lambda val: - int(val), items)), star_points.get("out")))
  [in_a, in_b, in_c, in_d, in_e] = list(map(lambda items: list(map(lambda val: - int(val), items)), star_points.get("in")))
  # 
  img = np.ones((600, 600, 3), np.uint8)*255
  # 不闭合折线
  # 五角星【线交叉】
  img[0:200,0:200] = create_five_pointed_star(a,b,c,d,e,isClosed=False)
  # 五边形
  img[200:400,0:200] = create_pentagon(a,b,c,d,e,isClosed=False)
  # 五角星【十点】
  img[400:600,0:200] = create_five_pointed_star_all(a,b,c,d,e,in_a,in_b,in_c,in_d,in_e,isClosed=False)

  # 闭合多边形
  # 五角星【线交叉】
  img[0:200,200:400] = create_five_pointed_star(a,b,c,d,e)
  # 五边形
  img[200:400,200:400] = create_pentagon(a,b,c,d,e)
  # 五角星【十点】
  img[400:600,200:400] = create_five_pointed_star_all(a,b,c,d,e,in_a,in_b,in_c,in_d,in_e)

  # # 闭合填充多边形
  # # 五角星【线交叉】
  img[0:200,400:600] = create_five_pointed_star(a,b,c,d,e,fill=True)
  # 五边形
  img[200:400,400:600] = create_pentagon(a,b,c,d,e,fill=True)
  # 五角星【十点】
  img[400:600,400:600] = create_five_pointed_star_all(a,b,c,d,e,in_a,in_b,in_c,in_d,in_e,fill=True)

  cv.imshow("img", img)
  cv.waitKey(0)
  cv.destroyAllWindows()

if __name__ == "__main__":
  create_demo()
5.2 实例运行结果

6. 总结

  1. 由于计算五角星各点坐标时,采用的时数学的四象限坐标,以重心为原点,创建坐标;
  2. opencv 绘制图形时,x轴和数学坐标轴一样,但是y是以向下为正轴,同时坐标原点在图像的左上角[0,0]位置;
  3. 通过以上两点,可以知道第一:需要将计算的y轴坐标取反;第二:需要将计算点的原点进行位移计算。

0 人点赞