Opencv(十八) : 图像凸包检测

文章目录

一、凸包是什么?

凸包就是包含某一点集所有点的最小凸多边形,特点是完全凸起、没有凹处。简单说,就像用一根橡皮筋紧紧围住所有点,松手后橡皮筋自然形成的轮廓------所有点要么在轮廓上,要么在轮廓内。

它的核心价值是简化物体形态,保留关键边界特征,常用在物体识别、手势识别、边界检测等场景。

二、4种核心凸包算法

1. 穷举法

  • 核心逻辑:把点集中所有点两两配对连线,检查其他所有点是否都在这条直线的同一侧。如果是,这两个配对点就是凸包点。
  • 优点:原理简单,不用复杂逻辑;
  • 缺点:效率极低,仅适合极少数点的场景(比如少于50个点),实际用得少。

2. Graham扫描法

步骤
  1. 将纵坐标最小的点记为P0,且以该点为原点构建二维坐标系,那么P0就一定是一个凸包点。
  2. 计算各个点对于P0的角度,按照从小到大的顺序进行排序(逆时针顺序),当角度相同时,与P0较近的点排在前面。那么角度最大的点和角度最小的点一定是凸包点。
  3. 用栈来记录已知的凸包点,先将P0和P1放入栈中,然后去求下一个凸包点。
  4. 入栈下一个点,将栈顶的两个点相连,得到一条直线。看下一个点在直线的右侧还是左侧,如果
    是右侧就执行步骤5,如果在左侧或在直线上就执行步骤6。
  5. 如果在右侧,说明栈顶的那个点不是凸包点,将栈顶元素出栈并执行步骤4。
  6. 如果在左侧或直线上,说明该点是凸包点,就将其保存。
  7. 检查栈顶的点是不是步骤2中角度值最大的那个点,如果是就结束了,如果不是就将当前点的下个
    点作为要计算的对象,执行步骤4,直到栈顶元素就是步骤2中角度值最大的点,那么循环结束。

3. Andrew扫描链法

步骤
  1. 对所有点按坐标x为第一关键字、y为第二关键字排序,第1个和最后一个
    肯定在凸包上。
  2. 先顺序遍历所有点,通过三个点所构建的两个向量的叉积来判断是不是凸
    包点,这样就可以构建出下凸包。
  3. 然后逆序遍历所有点,按照相同的方式就可以构建出上凸包,最后将上凸
    包和下凸包连接即可。
  • 优点:实现最简单、稳定性最高,是工程里最常用的算法;
  • 适用:几乎所有场景,从几百个点到几万个点都能高效处理。

4. QuickHull法

  • 核心步骤(3步搞定):
    1. 找横坐标最小的P1和最大的P2,连线后把点集分成"上包"(直线上方)和"下包"(直线下方);
    2. 以上包为例,找距离P1P2直线最远的点P3,连线P1P3和P2P3,再筛选出新的候选点集;
    3. 对新的点集重复步骤2,直到没有可添加的点,下包同理处理。
  • 优点:平均效率极高,适合大规模点集(比如几万个点);
  • 缺点:极端情况(比如所有点共线)效率会下降。

三、代码实现凸包检测

python 复制代码
# 导入opencv的库(计算机视觉处理核心库)
import cv2

# 1.读取图片(BGR格式,OpenCV默认读取方式)
image_np = cv2.imread('./picture.png')  # 替换为自己的图片路径

# 2.灰度化(降维:3通道彩色图→1通道灰度图,减少计算量)
image_gray = cv2.cvtColor(image_np,cv2.COLOR_BGR2GRAY)

# 3.二值化(黑白分割:将灰度图转为只有0/255的黑白图,突出轮廓)
ret,image_thresh = cv2.threshold(image_gray,127,255,cv2.THRESH_BINARY)

# 4.获取轮廓点的坐标(提取物体边界的关键步骤)
contours,hierarchy = cv2.findContours(image_thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

# 5.寻找凸包(核心:从轮廓点中筛选出凸包点)
# cv2.convexHull(points,hull,clockwise,returnPoints)
cnt = contours[0]  # 取第一个轮廓(假设图片只有一个物体)
hull = cv2.convexHull(cnt)  # 计算该轮廓的凸包
print(type(hull))  # 输出:<class 'numpy.ndarray'>,凸包点是多维数组

# 6.绘制凸包(把凸包轮廓画在原图上)
# polylines(img,pts,isClosed,color,thickness,lineType,shift)
image_poly = cv2.polylines(image_np,[hull],True,(0,0,255),2)  # 红色、线宽2

# 7.结果显示(弹出窗口展示图片)
cv2.imshow('image_np',image_np)  # 原图+凸包
cv2.imshow('image_poly',image_poly)  # 同image_np(因为polylines直接修改原图)
cv2.waitKey(0)  # 等待按键关闭窗口
cv2.destroyAllWindows()  # 补充:建议加这行,避免窗口残留

输出结果为:

四、核心总结

  1. 凸包的核心作用:简化形态、保留边界,为后续识别/检测提供基础;
  2. 算法选择优先级:Andrew扫描链法(首选,简单稳定)→ Graham扫描法(中大规模点集)→ QuickHull法(超大点集)→ 穷举法(仅学习用);
  3. 关键共性:所有算法都是通过"筛选最外层点"实现,核心是判断点与直线的位置关系(左侧/右侧/共线)。
相关推荐
冬奇Lab36 分钟前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab36 分钟前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP4 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年4 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼5 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS5 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区6 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈6 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang7 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx
shengjk18 小时前
NanoClaw 深度剖析:一个"AI 原生"架构的个人助手是如何运转的?
人工智能