惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
I
InfoQ
U
Unit 42
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks
月光博客
月光博客
D
Docker
Stack Overflow Blog
Stack Overflow Blog
D
DataBreaches.Net
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
V
Visual Studio Blog
博客园 - 聂微东
A
About on SuperTechFans
腾讯CDC
Jina AI
Jina AI
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
博客园 - 【当耐特】
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
M
MIT News - Artificial intelligence

又见苍岚

COLMAP PatchMatch Stereo 算法详解 事件驱动的状态机框架:从理论到工程实践 Git 在国内网络环境下无法 Push 的排查与修复 —— 配置 Clash 代理 分段五次多项式插值原理详解 路径插值方法深度对比研究 Claude Code 使用指南 OpenClaw 记忆管理与技能创建指南 CBS(Conflict-Based Search)算法详解 A* 算法及其变种详解 OpenClaw 配置多 Agents Windows Powershell 无法加载文件,因为在此系统上禁止运行脚本问题的解决方案 MaxClaw 安装流程 大模型 AI 名词介绍 AList 网盘聚合工具简介 Protobuf 简介与测试 Claude Code 简介以及 GLM 4.7 模型接入 Github 歌词下载工具 163MusicLyrics Python __getattr__ 懒加载 Python TypedDict 机器人仿真平台 Gazebo 安装记录 机器人仿真平台 Gazebo 简介 多机器人路径规划问题(Multi-Agent Path Finding, MAPF)简介 Python exifread 读取修改过的 jpeg 信息错误问题修复 3D 坐标系变换的理解 3D 旋转矩阵基本概念 MongoDB Compass 介绍 Python 环境管理工具 uv Flutter 开发指南 Snipaste 安装下载与黑屏问题解决方案 全局路径规划算法记录
OpenCV Subdiv2D 平面细分
Yiwei Zhang · 2024-09-03 · via 又见苍岚

Subdiv2D 类用于对一组 2D 点(表示为 Point2f 向量)执行各种平面细分。OpenCV 使用 Delaunay 算法对平面进行三角剖分,该算法对应于 Voronoi 图的偶图。在下图中,Delaunay 三角剖分用黑线标记,Voronoi 图用红线标记。

注意:我在使用这个函数的时候出现了返回点 nearestPt 坐标均为 0 的情况,个人怀疑是这个函数的 bug (opencv 4.9.0.80) ,所以碰到需要使用 nearestPt 信息的时候建议不要直接用这个函数返回的 nearestPt,而是结合 getVertex() 函数共同使用。

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
37
facetList -->
(array([[ 150., -1550.],
[ 150., 150.],
[-1550., 150.]], dtype=float32), array([[ 150. , 250. ],
[ -414.2857, 814.2857],
[-2116.6667, 683.3333],
[-1550. , 150. ],
[ 150. , 150. ],
[ 150. , 150. ]], dtype=float32), array([[ 837.8049 , -108.53658],
[ 450. , 150. ],
[ 150. , 150. ],
[ 150. , 150. ],
[ 150. , -1550. ],
[ 683.3333 , -2116.6667 ]], dtype=float32), array([[450., 150.],
[350., 250.],
[150., 250.],
[150., 150.]], dtype=float32), array([[ 350. , 250. ],
[-242.85715, 842.8571 ],
[-414.2857 , 814.2857 ],
[ 150. , 250. ],
[ 350. , 250. ]], dtype=float32), array([[ 350. , 1004.5455 ],
[ 350. , 250. ],
[ 350. , 250. ],
[ 450. , 150. ],
[ 837.8049 , -108.53658],
[1378.5714 , 1378.5714 ]], dtype=float32), array([[ 350. , 1004.5455 ],
[-242.85715, 842.8571 ],
[ 350. , 250. ]], dtype=float32))

facetCenters -->
[[100. 100.]
[100. 200.]
[200. 100.]
[200. 200.]
[200. 300.]
[400. 400.]
[300. 400.]]

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import cv2
import numpy as np
import random
import vvdutils as vv

# 检查一个点是否在矩形内
def rect_contains(rect, point) :
if point[0] < rect[0] :
return False
elif point[1] < rect[1] :
return False
elif point[0] > rect[2] :
return False
elif point[1] > rect[3] :
return False
return True

# 绘制一个点
def draw_point(img, p, color ) :
cv2.circle( img, p, 2, color, 2)

# 绘制 delaunay 三角剖分
def draw_delaunay(img, subdiv, delaunay_color ) :
triangleList = subdiv.getTriangleList()
size = img.shape
r = (0, 0, size[1], size[0])
for t in triangleList :
pt1 = (int(t[0]), int(t[1]))
pt2 = (int(t[2]), int(t[3]))
pt3 = (int(t[4]), int(t[5]))
if rect_contains(r, pt1) and rect_contains(r, pt2) and rect_contains(r, pt3) :
cv2.line(img, pt1, pt2, delaunay_color, 1)
cv2.line(img, pt2, pt3, delaunay_color, 1)
cv2.line(img, pt3, pt1, delaunay_color, 1)

# 绘制 voronoi 图
def draw_voronoi(img, subdiv) :
( facets, centers) = subdiv.getVoronoiFacetList([])
for i in range(0,len(facets)) :
ifacet_arr = facets[i]
center = centers[i].astype('int32')
ifacet = np.array(ifacet_arr)
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
cv2.fillConvexPoly(img, ifacet.astype('int32'), color)
ifacets = np.array([ifacet])
cv2.polylines(img, ifacets.astype('int32'), True, (0, 0, 0), 1)
cv2.circle(img, (center[0], center[1]), 3, (0, 0, 0), 1)

if __name__ == '__main__':
# 定义绘制颜色
delaunay_color = (255,255,255)
points_color = (0, 0, 255)

img = np.zeros([500,500,3],dtype=np.uint8)

# 创建用于Subdiv2D 的矩形
size = img.shape
rect = (0, 0, size[1], size[0])

# 创建Subdiv2D 实例
subdiv = cv2.Subdiv2D(rect)
points = []

points.append((100, 100))
points.append((100, 200))
points.append((200, 100))
points.append((200, 200))
points.append((200, 300))
points.append((400, 400))
points.append((300, 400))

# 将点依次插入subdiv中
for p in points :
subdiv.insert(p)
# 展示动画画板

img_copy = img.copy()
draw_delaunay(img_copy, subdiv, (255, 255, 255))
vv.PIS(img_copy)

# 绘制delaunay 三角剖分
draw_delaunay( img, subdiv, (255, 255, 255) )
for p in points :
draw_point(img, p, (0,0,255))
# 为Voronoi 图分配空间
img_voronoi = np.zeros(img.shape, dtype = img.dtype)
# 绘制 Voronoi 图
draw_voronoi(img_voronoi, subdiv)
vv.PIS(img_voronoi)
pass