ARKit功能demo

  1. ARKit點擊屏幕增加文字
  2. ARKit點擊屏幕增加3D模型
  3. ARKit檢測到平面自動增加3D模型
  4. QuickLook的最簡單使用
  5. ARKit人臉貼圖
  6. ARKit微笑檢測
  7. ARKit皺眉檢測
  8. ARKit人臉參數BlendShapes詳解
  9. demo

1. ARKit點擊屏幕增加文字

1.點擊屏幕增加文字.gif
  • command+shift+n新建一個項目氯哮,然后選擇Augmented Reality App

  • 在Content Technology中選擇SpriteKit即可

  • 控制文字距離相機的距離(改變這個Z感受一下變化)

matrix_float4x4 translation = matrix_identity_float4x4;
translation.columns[3].z = -1;

2. ARKit點擊屏幕增加3D模型

2.點擊屏幕增加3D模型.gif

2.1 畫面捕捉

主要就是三個類:

  • ARSCNView: 畫面顯示
  • ARConfiguration: 捕捉畫面
    • ARWorldTrackingConfiguration:后置攝像頭
    • ARFaceTrackingConfiguration:前置攝像頭,會實時監(jiān)測面部表情特征
  • ARSession:數據中轉

viewDidLoad的時候初始化資源

self.arSCNView = [[ARSCNView alloc] initWithFrame:self.view.bounds options:nil];
    self.arSCNView.session = [[ARSession alloc] init];
    // 1. 創(chuàng)建世界追蹤配置焰雕,需要支持A9芯片也就是iPhone6S以上
    self.arWordTrackingConfiguration = [[ARWorldTrackingConfiguration alloc] init];
    // 2. 設置追蹤方向,追蹤平面
    self.arWordTrackingConfiguration.planeDetection = ARPlaneDetectionHorizontal;
    self.arWordTrackingConfiguration.lightEstimationEnabled = YES;

viewDidAppear時讓session開始工作

[self.arSession runWithConfiguration:self.arWordTrackingConfiguration]

2.2 點擊增加3D圖像

當點擊屏幕的時候加載一個scn文件并且作為childNode添加到self.arSCNView.scene.rootNode

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 1. 使用場景加載scn文件
    SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/ship.scn"];
    
    SCNNode *shipNode = scene.rootNode.childNodes.firstObject;
    shipNode.position = SCNVector3Make(0, -1, -1);
    
    [self.arSCNView.scene.rootNode addChildNode:shipNode];
}

3. ARKit檢測到平面自動增加3D模型

3.檢測到平面增加3D模型.gif

前期準備工作和2.1一樣,只是增加了self.arSCNView.delegate = self
然后在代理方法renderer:didAddNode:forAnchor:中實現(xiàn)以下代碼:

#pragma mark - ARSCNViewDelegate
// 添加節(jié)點的時候調用(當開啟平地捕捉模式之后,如果捕捉到平地葱蝗,ARKit會自動添加一個平地節(jié)點)
- (void)renderer:(id<SCNSceneRenderer>)renderer didAddNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {
    
    if (![anchor isMemberOfClass:[ARPlaneAnchor class]]) return;
    
    // 添加一個3D平面模型,ARKit只有捕捉能力前弯,錨點只是一個空間位置有勾,想更加清楚看到這個空間,我們需要給控件添加一個平地的3D模型來渲染它
    // 1. 獲取捕捉到的平地錨點
    ARPlaneAnchor *planeAnchor = (ARPlaneAnchor *)anchor;
    // 2. 創(chuàng)建一個3D模型(系統(tǒng)捕捉到的平地是一個不規(guī)則的大小長方形林说,這里筆者q將其變成一個長方形煎殷,并且對平地做了一個縮放效果)
    // 參數分別是長、寬腿箩、高豪直、圓角
    SCNBox *planeBox = [SCNBox boxWithWidth:planeAnchor.extent.x * 0.3 height:0 length:planeAnchor.extent.x * 0.3 chamferRadius:0];
    // 3. 使用Material渲染3D模型(默認模型是白色的)
    planeBox.firstMaterial.diffuse.contents = [UIColor clearColor];
    // 4. 創(chuàng)建一個基于3D物體模型的節(jié)點
    SCNNode *planeNode = [SCNNode nodeWithGeometry:planeBox];
    // 5. 設置節(jié)點的位置為捕捉到的平地的錨點的中心位置
    // SceneKit中節(jié)點的位置position是一個基于3D坐標系的矢量坐標SCNVector3Make
    planeNode.position = SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z);
    
    [node addChildNode:planeNode];
    
    // 6. 創(chuàng)建一個花瓶場景
    SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/vase/vase.scn"];
    // 7. 獲取花瓶節(jié)點
    // 一個場景有多個節(jié)點,所有場景有且只有一個根節(jié)點珠移,其它所有節(jié)點都是根節(jié)點的子節(jié)點
    SCNNode *vaseNode = scene.rootNode.childNodes.firstObject;
    // 8. 設置花瓶節(jié)點的位置為捕捉到的平地的位置弓乙,如果不設置末融,則默認為原點位置也就是相機位置
    vaseNode.position = SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z);
    // 9. 將花瓶節(jié)點添加到屏幕中
    // !!!!FBI WARNING: 花瓶節(jié)點是添加到代理捕捉到的節(jié)點中,而不是AR視圖的根接節(jié)點暇韧。
    // 因為捕捉到的平地錨點是一個本地坐標系勾习,而不是世界坐標系
    [node addChildNode:vaseNode];
}

