OpenCV3.0-图像特征检测

偶尔善良 提交于 2019-11-30 04:02:30

使用opencv的一些内置的算法来实现对图像特征的检测 
从图像中提取的到的特征可以用来进行图像的匹配和检索
常用的图像特征检测算法
Harris:检测角点
SIFT:检测斑点
SURF:检测斑点
FAST:检测角点
BRIEF:检测斑点

什么是图像特征?
  图像特征就是图像中最具有独特性和具有区别性的图像区域.在图像中特征区域主要分布在角点,高密度区域,边缘(边缘可以将图像分成多个区域),斑点(与周围像素差别很大的区域)

cornerHarrir()角点的检测

import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread('data/aero3.jpg',cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
# 第二个参数:特征标记点的大小
# 第三个参数:特征检测敏感度大小,介于3-31之间的奇数
dst = cv2.cornerHarris(gray, 3, 23, 0.04)
# 特征点标记为红色
img1[dst>0.01*dst.max()] = [255,0,0]

Harri可以很好的检测角点,而且在旋转的条件下,也可以很好的检测,这跟角点的特性有关.

plt.figure(figsize=(12,7))
plt.imshow(img1)
plt.show()

这里写图片描述

DOG和SIFT进行特征提取

在某些情况下对图像进行缩放后,角点信息可能会丢失,这时候Harri便不能检测到所有的角点,SIFT(scale-invariant feature transform)刚好克服了这个问题,对图像特征的检测,尽量不受图像尺寸变化的影响.SIFT并不直接检测关键点,
关键点的检测是由DOG(Difference of Gaussians)检测的.SIFT仅通过特征向量来描述特征点周围的像素情况.
DOG是通过不同的高斯滤波器对同一张图像进行处理,来得到关键点的.

img2 = cv2.imread('data/aero3.jpg')
gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
keypoints, descriptor = sift.detectAndCompute(gray,None)
# 将关键点标记的图片上
img2 = cv2.drawKeypoints(image=img2, outImage=img2, keypoints=keypoints,
                        flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
                        color=(255,0,0))
plt.figure(figsize=(12,7))
plt.imshow(img2)
plt.show()

这里写图片描述

img3 = cv2.imread('data/building.jpg')
gray = cv2.cvtColor(img3, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
# 检测和计算,返回关键点和关键点的描述向量
keypoints, descriptor = sift.detectAndCompute(gray,None)
# 将关键点标记的图片上
img3 = cv2.drawKeypoints(image=img3, outImage=img3, keypoints=keypoints,
                        flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
                        color=(255,0,0))
plt.figure(figsize=(12,7))
plt.imshow(img3)
plt.show()

这里写图片描述

Hessian算法和SURF来提取和检测特征

SURF来提取特征,Hessian算法来检测关键点,SIFT和SURF都在xfeatures模块下面(这两个算法受专利保护)

img4 = cv2.imread('data/building.jpg')
gray = cv2.cvtColor(img4, cv2.COLOR_BGR2GRAY)
# 传递一个阈值,值越高识别的特征就越少
sift = cv2.xfeatures2d.SURF_create(8000)
keypoints, descriptor = sift.detectAndCompute(gray,None)
# 将关键点标记的图片上
# flags =4 等价于cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
img4 = cv2.drawKeypoints(image=img4, outImage=img4, keypoints=keypoints,
                        flags = 4, color=(255,0,0))
plt.figure(figsize=(12,7))
plt.imshow(img4)
plt.show()

这里写图片描述

基于ORB的特征检测

ORB是基于FAST关键点检测技术和BRIEF描述符结合的特征检测技术.
   FAST(Features from Accelerated Segment Test)算法会在像素周围绘制一个圆,圆内包含16个像素,FAST算法是将圆内的像素分别与加上一个阈值的圆心像素作比较,若圈内出现连续的几个像素比加上一个阈值的像素还亮或是暗,则可认为圆心是角点.FAST是一个很有效率的检测算法,但是需要确定阈值参数来检测角点.
   BRIEF(Binary Robust Independent Elementary Features)在OpenCV中主要是通过detectAndCompute()来实现,这个函数包含两个部分,检测和计算,同时也返回两个结果.一个是检测到的关键点,一个是描述符.SIFT和SURF也是这样.关键点的描述符包含了图像的关键信息,可看作是图像的另一种表现形式,在比较两个图像的时候可以通过比较两个图像的特征描述来实现.也可以用来做图像特征的匹配.

# 参数对照
# IMREAD_ANYCOLOR = 4
# IMREAD_ANYDEPTH = 2
# IMREAD_COLOR = 1
# IMREAD_GRAYSCALE = 0
# IMREAD_LOAD_GOAL = 8
# IMREAD_UNCHANGED = -1
img5 = cv2.imread('data/building.jpg',cv2.IMREAD_GRAYSCALE)
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img5, None)
img4 = cv2.drawKeypoints(image=img5, outImage=img5, keypoints=keypoints,
                        flags = 4, color=(255,0,0))
plt.figure(figsize=(12,7))
plt.imshow(img5)
plt.show()

这里写图片描述

最后详细说下特征提取的keypoints和descript包含哪些些信息

以最近的这幅图片为例,它是用ORB算法做的特征检测,先看下得到的关键点和描述符的数量

# 上图中关键点和描述符的数量
len(kp1),len(des1)
(500, 500)

特征点

特征点的数量和描述符的数量是相等的,他们是一一对应的,他们都存放在一个列表对象当中,每个关键点包含6个属性,分别是:
pt : 关键点在图像中的坐标信息
size : 关键点所在区域的直径信息
angle : 关键点的方向信息
response : 关键点的强度信息
octave : 是关于该特征来自图像金字塔的层级信息
calss_id : 特征id

# 第一个关键点的属性信息
b = kp1[0]
b.angle, b.class_id, b.octave, b.pt, b.response, b.size
(203.91419982910156, -1, 0, (762.0, 272.0), 0.0018553065601736307, 31.0)

描述符:一个长度为32的特征向量

# 第一个关键点的描述符
a = des1[0]
a
array([137, 159, 147, 191, 253, 141, 182, 247, 223,  14,  80,  86, 172,
       249,  33, 205, 207, 123, 134,   3,  34, 254,  74, 255, 173, 215,
        62,  10, 146,  88, 161, 139], dtype=uint8)
a[::-1]-30
array([109, 131,  58, 116, 236,  32, 185, 143, 225,  44, 224,   4, 229,
       104,  93, 177, 175,   3, 219, 142,  56,  50, 240, 193, 217, 152,
       111, 223, 161, 117, 129, 107], dtype=uint8)

可视化特征的坐标信息和特征强度

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
# points存储每个关键点的坐标和层级信息和特征强度
points = np.zeros((500,4))
points[0] = (1,2,3,4)
for index, kpoint in enumerate(kp1):
    points[index] = (kpoint.pt[0],kpoint.pt[1], kpoint.octave, kpoint.response)
fig = plt.figure(figsize=(15,8))
ax = fig.gca(projection = '3d')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z layer')
ax.set_title('Visualization keyPoints')
# 图像中的坐标是从左上角开始的,所以600-
ax.scatter(points[:,0], 600-points[:,1], points[:,2], c=points[:,3],s=30)
plt.show()

这里写图片描述

颜色越深代表特征越重要

最后补充一下图像金字塔

图像金字塔其实是图像的不同尺寸的多种表示,按照尺寸的大小排列,层数越高尺寸越小,这样做的目的是为了能够解决不同尺度下的目标检测问题,待检测的目标图像尺寸大小不同,在做特征匹配的时候,就需要多种不同大小的图像,对输入图像的不同尺寸进行特征检测.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!