[ARKit]7-ARKit1.5的圖片識別功能

說明

ARKit系列文章目錄node

ARKit1.5新增功能

  • iOS 11.3 上的視頻分辨率提高至 1080p,其他不變;
  • 新增豎直平面識別ARWorldTrackingConfiguration.PlaneDetection;
  • 新增ARPlaneAnchor中粗略平面估計,見ARPlaneAnchor;
  • 新增ARSession.setWorldOrigin方法能夠從新設置世界座標原點;
  • 新增圖片識別能力,示例代碼見Recognizing Images in an AR Experience
  • ARsession被打斷後,可嘗試恢復追蹤.詳見sessionShouldAttemptRelocalization代理方法;

還有一個加強功能:swift

  • 打了斷點,再恢復後,session的VIO(視覺慣性里程計)也會繼續工做了.原來放置在世界座標系中的虛擬物體仍然是可見的.

圖片識別

這個功能使用起來其實很是簡單,AR功能啓動時設置要識別的圖片,而後在回調方法中處理識別到的錨點就能夠了.數組

// 加載要識別的圖片組
guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else {
    fatalError("Missing expected asset catalog resources.")
}

let configuration = ARWorldTrackingConfiguration()
configuration.detectionImages = referenceImages //設置識別項
session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

複製代碼
// MARK: - ARSCNViewDelegate (Image detection results)
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    // 判斷識別到的錨點類型
    guard let imageAnchor = anchor as? ARImageAnchor else { return }
    let referenceImage = imageAnchor.referenceImage //獲取錨點對應的圖片
    updateQueue.async {
        
       // 建立一個平面來顯示檢測到的圖片(與圖片相同大小)
        let plane = SCNPlane(width: referenceImage.physicalSize.width,
                             height: referenceImage.physicalSize.height)
        let planeNode = SCNNode(geometry: plane)
        planeNode.opacity = 0.25
        
        /* `SCNPlane`在它的本地座標系是豎直的, 但`ARImageAnchor`會假設圖片在自身本地座標系中是水平的,因此要旋轉平面. */
        planeNode.eulerAngles.x = -.pi / 2
        
        /* 圖片錨點在初始化後是再也不被追蹤的,因此建立一個動畫效果以顯示平面出現了. */
        planeNode.runAction(self.imageHighlightAction)
        
        // 添加到場景中
        node.addChildNode(planeNode)
    }
   
}
// 高亮動畫
var imageHighlightAction: SCNAction {
    return .sequence([
        .wait(duration: 0.25),
        .fadeOpacity(to: 0.85, duration: 0.25),
        .fadeOpacity(to: 0.15, duration: 0.25),
        .fadeOpacity(to: 0.85, duration: 0.25),
        .fadeOut(duration: 0.5),
        .removeFromParentNode()
        ])
}
複製代碼

參考圖片referenceImages

參考圖片就是要被識別的圖片,須要放置在Xcode的素材文件夾asset catalog中:session

  1. 打開項目的asset catalog,點擊添加按鈕(+)來添加新的AR資源組;
  2. Finder中拖拽圖片到資源組中;
  3. 須要在檢查器中給每張圖片指定一個物理尺寸,還能夠設定一個描述性的名字(可選);

注意圖片識別的能力: 須要精心挑選,設計,配置圖片來達到更好的可靠性和性能表現:app

  • 圖片的物理尺寸設置應儘量精確.ARKit須要根據這個值來肯定真實世界中的圖片到相機的距離,設置不當會致使ARImageAnchor到相機的距離出錯;
  • 當向Xcode的素材文件夾asset catalog添加圖片時,應注意Xcode提供的圖片質量預估警告.高對比度的圖片在圖片識別中效果最好;
  • 使用平面圖片來檢測.若是要識別的圖片不是平面的,好比是酒瓶上的標籤,那ARKit可能不會識別或者給出錯誤的錨點位置;
  • 考慮你的圖片在不一樣光照下的表現.若是圖片是打印在光滑的紙上或者顯示在屏幕上,這些平面上的反光可能會妨礙識別;

應用最佳實踐

使用識別出的圖片做爲AR場景的參照系.使用識別出的圖片來錨定虛擬場景,而不是再讓用戶選擇場景的擺放位置,或直接粗暴地擺放在用戶的場景中.你甚至可使用多個識別圖片.例如,一個給零售店用的app,能夠經過識別貼在門兩側的海報(門左邊一個海報貼圖,右邊一個)來算出門的位置,從而建立出一個虛擬角色並從門中走出來.async

注意:可使用ARSession setWorldOrigin(relativeTransform:)方法來重設世界座標系,這樣就能夠放置全部錨點和其餘相關內容到你選擇的參考點上.post

設計AR流程,將識別出的圖片做爲虛擬內容的起始點.ARKit不會再追蹤已探測到的圖片的位置和朝向.若是你試圖讓虛擬內容一直緊貼在識別出的圖片上,那麼可能會顯示不正確.應該作的是,使用識別出的圖片做爲參照系,來開始一個動態場景.例如你的app須要識別出科幻電影的海報,而後會有幾個太空船從海報中飛出來,並飛到周圍環境中去.性能

考慮好什麼時候容許圖片檢測以觸發(或重複)AR交互.對於配置session configuration中的detectionImages數組中的每張參考圖片,ARKit都只會添加一個圖片錨點.若是你的AR流程中向一個識別出的圖片添加了虛擬內容,那這個動做默認狀況下只會發生一次.要想再體驗一次這個流程,能夠調用session的remove(anchor:)方法來移除對應的ARImageAnchor.移除該錨點以後,ARKit會在下次識別出圖片後,再添加一個新的錨點. 例如,仍是前面科幻電影海報的例子,當第一次的動畫正在播放時,太空船正從電影海報中飛出來時,你確定不想要再出現一個一樣的.要等到動畫播放完成後再移除錨點,這樣當用戶再對準海報時,就能夠再觸發一次動畫.動畫

ARReferenceImage的建立

除了前面講到的ARReferenceImage.referenceImages(inGroupNamed:bundle:)方法能夠從素材中加載圖片做爲參考圖片外,還有另外兩個建立方法:ui

- (instancetype)initWithCGImage:(CGImageRef)image orientation:(CGImagePropertyOrientation)orientation physicalWidth:(CGFloat)physicalWidth;
- (instancetype)initWithPixelBuffer:(CVPixelBufferRef)pixelBuffer orientation:(CGImagePropertyOrientation)orientation physicalWidth:(CGFloat)physicalWidth;
複製代碼

這兩種方法能夠分別從CGImageRefCVPixelBufferRef中建立參考圖片,這樣就靈活多了.

相關文章
相關標籤/搜索