4. QuickLook的最簡單使用

4.QuickLook簡單使用.gif

這個沒什么好說的蛤肌,直接上代碼

#import "ViewController.h"
#import <QuickLook/QuickLook.h>
#import "WYPreviewItem.h"

@interface ViewController ()<QLPreviewControllerDataSource, QLPreviewControllerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    QLPreviewController *preVC = [[QLPreviewController alloc] init];
    preVC.dataSource = self;
    preVC.delegate = self;
    
    [self presentViewController:preVC animated:YES completion:nil];
}

#pragma mark - QLPreviewControllerDataSource && QLPreviewControllerDelegate
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
    return 1;
}

- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
    
    return [[NSBundle mainBundle] URLForResource:@"plantpot.usdz" withExtension:nil];
}

- (UIImage *)previewController:(QLPreviewController *)controller transitionImageForPreviewItem:(id<QLPreviewItem>)item contentRect:(CGRect *)contentRect {
    
    CGRect rect = CGRectMake(100, 200, 300, 300);
    contentRect = &rect;
    
    return [UIImage imageNamed:@"wy.jpeg"];
}

5. ARKit人臉貼圖

5.人臉貼圖.gif

設置session的configuration為ARFaceTrackingConfiguration,然后在ARSCNView的代理renderer:willUpdateNode:forAnchor中增加一個SCNNode核心代碼如下:

  • 創(chuàng)建SCNNode
    • 試試看設置fillMesh為YES會怎么樣
    • 試試看設置masterial.diffuse.contents為一個顏色會怎么樣
- (SCNNode *)textureMaskNode {
    if (!_textureMaskNode) {
        
        id<MTLDevice> device = self.arSCNView.device;
        ARSCNFaceGeometry *geometry = [ARSCNFaceGeometry faceGeometryWithDevice:device fillMesh:NO];
        SCNMaterial *material = geometry.firstMaterial;
        material.fillMode = SCNFillModeFill;
        material.diffuse.contents = [UIImage imageNamed:@"wy.jpg"];
        _textureMaskNode = [SCNNode nodeWithGeometry:geometry];
    }
    _textureMaskNode.name = @"textureMask";
    return _textureMaskNode;
}
  • 添加SCNNode并更新人臉特征
- (void)renderer:(id<SCNSceneRenderer>)renderer willUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {
    
    if (!anchor || ![anchor isKindOfClass:[ARFaceAnchor class]]) return;
    ARFaceAnchor *faceAnchor = (ARFaceAnchor *)anchor;
    
    if (!_textureMaskNode) {
        [node addChildNode:self.textureMaskNode];
    }
    
    ARSCNFaceGeometry *faceGeometry = (ARSCNFaceGeometry *)self.textureMaskNode.geometry;
    if (faceGeometry && [faceGeometry isKindOfClass:[ARSCNFaceGeometry class]]) {
        [faceGeometry updateFromFaceGeometry:faceAnchor.geometry];
    }
}

6. ARKit微笑檢測

6.微笑檢測.gif

主要用到了ARBlendShapeLocationMouthSmileLeftARBlendShapeLocationMouthSmileRight表示微笑的鍵值
我提供的demo是用于調試微笑閥值的
核心代碼:

