OpenCV---pointPolygonTest

article/2025/7/16 2:47:50

一、基本概念与用途

pointPolygonTest 是 OpenCV 中用于判断点与多边形关系的重要函数,常用于:

  • 目标检测:判断像素点是否属于检测到的轮廓区域
  • 碰撞检测:检测物体是否重叠
  • 图像分割:确定点是否在分割区域内
  • 几何分析:计算点到多边形边界的距离

与简单边界框判断的区别:

  • 边界框只能进行粗略的矩形区域判断
  • pointPolygonTest 能够精确判断任意形状的多边形区域

在这里插入图片描述

二、函数定义与参数

1. 函数原型(C++/Python)
// C++
double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist);// Python
retval = cv2.pointPolygonTest(contour, pt, measureDist)
2. 参数说明
参数名类型描述
contourInputArray输入的多边形轮廓,通常为 vector<Point>numpy.ndarray
ptPoint2f待测试的二维点坐标
measureDistbool是否计算距离:
- True:返回带符号的距离值
- False:返回-1/0/1的符号值

三、返回值详解

函数返回值根据 measureDist 参数分为两种模式:

1. 符号判断模式(measureDist = False
  • 返回值 > 0:点在多边形内部
  • 返回值 = 0:点在多边形边界上
  • 返回值 < 0:点在多边形外部
2. 距离计算模式(measureDist = True
  • 返回正值:点在多边形内部,值为点到最近边界的距离
  • 返回0:点在多边形边界上
  • 返回负值:点在多边形外部,值为点到最近边界的负距离
3. 精度说明
  • 边界判断使用 eps = 1e-5 的容差(即距离小于该值被认为在边界上)
  • 返回值类型为 double(C++)或 float(Python)

四、核心知识点讲解

1. 多边形表示要求
  • 多边形轮廓需为简单闭合曲线(不自交)
  • 顶点顺序可为顺时针或逆时针
  • 推荐使用 findContours 函数获取的轮廓作为输入
2. 算法原理

函数基于射线法(Ray Casting Algorithm)实现:

  1. 从测试点发射一条水平射线(通常向右)
  2. 统计射线与多边形边的交点数量
  3. 奇数交点表示点在内部,偶数交点表示点在外部
3. 距离计算方法
  • 内部点:计算到最近边的垂直距离
  • 外部点:计算到最近顶点或边的最小距离
  • 边界点:返回0(考虑浮点数精度误差)
4. 性能特性
  • 时间复杂度:O(n),n为多边形顶点数
  • 空间复杂度:O(1)
  • 适合处理中小规模多边形(顶点数<1000)

五、示例代码

1. 基本用法示例
import cv2
import numpy as np# 创建测试多边形
contour = np.array([[10, 10], [100, 10], [100, 100], [10, 100]], dtype=np.int32)# 测试点
point_inside = (50, 50)
point_outside = (150, 150)
point_boundary = (10, 50)# 符号判断模式
ret_inside = cv2.pointPolygonTest(contour, point_inside, False)
ret_outside = cv2.pointPolygonTest(contour, point_outside, False)
ret_boundary = cv2.pointPolygonTest(contour, point_boundary, False)print(f"内部点结果: {ret_inside}")  # 输出: 1
print(f"外部点结果: {ret_outside}")  # 输出: -1
print(f"边界点结果: {ret_boundary}")  # 输出: 0# 距离计算模式
dist_inside = cv2.pointPolygonTest(contour, point_inside, True)
dist_outside = cv2.pointPolygonTest(contour, point_outside, True)
dist_boundary = cv2.pointPolygonTest(contour, point_boundary, True)print(f"内部点距离: {dist_inside}")  # 输出: 40.0
print(f"外部点距离: {dist_outside}")  # 输出: -70.71067811865476
print(f"边界点距离: {dist_boundary}")  # 输出: 0.0
2. 可视化示例
import cv2
import numpy as np# 创建空白图像
img = np.ones((200, 200, 3), dtype=np.uint8) * 255# 定义多边形
contour = np.array([[50, 50], [150, 30], [180, 120], [80, 150]], dtype=np.int32)# 绘制多边形
cv2.drawContours(img, [contour], -1, (0, 255, 0), 2)# 测试多个点
test_points = [(100, 80), (20, 20), (100, 100), (150, 150)]
colors = [(255, 0, 0), (0, 0, 255), (0, 255, 255), (255, 255, 0)]for i, pt in enumerate(test_points):# 计算距离dist = cv2.pointPolygonTest(contour, pt, True)# 根据距离判断颜色和标签if dist > 0:status = "内部"color = (0, 0, 255)  # 红色elif dist < 0:status = "外部"color = (255, 0, 0)  # 蓝色else:status = "边界"color = (0, 255, 0)  # 绿色# 绘制点和标签cv2.circle(img, pt, 5, colors[i], -1)cv2.putText(img, f"{status}:{dist:.1f}", (pt[0]+10, pt[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)# 显示结果
cv2.imshow("Point Polygon Test", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

六、注意事项与常见误区

  1. 多边形方向无关性

    • 函数对顺时针和逆时针多边形同样有效
    • 无需关心轮廓的生成方向
  2. 浮点数精度问题

    • 边界判断存在 1e-5 的容差
    • 对于精确边界判断,建议先进行整数化处理
  3. 性能优化建议

    • 对于大规模点集测试,可先进行边界框粗筛
    • 使用 measureDist = False 可提升约30%的性能
  4. 自相交多边形处理

    • 函数对自相交多边形可能返回不可预期的结果
    • 建议先使用 approxPolyDP 进行多边形简化

七、进阶应用场景

1. 图像分割后处理
# 根据距离值进行区域细化
mask = np.zeros((height, width), dtype=np.uint8)
for y in range(height):for x in range(width):dist = cv2.pointPolygonTest(contour, (x, y), True)if dist >= 0:  # 内部点mask[y, x] = 255elif dist > -5:  # 边界附近点mask[y, x] = 128  # 半透明区域
2. 非均匀边界缓冲区域生成
# 生成边界内外的缓冲区域
inner_buffer = np.zeros_like(mask)
outer_buffer = np.zeros_like(mask)for y in range(height):for x in range(width):dist = cv2.pointPolygonTest(contour, (x, y), True)if 0 < dist <= 10:  # 内部10像素缓冲inner_buffer[y, x] = 255elif -10 <= dist < 0:  # 外部10像素缓冲outer_buffer[y, x] = 255
3. 多边形碰撞检测优化
def polygon_collision(poly1, poly2):# 快速边界框检测rect1 = cv2.boundingRect(poly1)rect2 = cv2.boundingRect(poly2)if not (rect1[0] < rect2[0]+rect2[2] and rect1[0]+rect1[2] > rect2[0] and rect1[1] < rect2[1]+rect2[3] and rect1[1]+rect1[3] > rect2[1]):return False# 精确点集检测for pt in poly1:if cv2.pointPolygonTest(poly2, tuple(pt[0]), False) >= 0:return Truefor pt in poly2:if cv2.pointPolygonTest(poly1, tuple(pt[0]), False) >= 0:return Truereturn False

八、跨语言差异(C++ vs Python)

特性C++Python
函数参数InputArray, Point2f, boolnumpy.ndarray, tuple, bool
返回值类型doublefloat
异常处理可能抛出 cv::Exception返回 None 或抛出异常
内存管理自动管理自动垃圾回收

九、数学原理补充

1. 点到线段的距离计算

设线段端点为 A(x1,y1)B(x2,y2),测试点为 P(x0,y0),则距离计算步骤:

  1. 计算线段向量 AB = (x2-x1, y2-y1)
  2. 计算点P到A的向量 AP = (x0-x1, y0-y1)
  3. 计算点积 dot = AP · AB
  4. 计算投影比例 t = dot / ||AB||²
  5. 确定最近点:
    • t < 0 时,最近点为A
    • t > 1 时,最近点为B
    • 0 ≤ t ≤ 1 时,最近点为 A + t·AB
  6. 计算点P到最近点的欧氏距离
2. 射线法判断点在多边形内部的原理
  • 从测试点水平向右发射射线
  • 统计与多边形边的交点数量
  • 交点数量为奇数时,点在内部
  • 特殊情况处理:
    • 射线经过顶点时,仅统计边的起点
    • 射线与边共线时,忽略该边

http://www.hkcw.cn/article/xFkgPfMNGr.shtml

相关文章

深入详解DICOMweb:WADO与STOW-RS的技术解析与实现

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

20250530-C#知识:万物之父Object

C#知识&#xff1a;万物之父Object Object类&#xff08;即object&#xff09;是所有类的基类&#xff0c;这里面的方法还是需要好好了解一下。 1、Object类 是顶级父类&#xff0c;其他类默认都是Object类的子类&#xff08;自定义类也会默认继承Object类&#xff09;可以用O…

ollama国内安装使用

解决国内下载慢和安装卡住问题 docker安装-优先推荐 https://hub.docker.com/r/ollama/ollama/tags docker pull ollama/ollama:latestGitHub 镜像加速 改安装脚本、使用 GitHub 镜像和文件加速服务 https://defagi.com/ai-case/ollama-installation-guide-china/ modelsco…

阻塞队列的学习以及模拟实现一个阻塞队列

前言 今天上午学习了阻塞队列。之前在数据结构的时候&#xff0c;学过队列。把队列放在多线程中&#xff0c;对队列会有新的体会。我自己也实现了一个阻塞队列结合生产消费模型&#xff0c;希望对于大家有帮助~ 阻塞队列的相关知识 结语 本次的分享就结束啦。端午安康~

深度学习赋能图像识别:技术、应用与展望

论文&#xff1a; 一、引言​ 1.1 研究背景与意义​ 在当今数字化时代&#xff0c;图像作为信息的重要载体&#xff0c;广泛存在于各个领域。图像识别技术旨在让计算机理解和识别图像内容&#xff0c;将图像中的对象、场景、行为等信息转化为计算机能够处理的符号或数据 &am…

如何通过一次需求评审,让项目效率提升50%?

想象一下&#xff0c;你的团队启动了一个新项目&#xff0c;但需求模糊不清&#xff0c;开发到一半才发现方向错了&#xff0c;返工、加班、客户投诉接踵而至……听起来像噩梦&#xff1f;一次完美的需求评审就能避免这一切&#xff01;它就像项目的“导航仪”&#xff0c;确保…

粽叶飘香时 山水有相逢

粽叶飘香时 山水有相逢 尊敬的广大客户们&#xff1a; 五月初五&#xff0c;艾叶幽香。值此端午佳节&#xff0c;衡益科技全体同仁向您致以最诚挚的祝福&#xff01; 这一年我们如同协同竞渡的龙舟&#xff0c;在数字化转型的浪潮中默契配合。每一次技术对接、每轮方案优化&a…

【PyTroch学习-001】从一个简单示例开始:手写数字识别

一、PyTroch简介 PyTorch 是由 Meta&#xff08;原 Facebook&#xff09;开发的开源深度学习框架&#xff0c;以动态计算图和易用性著称&#xff0c;广泛应用于计算机视觉、自然语言处理等领域。其核心特性包括&#xff1a; ​动态计算图​&#xff1a;支持运行时灵活调整计算…

备战2025全国青少年信息素养大赛省赛—图形化编程—每一练——打开密码锁

备战2025全国青少年信息素养大赛省赛—图形化编程—每一练——打开密码锁 题目可看下方去处&#xff0c;支持在线编程&#xff0c;在线获取源码和素材&#xff5e; 打开密码锁_scratch_少儿编程题库学习中心-嗨信奥 题库收集了历届各白名单赛事真题和权威机构考级真题&#xf…

MPLS的基础配置

MPLS概念&#xff08;AI&#xff09; ‌MPLS&#xff08;多协议标签交换&#xff09;的工作原理是通过标签&#xff08;Label&#xff09;引导数据转发&#xff0c;将固定长度的短标签与数据分组封装&#xff0c;交换节点仅根据标签进行快速转发&#xff0c;从而提升网络传输效…

一篇文章玩转CAP原理

CAP 原理是分布式系统设计的核心理论之一&#xff0c;揭示了系统设计中的 根本性权衡。 一、CAP 的定义 CAP 由三个核心属性组成&#xff0c;任何分布式系统最多只能同时满足其中两个&#xff1a; 一致性&#xff08;Consistency&#xff09; 所有节点在同一时刻看到的数据完全…

AI FOR SCIENCE 2025 报告解读

《AI FOR SCIENCE 2025》梳理了人工智能在科学研究各领域的应用现状、关键挑战与未来趋势&#xff0c;并提出了相应的政策建议。 一、报告概述 发布机构&#xff1a; 复旦大学、上海科学智能研究院&#xff08;SAIS&#xff09;、自然科研智讯&#xff08;Nature Research In…

CppCon 2014 学习第5天:Where did my performance go

我的性能去哪儿了 主题简介&#xff1a; 如何为一个并发程序生成详细且有用的性能分析信息&#xff08;事件时间线&#xff09;。 我们将讨论&#xff1a; 为什么我们需要这样做&#xff1f;我们要解决什么问题&#xff1f; ⟶ 并发程序性能难以调优&#xff0c;调试更难&…

将ipynb文件转换为markdown格式文件

文章目录 将ipynb文件转换为markdown格式文件nbconvert 包安装nbconvert 使用 将ipynb文件转换为markdown格式文件 有时候&#xff0c;我们需要把Jupyter notebook的.ipynb格式文件转换为markdown格式.md&#xff0c;便于使用。 那么&#xff0c;我们可以通过安装nbconvert包&a…

在日常管理服务器中如何防止SQL注入与XSS攻击?

在日常管理服务器时&#xff0c;防止SQL注入&#xff08;Structured Query Language Injection&#xff09;和XSS&#xff08;Cross-Site Scripting&#xff09;攻击是至关重要的&#xff0c;这些攻击可能会导致数据泄露、系统崩溃和信息泄露。以下是一份技术文章&#xff0c;介…

ToolsSet之:十六进制及二进制编辑运算工具

ToolsSet是微软商店中的一款包含数十种实用工具数百种细分功能的工具集合应用&#xff0c;应用基本功能介绍可以查看以下文章&#xff1a; Windows应用ToolsSet介绍https://blog.csdn.net/BinField/article/details/145898264 ToolsSet中Number菜单下的Hex Operate工具可以进…

利用计算机模拟和玉米壳废料开发新型抗病毒药物合成方法

参阅&#xff1a;Top 创新大奖 这个课题将农业废弃物资源化利用、计算机辅助药物设计和绿色化学完美结合&#xff0c;是一个极具创新性和应用前景的研究方向&#xff01; 以下是如何利用计算机模拟和玉米壳废料开发新型抗病毒药物合成方法的系统思路&#xff1a; 核心思路 玉…

什么是AI Agent?大白话新手教学

Agent的诞生背景 如果只有LLM的话&#xff0c;那么LLM就相当于一个脑子&#xff0c;你问他一个问题&#xff0c;他会给你答案或者告诉你怎么做&#xff0c;但并不会帮你去解决这个问题&#xff0c;实际还是需要你自己动手去解决。 &#xff08;比如我问大模型&#xff1a;“我要…

Unity链接Mysql 数据库实现注册登录

1.搭建注册和登录的UI以及跳转代码撰写 2.安装Mysql 数据库到服务器或者本地电脑 我这里使用的是小皮工具&#xff0c;安装玩数据库后创建一个新的用户以及表格 安装Navicate 链接数据库&#xff0c;方便可视化数据库 点击查询-新建查询-输入命令-运行&#xff01;完成表格创…

你了解ConcurrentHashMap吗?ConcurrentHashMap九连问

多线程环境下&#xff0c;使用Hashmap进行put操作会造成数据覆盖&#xff0c;应该使用支持多线程的 ConcurrentHashMap。 HashMap为什么线程不安全 put的不安全 由于多线程对HashMap进行put操作&#xff0c;调用了HashMap的putVal()&#xff0c;具体原因&#xff1a; 假设两…