我们常常会想要画一幅图片,或者在某个其他地方得来的图片上画些东西。为了实现这个目标,OpenCV提供了一大批可以供我们画直线、矩形、圆等图形的函数。本文记录相关内容。
序号 | 函数 | 描述 |
---|---|---|
1 | cv2.circle() | 画一个简单圆 |
2 | cv2.clipLine() | 判断一条直线是否在给定的矩形内 |
3 | cv2.ellipse() | 画一个椭圆(可以倾斜,或者只有部分圆弧) |
4 | cv2.ellipse2Poly() | 计算一个近似椭圆的多边形 |
5 | cv2.fillConvexPoly() | 画一个填充的简单多边形 |
6 | cv2.fillPoly() | 画一个填充的任意多边形 |
7 | cv2.line() | 画一个简单直线 |
8 | cv2.rectangle() | 画一个简单矩形 |
9 | cv2.polylines() | 画多重折线 |
10 | cv2.putText() | 在图像中绘制指定文字 |
11 | cv2.getTextSize() | 获取一个文字的宽度和高度 |
import cv2
import numpy as np
import mtutils as mt
from mtutils import PIS
img1.jpg
和 img2.jpg
func
文档可以运行:print(cv2.<func>.__doc__)
lineType
是绘图常用参数之一,表示绘制时线条的绘制方式,lineType
参数可选4
,8和 cv2.LINE_AA
,分别表示直线是“4邻域连接”或者“8邻域连接”或者是平滑处理。
thickness
thickness
参数是指线宽的像素数。对于圆、矩形和其他封闭图形,thickness
参数可以被设置为cv2.FILLED
(相当于-1),表示填充整个图形。
画一个简单圆
cv2.circle(img, center, radius, color, thickness=1, lineType=8, shift=0)
canvas = np.zeros([400, 400, 3], dtype='uint8')
center = [150, 150]
radius = 50
color = [255, 255, 0]
thickness = 4
lineType = 8
shift = 0
cv2.circle(canvas, center, radius, color, thickness, lineType, shift)
PIS(canvas)
判断一条直线是否在给定的矩形内
cv2.clipLine(imgRect, pt1, pt2)
点都是 (x, y) 的格式,rect 为 (x, y, w, h) 格式
只有当直线完全在指定的矩形范围之外时,函数cv2.clipLine()
才会返回False
rec = [20, 20, 80, 80]
point1 = [210, 110]
point2 = [110, 110]
res = cv2.clipLine(rec, point1, point2)
-->
res
(False, (210, 110), (110, 110))
画一个椭圆(可以倾斜,或者只有部分圆弧)
cv2.ellipse(img, [center, axes, angle], color, thickness=1, lineType=8)
参数 | 含义 |
---|---|
img | 图像 |
center | 中心坐标 (x, y) |
axes | 长短轴长度 (长轴长度, 短轴长度) |
angle | 角度 (角度制) |
color | 颜色 |
thickness | 线条粗细程度 |
lineType | 线型 |
canvas = np.zeros([400, 400, 3], dtype='uint8')
center = [150, 150]
axes = [100, 70]
angle = 45
startAngle = 0
endAngle = 270
color = [255, 0, 255]
thickness = -1
cv2.ellipse(canvas, [center, axes, angle], color, thickness)
PIS(canvas)
计算一个近似椭圆的多边形
cv2.ellipse2Poly(center, axes, angle, startAngle, endAngle, delta)
delta
为间隔角度,'angle
, startAngle
, endAngle
, delta
’均为角度制
canvas = np.zeros([400, 400, 3], dtype='uint8')
center = [150, 150]
axes = [100, 70]
angle = 45
startAngle = 0
endAngle = 270
delta = 30
color = [0, 255, 255]
points = cv2.ellipse2Poly(center, axes, angle, startAngle, endAngle, delta)
cv2.fillPoly(canvas, [points], color)
PIS(canvas)
-->
points
array([[221, 221],
[186, 236],
[142, 228],
[101, 199],
[ 72, 158],
[ 64, 114],
[ 79, 79],
[114, 64],
[158, 72],
[199, 101]])
画一个填充的简单多边形
cv2.fillConvexPoly(img, pts, color)
这个函数用来绘制一个填充的多边形。这个函数比 cv2.fi11Po1y()
速度快很多,因为它使用了更简单的算法。需要注意的是cv2.fillConvexPoly()
使用的算法在多边形有自交点时不能正确工作。
pts
中的点将被按顺序用直线段连接起来,第一个点和最后一个点之间也会连接起来(也就是说多边形被认为是封闭的)
canvas = np.zeros([300, 300, 3], dtype='uint8')
porints = np.array([[20, 50], [130, 30], [125, 100]])
color = [0, 255, 0]
cv2.fillConvexPoly(canvas, porints, color)
PIS(canvas)
画一个填充的任意多边形
cv2.fillPoly(canvas, [points1, points2, ...], color)
canvas = np.zeros([300, 300, 3], dtype='uint8')
porints1 = np.array([[20, 50], [130, 30], [125, 100]])
porints2 = porints1[:, ::-1]
color = [0, 0, 255]
cv2.fillPoly(canvas, [porints1, porints2], color)
PIS(canvas)
画一个简单直线
cv2.line(img, pt1, pt2, color, thickness, lineType, shift)
canvas = np.zeros([300, 300, 3], dtype='uint8')
pt1 = [12, 186]
pt2 = [192, 399]
color = [255, 255, 255]
cv2.line(canvas, pt1, pt2, color, thickness=5)
PIS(canvas)
画一个简单矩形
cv2.rectangle(img, pt1, pt2, color, thickness, lineType)
canvas = np.zeros([300, 300, 3], dtype='uint8')
pt1 = [12, 186]
pt2 = [192, 199]
color = [255, 255, 255]
cv2.rectangle(canvas, pt1, pt2, color, thickness=5)
PIS(canvas)
画多重折线
cv2.polylines(img, pts, isclosed, color, thickness, lineType)
canvas = np.zeros([300, 300, 3], dtype='uint8')
pts1 =np.array([[12, 186], [56, 96], [156, 198], [222, 29]])
pts2 = np.array([[192, 199], [98, 65], [299, 365], [55, 99]])
color = [255, 255, 255]
cv2.polylines(canvas, [pts1, pts2], True, color, thickness=5)
PIS(canvas)
在图像中绘制指定文字
cv2.putText(canvas, text, origin, fontFace, fontScale, color, thickness=1, lineType=8, bottomLeftOrigin=False)
参数 | 说明 |
---|---|
canvas | 画布 |
text | 文字字符,无法正确绘制中文 |
origin | 文字左上角坐标 |
fontFace | 字体 |
fontScale | 文字尺寸 |
color | 文字颜色 |
bottomLeftOrigin | 偏移从左下角计算 |
标识符 | 描述 |
---|---|
cv2.FONT_HERSHEY_SIMPLEX | 普通大小无衬线字体 |
cv2.FONT_HERSHEY_PLAIN | 小号无衬线字体 |
cv2.FONT_HERSHEY_DUPLEX | 普通大小无衬线字体,比cv2.FONT_HERSHEY_SIMPLEX更复杂 |
cv2.FONT_HERSHEY_COMPLEX | 普通大小无衬线字体;比cv2.FONT_HERSHEY_DUPLEX更复杂 |
cv2.FONT_HERSHEY_TRIPLEX | 普通大小无衬线字体;比cv2.FONT_HERSHEY_COMPLEX更复杂 |
cv2.FONT_HERSHEY_COMPLEX_SMALL | 小号版本的cv2.FONT_HERSHEY_COMPLEX |
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX | 手写体 |
cv2.FONT_HERSHEY_SCRIPT_COMPLEX | 比cv2.FONT_HERSHEY SCRIPT SIMPLEX更复杂的变体 |
canvas = np.zeros([200, 600, 3], dtype='uint8')
text = 'hello world! 表独立兮山之上'
origin = [20, 100]
fontFace=cv2.FONT_HERSHEY_TRIPLEX
fontScale = 1.3
color = [255, 255, 0]
thickness = 2
lineType = 8
bottomLeftOrigin = False
cv2.putText(canvas, text, origin, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin)
PIS(canvas)
获取一个文字的宽度和高度
cv2.getTextSize(text, fontFace, fontScale, thickness)
cv2.getTextSize()
函数回答了如果把文字绘制出来将有多大的问题(使用一组参数而不用实际将文字绘制到图上)。
text = 'hello world!'
origin = [20, 100]
fontFace=cv2.FONT_HERSHEY_TRIPLEX
fontScale = 1.3
thickness = 2
res = cv2.getTextSize(text, fontFace, fontScale, thickness)
-->
res
((271, 28), 13)