12.1 关键点提取------Harris原理及代码

一、原理

该原理看了Harris角点检测原理详解-CSDN博客的博文,在这里写一遍是作为笔记,以供后参考。

1.什么是角点

       角点就是图片中的一些突变的点,如下图所示。图中的点都是菱角分明的一些凸出来或凹进去的点。

我们可以直观的概括下角点所具有的特征:

>轮廓之间的交点;

>对于同一场景,即使视角发生变化,通常具备稳定性质的特征;

>该点附近区域的像素点无论在梯度方向上还是其梯度幅值上有着较大变化;

2. 角点检测算法基本思想是什么?

       算法基本思想是使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。

3.如何用数学方法去刻画角点特征?

当窗口发生[u,v]移动时,那么滑动前与滑动后对应的窗口中的像素点灰度变化描述如下:

公式解释:

>[u,v]是窗口的偏移量

>(x,y)是窗口内所对应的像素坐标位置,窗口有多大,就有多少个位置

>w(x,y)是窗口函数,最简单情形就是窗口内的所有像素所对应的w权重系数均为1。但有时候,我们会将w(x,y)函数设定为以窗口中心为原点的二元正态分布。如果窗口中心点是角点时,移动前与移动后,该点的灰度变化应该最为剧烈,所以该点权重系数可以设定大些,表示窗口移动时,该点在灰度变化贡献较大;而离窗口中心(角点)较远的点,这些点的灰度变化几近平缓,这些点的权重系数,可以设定小点,以示该点对灰度变化贡献较小,那么我们自然想到使用二元高斯函数来表示窗口函数,这里仅是个人理解,大家可以参考下。

所以通常窗口函数有如下两种形式:

         根据上述表达式,当窗口处在平坦区域上滑动,可以想象的到,灰度不会发生变化,那么E(u,v) = 0;如果窗口处在比纹理比较丰富的区域上滑动,那么灰度变化会很大。算法最终思想就是计算灰度发生较大变化时所对应的位置,当然这个较大是指针任意方向上的滑动,并非单指某个方向。

4.E(u,v)表达式进一步演化

首先需要了解泰勒公式,任何一个函数表达式,均可有泰勒公式进行展开,以逼近原函数,我们可以对下面函数进行一阶展开(如果对泰勒公式忘记了,可以翻翻本科所学的高等数学)

那么,

所以E(u,v)表达式可以更新为:

这里矩阵M为,

5.矩阵M的关键性

难道我们是直接求上述的E(u,v)值来判断角点吗?Harris角点检测并没有这样做,而是通过对窗口内的每个像素的x方向上的梯度与y方向上的梯度进行统计分析。这里以Ix和Iy为坐标轴,因此每个像素的梯度坐标可以表示成(Ix,Iy)。针对平坦区域,边缘区域以及角点区域三种情形进行分析:

下图是对这三种情况窗口中的对应像素的梯度分布进行绘制:

如果使用椭圆进行数据集表示,则绘制图示如下:

不知道大家有没有注意到这三种区域的特点,平坦区域上的每个像素点所对应的(IX,IY)坐标分布在原点附近,其实也很好理解,针对平坦区域的像素点,他们的梯度方向虽然各异,但是其幅值都不是很大,所以均聚集在原点附近;边缘区域有一坐标轴分布较散,至于是哪一个坐标上的数据分布较散不能一概而论,这要视边缘在图像上的具体位置而定,如果边缘是水平或者垂直方向,那么Iy轴方向或者Ix方向上的数据分布就比较散;角点区域的x、y方向上的梯度分布都比较散。我们是不是可以根据这些特征来判断哪些区域存在角点呢?

虽然我们利用E(u,v)来描述角点的基本思想,然而最终我们仅仅使用的是矩阵M。让我们看看矩阵M形式,是不是跟协方差矩阵形式很像,像归像,但是还是有些不同,哪儿不同?一般协方差矩阵对应维的随机变量需要减去该维随机变量的均值,但矩阵M中并没有这样做,所以在矩阵M里,我们先进行各维的均值化处理,那么各维所对应的随机变量的均值为0,协方差矩阵就大大简化了,简化的最终结果就是矩阵M,是否明白了?我们的目的是分析数据的主要成分,相信了解PCA原理的,应该都了解均值化的作用。

