目录
- 1.读取图片,阈值处理
- 2.获取轮廓
- 3.直线和boundingbox
- 3.测试枚举线段点
- 4.完整测试代码
实例图片镇楼

1.读取图片,阈值处理
复制代码
1
2
3
4
5
6
7# 读取图片并灰度值化 img = cv2.imread('d:1.jpg', 0) # 二值化,过滤掉噪音 img = np.where(img < 100, 0, 255).astype(np.uint8) cv2.imshow('0', img) cv2.waitKey(0)
2.获取轮廓
复制代码
1
2conts, _ = cv2.findContours(img, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
3.直线和boundingbox
如给定一条直线,用点p1(20, 200),p2(340, 90)来表示。若已知在这条直线上位于轮廓2外侧的2个点A,B,就可枚举线段AB上所有的点,推断这些点和轮廓的关系(轮廓上,轮廓内,轮廓外)。如何求解点A和B? 为了提高枚举速度,可先求轮廓的boundingbox,直线和boundingbox的交点即A和B点。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17x, y, w, h = cv2.boundingRect(conts[0]) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 1) # 随便画一条直线 p1, p2 = (20, 200), (340, 90) if p2[0] != p1[0]: # 若存在斜率 y=kx+b k = (p2[1] - p1[1]) / (p2[0] - p1[0]) b = p1[1] - p1[0] * k # 求解直线和boundingbox的交点A和B pa, pb = (x, int(k * x + b)), ((x + w), int(k * (x + w) + b)) else: # 若斜率不存在,垂直的直线 pa, pb = (p1[0], y), (p1[0], y + h) cv2.circle(img, pa, 2, (0, 255, 255), 2) cv2.circle(img, pb, 2, (0, 255, 255), 2) cv2.putText(img, 'A', (pa[0] - 10, pa[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1) cv2.putText(img, 'B', (pb[0] + 10, pb[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1) cv2.line(img, p1, p2, (255, 255, 0), 1)
3.测试枚举线段点
C++版opencv中枚举点的函数有LineIterator,但cv2中好像无类似函数,因此使用skimage.draw.line来代替。(PS:若枚举的点全都不在轮廓上,可使用1内1外的中点近似)
复制代码
1
2
3
4
5# 枚举2点之间的线段点 for pt in zip(*line(*pa, *pb)): if cv2.pointPolygonTest(conts[0], pt, False) == 0: # 若点在轮廓上 cv2.circle(img, pt, 2, (0, 0, 255), 2)
4.完整测试代码
复制代码
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
37import cv2, os import numpy as np from skimage.draw import line # 读取图片并灰度值化 img = cv2.imread('d:1.jpg', 0) # 二值化,过滤掉噪音 img = np.where(img < 100, 0, 255).astype(np.uint8) # 假定只有一个轮廓conts[0] conts, _ = cv2.findContours(img, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE) # 颜色区分,把原图再转为BGR img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) cv2.drawContours(img, conts, -1, (0, 255, 0), 1) x, y, w, h = cv2.boundingRect(conts[0]) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 1) # 随便画一条直线 p1, p2 = (20, 200), (340, 90) if p2[0] != p1[0]: # 若存在斜率 y=kx+b k = (p2[1] - p1[1]) / (p2[0] - p1[0]) b = p1[1] - p1[0] * k # 求解直线和boundingbox的交点A和B pa, pb = (x, int(k * x + b)), ((x + w), int(k * (x + w) + b)) else: # 若斜率不存在,垂直的直线 pa, pb = (p1[0], y), (p1[0], y + h) cv2.circle(img, pa, 2, (0, 255, 255), 2) cv2.circle(img, pb, 2, (0, 255, 255), 2) cv2.putText(img, 'A', (pa[0] - 10, pa[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1) cv2.putText(img, 'B', (pb[0] + 10, pb[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1) cv2.line(img, p1, p2, (255, 255, 0), 1) # 枚举2点之间的线段点 for pt in zip(*line(*pa, *pb)): if cv2.pointPolygonTest(conts[0], pt, False) == 0: # 若点在轮廓上 cv2.circle(img, pt, 2, (0, 0, 255), 2) cv2.imshow('0', img) cv2.waitKey(0)
reference:
https://stackoverflow.com/questions/32328179/opencv-3-0-lineiterator
https://zhuanlan.zhihu.com/p/46055147
最后
以上就是精明萝莉最近收集整理的关于python-cv2:求直线和轮廓的交点的全部内容,更多相关python-cv2:求直线和轮廓内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复