用SIFT算法进行角点检测时遇到Set OPENCV_ENABLE_NONFREE CMake option and rebuild the library in function报错的两种解决方法

一、第一种:安装opencv-contrib-python
使用此种方法的原因:由于SIFT算法需要用到opencv-contrib-python包中的cv2.xfeatures2d,所以可以通过安装opencv-contrib-python来解决这个问题。
1.卸载opencv-python

pip uninstall opencv-python

2.安装opencv-contrib-python

pip install -i http://pypi.douban.com/simple --trusted-host pypi.douban.com opencv-contrib-python==3.4.2.17

注意第二步要指定版本,安装新版本有风险

二、换一种算法实现角点检测:ORB算法
1.使用ORB算法的原因:
(1)由于我的代码问题使用和第一种方法类似的几种方法都没能解决,花了好几天时间,为了不耽误更多的时间,我只能寻求另外一种算法实现角点检测。

(2)SIFT和SURF提取到的特征也是非常的优秀(有较强的不变性),但是时间消耗依然十分巨大.这就使得系统的实时性不是很好,降低了系统的性能。
在这里插入图片描述

2.对ORB算法的简介:Oriented FAST and Rotated BRIEF,简称ORB,该特征检测算子是在著名的FAST特征检测和BRIEF特征描述子的基础上提出来的,其运行时间远远优于SIFT和SURF,可应用于实时性特征检测。ORB特征检测主要分为两个步骤:

(1)方向FAST特征点检测(FAST只是一种特点检测算法,并不涉及特征点的描述。ORB采用的是FAST算子检测特征点,然后再给检测到的特征点加个特征方向信息,构成oFAST。解决了FAST算子不带有方向的严重缺陷。)

(2)BRIEF特征描述:BRIEF仅仅是特征描述子,所以还需要配合特征点检测算法一起使用,如FAST算法、Harris算法等。
在这里插入图片描述

3.ORB算法的优点:ORB特征检测具有尺度和旋转不变性,对于噪声及其透视变换也具有不变性.

4.如何判断一个点为角点:
要判断这点是否为角点:将这点的灰度值和它邻域内的16个像素点的灰度值进行比较,如果这点的像素值和圆圈上邻域内n个连续的像素点的像素值相减大于阈值t,那么就认为这点是一个角点.(通俗一点的说,就是拿出一个点跟它周围足够多的点比较,如果这个点和周围足够多的点不一样,那么就认为它是一个FAST角点)

5.方向FAST特征点检测的五个步骤:
(1)粗提取。提取大量的特征点,但是有很大一部分的特征点的质量不高。我们判断该点是不是特征点的方法是,以此点为圆心画一个半径为3pixel的圆。圆周上如果有连续n个像素点的灰度值比点的灰度值大或者小,则认为此点为特征点。一般n设置为12。为了加快特征点的提取,快速排出非特征点,首先检测1、9、5、13位置上的灰度值,如果P是特征点,那么这四个位置上有3个或3个以上的的像素值都大于或者小于P点的灰度值。如果不满足,则直接排出此点。

(2)机器学习的方法筛选最优特征点。简单来说就是使用ID3算法训练一个决策树,将特征点圆周上的16个像素输入决策树中,以此来筛选出最优的FAST特征点。

(3)非极大值抑制去除局部较密集特征点。使用非极大值抑制算法去除临近位置多个特征点的问题。为每一个特征点计算出其响应大小。计算方式是特征点P和其周围16个特征点偏差的绝对值和。在比较临近的特征点中,保留响应值较大的特征点,删除其余的特征点。

(4)特征点的尺度不变形。建立金字塔,来实现特征点的多尺度不变性。设置一个比例因子scaleFactor(OpenCV默认为1.2)和金字塔的层数nlevels(OpenCV默认为8)。将原图像按比例因子缩小成nlevels幅图像。缩放后的图像为:I’= I/scaleFactork(k=1,2,…, nlevels)。nlevels幅不同比例的图像提取特征点总和作为这幅图像的oFAST特征点。

(5)特征点的旋转不变性。ORB算法提出使用矩(moment)法来确定FAST特征点的方向。也就是说通过矩来计算特征点以r为半径范围内的质心,特征点坐标到质心形成一个向量作为该特征点的方向。矩定义如下:
在这里插入图片描述
6.在应用到实际的代码实现前先和大家简单理解以下ORB的参数:

cv2.ORB_create(nfeatures = 500,      #最多提取的特征点的数量
               scaleFactor = 1.2,     #金字塔图像之间的尺度参数      
               nlevels = 8,       #金字塔层数
               edgeThreshold = 31,      #边缘阈值,这个值主要是根据后面的patchSize来定的,靠近边缘edgeThreshold以内的像素是不检测特征点的   
               firstLevel = 0,    #第一层的索引值             
               WTA_K = 2,              
               scoreType = HARRIS_SCORE,                 
               patchSize = 31,      #用于计算BIREF描述子的特征点邻域大小
               fastThreshold = 20)
               
#较为详细的解释:

#nfeatures确定要定位的要素(即关键点)的最大数目,此参数应取int整型数据

#scaleFactor:缩放因子,金字塔抽取率,必须大于1。ORB使用图像棱锥体来查找特征,因此必须提供棱锥体中每个层之间的比例因子和棱锥体的层数,此参数应取float浮点型数据

#nlevels: 因子的水平个数,金字塔的层数。最小级别的线性大小等于输入图像的线性大小/pow(scaleFactor,nlevels)此参数应取int浮点型数据 

#edgeThreshold:未检测到特征的边框的大小。由于关键点具有特定的像素大小,因此必须从搜索中排除图像的边缘,edgeThreshold的大小应等于或大于patchSize参数,此参数应取int整型数据 

#firstLevel:此参数允许您确定应将哪个级别视为棱锥体中的第一个级别。当前实现中应为0,通常,具有统一比例的金字塔层被认为是第一层, 此参数应取int整型数据      

#WTA_K:用于生成定向简短描述符的每个元素的随机像素数。可能的值是2、3和4,其中2是默认值。例如,值3表示一次选择三个随机像素来比较它们的亮度。返回最亮像素的索引。因为有3个像素,所以返回的索引将是0、1或2. 
  
#scoreType:此参数可以设置为HARRIS_SCORE或FAST_SCORE。默认的HARRIS_SCORE表示使用HARRIS角点算法对特征进行排序。分数只用来保留最好的特征。FAST_SCORE生成的关键点稍微不太稳定,但计算起来要快一点。 

#patchSize:定向简短描述符使用的修补程序的大小。当然,在较小的金字塔层上,特征覆盖的感知图像区域将更大.此参数应取int整型数据                    

在这里插入图片描述
7.以下是具体的代码实现,我在代码上加上了一些备注和自己的理解,希望对大家的理解有帮助:

import copy       #导入副本以复制训练图像
import cv2
import cv2 as cv
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = [14.0, 7.0]  # 设置figure_size尺寸,图像显示大小(设置默认图形大小)

#读取目标图片并将目标图片转换成灰度图
varese_gray = cv.imread('C:/Users/xiaoyan/opencv-picture/varese_gray.png',cv2.IMREAD_GRAYSCALE)
cv.imshow('varese_gray',varese_gray)

print (varese_gray.shape)#显示目标图片的尺寸
#读取目标彩色图片
varese = cv.imread('C:/Users/xiaoyan/opencv-picture/varese.png')
cv.imshow('varese',varese)

#通过指定要定位的最大关键点数和金字塔抽取率设置ORB算法的参数,这里感觉陌生的朋友可以看上面对ORB参数的描述。
orb = cv2.ORB_create(200, 2.0)

#在灰度训练图像中找到关键点,并计算它们的ORB描述符
keypoints, descriptor = orb.detectAndCompute(varese_gray, None)#None参数表示我们没有使用掩码

#创建训练图像的副本来绘制我们的关键点
keyp_without_size = copy.copy(varese)
keyp_with_size = copy.copy(varese)

#在训练图像的一个副本上绘制不带大小或方向的关键点
cv2.drawKeypoints(varese, keypoints, keyp_without_size, color = (0, 255,0 ))

#在训练图像的另一个副本上绘制具有大小和方向的关键点
cv2.drawKeypoints(varese, keypoints, keyp_with_size,
                  flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

#显示没有关键尺寸或方向的关键点的图像,2
plt.subplot(121)
plt.title('2')
plt.imshow(keyp_without_size)

#显示带有带大小和方向的关键点的图像,1
plt.subplot(122)
plt.title('1')
plt.imshow(keyp_with_size)
plt.show()

#打印检测到的关键点数量
print("\nNumber of keypoints Detected: ", len(keypoints))

在这里插入图片描述
三、以上就是用SIFT算法进行角点检测时遇到Set OPENCV_ENABLE_NONFREE CMake option and rebuild the library in function报错的两种解决方法啦,希望对大家有所帮助哦!
在这里插入图片描述
参考链接:https://www.cnblogs.com/qiuheng/p/9274583.html

发布了10 篇原创文章 · 获赞 13 · 访问量 2624

猜你喜欢

转载自blog.csdn.net/weixin_45870610/article/details/104896233