- (void)renderer:(id<SCNSceneRenderer>)renderer didUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {
    
    if (!anchor || ![anchor isKindOfClass:[ARFaceAnchor class]]) return;
    
    ARFaceAnchor *faceAnchor = (ARFaceAnchor *)anchor;
    
    NSDictionary *blendShips = faceAnchor.blendShapes;
    CGFloat leftSmile = [blendShips[ARBlendShapeLocationMouthSmileLeft] floatValue];
    CGFloat rightSmile = [blendShips[ARBlendShapeLocationMouthSmileRight] floatValue];
    
    NSLog(@"leftSmile = %f, rightSmile = %f", leftSmile, rightSmile);
    if (leftSmile > self.smileValue && rightSmile > self.smileValue) {
        NSLog(@"檢測到笑容");
        [self.arSession pause];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.resultLabel.hidden = NO;
        });
    }
}

7. ARKit皺眉檢測

7.皺眉檢測.gif

我這里用的是眉毛向上的鍵值ARBlendShapeLocationBrowInnerUp
核心代碼:

- (void)renderer:(id<SCNSceneRenderer>)renderer didUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {
    
    if (!anchor && ![anchor isKindOfClass:[ARFaceAnchor class]]) return;
    
    ARFaceAnchor *faceAnchor = (ARFaceAnchor *)anchor;
    NSDictionary *blendShapes = faceAnchor.blendShapes;
    NSNumber *browInnerUp = blendShapes[ARBlendShapeLocationBrowInnerUp];
    
    if ([browInnerUp floatValue] > self.browValue) {
        [self.arSession pause];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.resultLabel.hidden = NO;
        });
    }
    
    NSLog(@"browInnerUp = %@", browInnerUp);
}

8. BlendShapes

  • 僅在iOS11及以上可用蹄咖,每個參數的詳細介紹和圖片對比可以打開Xcode->Window->Developer Documentation,然后搜索對應的鍵值即可
  • 每個建對應的值都是0~1的值
  • 共51個表示人臉特征的參數


