目录
cv2.minAreaRect (4.4.0.46 | 4.5.5.64)
矩形(rectangle)
# pt:`(x, y)`, color:`BGR`, 该方法直接作用于img, 并返回img自身
cv2.rectangle(img_bgr, (w//4, h//4), (w//2, h//2), color=(0, 0, 255), thickness=2)
直线
cv2.fitLine (4.5.3.56)
输入:shape=(M,2)的点集,M为点数,注意与轮廓(M,1,2)的区别
输出:shape=(4,1),代表一条直线
提取直线,假设已知直线上的两个点,在图像中像素坐标分别为(100, 100)和(150, 50)
>>> cv2.fitLine(np.array([[100, 100], [150, 50]]), cv2.DIST_L1, 0, 1, 1)
array([[ 0.70710677],
[ -0.70710677],
[125. ],
[ 75. ]], dtype=float32)
array([[cos_Theta],
[sin_Theta],
[x0 ],
[y0 ]], dtype=float32)
Theta是x轴旋转到与直线重合的角度(x轴水平与直线相交,按就近原则,x轴旋转到与直线重合,所经过的角度值;若逆时针更近则角度值为-89.9999~0,若顺时针更近则角度值为0~90,垂直为90)。
计算斜率:
k_inv = 0
if abs(line[1]) > 1e-10:
k_inv = line[0] / line[1] # 斜率k=x/y
圆(circle)
cv2.HoughCircles
todo…
椭圆(ellipse)
椭圆转多边形
cv2.fitEllipse(4.4.0.46)
todo…
多边形
fillConvexPoly,fillPoly,polylines
cv2.fillPoly
fillPoly(img, pts, color[, lineType[, shift[, offset]]]) -> img
用于一个或多个图形(不规则多边形)的填充。
多边形的列表,每个多边形可以是shape=(M,2)或(M,1,2)轮廓。
polygons = [np.array([[100,100], [200,230], [150,200], [100,220]], dtype = np.int32), ...]
cv2.fillPoly(img, polygons, color)
官方解释是一次填充多个多边形,但某次我使用过程中,一次无法填充多个多边形!还是逐个填充是比较保险的方法:
[cv2.fillPoly(img, [poly], color) for poly in polygons]
假设用轮廓,contours.shape=(N,M,1,2),下列两种方式,结果不同:
# 填充内部
cv2.fillPoly(img,[contours[1]],(255,0,0))
# 只染色边界,原因是把轮廓上的M个点当成M个多边形
cv2.fillPoly(img,contours[1],(255,0,0))
实例:
area1 = np.array([[250, 200], [300, 100], [750, 800], [100, 1000]])
area2 = np.array([[1000, 200], [1500, 200], [1500, 400], [1000, 400]])
img = np.zeros((1080, 1920, 3), np.uint8)
cv2.fillPoly(img, [area1, area2], color=(255, 255, 255))
轮廓(Contours)
cv2.findContours (4.4.0.46)
findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy
找图中轮廓。
conts, hier = cv2.findContours(cls_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
输入
- image:8-bit单通道,非0为1,视为二值化图像
- mode:轮廓层级关系的模式
-
- 0=cv2.RETR_EXTERNAL:仅检测外轮廓
- 1=cv2.RETR_LIST:检测所有轮廓,但轮廓间没有给出层级关系
- 2=cv2.RETR_CCOMP:仅给出两层包含关系,即某个轮廓包含其他轮廓,就算外轮廓
- 3=cv2.RETR_TREE:检测所有轮廓,并给出完整的层级关系
- 4=cv2.RETR_FLOODFILL:
- method:轮廓点集存储的近似算法
-
- 1=cv2.CHAIN_APPROX_NONE:连续点只相差一个像素,密集型
- 2=cv2.CHAIN_APPROX_SIMPLE:横向/纵向/对角线段上的点只保存端点,例如矩形只存四个顶点
- 3=cv2.CHAIN_APPROX_TC89_L1:
- 4=cv2.CHAIN_APPROX_TC89_KCOS:
输出
- contours:检测到的轮廓列表( __len__ =N=轮廓数),N个轮廓都是shape=(M,1,2)的ndarray(int32),M为每个轮廓的点数,shape为啥不是(M,2)?
- hierarchy:轮廓之间的层级关系,shape=(1,N,4),依次标识N个轮廓的 同级后一个轮廓的序号 、 同级前一个轮廓的序号 、 第一个子轮廓的序号 和 父轮廓的序号 ,没有则为-1
参考:
https://blog.csdn.net/zb1165048017/article/details/109404373
https://docs.opencv.org/4.5.0/d9/d8b/tutorial_py_contours_hierarchy.html
cv2.drawContours (4.5.5.64)
drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) -> image
原地修改绘制多个轮廓。
- contourIdx表示绘制轮廓的id,若为负则绘制所有轮廓
- color绘制颜色值
- thickness轮廓粗细,若为负则填充轮廓(closed)
cv2.contourArea (4.4.0.46)
contourArea(contour[, oriented]) -> area: float
凸包 cv2.convexHull (4.5.5.64)
convexHull(points[, hull[, clockwise[, returnPoints]]]) -> hull
根据点集/轮廓,计算凸包。
输入:shape=(M,2)/(M,1,2)/(1,M,2)的点集,M为点数
输出:shape=(N,1,2),代表一个凸包,N为凸包点数
cv2.boundingRect (4.4.0.46)
boundingRect(array) -> (x, y, w, h)
找包围了所有点/灰度图所有非0像素点的正外接矩形(直边界)。
输入:array.shape=(M,1,2)的二维点集或shape=(H,W)的灰度图
cv2.minAreaRect (4.4.0.46 | 4.5.5.64)
minAreaRect(points) -> ((cx, cy), (cw, ch), angle)
找包围了所有点的最小面积外接旋转矩形框。输入可以是二维点集/轮廓shape=(M,1,2)。
返回值都是float类型,分别表示旋转矩形的中心点坐标、宽高和角度。
在OpenCV(4.5)之前:
角度为[-90, 0),由矩形最低点所在x轴 逆时针旋转到 第一次重合的边 所经过的角度值;首次重合的边即为新的x轴==w宽度(因此旋转矩形的宽度不一定是横向的那条边长,也可能是纵向的边长)
而(4.5.3.56)及之后 角度 改了, 宽w 的定义也有变化!!!
角度angle总是为(0, 90],为x轴(矩形最低点) 顺时针 旋转的角度,最先重合的边为w
x轴顺时针为正数,逆时针为负数。
角度在旋转图像中有用,角度为正==x轴顺时针旋转,角度为负==x轴逆时针旋转,图像整体则是反方向转
旋转矩形框rect就只分长边和短边。
算法上只需分两种情况:w是不是短边?
long_angle = w>h ? angle : angle-90,其中long_angle是长边方向角度,angle是旋转框角度
4.4.0.46及之前(逆时针旋转30°)
4.5.3.56及之后(顺时针旋转60°)—— w 和 h 互换,angle 由逆变顺
虽然不同版本cv2.minAreaRect计算得到的宽高、角度不同,但中心点和旋转结果图是一样的。
参考:https://zhuanlan.zhihu.com/p/491547614
cv2.boxPoints (4.5.3.56)
boxPoints(box[, points]) -> points
官方解释:Finds the four vertices of a rotated rect. Useful to draw the rotated rectangle.
计算旋转框的四个角点坐标,返回值为<class 'numpy.ndarray'>, array([ x, y ], dtype=float32), shape=(4, 2), 闭合多边形按逆时针顺序(但起始点和结束点不明确),如:
rotRect = cv2.minAreaRect(contour)
box_pts = cv2.boxPoints(rotRect)
box_pts =
[[ 78.349365 69.19873 ]
[121.650635 44.19873 ]
[171.65063 130.80127 ]
[128.34937 155.80127 ]]
可以cv2.polylines用来绘制:
cv2.polylines(img, [box_pts.astype(np.int32)], 1, 255)
箭头线段
arrowedLine
标记
cv2.drawMarker
文字
cv2字体大小计算
getFontScaleFromHeight
getTextSize
# 该方法直接作用于img, 返回img
cv2.putText(img_bgr, '~', (w//4, h//4),cv2.FONT_HERSHEY_SIMPLEX, 1.5, [255, 0, 255], 3, cv2.LINE_AA)
官网:https://docs.opencv.org/4.5.5/d6/d6e/group__imgproc__draw.html
持续更新中……