热门标签 | 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

推荐阅读
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社区 版权所有