如果我们对协方差矩阵M进行对角化,很明显,特征值就是主分量上的方差,这点大家应该明白吧?不明白的话可以复习下PCA原理。如果存在两个主分量所对应的特征值都比较大,说明什么? 像素点的梯度分布比较散,梯度变化程度比较大,符合角点在窗口区域的特点;如果是平坦区域,那么像素点的梯度所构成的点集比较集中在原点附近,因为窗口区域内的像素点的梯度幅值非常小,此时矩阵M的对角化的两个特征值比较小;如果是边缘区域,在计算像素点的x、y方向上的梯度时,边缘上的像素点的某个方向的梯度幅值变化比较明显,另一个方向上的梯度幅值变化较弱,其余部分的点都还是集中原点附近,这样M对角化后的两个特征值理论应该是一个比较大,一个比较小,当然对于边缘这种情况,可能是呈45°的边缘,致使计算出的特征值并不是都特别的大,总之跟含有角点的窗口的分布情况还是不同的。

注:M为协方差矩阵,需要大家自己去理解下,窗口中的像素集构成一个矩阵(2*n,假设这里有n个像素点),使用该矩阵乘以该矩阵的转置,即是协方差矩阵

因此可以得出下列结论:

>特征值都比较大时,即窗口中含有角点

>特征值一个较大,一个较小,窗口中含有边缘

>特征值都比较小,窗口处在平坦区域

6. 如何度量角点响应?

通常用下面表达式进行度量:

其中k是常量,一般取值为0.04~0.06,这个参数仅仅是这个函数的一个系数,它的存在只是调节函数的形状而已。

但是为什么会使用这样的表达式呢?一下子是不是感觉很难理解?其实也不难理解,函数表达式一旦出来,我们就可以绘制它的图像,而这个函数图形正好满足上面几个区域的特征。 通过绘制函数图像,直观上更能理解。绘制的R函数图像如下:

二、代码实现

1.C++代码实现

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/time.h>
#include <pcl/keypoints/harris_3D.h>//harris
using namespace pcl;int main(int argc, char **argv)
{//读取点云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile<pcl::PointXYZ>("test.pcd", *cloud) == -1){PCL_ERROR("Cloudn't read file!");system("pause");return -1;}//Harris关键点提取float r_normal;float r_keypoint;r_normal = 0.6;r_keypoint = 0.8;typedef pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZI> ColorHandlerT3;pcl::PointCloud<pcl::PointXYZI>::Ptr Harris_keypoints(new pcl::PointCloud<pcl::PointXYZI>());    pcl::HarrisKeypoint3D<pcl::PointXYZ,pcl::PointXYZI,pcl::Normal>* harris_detector = new pcl::HarrisKeypoint3D<pcl::PointXYZ, pcl::PointXYZI, pcl::Normal>;harris_detector->setRadius(r_normal);         //设置法向量估算的半径harris_detector->setRadiusSearch(r_keypoint);
//设置关键点估计的近邻搜索半径harris_detector->setInputCloud(cloud);harris_detector->compute(*Harris_keypoints);cout<< "Harris_keypoints的大小是" <<Harris_keypoints->size()<< endl;//显示harris关键点pcl::visualization::PCLVisualizer viewer("clouds");viewer.setBackgroundColor(255,255, 255);    viewer.addPointCloud(Harris_keypoints,ColorHandlerT3(Harris_keypoints,0.0, 0.0, 255.0),
"Harris_keypoints");    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,8, "Harris_keypoints");viewer.addPointCloud(cloud,"cloud"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,0,0, 0, "cloud");  viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
2, "cloud");viewer.setCameraPosition(0,0, 0, 0, 156, -20, 0, 0, 1, 0);//设置相机位置,焦点,方向viewer.spin();return 0;
}

2.python代码实现

