热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

OpenCV—python角点特征检测之一(cornerHarris、ShiTomasi、FAST)

OpenCV—python角点特征检测之一(cornerHarris、Shi-Tomasi、FAST),Go语言社区,Golang程序员人脉社

角点检测

          • 一、cornerHarris() 函数
          • 二、Shi-Tomasi 角点检测 goodFeaturesToTrack()
          • 三、FAST() 特征检测
            • cv2.drawKeypoints() 函数讲解
            • 关于FAST()函数示例,参数如下


一、cornerHarris() 函数

cornerHarris() 角点检测具有旋转不变特性。关于角点检测用一幅图来讲解:


  • 红框进行移动:无论是往哪个方向进行偏移,都会对框框内的像素值造成很大的变动。那么红框 框住的区域的边角点,就是检测到的角点。

  • 黑框进行移动:水平方向上移动像素值的变化不大,垂直方向上移动那么就会变化很大;或者相反,则这种一般称为边缘区域。

  • 蓝框进行移动:无论是水平还是垂直的方向移动,框内像素值的变化不大。这种是内部区域。
    在这里插入图片描述

    1988 年的文章《A CombinedCorner and Edge Detector》中就已经提出了焦点检测的方法,被称为Harris 角点检测。他把这个简单的想法转换成了数学形式。将窗口向各个方向移动 (u,v)(u,v) 然后计算所有差异的总和。表达式如下:
    E(u,v)=x,yw(x,y)window function[I(x+u,y+v)shifted intensityI(x,y)]2intensityE(u,v) = sum_{x,y} underbrace{w(x,y)}_{window function} underbrace{[I(x+u,y+v)}_{shifted intensity}-underbrace{I(x,y)]^2}_{intensity}

窗口函数(Sobel求导中使用的窗口) :可以是正常的矩形窗口,也可以是对每一个像素给予不同权重的高斯窗口

角点检测中要使 E(μ,ν)E(μ,ν) 的值最大。这就是说必须使方程右侧的第二项的取值最大。对上面的等式进行泰勒级数展开然后再通过几步数学换算(可以参考其他标准教材),我们得到下面的等式:
E(u,v)=[uv]M[uv]E(u,v) = begin{bmatrix}
u & v end{bmatrix}approx Mbegin{bmatrix}
u\ vend{bmatrix}

其中:
E(u,v)=x,yw(x,y)[Ix2IxIyIxIyIy2]E(u,v) = sum_{x,y}w(x,y)begin{bmatrix}I_x^2 & I_xI_y\I_xI_y
& I_y^2end{bmatrix}

这里 Ixrm I_x

他们根据一个用来判定窗口内是否包含角点的等式进行打分。

R=det(M)k(trace(M))2R = det(M) - k(trace(M))^2

其中:
det(M)=λ1λ2det(M) = lambda_1 lambda_2

trace(M)=λ1+λ2trace(M) = lambda_1+lambda_2

λ1λ1λ2λ2 是矩阵 M 的特征值:我们可以判断一个区域是否是角点,边界或者是平面。


cv2.cornerHarris(src=gray, blockSize, ksize, k, dst=None, borderType=None)
"""
cornerHarris参数:
src - 数据类型为 float32 的输入图像。(输入单通道图)
blockSize - 角点检测中要考虑的领域大小。也就是计算协方差矩阵时的窗口大小
ksize - Sobel求导中使用的窗口大小
k - Harris 角点检测方程中的自由参数,取值参数为 [0.04,0.06].
dst - 输出图像
borderType - 边界的类型
"""

示例一:

