特征点提取
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;
}
通过平面检测,为后续模型的放置等提供了基础。