day30 学习笔记
文章目录
- 前言
- 一、凸包特征检测
- 1.穷举法
- 2.QuickHull法
- 二、图像轮廓特征查找
- 1.外接矩形
- 2.最小外接矩形
- 3.最小外接圆
前言
- 通过今天的学习,我掌握了OpenCV中有关凸包特征检测,图像轮廓特征查找的相关原理和操作
一、凸包特征检测
-
- 通俗的讲,凸包其实就是将一张图片中物体的最外层的点连接起来构成的凸多边形,它能包含物体中所有的内容。
- 凸包检测常用在物体识别、手势识别、边界检测等领域。
tips:凸包与图像的轮廓的区别在于:图像轮廓可能含有凹集,保留了图像的细节;而凸包只含有凸集,是图像的凸近似
1.穷举法
- 对集合中的所有点进行两两配对后连接,对于每条直线,检查其余所有点是否处于直线的同一侧,如果是,那么这两个点是凸包点
-
- 用向量的思想,点都是有坐标的,连起来就可以构成一个向量。再以其中一个点,连接另一个点,构成另一个向量,让两个向量做外积,就是叉积。也就是 s t d = ∣ 向量 a ∣ ∗ ∣ 向量 b ∣ ∗ s i n ( θ ) std=|向量a|*|向量b|*sin(\theta) std=∣向量a∣∗∣向量b∣∗sin(θ) ,能控制 s t d std std的正负的只能是 θ \theta θ,如果计算出来的 s t d std std的正负都相同,说明这些点都在这条直线的同一侧,那么这两个点就是凸包的边界点。
2.QuickHull法
- 将所有点放在二维坐标系中,找到横坐标最小和最大的两个点 P 1 P_1 P1和 P 2 P_2 P2并连线。此时整个点集被分为两部分,直线上为上包,直线下为下包。
- 以上包为例,找到上包中的点距离该直线最远的点 P 3 P_3 P3,连线并寻找直线 P 1 P 3 P1P3 P1P3左侧的点和 P 2 P 3 P2P3 P2P3右侧的点,然后重复本步骤,直到找不到为止。对下包也是这样操作。
对于未经处理的图像,我们无法直接获取点的坐标。特别是对于彩色图像,我们需要将其转换为二值图像,并使用轮廓检测技术来获取轮廓边界的点的坐标。然后,我们才能进行上述寻找凸包点的过程。
1.获取凸包点
- cv2.convexHull(points)
- points:输入参数,图像的轮廓
2.绘制凸包
- cv2.polylines(image, pts, isClosed, color, thickness=1)
- pts:输入凸包点组成的列表
- isclosed:表示是否为闭合多边形
# 获取图像
img = cv.imread(r'D:\AI\笔记课件\images\num.png')
# 灰度化
img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 二值化
_,img_binary = cv.threshold(img_gray,127,255,cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
# 获取轮廓
contours,hierarchy = cv.findContours(img_binary,mode=cv.RETR_EXTERNAL,method=cv.CHAIN_APPROX_SIMPLE)
# 获取凸包
points = [cv.convexHull(i) for i in contours]
# 绘制凸包
cv.polylines(img,points,True,(255,0,0),3,cv.LINE_AA)
# 显示图像
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
二、图像轮廓特征查找
- 查找图像的轮廓特征就是查找图像的外接轮廓
- 根据轮廓点进行查找,所以需要先找到轮廓点
- 对图像进行灰度化和二值化,目标区域设为白色,其余部分为黑色
1.外接矩形
- cv2.boundingRect(轮廓点坐标)
- 返回的是外接矩形的空间位置信息,即轮廓坐标中最上、最下、最左、最右的点的坐标
img = cv.imread(r"D:\AI\笔记课件\images\flower2.png")
img_copy = img.copy()
# 灰度化
img_gray = cv.cvtColor(img_copy,cv.COLOR_BGR2GRAY)
# 二值化
_,img_binary = cv.threshold(img_gray,127,255,cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
# 查找轮廓
contours,hierarchy = cv.findContours(img_binary,mode=cv.RETR_EXTERNAL,method=cv.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv.drawContours(img_copy,contours,-1,(255,0,0),3)
# 获取外接矩阵位置
for i in contours:x_min,y_min,w,h = cv.boundingRect(i)# 绘制外接矩形cv.rectangle(img_copy,(x_min,y_min),(x_min+w,y_min+h),(0,0,255),3,cv.LINE_AA)
# 显示效果
cv.imshow('img',img_copy)
cv.waitKey(0)
cv.destroyAllWindows()
2.最小外接矩形
-
使用旋转卡壳算法
-
对于多边形P的一个外接矩形存在一条边与原多边形的边共线。
-
对于每一条边,找到距离边变最远的点的距离作为矩形的高
-
对于每一条边,找到投影到边最大的距离计算矩形的宽
-
比较通过每一条边计算得到的矩形面积进行比较,找到最小的矩形面积
w i d t h = ∣ b h ‾ ∣ × cos a + ∣ a d ‾ ∣ × cos θ − ∣ a b ‾ ∣ w i d t h=|\overline{{{b h}}}|\times\cos a+|\overline{{{a d}}}|\times\cos\theta-|\overline{{{a b}}}| width=∣bh∣×cosa+∣ad∣×cosθ−∣ab∣ -
在OpenCV中,可以直接使用cv2.minAreaRect()来获取最小外接矩形,该函数只需要输入一个参数,就是凸包点的坐标,然后会返回最小外接矩形的中心点坐标、宽高以及旋转角度。
rect = cv2.minAreaRect(cnt) -
传入的cnt参数为contours中的轮廓,可以遍历contours中的所有轮廓,然后计算出每个轮廓的小面积外接矩形
-
rect 是计算轮廓最小面积外接矩形:rect 结构通常包含中心点坐标
(x, y)、宽度width、高度height和旋转角度angle
cv2.boxPoints(rect).astype(int) -
cv2.boxPoints(rect)返回 是一个形状为4行2列的数组,每一行代表一个点的坐标(x, y),顺序按照逆时针或顺时针方向排列
-
将最小外接矩形转换为边界框的四个角点,并转换为整数坐标
img = cv.imread(r"D:\AI\笔记课件\images\num.png")
# 灰度化
img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 二值化
_,img_binary = cv.threshold(img_gray,127,255,cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
# 查找轮廓
contours,hierarchy = cv.findContours(img_binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
# 获取最小外接矩形
for i in contours:rect = cv.minAreaRect(i)# 获取每个顶点的坐标box = cv.boxPoints(rect).astype(np.int32)# 绘制图像cv.drawContours(img,[box],-1,(255,0,0),2,cv.LINE_AA)
# 显示效果
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
3.最小外接圆
- 寻找最小外接圆使用的算法是Welzl算法。Welzl算法基于一个定理:希尔伯特圆定理,对于平面上的任意三个不在同一直线上的点,存在一个唯一的圆同时通过这三个点,且该圆是最小面积的圆(即包含这三个点的圆中半径最小的圆,也称为最小覆盖圆)。
- 新加入的点一定在新的最小覆盖圆的圆周上
cv2.minEnclosingCircle(points) -> (center, radius)
参数说明:
points:输入参数图片轮廓数据
返回值:
center:一个包含圆心坐标的二元组(x, y)。radius:浮点数类型,表示计算得到的最小覆盖圆的半径。
cv2.circle(img, center, radius, color, thickness)
img:输入图像,通常是一个numpy数组,代表要绘制圆形的图像。center:一个二元组(x, y),表示圆心的坐标位置。radius:整型或浮点型数值,表示圆的半径长度。color:颜色标识,可以是BGR格式的三元组(B, G, R),例如(255, 0, 0)表示红色。thickness:整数,表示圆边框的宽度。如果设置为-1,则会填充整个圆。
img = cv.imread(r"D:\AI\笔记课件\images\num.png")
# 灰度化
img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 二值化
_,img_binary = cv.threshold(img_gray,127,255,cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
# 查找轮廓
contours,_ = cv.findContours(img_binary,mode=cv.RETR_EXTERNAL,method=cv.CHAIN_APPROX_SIMPLE)
# 获取最小外接圆
for i in contours:# 获取每个点的位置信息(x,y),radius = cv.minEnclosingCircle(i)# 数据类型转换,元组不能直接使用astype进行类型转换x,y,radius = np.int_(x),np.int_(y),np.int_(radius)# 绘制图像cv.circle(img,(x,y),radius,(255,0,0),3,cv.LINE_AA)
# 显示效果
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
THE END
相关文章:
day30 学习笔记
文章目录 前言一、凸包特征检测1.穷举法2.QuickHull法 二、图像轮廓特征查找1.外接矩形2.最小外接矩形3.最小外接圆 前言 通过今天的学习,我掌握了OpenCV中有关凸包特征检测,图像轮廓特征查找的相关原理和操作 一、凸包特征检测 通俗的讲,凸…...
[密码学基础]密码学发展简史:从古典艺术到量子安全的演进
密码学发展简史:从古典艺术到量子安全的演进 密码学作为信息安全的基石,其发展贯穿人类文明史,从最初的文字游戏到量子时代的数学博弈,每一次变革都深刻影响着政治、军事、科技乃至日常生活。本文将以技术演进为主线,…...
(51单片机)LCD显示温度(DS18B20教程)(LCD1602教程)(延时函数教程)(单总线教程)
演示视频: LCD显示温度 源代码 如上图将9个文放在Keli5 中即可,然后烧录在单片机中就行了 烧录软件用的是STC-ISP,不知道怎么安装的可以去看江科大的视频: 【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】https://www.…...
服务器运维:服务器流量的二八法则是什么意思?
文章目录 用户行为角度时间分布角度应用场景角度 服务器流量的二八法则,又称 80/20 法则,源自意大利经济学家帕累托提出的帕累托法则,该法则指出在很多情况下,80% 的结果是由 20% 的因素所决定的。在服务器流量领域,二…...
高并发秒杀使用RabbitMQ的优化思路
高并发秒杀使用RabbitMQ的优化思路 一、判断是否重复抢购(防止一人多次秒杀)的逻辑1. 整体逻辑代码2. 原始判断重复抢购的方式:3. 后来优化为什么用 Redis 判断? 二、高并发下优化过的秒杀逻辑1.秒杀核心逻辑(请求入口)…...
B + 树与 B 树的深度剖析
在数据库领域,B 树和 B 树是两种极为关键的数据结构,它们对于数据的存储、查询以及索引的构建等方面都有着深远的影响。深刻理解这两种树的原理、特性以及它们之间的差异,对于数据库的性能优化、数据组织和管理等工作具有不可替代的重要作用…...
【LeetCode】嚼烂热题100【持续更新】
2、字母异位词分组 方法一:排序哈希表 思路:对每个字符串排序,排序后的字符串作为键插入到哈希表中,值为List<String>形式存储单词原型,键为排序后的字符串。 Map<String, List<String>> m new Ha…...
赛灵思 XC7K325T-2FFG900I FPGA Xilinx Kintex‑7
XC7K325T-2FFG900I 是 Xilinx Kintex‑7 系列中一款工业级 (I) 高性能 FPGA,基于 28 nm HKMG HPL 工艺制程,核心电压标称 1.0 V,I/O 电压可在 0.97 V–1.03 V 之间灵活配置,并可在 –40 C 至 100 C 温度范围内稳定运行。该器件提供…...
【速写】多LoRA并行衍生的一些思考
迁移学习上的一个老问题,怎么做多领域的迁移?以前的逻辑认为领域迁移属于是对参数做方向性的调整,如果两个领域方向相左,实际上不管怎么加权相加都是不合理的。 目前一些做法想着去观察LoRA权重矩阵中的稠密块与稀疏块࿰…...
探索智能仓颉!Cangjie Magic:码字之间,意境自生
仓颉输入法,对于许多老牌中文使用者来说,不仅仅是一种输入工具,更是一种情怀,一种文化符号。它以拆字为核心,将汉字结构还原成最原始的构件,再通过特定的编码规则进行输入。然而,随着拼音输入法…...
py默认框架和代码
py默认框架 平常工作日常需要频繁写python脚本,留下一个常用的模板 # template.py import logging import json import time import functools import os from typing import Any, Dict, Optional, Union from pathlib import Path from logging.handlers import …...
通过 Samba 服务实现 Ubuntu 和 Windows 之间互传文件
在 Ubuntu 上进行配置 1. 安装 Samba 服务 打开终端,输入以下命令来安装 Samba: sudo apt update sudo apt install samba2. 创建共享目录 可以使用以下命令创建一个新的共享目录,例如创建名为 shared_folder 的目录: sudo m…...
k8s-1.28.10 安装metrics-server
1.简介 Metrics Server是一个集群范围的资源使用情况的数据聚合器。作为一个应用部署在集群中。Metric server从每个节点上KubeletAPI收集指标,通过Kubernetes聚合器注册在Master APIServer中。为集群提供Node、Pods资源利用率指标。 2.下载yaml文件 wget https:/…...
基于外部中中断机制,实现以下功能: 1.按键1,按下和释放后,点亮LED 2.按键2,按下和释放后,熄灭LED 3.按键3,按下和释放后,使得LED闪烁
题目: 参照外部中断的原理和代码示例,再结合之前已经实现的按键切换LED状态的实验,用外部中断改进其实现。 请自行参考文档《中断》当中,有关按键切换LED状态的内容, 自行连接电路图,基于外部中断机制,实现以下功能&am…...
【我的创作纪念日】 --- 与CSDN走过的第365天
个人主页:夜晚中的人海 不积跬步,无以至千里;不积小流,无以成江海。-《荀子》 文章目录 🎉一、机缘🚀二、收获🎡三、 日常⭐四、成就🏠五、憧憬 🎉一、机缘 光阴似箭&am…...
学习笔记——《Java面向对象程序设计》-继承
参考教材: Java面向对象程序设计(第3版)微课视频版 清华大学出版社 1、定义子类 class 子类名 extends 父类名{...... }如: class Student extends People{...... } (1)如果一个类的声明中没有extends关…...
鸿蒙生态新利器:华为ArkUI-X混合开发框架深度解析
鸿蒙生态新利器:华为ArkUI-X混合开发框架深度解析 作者:王老汉 | 鸿蒙生态开发者 | 2025年4月 📢 前言:开发者们的新机遇 各位鸿蒙开发者朋友们,是否还在为多平台开发重复造轮子而苦恼?今天给大家介绍一位…...
如何收集用户白屏/长时间无响应/接口超时问题
想象一下这样的场景:一位用户在午休时间打开某电商应用,准备购买一件心仪已久的商品。然而,页面加载了数秒后依然是一片空白,或者点击“加入购物车”按钮后没有任何反馈,甚至在结算时接口超时导致订单失败。用户的耐心被迅速消耗殆尽,关闭应用,转而选择了竞争对手的产品…...
信号调制与解调技术基础解析
调制解调技术是通信系统中实现基带信号与高频载波信号相互转换的主要技术,通过调整信号特性使其适应不同信道环境,保障信息传输的效率和可靠性。 调制与解调的基本概念 调制(Modulation) 将低频基带信号(如语音或数…...
[PTA]2025 CCCC-GPLT天梯赛 胖达的山头
来源:L2-055 胖达的山头-Pintia题意:给定 n n n 个事件的起始和终止时刻(以hh:mm:ss给出),求最多并行事件数。关键词:差分(签到,模板题)题解:将所有时刻转换为秒,当某事件开始1,结束则-1。按时…...
基于Spring Cloud 2023.0.x + Micrometer Tracing的分布式链路追踪详细解析
前言 在微服务架构中,复杂的调用链路常让问题排查如大海捞针。Spring Cloud 2023.0.x整合Micrometer Tracing,深度支持OpenTelemetry标准,为开发者提供了轻量、高效的分布式链路追踪能力。本文将深入解析从TraceID透传到可视化分析的全流程实现,结合最新技术栈代码…...
【扫描件批量改名】批量识别扫描件PDF指定区域内容,用识别的内容修改PDF文件名,基于C++和腾讯OCR的实现方案,超详细
批量识别扫描件PDF指定区域内容并重命名文件方案 应用场景 本方案适用于以下场景: 企业档案数字化管理:批量处理扫描的合同、发票等文件,按内容自动分类命名财务票据处理:自动识别票据上的关键信息(如发票号码、日期)用于归档医疗记录管理:从扫描的检查报告中提取患者I…...
LOH 怎么进行深度标准化?
The panel of normals is applied by replacing the germline read depth of the sample with the median read depth of samples with the same genotype in our panel. 1.解释: panel of normal 正常组织,用于识别技术噪音 germline read depth: 胚系测序深度。根…...
【Python Web开发】01-Socket网络编程01
文章目录 1.套接字(Socket)1.1 概念1.2 类型1.3 使用步骤 Python 的网络编程主要用于让不同的计算机或者程序之间进行数据交换和通信,就好像人与人之间打电话、发消息一样。 下面从几个关键方面通俗易懂地介绍一下: 1.套接字(Socket) 在 Python 网络编…...
序列决策问题(Sequential Decision-Making Problem)
序列决策问题(Sequential Decision-Making Problem)是强化学习(Reinforcement Learning, RL)的核心研究内容,其核心思想是:智能体(Agent)需要在连续的时间步骤中,通过…...
L2-1、打造稳定可控的 AI 输出 —— Prompt 模板与格式控制
一、为什么需要 Prompt 模板? 在与 AI 模型交互时,我们经常会遇到输出不稳定、格式混乱的问题。Prompt 模板帮助我们解决这些问题,通过结构化的输入指令来获得可预测且一致的输出结果。 模板的作用主要体现在: 固定输出格式&am…...
ClickHouse进行LEFT JOIN 关联查询时, 关联键的数据类型不一致,导致报错 的解决方案详解
一.场景 使用golang语言操作ClickHouse数据库进行LEFT JOIN关联查询查询计算: 关联键在不同数据表中的数据类型不一致, 这样SQL语句就会报错, 二.问题 通过上面场景描述, 下面贴出具体的sql语句相关: 表user_phone_bind: 字段UserId(用户id): 类型Int64字段Phone(手机号): 类型…...
LLM中什么是模板定义、提示工程和文档处理链
LLM中什么是模板定义、提示工程和文档处理链 定义提示模板(prompt_template):prompt_template = """Use the following pieces of context to answer the question at the end. If you dont know the answer, just say that you dont know, dont try to make…...
密码学(二)流密码
2.1流密码的基本概念 流密码的基本思想是利用密钥 k 产生一个密钥流...,并使用如下规则对明文串 ... 加密:。密钥流由密钥流发生器产生: ,这里是加密器中的记忆元件(存储器)在时刻 i 的状态,…...
深度学习与总结JVM专辑(七):垃圾回收器—CMS(图文+代码)
CMS垃圾收集器深度解析教程 1. 前言:为什么需要CMS?2. CMS 工作原理:一场与时间的赛跑2.1. 初始标记(Initial Mark)2.2. 并发标记(Concurrent Mark)2.3. 重新标记(Remark)…...