# encoding:utf-8
import cv2
import numpy as np
filename = 'D:\image_person\00001.png'
img = cv2.imread(filename)
img = cv2.resize(img, (640, 480))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
# 输入图像必须是float32, 最后一个参数[0.04,0.06]
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
cv2.imshow('dst', dst)
dst = cv2.dilate(dst, None)
img[dst > 0.01 * dst.max()] = [0, 0, 255]
cv2.imshow('img', img)
cv2.imshow('dst2', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

左侧为原图,右侧为检测之后的图像。
在这里插入图片描述

参数测试:(我写了两组数据测试,使大家一目了然,BlockSize ,Ksize 这两个参数的含义)

import cv2
import numpy as np
img = cv2.imread('D:\image_person\06_01.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray) # cornerHarris函数图像格式为 float32
BlockSize =(2,3,4,5,7,9)
Ksize =(3,5,5,9,11,23)
for i,j in zip(BlockSize,Ksize):
dst = cv2.cornerHarris(src=gray, blockSize=i, ksize=j, k=0.04)
# 变量a的阈值为0.01 * dst.max(),如果dst的图像值大于阈值,那么该图像的像素点设为True,否则为False
# 将图片每个像素点根据变量a的True和False进行赋值处理,赋值处理是将图像角点勾画出来
a = dst>0.01 * dst.max()
img[a] = [0, 0, 255]
cv2.imshow('corners_' + str(i) + '_' + str(j), img)
cv2.waitKey(0) # 按Esc查看下一张
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

有时候我们检验时有很多角点都是粘连在一起的,通过加入非极大值抑制来进一步去除一些粘在一起的角点。也就是在一个窗口内,如果有多个角点则用值最大的那个角点,其他的角点都删除。

请看如下示例:

import cv2
import numpy as np
img = cv2.imread('./lou.png')
cv2.imshow('raw_img', img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray) # cornerHarris函数图像格式为 float32
J = (0.05,0.01,0.005)
for j in J: # 遍历设置阈值:j * dst.max()
dst = cv2.cornerHarris(src=gray, blockSize=5, ksize=7, k=0.04)
a = dst>j * dst.max()
img[a] = [0, 0, 255]
cv2.imshow('corners_'+ str(j), img)
cv2.waitKey(0) # 按Esc查看下一张
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述


二、Shi-Tomasi 角点检测 goodFeaturesToTrack()

goodFeaturesToTrack()是cornerHarris() 函数升级版。该函数的角点检测效果与cornerHarris()函数效果差不多。

Harris 角点检测的打分公式为:
R=λ1λ2k(λ1+λ2)2R =λ_1λ_2-k(λ_1+λ_2)^2

推荐阅读
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 使用GDI的一些AIP函数我们可以轻易的绘制出简 ... [详细]
  • 本题探讨如何通过最大流算法解决农场排水系统的设计问题。题目要求计算从水源点到汇合点的最大水流速率,使用经典的EK(Edmonds-Karp)和Dinic算法进行求解。 ... [详细]
  • 作为一名新手,您可能会在初次尝试使用Eclipse进行Struts开发时遇到一些挑战。本文将为您提供详细的指导和解决方案,帮助您克服常见的配置和操作难题。 ... [详细]
  • 本文介绍了如何在C#中启动一个应用程序,并通过枚举窗口来获取其主窗口句柄。当使用Process类启动程序时,我们通常只能获得进程的句柄,而主窗口句柄可能为0。因此,我们需要使用API函数和回调机制来准确获取主窗口句柄。 ... [详细]
  • Splay Tree 区间操作优化
    本文详细介绍了使用Splay Tree进行区间操作的实现方法,包括插入、删除、修改、翻转和求和等操作。通过这些操作,可以高效地处理动态序列问题,并且代码实现具有一定的挑战性,有助于编程能力的提升。 ... [详细]
  • 本文探讨了如何优化和正确配置Kafka Streams应用程序以确保准确的状态存储查询。通过调整配置参数和代码逻辑,可以有效解决数据不一致的问题。 ... [详细]
  • 本文详细介绍了中央电视台电影频道的节目预告,并通过专业工具分析了其加载方式,确保用户能够获取最准确的电视节目信息。 ... [详细]
  • 本题通过将每个矩形视为一个节点,根据其相对位置构建拓扑图,并利用深度优先搜索(DFS)或状态压缩动态规划(DP)求解最小涂色次数。本文详细解析了该问题的建模思路与算法实现。 ... [详细]
  • PHP数组平均值计算方法详解
    本文详细介绍了如何在PHP中计算数组的平均值,涵盖基本概念、具体实现步骤及示例代码。通过本篇文章,您将掌握使用PHP函数array_sum()和count()来求解数组元素的平均值。 ... [详细]
  • 作为一名专业的Web前端工程师,掌握HTML和CSS的命名规范是至关重要的。良好的命名习惯不仅有助于提高代码的可读性和维护性,还能促进团队协作。本文将详细介绍Web前端开发中常用的HTML和CSS命名规范,并提供实用的建议。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
author-avatar
手机用户2602879695
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有