OpenCv学习笔记10--尺度不变特征(SIFT)

版权声明:本样板的所有内容,包括文字、图片,均为原创。如有问题可以邮箱[email protected] https://blog.csdn.net/qq_29893385/article/details/84388259

此opencv系列博客只是为了记录本人对<<opencv3计算机视觉-pyhton语言实现>>的学习笔记,所有代码在我的github主页https://github.com/RenDong3/OpenCV_Notes.

欢迎star,不定时更新...

上一节中,我们介绍了Harris角点检测。角点在图像旋转的情况下也可以检测到,但是如果减小(或者增加)图像的大小,可能会丢失图像的某些部分,甚至导致检测到的角点发生改变。这样的损失现象需要一种与图像比例无关的角点检测方法来解决。尺度不变特征变换(Scale-Invariant Feature Transform,SIFT)可以解决这个问题。我们使用一个变换来进行特征变换,并且该变换会对不同的图像尺度输出相同的结果。

到底什么是SIFT算法?通俗一点说,SIFT算法利用DoG(差分高斯)来提取关键点(或者说成特征点),DoG的思想是用不同的尺度空间因子(高斯正态分布的标准差σσ)对图像进行平滑,然后比较平滑后图像的区别,差别大的像素就是特征明显的点,即可能是特征点。对得到的所有特征点,我们剔除一些不好的,SIFT算子会把剩下的每个特征点用一个128维的特征向量进行描述

由上,易知,一幅图像经过SIFT算法后可以表示为一个128维的特征向量集

SIFT具有一下特征:

  • SIFT特征,对旋转、尺度缩放、亮度变化等保持不变性,对视角变换、仿射变化、噪声也保持一定程度的稳定性,是一种非常优秀的局部特征描述算法;
  • 独特性好,信息量丰富,适用于海量特征库进行快速、准确的匹配;
  • 多量性,即使是很少几个物体也可以产生大量的SIFT特征;
  • 高速性,经优化的SIFT匹配算法甚至可以达到实时性的要求;
  • 扩展性,可以很方便的与其他的特征向量进行联合。

一 使用DoG和SIFT进行特征提取和描述

我们先用OpenCV库函数演示一下DoG和SIFT特征提取的效果,然后再来讲述一下SIFT的原理。

我们先来介绍一下Different of Gaussians(DoG),DoG是对同一图象使用不同高斯滤波器作差所得到的结果。DoG操作的最终结果会得到感兴趣的区域(关键点),这将通过SIFT来进行特征描述。

我们来看看如何通过SIFT得到充满角点和特征的图像:

# -*- coding:utf-8 -*-
import os
import cv2
import numpy as np

'''
        created on 08:05:10 2018-11-20
        @author ren_dong

        使用DoG和SIFT进行特征提取和描述

        cv2.SIFT.detectAndCompute(image, mask[, descriptors[, useProvidedKeypoints]]) → keypoints, descriptors
        
        cv2.drawKeypoints(image, keypoints[, outImage[, color[, flags]]]) → outImage
        
        首先创建了一个SIFT对象,SIFT对象会使用DoG检测关键点,并且对每个关键点周围区域计算特征向量。
        detectAndCompute()函数会返回关键点信息(每一个元素都是一个对象,有兴趣的可以看一下OpenCV源码)和关键点的描述符。
        然后,我们在图像上绘制关键点,并显示出来。

'''
img = cv2.imread('chess.jpg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#创建sift对象
sift = cv2.xfeatures2d.SIFT_create()

#进行检测和计算  返回特征点信息和描述符
keypoints , descriptor = sift.detectAndCompute(gray, None)
#keypoints:特征点集合list,向量内每一个元素是一个KeyPoint对象,包含了特征点的各种属性信息;



#绘制关键点
img = cv2.drawKeypoints(img, keypoints=keypoints, outImage=img, color= (51, 163, 236), flags= cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

#sift得到的图像为128维的特征向量集

print len(keypoints)
print descriptor.shape

cv2.imshow('sift_keypoints',img)
cv2.waitKey()
cv2.destroyAllWindows()

我们首先创建了一个SIFT对象,SIFT对象会使用DoG检测关键点,并且对每个关键点周围区域计算特征向量。detectAndCompute()函数会返回关键点信息(每一个元素都是一个对象,有兴趣的可以看一下OpenCV源码)和关键点的描述符。然后,我们在图像上绘制关键点,并显示出来。

 上面我们用到了一个函数,下面来介绍一下:

1cv2.drawKeypoints(image, keypoints[, outImage[, color[, flags]]]) → outImage

 参数描述:

image:原始图像,可以使三通道或单通道图像;

keypoints:特征点集合list,向量内每一个元素是一个KeyPoint对象,包含了特征点的各种属性信息;

outImage:特征点绘制的画布图像,可以是原图像;

color:颜色设置,绘制的特征点的颜色信息,默认绘制的是随机彩色;

flags:特征点的绘制模式,其实就是设置特征点的哪些信息需要绘制,哪些不需要绘制,有以下几种模式可选:

  •  cv2.DRAW_MATCHES_FLAGS_DEFAULT:创建输出图像矩阵,使用现存的输出图像绘制匹配对和特征点,对每一个关键点只绘制中间点;
  • cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG:不创建输出图像矩阵,而是在输出图像上绘制匹配对;
  • cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS:对每一个特征点绘制带大小和方向的关键点图形;
  • cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制;

我们传入了DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS标志位,表明对图像每个关键点都绘制圆圈(大小)和方向。

总结下就是SIFT算法利用DOG进行特征点检测,然后对每个关键点周围的区域计算特征向量.解决了Harris角点检测的尺度变化影响问题.

这里并没有对SIFT算法的原理进行详细介绍,对此感兴趣的同学可以去大神的博客浏览观看,里面讲的非常详细,下面给上链接:

https://www.cnblogs.com/zyly/p/9519011.html 

猜你喜欢

转载自blog.csdn.net/qq_29893385/article/details/84388259