AR特征点提取与匹配
admin
2023-09-13 11:22:01
0

特征点提取

3维物体的特征点提取我们可以采取ios上集成的空间特征信息扫描工具,是一个XCode工程源码,我们通过将3d物体放入框内,完成对物体特征点的采集,并且存储导出。



但该方法运用起来的问题在于,景区景观体积非常大,很难进行这样的采集。因此我们采用特征点提取算法来解决 ,目前比较流行的算法有SIFT,SURF,ORB这三种,我们综合选择了SURF算法,该算法对于模糊处理方面表现良好,比较适用于本系统。

我们首先应对我们要设置的特殊位置的景点进行特征点提取,核心代码实现如下:

import numpy as np
import cv2 as cv
surf = cv.xfeatures2d.SURF_create(2000)

kp, des = surf.detectAndCompute(img,None)
img1 = cv.drawKeypoints(img,kp,None,(0,0,255),4)
cv.imshow('surf', img1)
cv.waitKey(0)
cv.destroyAllWindows()

将我们预先提取好的这些特征点分类存储到数据库,用于匹配检测。

匹配算法

游客在对准有AR扫描点的景物之后,通过对准拍照上传图像,与数据库中存储的相应特征点进行比对,若匹配成功,就进行相应的操作;如果失败,就提醒游客重新扫描。

匹配算法同样是基于opencv进行的,核心代码示例:

bf = cv2.BFMatcher(cv2.NORM_L2)
matches = bf.knnMatch(des1, des2, k=2)

goodMatch = []
for m, n in matches:
if m.distance < 0.50 * n.distance:
goodMatch.append(m)

goodMatch = np.expand_dims(goodMatch, 1)
# print(goodMatch[:20])

# drawMatchesKnn_cv2(img1_gray, kp1, img2_gray, kp2, goodMatch[:20])
res = cv2.drawMatchesKnn(img1_gray, kp1, img2_gray, kp2, goodMatch[:100], None, flags=2)

cv2.namedWindow('res', cv2.WINDOW_NORMAL)
cv2.resizeWindow('res', 1080, 720)
cv2.imshow('res', res)

使用Hessian算法检测关键点,并且对每个关键点周围的区域计算特征向量

SURF通过计算两个特征点间特征向量的欧氏距离来确定匹配度,欧式距离越短,代表两个特征点的匹配度越好。SURF还加入了Hessian矩阵迹(矩阵特征值的和)的判断

综上,我们实现了特征点的提取与匹配。

数据库存取

我们采用MySQL数据库进行数据的存储,创建基本函数接口如下:

//初始化
def __init__(self)
//创建游标对象
def processData(self, sqlstr, args=())
//保存
def saveData(self,id,encoding_str)
//更新
def updateData(self, id, encoding_str)
//执行语句
def execute_float_sqlstr(self, sqlstr)

接下来是对特征点保存到数据库的过程:

//编码,将特征点转化为字符串
def encoding_Str
//读入文件路径
def load_file(self,filepath)
//添加到数据库
def add_img(self,image_name, id)

平面检测

arkit平面检测主要通过

ARPlaneDetectionHorizontal 检测水平面

ARPlaneDetectionVertical 检测垂直面,实现

当检测到平面后,需要用到unity结合arkit中一个重要的类UnityARSessionNativeInterface,该类起到一个桥接的作用

首先可以接受arkit检测到的特征点:

public void Start()
{
UnityARSessionNativeInterface.ARFrameUpdatedEvent + = ARFrameUpdated;
}
public void ARFrameUpdated(UnityAR Camera camera)
{
Vecter3 [] pointCloud = camera.pointCloudData;
}

另外可以接受检测到的平面信息

public void Start()
{
UnityARSessionNativeInterface.ARAnchorAddedEvent + = AddAnchor;
UnityARSessionNativeInterface.ARAnchorUpdatedEvent + = UpdateAnchor;
UnityARSessionNativeInterface.ARAnchorRemovedEvent + = RemoveAnchor;
}

通过平面检测,为后续模型的放置等提供了基础。

相关内容