import cv2
import numpy as np
import matplotlib
import math
from matplotlib import pyplot as plt  #根据一阶锐化算子,求x,y的梯度,显示锐化图像
#读取图片
filename = 'girl.jpg'
tu = cv2.imread(filename)#转换为灰度图
gray = cv2.cvtColor(tu, cv2.COLOR_RGB2GRAY)#获取图像属性
print '获取图像大小: '
print gray.shape
print '\n'#打印数组gray
print '灰度图像数组:\n %s \n \n' % (gray)#输出n*n的数组
#print gray[:2,:2]#转换为矩阵
m = np.matrix(gray)#计算x方向的梯度的函数(水平方向锐化算子)
delta_h = m
def grad_x(h):a = int(h.shape[0])b = int(h.shape[1])for i in range(a):for j in range(b):if i-1>=0 and i+1<a and j-1>=0 and j+1<b:c = abs(int(h[i-1,j-1]) - int(h[i+1,j-1]) + 2*(int(h[i-1,j]) - int(h[i+1,j])) + int(h[i-1,j+1]) - int(h[i+1,j+1]))
#                print cif c>255:
#                    print cc = 255delta_h[i,j] = celse:delta_h[i,j] = 0print 'x方向的梯度:\n %s \n' %delta_hreturn delta_h##计算y方向的梯度的函数(水平方向锐化算子)
def grad_y(h):a = int(h.shape[0])b = int(h.shape[1])for i in range(a):for j in range(b):if i-1>=0 and i+1<a and j-1>=0 and j+1<b:c = abs(int(h[i-1,j-1]) - int(h[i-1,j+1]) + 2*(int(h[i,j-1]) - int(h[i,j+1])) + (int(h[i+1,j-1]) - int(h[i+1,j+1])))  #注意像素不能直接计算,需要转化为整型
#                print cif c > 255:c = 255delta_h[i,j] = celse:delta_h[i,j] = 0print 'y方向的梯度:\n %s \n' %delta_hreturn delta_h# Laplace 算子  
img_laplace = cv2.Laplacian(gray, cv2.CV_64F, ksize=3)  dx = np.array(grad_x(gray))
dy = np.array(grad_y(gray))#dxy = dx + dy
#print 'dxy1:'
#print dxyA = dx * dx
B = dy * dy 
C = dx * dyprint A
print B
print CA1 = A
B1 = B
C1 = CA1 = cv2.GaussianBlur(A1,(3,3),1.5)
B1 = cv2.GaussianBlur(B1,(3,3),1.5)
C1 = cv2.GaussianBlur(C1,(3,3),1.5)print A1
print B1
print C1a = int(gray.shape[0])
b = int(gray.shape[1])R = np.zeros(gray.shape)
for i in range(a):for j in range(b):M = [[A1[i,j],C1[i,j]],[C1[i,j],B1[i,j]]]R[i,j] = np.linalg.det(M) - 0.06 * (np.trace(M)) * (np.trace(M))print Rcv2.namedWindow('R',cv2.WINDOW_NORMAL)
cv2.imshow('R',R)cv2.waitKey(0)
cv2.destroyAllWindows()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/247928.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

广东盈致mes系统在注塑行业的应用

广东盈致MES系统在注塑行业的应用主要体现在以下几个方面&#xff1a; 生产计划与调度&#xff1a;盈致MES系统能够根据订单需求和生产计划&#xff0c;自动生成生产任务&#xff0c;并跟踪生产进度&#xff0c;确保按时完成生产任务。通过与注塑机的集成&#xff0c;系统可以自…

Jupyter notebook文件默认存储路径以及更改方法

目录 1、文件默认存储路径怎么查&#xff1f;2、文件默认存储路径怎么改&#xff1f; 转自&#xff1a;https://blog.csdn.net/fengyeer20120/article/details/109483362 初次使用Jupyter Notebook&#xff0c;确实好用啊&#xff01;但安装Anaconda后&#xff0c;打开Jupyter …

【Pg数据库】删除数据库失败,提示有session正在连接

目录 问题现象原因分析处理方法1.断开所有连接2. 查找相关连接数据库的主机信息3. 再次删除 总结 问题现象 Navicat 删除 PostgreSQL 数据库时失败&#xff0c;提示&#xff1a;正在被其他用户访问&#xff08;有session正在连接&#xff09;如何处理&#xff1f; 如下所示&am…

时隔3年 | 微软 | Windows Server 2025 重磅发布

最新功能 以下是微软产品团队正在努力的方向&#xff1a; Windows Server 2025 为所有人提供的热补丁下一代 AD 活动目录和 SMB数据与存储Hyper-V 和人工智能还有更多… Ignite 发布视频 Windows Server 2025 Ignite Video 介绍 Windows Server 2022 正式发布日期是2021年…

openGauss学习笔记-210 openGauss 数据库运维-常见故障定位案例-谓词下推引起的查询报错

文章目录 openGauss学习笔记-210 openGauss 数据库运维-常见故障定位案例-谓词下推引起的查询报错210.1 谓词下推引起的查询报错210.1.1 问题现象210.1.2 原因分析210.1.3 处理办法 openGauss学习笔记-210 openGauss 数据库运维-常见故障定位案例-谓词下推引起的查询报错 210.…

Zerosync:构建基于STARK的Bitcoin证明系统

1. 引言 前序博客&#xff1a; BitcoinSTARK: ZeroSync & Khepri Robin Linus、Tino Steffens、Lukas George 等人成立了一个名为 ZeroSync 协会&#xff08;ZeroSync Association&#xff09;的瑞士非营利组织&#xff0c;该组织将牵头开发比特币证明系统。ZeroSync 于…

uni-app app引入天地图

话不多说咸鱼来了 <template><view><div class"mapBox" style"width: 100%; height: 100vh;background: #ddc0c0;" id"mapId" ></div></view> </template> <script module"test" lang"r…

python统计分析——样本方差的分布

