内容简介:本文是Ray Wenderlich上《ARKit by Tutorials》的读书笔记,主要讲内容概要和读后感ARKit by Tutorials中讲到了图像识别触发AR场景交互的一种特殊方法:利用
本文是Ray Wenderlich上《ARKit by Tutorials》的读书笔记,主要讲内容概要和读后感
ARKit by Tutorials中讲到了图像识别触发AR场景交互的一种特殊方法:利用 Vision Framework 来识别一些物体,然后在上面展示一些图片或动画.
还有利用地理定位和iBeacon触发AR交互的方法.
为什么用Vision
可能你会觉得奇怪:为什么不用ARKit自带的图片检测功能? 只要把参考图片的素材放好,设置好物理尺寸,ARKit就可以检测到图片,在WWDC2018上ARKit 2更是增加了图片追踪功能,效果非常好,识别率高,追踪稳定.
那是因为,ARKit目前自带的图片检测和追踪功能,有几点要求不太好满足:
- 图片不能过于相似;
- 图片的色彩直方图分布要均匀(不能是黑白的);
- 图片不能有大片相同颜色的区域;
- 图片的物理尺寸必须是已知且准确的.
比如下面的图片就不满足要求,虽然也能检测到,但追踪效果会差很多.
更麻烦的是:二维码.
- 虽然不同内容的二维码图片本身并不相同,但是仍然太相似了,尤其是文本很长的时候;
- 二维码一般是黑白的;
- 二维码中有大片相同颜色的区域;
- 二维码的尺寸往往是不同的;
而 Vision 框架可以识别的内容就很多,可以识别矩形,二维码等等.我们可以把它们两个结合起来使用,达到神奇的效果.
识别任意矩形
Vision框架的使用本身并不难,在AR项目中,写个 touchesBegan() 方法,在其中写上:
// 1
guard let currentFrame = sceneView.session.currentFrame else {
return
}
// 2
DispatchQueue.global(qos: .background).async {
// 3
do {
// 4
let request = VNDetectRectanglesRequest {(request, error) in
// Access the first result in the array,
// after converting to an array
// of VNRectangleObservation
// 5
guard
let results = request.results?.compactMap({ $0 as? VNRectangleObservation }),
// 6
let result = results.first else {
print ("[Vision] VNRequest produced no result")
return
}
// 得到识别结果,稍后在这里添加处理代码.
}
let handler = VNImageRequestHandler(cvPixelBuffer: currentFrame.capturedImage)
try handler.perform([request])
} catch(let error) {
print("An error occurred during rectangle detection: \(error)")
}
}
复制代码
可以看到,在上面第6步之后,已经得到了识别出的矩形的结果,继续通过hitTest方法,根据二维的屏幕坐标上矩形的四个角的位置(二维坐标),找到三维空间里矩形的四个角的位置(三维坐标).
// 1
let coordinates: [matrix_float4x4] = [
result.topLeft,
result.topRight,
result.bottomRight,
result.bottomLeft
].compactMap {
// 2
guard let hitFeature = currentFrame.hitTest($0, types: .featurePoint).first else { return nil }
// 3
return hitFeature.worldTransform
}
// 4
guard coordinates.count == 4 else { return }
// 5
DispatchQueue.main.async {
// 6
self.removeBillboard()
let (topLeft, topRight, bottomRight, bottomLeft) = (coordinates[0], coordinates[1],
coordinates[2], coordinates[3])
// 7
self.createBillboard(topLeft: topLeft, topRight: topRight,
bottomRight: bottomRight, bottomLeft: bottomLeft)
}
复制代码
利用hitTest方法得到了四个featurePoint,后创建一个三维的平面Billboard.
三维平面的位置由锚点决定,锚点位置则由4个点的中心点确定:
let anchor = ARAnchor(transform: plane.center) sceneView.session.add(anchor: anchor) 复制代码
同时还可以创建四个SCNBox来标识矩形的四个角,效果如下
坐标系的处理
但这样创建出的平面有个问题,朝向不正确
print(coordinates[0])
结果如下:
simd_float4x4([ [1.0, 0.0, 0.0, 0.0)], [0.0, 1.0, 0.0, 0.0)], [0.0, 0.0, 1.0, 0.0)], [-0.0293431, -0.238044, -0.290515, 1.0)] ]) 复制代码
用这样的4个点去创建平面,过程如下:
func addBillboardNode() -> SCNNode? {
guard let billboard = billboard else { return nil }
// 1 宽和高是从4个点的位置计算出来的
let rectangle = SCNPlane(width: billboard.plane.width,
height: billboard.plane.height)
// 2 无法得到transform信息,不能正确显示方向,而SCNPlane的默认方向是在x-y平面上,也就是垂直于地面(沿y轴方向),与手机的初始化方向平行(x-y平面方向平行)
let rectangleNode = SCNNode(geometry: rectangle)
self.billboard?.billboardNode = rectangleNode
return rectangleNode
}
复制代码
这里就能看出问题:创建平面只利用了4个点的宽高信息,朝向信息没有设置使用了默认方向.
书中给出了一种处理方式:更改ARKit配置项 ARConfiguration 中的 worldAlignment 属性.这个属性有三个值:
- gravity :坐标系的y轴是与重力方向平行的,坐标原点及x-z轴则是设备初始化时的位置和朝向.也就是默认设置项
- gravityAndHeading :y轴与重力方向平行,而x轴指向东,z轴指向南.和现实世界保持一致.
- camera :坐标系始终跟随摄像机(也就是手机)的位置和朝向,伴随移动.
如果我们采用第三种配置,那么创建出的平面是平行于x-y平面的,即平行于手机屏幕的.但是由于正常情况下,识别过程中手机是正对着要识别对象的,所以得到的结果就是几乎是正确的.
configuration.worldAlignment = .camera 复制代码
个人认为:这种做法很扯蛋,根本没有解决问题,只是当用户垂直于矩形进行识别时,效果较好(远远算不上完美)而已.
我认为可以这样解决,欢迎大家讨论:
- 利用4个点,计算所在平面的法线A,法线A的方向就取指向摄像机(手机)方向为正.考虑到4个点可能不共面(毕竟立体几何中3点确定一个平面),可以用排列组合的方式轮流取3个点求法向量,总共求出4个法向量再求平均值做为法线A;(求平面的法向量可以用两条边向量的叉乘)
- 将创建出的平面的法线B对准刚才计算出的法线A.如何对准呢?变换矩阵是什么? 这就是一个数学问题:已知初始法线B,和目标法线A,求变换矩阵;可以借助四元数进行求解,或者直接设置四元数来处理旋转;
- 将创建出的平面SCNNode的矩阵属性设置为求出的变换矩阵就可以了;
// 可以先求出从法线B到法线A的四元数
extension simd_quatf {
/// A quaternion whose action rotates the vector `from` onto the vector `to`.
public init(from: float3, to: float3)
}
// 从四元数中得到变换矩阵或直接使用四元数
extension simd_float4x4 {
/// Construct a 4x4 matrix from `quaternion`.
public init(_ quaternion: simd_quatf)
}
复制代码
Vision能实现的其它功能
除了矩形之外,Vision还能识别出其它物体:
- Horizon :
VNDetectHorizonRequest类可以得到画面的水平角度. - Faces :
VNDetectFaceRectanglesRequest类可以实现人脸识别; - Text :
VNDetectTextRectanglesRequest类可以识别文本和区域; - Rectangle 和 object 追踪:
VNTrackRectangleRequest和VNTrackObjectRequest类可以追踪识别出的物体.
例如,上面的例子想改成识别二维码,并在二维码上显示图片或视频,只需要更改Vision部分的代码就行了:
let request = VNDetectBarcodesRequest { (request, error) in
// Access the first result in the array,
// after converting to an array
// of VNBarcodeObservation
guard let results = request.results?.compactMap({
$0 as? VNBarcodeObservation }),
let result = results.first else {
print ("[Vision] VNRequest produced no result")
return
}
...
}
复制代码
效果如下:
后续还可以在识别出二维码的内容后,在上面展示图片,打开网页或播放视频等
地理定位相关
除了Vision识别来触发场景外,还讲到了利用地理定位和iBeacon来触发AR场景,其实核心代码非常简单,如果你做过地图开发或iBeacon开发的话,就知道其实就是下面几个代理方法:
// MARK: - LocationManagerDelegate
extension AdViewController: LocationManagerDelegate {
// MARK: Location
func locationManager(_ locationManager: LocationManager,
didEnterRegionId regionId: String) {
}
func locationManager(_ locationManager: LocationManager,
didExitRegionId regionId: String) {
}
// MARK: Beacons
func locationManager(_ locationManager: LocationManager,
didRangeBeacon beacon: CLBeacon) {
}
func locationManager(_ locationManager: LocationManager,
didLeaveBeacon beacon: CLBeacon) {
}
}
复制代码
具体业务逻辑没有什么太大的难点,不再赘述了.
需要注意的是,提到了地理定位的测试方法:
- 用 .gpx 文件来做虚拟定位测试;
- 用lightblue等蓝牙软件来模拟iBeacon定位;
第三部分读书笔记结束!
以上所述就是小编给大家介绍的《16-《ARKit by Tutorials》读书笔记3:交互操作》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- MongoDB的聚合操作以及与Python的交互
- RedisPlus 3.1.0 优化操作体验 新增命令交互
- gitsh 0.13 发布,Git 交互操作环境
- 隔空操作有哪些应用场景?(mixlab 人机交互技术)
- C++操作Kafka使用Protobuf进行跨语言数据交互
- 统信桌面 v20 个人版 1030 发布,优化交互操作
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Design Accessible Web Sites
Jeremy Sydik / Pragmatic Bookshelf / 2007-11-05 / USD 34.95
It's not a one-browser web anymore. You need to reach audiences that use cell phones, PDAs, game consoles, or other "alternative" browsers, as well as users with disabilities. Legal requirements for a......一起来看看 《Design Accessible Web Sites》 这本书的介绍吧!