屬性 說明 備注
ARBlendShapeLocationBrowDownLeft 左眉毛外部向下
ARBlendShapeLocationBrowDownRight 右眉毛外部向下
ARBlendShapeLocationBrowInnerUp 兩眉毛內部向上
ARBlendShapeLocationBrowOuterUpLeft 左眉毛外部向上
ARBlendShapeLocationBrowOuterUpRight 右眉毛外部向上
ARBlendShapeLocationCheekPuff 兩個臉頰向外
ARBlendShapeLocationCheekSquintLeft 左眼向下斜視
ARBlendShapeLocationCheekSquintRight 右眼向下斜視
ARBlendShapeLocationEyeBlinkLeft 眨左眼
ARBlendShapeLocationEyeBlinkRight 眨右眼
ARBlendShapeLocationEyeLookDownLeft 左眼瞼運動的系數與向下凝視一致
ARBlendShapeLocationEyeLookDownRight 右眼瞼運動的系數與向下凝視一致
ARBlendShapeLocationEyeLookInLeft 左眼瞼運動的系數與向右凝視一致。
ARBlendShapeLocationEyeLookInRight 右眼瞼運動的系數與向左凝視一致霜威。
ARBlendShapeLocationEyeLookOutLeft 左眼瞼運動的系數與向左凝視一致
ARBlendShapeLocationEyeLookOutRight 右眼瞼運動的系數與向右凝視一致
ARBlendShapeLocationEyeSquintLeft 左眼臉部收縮
ARBlendShapeLocationEyeSquintRight 右眼臉部收縮
ARBlendShapeLocationEyeWideLeft 左眼周圍眼瞼變寬
ARBlendShapeLocationEyeWideRight 右眼周圍眼瞼變寬
ARBlendShapeLocationJawForward 下頜向前運動
ARBlendShapeLocationJawLeft 下頜向左運動
ARBlendShapeLocationJawOpen 下頜開口
ARBlendShapeLocationJawRight 下頜向右運動
ARBlendShapeLocationMouthClose 嘴唇閉合的系數與頜位置無關
ARBlendShapeLocationMouthDimpleLeft 嘴左角后移
ARBlendShapeLocationMouthDimpleRight 嘴右角后移
ARBlendShapeLocationMouthFrownLeft 嘴左角向下運動
ARBlendShapeLocationMouthFrownRight 嘴右角向下運動
ARBlendShapeLocationMouthFunnel 兩個嘴唇收縮成開放形狀
ARBlendShapeLocationMouthLeft 兩個嘴唇向左移動
ARBlendShapeLocationMouthLowerDownLeft 左側下唇向下運動
ARBlendShapeLocationMouthLowerDownRight 又側下唇向下運動
ARBlendShapeLocationMouthPressLeft 左側下唇向上壓縮
ARBlendShapeLocationMouthPressRight 右側下唇向上壓縮
ARBlendShapeLocationMouthPucker 兩個閉合嘴唇的收縮和壓縮
ARBlendShapeLocationMouthRight 兩個嘴唇向右運動
ARBlendShapeLocationMouthRollLower 下唇向嘴內側移動
ARBlendShapeLocationMouthRollUpper 上唇向嘴內側移動
ARBlendShapeLocationMouthShrugLower 下唇向外運動
ARBlendShapeLocationMouthShrugUpper 上唇向外運動
ARBlendShapeLocationMouthSmileLeft 嘴左角向上運動
ARBlendShapeLocationMouthSmileRight 嘴右角向上運動
ARBlendShapeLocationMouthStretchLeft 嘴左角向左移動
ARBlendShapeLocationMouthStretchRight 嘴左角向右移動
ARBlendShapeLocationMouthUpperUpLeft 左側上唇向上運動
ARBlendShapeLocationMouthUpperUpRight 右側上唇向上運動
ARBlendShapeLocationNoseSneerLeft 左鼻孔抬高
ARBlendShapeLocationNoseSneerRight 右鼻孔抬高
ARBlendShapeLocationTongueOut 舌頭延伸
ARBlendShapeLocationMouthClose
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末酪刀,一起剝皮案震驚了整個濱河市粹舵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌骂倘,老刑警劉巖眼滤,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異历涝,居然都是意外死亡诅需,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門荧库,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堰塌,“玉大人,你說我怎么就攤上這事分衫〕⌒蹋” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵蚪战,是天一觀的道長牵现。 經常有香客問我,道長邀桑,這世上最難降的妖魔是什么瞎疼? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮壁畸,結果婚禮上贼急,老公的妹妹穿的比我還像新娘。我一直安慰自己捏萍,他們只是感情好太抓,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著令杈,像睡著了一般腻异。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上这揣,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天悔常,我揣著相機與錄音影斑,去河邊找鬼。 笑死机打,一個胖子當著我的面吹牛矫户,可吹牛的內容都是我干的。 我是一名探鬼主播残邀,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼皆辽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了芥挣?” 一聲冷哼從身側響起驱闷,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎空免,沒想到半個月后空另,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡蹋砚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年扼菠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坝咐。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡循榆,死狀恐怖,靈堂內的尸體忽然破棺而出墨坚,到底是詐尸還是另有隱情秧饮,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布泽篮,位于F島的核電站盗尸,受9級特大地震影響,放射性物質發(fā)生泄漏咪辱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一椎组、第九天 我趴在偏房一處隱蔽的房頂上張望油狂。 院中可真熱鬧,春花似錦寸癌、人聲如沸专筷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽磷蛹。三九已至,卻和暖如春溪烤,著一層夾襖步出監(jiān)牢的瞬間味咳,已是汗流浹背庇勃。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留槽驶,地道東北人责嚷。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像掂铐,于是被迫代替她去往敵國和親罕拂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內容

  • 引言ARKit 為開發(fā) iPhone 和 iPad 增強現(xiàn)實(AR)app 提供了一個前沿平臺全陨。本文為你介紹 AR...
    螞蟻安然閱讀 9,309評論 0 14
  • ARKit ARKit框架通過集成iOS設備攝像頭和運動功能爆班,在您的應用程序或游戲中產生增強現(xiàn)實體驗。 概述 增強...
    暗夜夜夜行路閱讀 5,807評論 0 17
  • 今天周三辱姨,而且是單周柿菩,意味著今天沒有課程安排,5小只開心的奔赴彭老師家炮叶,雖然旅途是遙遠而暈眩的碗旅,但是下車的一刻大家...
    一只亂寫亂畫的喵閱讀 611評論 0 0
  • 在一個地方住的久了,那里的每一棵樹镜悉,每一個人都仿佛成為生命中的一部分祟辟。 好像活在這個世上,就是為了每天看著那棵樹上...
    郭清平閱讀 283評論 0 3
  • 去年寒假侣肄,我第一次嘗試為笑儒報名參加冬令營旧困。 當時有兩條線路可以選擇,一條是國內線去紹興稼锅、杭州吼具,另一條是國外線去韓...
    午后紅茶_雙子座閱讀 256評論 0 0