参考资料&#xff1a;用python动手学统计学 1、导入库 import numpy as np import pandas as pd import scipy as sp from scipy import statsfrom matplotlib import pyplot as plt import seaborn as sns 2、数据准备 建立一个平均数为4&#xff0c;标准差为0.8的正态分布…

http和https的区别是什么?https有什么优缺点?

HTTP&#xff08;Hypertext Transfer Protocol&#xff0c;超文本传输协议&#xff09;是一个简单的请求-响应协议&#xff0c;它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。这个简单模型是早期Web成功的有功之臣&#xff0c;因为它…

【运行Python爬虫脚本示例】

主要内容&#xff1a;Python中的两个库的使用。 1、requests库&#xff1a;访问和获取网页内容&#xff0c; 2、beautifulsoup4库&#xff1a;解析网页内容。 一 python 爬取数据 1 使用requests库发送GET请求&#xff0c;并使用text属性获取网页内容。 然后可以对获取的网页…

Orion-14B-Chat-Plugin本地部署的解决方案

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

数据结构-数组(详细讲解)

文章目录 数组数组的概述数组的图示一维数组二维数组 数组的定义一维数组的定义二维数组的定义 数组的取值赋值一维数组二维数组 数组的操作一维数组的操作索引实现指针实现 二位数组的操作矩阵转三元组矩阵的乘法 数组 数组的概述 概述&#xff1a;数组是一种线性数据结构&a…

游戏设计模式

单列模式 概念 单例模式是一种创建型设计模式&#xff0c;可以保证一个类只有一个实例&#xff0c;并提供一个访问该实例的全局节点。 优点 可以派生&#xff1a;在单例类的实例构造函数中可以设置以允许子类派生。受控访问&#xff1a;因为单例类封装他的唯一实例&#xf…

prism 10 for Mac v10.1.1.270激活版 医学绘图分析软件

GraphPad Prism 10 for Mac是一款专为科研工作者和数据分析师设计的绘图和数据可视化软件。以下是该软件的一些主要功能&#xff1a; 软件下载&#xff1a;prism 10 for Mac v10.1.1.270激活版 数据整理和导入&#xff1a;GraphPad Prism 10支持从多种数据源导入数据&#xff0…

Linux的bash命令语法

可用点 #!/bin/bash # 文件要以上面开始,.sh结尾的文件不需要# 赋权文件可执行权限 chmod x <fileName># 获取java jar包启动的进程id ps -ef | grep *.jar | grep -v grep | awk {print $2}shell变量 变量命令规则&#xff1a; 只能包含字母、数字、下划线&#xff1…

银行数据仓库体系实践(6)--调度系统

调度系统是数据仓库的重要组成部分&#xff0c;也是每个银行或公司一个基础软件或服务&#xff0c;需要在全行或全公司层面进行规划&#xff0c;在全行层面统一调度工具和规范&#xff0c;由于数据类系统调度作业较多&#xff0c;交易类系统批量优先级高&#xff0c;为不互相影…

uniapp对接微信APP支付返回requestPayment:fail [payment微信:-1]General errors错误-全网总结详解

一、问题描述 uniapp对接微信APP支付&#xff0c;本来是很简单的一件事&#xff0c;后端本来就是好的&#xff0c;只要填一些参数就行了&#xff0c;搞了我一晚上&#xff0c;主要卡在uniapp这边&#xff0c;拉起支付的时候&#xff0c;一直提示以下错误&#xff1a; {"er…

js数组/对象的深拷贝与浅拷贝

文章目录 一、js中的深拷贝和浅拷贝二、浅拷贝1、Object.assign()2、利用es6扩展运算符&#xff08;...&#xff09; 二、深拷贝1、JSON 序列化和反序列化2、js原生代码实现3、使用第三方库lodash等 四、总结 一、js中的深拷贝和浅拷贝 在JS中&#xff0c;深拷贝和浅拷贝是针对…

数学电路与电子工程1(MEE)—— 锁存器和触发器

1 逻辑综合 1.1 DCB/DEC转换器 下图是一个74HC42集成电路的逻辑图&#xff0c;它是一个二进制编码的十进制&#xff08;BCD to Decimal&#xff09;转换器&#xff0c;也称为DCB/DEC转换器。这种类型的IC通常用于将4位二进制数&#xff08;BCD&#xff09;转换为十进制输出。 …

PHP文件相关函数大总结

PHP中与文件相关的函数&#xff1a; 以下示例均以读取example.txt为例&#xff1a; example.txt的内容&#xff1a; this is a txt. 这是一个文件 1 .使用 file_get_contents 读取整个文件内容&#xff1a; $fileContent file_get_contents(example.txt); echo $fileContent…