python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测
角点检测(Corner Detection)是计算机视觉和图像处理中重要的步骤,主要用于提取图像中的关键特征,以便进行后续的任务,比如图像匹配、物体识别、运动跟踪等。下面介绍几种常用的角点检测方法及其应用。
1. Harris角点检测
Harris角点检测是一种经典的角点检测算法,基于图像的局部特征,通过计算图像的自相关矩阵来判断一个点是否为角点。
-
原理:
- 计算局部窗口内的图像梯度,并构造自相关矩阵。
- 通过计算赫希因子(Harris Matrix),确定强度响应,响应值大于一定阈值的点被认为是角点。
-
优点:
- 对于噪声具有一定的鲁棒性。
- 可以检测到多种类型的角点。
OpenCV 中的 cv.cornerHarris() 函数用来实现 Harris 角点检测。它的参数是:
img - 输入图像,应为 float32 类型的灰度图。
blockSize - 角点检测所考虑的邻域大小。
ksize - Sobel 导数的内核大小。
k - Harris 检测器方程中的自由参数。
OpenCV 带有一个函数 cv.cornerSubPix() ,它进一步细化了角点检测,以达到亚像素级精度。
import numpy as np
import cv2 as cv
filename = 'output.png'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# find Harris corners
gray = np.float32(gray)
dst = cv.cornerHarris(gray,2,3,0.04)
dst = cv.dilate(dst,None)
ret, dst = cv.threshold(dst,0.01*dst.max(),255,0)
dst = np.uint8(dst)
# find centroids
ret, labels, stats, centroids = cv.connectedComponentsWithStats(dst)
# define the criteria to stop and refine the corners
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 100, 0.001)
corners = cv.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)
# Now draw them
res = np.hstack((centroids,corners))
res = np.intp(res)
img[res[:,1],res[:,0]]=[0,0,255]
img[res[:,3],res[:,2]] = [0,255,0]
cv.imshow('sobely',img)
cv.waitKey(0)
2. Shi-Tomasi角点检测
Shi-Tomasi角点检测法是对Harris方法的改进,更注重测量响应函数的特征。
-
原理:
- 通过计算两个特征值,选择具有较大特征值的点作为角点。
- 角点的选择更为简洁和高效。
-
优点:
- 对图像旋转和尺度变化具有更好的鲁棒性。
- 适合实时应用,如视频监控。
OpenCV 有一个函数, cv.goodFeaturesToTrack() 。它通过 Shi-Tomasi 方法(或 Harris 角点检测,如果你指定它)在图像中找到 N 个最佳的角点。输入图像应该是灰度图像。然后指定要查找的角点数量。然后指定质量等级,该等级是 0-1 之间的值,所有低于这个质量等级的角点都将被忽略。最后设置检测到的两个角点之间的最小欧氏距离。
例如尝试找到 25 个最佳角点:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('f:/apple.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
corners = cv.goodFeaturesToTrack(gray,25,0.01,10)
corners = np.intp(corners)
for i in corners:x,y = i.ravel()cv.circle(img,(x,y),3,255,-1)
plt.imshow(img),plt.show()
3. SIFT(尺度不变特征变换)
SIFT是一种用于检测和描述局部特征的算法,具有对尺度、旋转和光照变化的高鲁棒性。
-
原理:
- 检测图像中多个尺度的关键点。
- 生成每个关键点的描述符,以便进行特征匹配。
-
优点:
- 高鲁棒性,适用于图像匹配、拼接等应用。
- 可以处理遮挡和光照变化。
SIFT算法主要可以分成以下几个步骤:
-
构建高斯金字塔(Gaussian Pyramid)
- 对于给定的图像,首先通过对图像进行不同尺度的高斯模糊,构建一个高斯金字塔。这涉及到对原图像逐层进行模糊,每一层的尺度增大。通常,金字塔中的每一层是上一层的平滑图像。
-
构建差分高斯金字塔(Difference of Gaussian)
- 通过相邻的高斯图像层之间进行减法来计算差分高斯(DoG),该过程可以近似计算图像的拉普拉斯金字塔(Laplacian Pyramid)。
- 公式为:
3. 关键点检测
- 对于每个像素点,寻找极值点,即在当前尺度和相邻的尺度(上层和下层)中具有极大或极小值的点。具体步骤如下:
- 遍历图像的每个像素,检查其是否在其邻域内(包括尺度上和空间上)是最大或最小点。
- 一般使用3x3x3的邻域,即考虑9个临近像素的3个尺度。
4. 精确定位关键点
- 对检测到的关键点进行细化,以提高其定位精度。常用的方法是通过泰勒级数展开。即优化关键点的位置,利用Hessian矩阵或者主导方向计算来细化关键点的位置和尺度。
5. 选择主方向
- 为每个关键点分配一个或多个主方向,以使得描述符具有旋转不变性。
- 计算关键点周围一定半径内的梯度值,并确定主方向。
- 形成一个方向直方图,用于统计方向,并选择最大直方图峰值作为关键点的主方向。
6. 生成关键点描述符
- 在每个关键点的周围区域中,计算其特征描述符。通常,这个区域被划分为多个子区块,并在每个子区块内计算梯度方向和幅值。
- 将每个子块的梯度信息汇总,形成一个包含多维信息的特征向量。
7. 特征点匹配(可选)
- 利用上述计算得到的描述符,针对不同图像中的特征点进行匹配。通常采取欧几里德距离或二元汉明距离来计算描述符之间的相似度。
具体步骤
-
构建高斯金字塔:对图像进行多次高斯模糊,生成一系列不同尺度的图像。
-
计算差分高斯:通过相邻两层的高斯图像做差,提取出潜在的特征点。
-
找到极值点:例如,对于某个像素,比较它与相邻8个像素以及上面和下面的对应像素,如果它是最大的或最小的,则记为一个关键点。
-
关键点精确定位:利用插值方法进行位置微调,去除那些边缘响应较强或低对比度的关键点。
-
计算方向:统计关键点周围像素的梯度直方图,确定主要方向。
-
生成描述符:以关键点的主方向为基准,计算关键点周围小块的描述符。
-
匹配过程:对于每个图像的特征点,可以使用最近邻法或比例测试进行匹配。
import numpy as np
import cv2 as cv
img = cv.imread('f:/apple.jpg')
gray= cv.cvtColor(img,cv.COLOR_BGR2GRAY)
sift = cv.xfeatures2d.SIFT_create()
kp = sift.detect(gray,None)
img=cv.drawKeypoints(gray,kp,img)
img=cv.drawKeypoints(gray,kp,img,flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv.imshow('SIFT',img)
cv.waitKey(0)
4. SURF算法
SURF的基本理念是在SIFT的基础上,通过加快特征点检测和描述过程,取得更高的效率。SURF的主要步骤如下:
1.1 特征点检测
-
Hessian矩阵:SURF使用Hessian矩阵的行列式来检测特征点。通过计算每个像素点的Hessian矩阵,可以快速找到潜在的特征点。Hessian矩阵具有以下形式:
- 盒子滤波:为了计算Hessian矩阵的行列式,SURF使用的是快速的Haar小波卷积。这种方法通过将图像分为不同大小的盒子,并使用加权和减少计算复杂度。
-
梯度计算:SURF在特征点周围的邻域内计算图像的梯度值,并将其组织成一个描述符。描述符的生成过程涉及多个子块,各子块的特征会被汇总成一个固定长度的描述符。
-
方向归一化:为了确保特征描述符具有方向不变性,SURF根据特征点的主方向进行方向归一化。
1.2 特征描述符生成
-
梯度计算:SURF在特征点周围的邻域内计算图像的梯度值,并将其组织成一个描述符。描述符的生成过程涉及多个子块,各子块的特征会被汇总成一个固定长度的描述符。
-
方向归一化:为了确保特征描述符具有方向不变性,SURF根据特征点的主方向进行方向归一化。
import cv2 as cv
from matplotlib import pyplot as plt# 读取图像
img = cv.imread('f:/apple.jpg', 0)# Create SURF object. You can specify params here or later.
# Here I set Hessian Threshold to 400
surf = cv.xfeatures2d.SURF_create(400)
# Find keypoints and descriptors directly
kp, des = surf.detectAndCompute(img,None)# Check present Hessian threshold
print( surf.getHessianThreshold() )# We set it to some 50000. Remember, it is just for representing in picture.
# In actual cases, it is better to have a value 300-500
surf.setHessianThreshold(50000)
# Again compute keypoints and check its number.
kp, des = surf.detectAndCompute(img,None)
print( len(kp) )img2 = cv.drawKeypoints(img,kp,None,(255,0,0),4)
plt.imshow(img2),plt.show()
5. ORB(Oriented FAST and Rotated BRIEF)
ORB结合了FAST特征检测和BRIEF特征描述,可以更快速地进行角点检测和描述。ORB 基本上是 FAST 特征点检测器和 Brief 描述子的融合,并进行了许多修改以增强性能。首先,它使用 FAST 查找特征点,然后应用 Harris 角点的测量方法来查找其中的前 N 个点。它还使用金字塔来生成多尺度特征。但有一个问题是,FAST 不计算方向。
-
原理:
- 使用FAST算法检测特征点,计算点的方向和角度。
- 采用BRIEF描述符来描述特征。
-
优点:
- 快速高效,适合实时应用。
- 对于图像的旋转具有稳健性。
cv.ORB()使用 feature2d 通用接口创建 ORB 对象。它有许多可选参数。
nFeatures,表示要保留的最大要素数量(默认为 500),
scoreType, 表示对特征点进行排序使用 Harris 得分或 FAST 得分(默认为 Harris 得分)等。
WTA_K, 决定生成一个 oriented BRIEF 描述子的所用的像素点数目。默认情况下它是 2,即一次选择两个点。在这种情况下进行匹配,使用 NORM_HAMMING 距离。如果 WTA_K 为 3 或 4,则需要 3 或 4 个点来产生 BRIEF 描述子,匹配距离由 NORM_HAMMING2 定义。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('f:/apple.jpg',0)
# Initiate ORB detector
orb = cv.ORB_create()
# find the keypoints with ORB
kp = orb.detect(img,None)
# compute the descriptors with ORB
kp, des = orb.compute(img, kp)
# draw only keypoints location,not size and orientation
img2 = cv.drawKeypoints(img, kp, None, color=(0,255,0), flags=0)
plt.imshow(img2), plt.show()
相关文章:

python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测
角点检测(Corner Detection)是计算机视觉和图像处理中重要的步骤,主要用于提取图像中的关键特征,以便进行后续的任务,比如图像匹配、物体识别、运动跟踪等。下面介绍几种常用的角点检测方法及其应用。 1. Harris角点检…...

费解的开关
费解的开关 你玩过“拉灯”游戏吗? 25 盏灯排成一个 55 的方形。 每一个灯都有一个开关,游戏者可以改变它的状态。 每一步,游戏者可以改变某一个灯的状态。 游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也…...

【机器学习】机器学习引领数学难题攻克:迈向未知数学领域的新突破
我的个人主页 我的领域:人工智能篇,希望能帮助到大家!!!👍点赞 收藏❤ 一、引言 在数学的浩瀚领域中,存在着诸多长期未解的难题,这些难题犹如高耸的山峰,吸引着无数数…...

Qt之QDjango-db的简单使用
QDjango是一款由C编写、依托于Qt库的Web开发框架,其设计理念受到了广受欢迎的Python框架Django的影响。这个项目旨在提供一个高效、灵活且易于使用的工具集,帮助开发者构建高质量的Web应用。其项目地址: https://gitcode.com/gh_mirrors/qd/qdjango&…...

缓存、数据库双写一致性解决方案
双写一致性问题的核心是确保数据库和缓存之间的数据同步,以避免缓存与数据库数据不同步的问题,尤其是在高并发和异步环境下。本文将探讨双写一致性面临的主要问题和解决方案,重点关注最终一致性。 本文讨论的是最终一致性问题 双写一致性面…...

SUnet: A multi-organ segmentation network based on multiple attention【医学图像分割】
一、论文信息 1.1、中文名称 名称:SUnet:基于多重注意力的多器官分割网络 1.2、论文关键词 医学图像分割、Transformer、注意力机制、高效特征融合模块 1.3、核心概述 本文提出了一种新颖有效的医学图像分割方法 SUnet,用于腹部和胸部的多…...
uniapp实现“到这儿去”、拨打电话功能
"到这儿去" 在 UniApp 中实现“到这儿去”的功能,即调起地图导航至指定位置,对于不同的平台(小程序、H5、App)有不同的处理方式。下面将简单介绍如何在这些平台上实现该功能,并讨论位置信息的获取。后面需求会用到,先来找一些相关资料,并不一定很准确,但也来…...

2025年入职/转行网络安全,该如何规划?网络安全职业规划
网络安全是一个日益增长的行业,对于打算进入或转行进入该领域的人来说,制定一个清晰且系统的职业规划非常重要。2025年,网络安全领域将继续发展并面临新的挑战,包括不断变化的技术、法规要求以及日益复杂的威胁环境。以下是一个关…...

【博客之星】2024年度个人成长、强化学习算法领域总结
📢在2025年初,非常荣幸能通过审核进入到《2024年度CSDN博客之星总评选》TOP300的年度评选中,排名40。这还是第一次来到这个阶段,作为一名博士研究生,还是备受鼓舞的。在这里我将以回顾的方式讲述一下这一年在CSDN中走过…...
HTML5 Canvas实现的跨年烟花源代码
以下是一份基于HTML5 Canvas实现的跨年烟花源代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">…...

使用通用预训练范式为 3D 基础模型铺平道路
大家读完觉得有帮助记得关注和点赞!!!,本次是英文需要英文功底扎实的阅读。 Abstract In contrast to numerous NLP and 2D vision foundational models, learning a 3D foundational model poses considerably greater challenge…...

SpringMVC (2)
目录 1. RequestMapping 注解介绍 2. RequestMapping 使用 3. RequestMapping与请求方式 3.1 RequestMapping 支持Get和Post类型的请求 3.2 RequestMapping 指定接收某种请求 3.3 GetMapping和PostMapping 4. 传参 4.1 通过查询字符串传参 4.2 在 Body 中传参 4.2.1 …...
【Vim Masterclass 笔记16】S07L32 + L33:同步练习09 —— 掌握 Vim 宏操作的六个典型案例(含点评课内容)
文章目录 S07L32 Exercise 09 - Macros1 训练目标2 操作指令2.1. 打开 macros-practice.txt 文件2.2. 练习1:将旧版 Python 代码转换为新版写法2.3. 练习2:根据列表内容批量创建 Shell 脚本2.4. 练习3:对电话号码作格式化处理2.5. 练习4&…...
爬楼梯问题(Leetcode 第70题)
爬楼梯问题(Leetcode 第70题) 问题描述 假设你正在爬楼梯。每次你可以爬 1 个或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 示例 1: 输入:n 2 输出:2 解释:有两种方法可以爬到楼顶。…...

6.5 正定矩阵
一、正定矩阵 这一节关注的是特征值都是正数的对称矩阵。如果对称使得矩阵很重要,那么这个额外的性质(所有的 λ > 0 \lambda>0 λ>0)会使得它更加的特殊。我们所说的特殊并不表示它稀有,特征值都是正数的对称矩阵几乎…...
verilog笔记1
1. 阻塞赋值 阻塞赋值,顾名思义即在一个 always 块中,后面的语句会受到前语句的影响,具体来说就是在同一个always 中,一条阻塞赋值语句如果没有执行结束,那么该语句后面的语句就不能被执行,即被“阻塞”。也…...

游戏引擎学习第81天
仓库:https://gitee.com/mrxiao_com/2d_game_2 或许我们应该尝试在地面上添加一些绘图 在这段时间的工作中,讨论了如何改进地面渲染的问题。虽然之前并没有专注于渲染部分,因为当时主要的工作重心不在这里,但在实现过程中,发现地…...

git系列之revert回滚
1. Git 使用cherry-pick“摘樱桃” step 1: 本地切到远程分支,对齐要对齐的base分支,举例子 localmap git pull git reset --hard localmap 对应的commit idstep 2: 执行cherry-pick命令 git cherry-pick abc123这样就会将远程…...
监控与调试:性能优化的利器 — ShardingSphere
在分布式数据库系统中,监控和调试是确保系统高效运行的关键。ShardingSphere 提供了多种监控和调试工具,帮助开发者实时跟踪和优化性能,识别瓶颈,进行故障排查,从而提升系统的稳定性和响应速度。本文将介绍如何使用 Sh…...
LLVM - 编译器前端 - 理解BNF(巴科斯-诺尔范式)
一:概述 BNF(Backus-Naur Form,巴科斯-诺尔范式)是一种用于描述上下文无关文法的形式语言,广泛应用于定义编程语言、协议和文件格式的语法规则。 下面是一小段类Pascal编程语言,这个编程语言就可以用BNF描述。用BNF描述编程语言的语法规则之后,就可以根据这个规则生成抽…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...