iOS開發(fā) - Vision 圖像識(shí)別框架的使用

北京時(shí)間2017.6.6日凌晨1點(diǎn),新一屆的WWDC召開蛉艾,蘋果在大會(huì)上發(fā)布了iOS11的beta版含末,伴隨著iOS 11的發(fā)布,也隨之推出了一些新的API绍昂,如:ARKit 、Core ML偿荷、FileProvider窘游、IdentityLookup 、Core NFC跳纳、Vison 等忍饰。

本篇文章主要簡(jiǎn)單介紹下其中的 Vision API 的使用(Vision更強(qiáng)大的地方是可以結(jié)合Core ML模型實(shí)現(xiàn)更強(qiáng)大的功能,本篇文章就不詳細(xì)展開了)

Vison 與 Core ML 的關(guān)系

  • Vision 是 Apple 在 WWDC 2017 推出的圖像識(shí)別框架寺庄。

  • Core ML 是 Apple 在 WWDC 2017 推出的機(jī)器學(xué)習(xí)框架艾蓝。

Core ML


根據(jù)這張圖就可以看出,Core ML的作用就是將一個(gè)Core ML模型斗塘,轉(zhuǎn)換成我們的App工程可以直接使用的對(duì)象,就是可以看做是一個(gè)模型的轉(zhuǎn)換器赢织。

Vision在這里的角色,就是相當(dāng)于一個(gè)用于識(shí)別Core ML模型的一個(gè)角色.

Vision

screenshot.png
  • 根據(jù)官方文檔看逛拱,Vision 本身就有Face Detection and Recognition(人臉檢測(cè)識(shí)別)敌厘、Machine Learning Image Analysis(機(jī)器學(xué)習(xí)圖片分析)、Barcode Detection(條形碼檢測(cè))朽合、Text Detection(文本檢測(cè))俱两。。曹步。宪彩。。等等這些功能讲婚。

  • 所以可以這樣理解:
    Vision庫里本身就已經(jīng)自帶了很多訓(xùn)練好的Core ML模型尿孔,這些模型是針對(duì)上面提到的人臉識(shí)別、條形碼檢測(cè)等等功能筹麸,如果你要實(shí)現(xiàn)的功能剛好是Vision庫本身就能實(shí)現(xiàn)的活合,那么你直接使用Vision庫自帶的一些類和方法就行,但是如果想要更強(qiáng)大的功能物赶,那么還是需要結(jié)合其它Core ML模型白指。

Vision 與 Core ML 總結(jié)

  • Core ML可以看做一個(gè)模型的轉(zhuǎn)換器,可以將一個(gè) ML Model 格式的模型文件自動(dòng)生成一些類和方法酵紫,可以直接使用這些類去做分析告嘲,讓我們更簡(jiǎn)單的在app中使用訓(xùn)練好的模型错维。

  • Vision本身就是能對(duì)圖片做分析,他自帶了針對(duì)很多檢測(cè)的功能橄唬,相當(dāng)于內(nèi)置了一些Model赋焕,另外Vision也能使用一個(gè)你設(shè)置好的其它的Core ML Model來對(duì)圖進(jìn)行分析。

  • Vision就是建立在Core ML層之上的仰楚,使用Vision其實(shí)還是用到了Core ML隆判,只是沒有顯式地直接寫Core ML的代碼而已。

Vison 的應(yīng)用場(chǎng)景

  • 圖像配準(zhǔn)

  • 矩形檢測(cè)


  • 二維碼/條形碼檢測(cè)


  • 目標(biāo)跟蹤:臉部僧界,矩形和通用模板


  • 文字檢測(cè):監(jiān)測(cè)文字外框蜜氨,和文字識(shí)別


  • 人臉檢測(cè):支持檢測(cè)笑臉、側(cè)臉捎泻、局部遮擋臉部飒炎、戴眼鏡和帽子等場(chǎng)景,可以標(biāo)記出人臉的矩形區(qū)域


  • 人臉特征點(diǎn):可以標(biāo)記出人臉和眼睛笆豁、眉毛郎汪、鼻子、嘴闯狱、牙齒的輪廓煞赢,以及人臉的中軸線


Vison 的設(shè)計(jì)理念

蘋果最擅長(zhǎng)的,把復(fù)雜的事情簡(jiǎn)單化哄孤,Vision的設(shè)計(jì)理念也正是如此照筑。
對(duì)于使用者我們抽象的來說,我們只需要:提出問題-->經(jīng)過機(jī)器-->得到結(jié)果瘦陈。

開發(fā)者不需要是計(jì)算機(jī)視覺專家凝危,開發(fā)者只需要得到結(jié)果即可,一切復(fù)雜的事情交給Vision晨逝。


Vison 的性能對(duì)比

Vision 與 iOS 上其他幾種帶人臉檢測(cè)功能框架的對(duì)比:



根據(jù)官方提供的資料可以看出來蛾默,Vision 和 Core Image、AV Capture 在精確度捉貌,耗時(shí)支鸡,耗電量來看基本都是Best、Fast趁窃、Good牧挣。

Vision 支持的圖片類型

Vision 支持多種圖片類型,如:

  • CIImage

  • NSURL

  • NSData

  • CGImageRef

  • CVPixelBufferRef

Vison 的使用 與結(jié)構(gòu)圖

Vision使用中的角色有:
Request醒陆,RequestHandler瀑构,results和results中的Observation數(shù)組。

Request類型:
有很多種统求,比如圖中列出的 人臉識(shí)別检碗、特征識(shí)別、文本識(shí)別码邻、二維碼識(shí)別等折剃。

結(jié)果圖

screenshot.png

使用概述:
我們?cè)谑褂眠^程中是給各種功能的 Request 提供給一個(gè) RequestHandler,Handler 持有需要識(shí)別的圖片信息像屋,并將處理結(jié)果分發(fā)給每個(gè) Request 的 completion Block 中怕犁。可以從 results 屬性中得到 Observation 數(shù)組己莺。

observations數(shù)組中的內(nèi)容根據(jù)不同的request請(qǐng)求返回了不同的observation奏甫,如:VNFaceObservation、VNTextObservation凌受、VNBarcodeObservation阵子、VNHorizonObservation,不同的Observation都繼承于VNDetectedObjectObservation胜蛉,而VNDetectedObjectObservation則是繼承于VNObservation挠进。每種Observation有boundingBox,landmarks等屬性誊册,存儲(chǔ)的是識(shí)別后物體的坐標(biāo)领突,點(diǎn)位等,我們拿到坐標(biāo)后案怯,就可以進(jìn)行一些UI繪制君旦。

具體人臉識(shí)別使用示例:

1,創(chuàng)建處理圖片處理對(duì)應(yīng)的RequestHandler對(duì)象嘲碱。

    // 轉(zhuǎn)換CIImage
    CIImage *convertImage = [[CIImage alloc]initWithImage:image];
    
    // 創(chuàng)建處理requestHandler
    VNImageRequestHandler *detectRequestHandler = [[VNImageRequestHandler alloc]initWithCIImage:convertImage options:@{}];

2金砍, 創(chuàng)建回調(diào)Handler。(用于識(shí)別成功后進(jìn)行回調(diào)執(zhí)行的一個(gè)Block)

    // 設(shè)置回調(diào)
    CompletionHandler completionHandler = ^(VNRequest *request, NSError * _Nullable error) {
        NSArray *observations = request.results;
    };

3麦锯, 創(chuàng)建對(duì)應(yīng)的識(shí)別 Request 請(qǐng)求捞魁,指定 Complete Handler

    VNImageBasedRequest *detectRequest = [[VNDetectFaceRectanglesRequest alloc]initWithCompletionHandler: completionHandler];

4,發(fā)送識(shí)別請(qǐng)求离咐,并在回調(diào)中處理回調(diào)接受的數(shù)據(jù)

  [detectRequestHandler performRequests:@[detectRequest] error:nil];

代碼整合:

總的來說一共經(jīng)過這幾步之后基本的人臉識(shí)別就實(shí)現(xiàn)了谱俭。

    // 轉(zhuǎn)換CIImage
    CIImage *convertImage = [[CIImage alloc]initWithImage:image];
    
    // 創(chuàng)建處理requestHandler
    VNImageRequestHandler *detectRequestHandler = [[VNImageRequestHandler alloc]initWithCIImage:convertImage options:@{}];
    
    // 設(shè)置回調(diào)
    CompletionHandler completionHandler = ^(VNRequest *request, NSError * _Nullable error) {
        NSArray *observations = request.results;
        [self handleImageWithType:type image:image observations:observations complete:complete];
    };
    
    // 創(chuàng)建BaseRequest
    VNImageBasedRequest *detectRequest = [[VNDetectFaceRectanglesRequest alloc]initWithCompletionHandler:completionHandler];
    
    // 發(fā)送識(shí)別請(qǐng)求
    [detectRequestHandler performRequests:@[detectRequest] error:nil];
    

VNFaceObservation 介紹:

VNFaceObservation里面,我們能拿到的有用信息就是boundingBox宵蛀。

/// 處理人臉識(shí)別回調(diào)
+ (void)faceRectangles:(NSArray *)observations image:(UIImage *_Nullable)image complete:(detectImageHandler _Nullable )complete{
    
    NSMutableArray *tempArray = @[].mutableCopy;
    
    for (VNFaceObservation *observation  in observations) {
        CGRect faceRect = [self convertRect:observation.boundingBox imageSize:image.size];
    }
    

boundingBox直接是CGRect類型昆著,但是boundingBox返回的是x,y,w,h的比例,需要進(jìn)行轉(zhuǎn)換术陶。

/// 轉(zhuǎn)換Rect
+ (CGRect)convertRect:(CGRect)oldRect imageSize:(CGSize)imageSize{
    
    CGFloat w = oldRect.size.width * imageSize.width;
    CGFloat h = oldRect.size.height * imageSize.height;
    CGFloat x = oldRect.origin.x * imageSize.width;
    CGFloat y = imageSize.height - (oldRect.origin.y * imageSize.height) - h;
    return CGRectMake(x, y, w, h);
}

關(guān)于Y值為何不是直接oldRect.origin.y * imageSize.height出來凑懂,是因?yàn)檫@個(gè)時(shí)候直接算出來的臉部是MAX Y值而不是min Y值,所以需要進(jìn)行轉(zhuǎn)換一下梧宫。


特征識(shí)別介紹:

VNDetectFaceLandmarksRequest 特征識(shí)別請(qǐng)求返回的也是VNFaceObservation接谨,但是這個(gè)時(shí)候VNFaceObservation 對(duì)象的 landmarks 屬性就會(huì)有值摆碉,這個(gè)屬性里面存儲(chǔ)了人物面部特征的點(diǎn)。
如:

// 臉部輪廊
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nonnull faceContour;

// 左眼脓豪,右眼
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable leftEye;
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable rightEye;

// 鼻子巷帝,鼻嵴
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable nose;
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable noseCrest;
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable medianLine;

// 外唇,內(nèi)唇
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable outerLips;
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable innerLips;

// 左眉毛扫夜,右眉毛
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable leftEyebrow;
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable rightEyebrow;

// 左瞳,右瞳
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable leftPupil;
@property (nonatomic, strong) VNFaceLandmarkRegion2D * _Nullable rightPupil;

每個(gè)特征對(duì)象里面都有一個(gè)pointCount屬性楞泼,通過特征對(duì)象的normalizedPoints方法,可以取出來特征里面的每一個(gè)點(diǎn)笤闯,我們拿到點(diǎn)進(jìn)行轉(zhuǎn)換后堕阔,相應(yīng)的UI繪制或其他操作。
例如:


    UIImage *sourceImage = image;
    
    // 遍歷所有特征
    for (VNFaceLandmarkRegion2D *landmarks2D in pointArray) {
        
        CGPoint points[landmarks2D.pointCount];
        // 轉(zhuǎn)換特征的所有點(diǎn)
        for (int i=0; i<landmarks2D.pointCount; i++) {
           CGPoint point = landmarks2D.normalizedPoints[i];
            CGFloat rectWidth  = sourceImage.size.width * observation.boundingBox.size.width;
            CGFloat rectHeight = sourceImage.size.height * observation.boundingBox.size.height;
            CGPoint p = CGPointMake(point.x * rectWidth + observation.boundingBox.origin.x * sourceImage.size.width, observation.boundingBox.origin.y * sourceImage.size.height + point.y * rectHeight);
            points[i]  = p;
        }
        
        UIGraphicsBeginImageContextWithOptions(sourceImage.size, false, 1);
        CGContextRef context = UIGraphicsGetCurrentContext();
        [[UIColor greenColor] set];
        CGContextSetLineWidth(context, 2);
        
        // 設(shè)置翻轉(zhuǎn)
        CGContextTranslateCTM(context, 0, sourceImage.size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        
        // 設(shè)置線類型
        CGContextSetLineJoin(context, kCGLineJoinRound);
        CGContextSetLineCap(context, kCGLineCapRound);
        
        // 設(shè)置抗鋸齒
        CGContextSetShouldAntialias(context, true);
        CGContextSetAllowsAntialiasing(context, true);
        
        // 繪制
        CGRect rect = CGRectMake(0, 0, sourceImage.size.width, sourceImage.size.height);
        CGContextDrawImage(context, rect, sourceImage.CGImage);
        CGContextAddLines(context, points, landmarks2D.pointCount);
        CGContextDrawPath(context, kCGPathStroke);
        
        // 結(jié)束繪制
        sourceImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }

Vision Demo演示:

以上是簡(jiǎn)單列舉了一些代碼颗味,具體更詳細(xì)的可參考官方文檔或Demo代碼(后面有Demo 下載鏈接)
下面GIF演示一下Vision Demo 超陆,此Demo比較簡(jiǎn)單,演示了基本的一些Vision的使用

圖像識(shí)別:

人臉識(shí)別浦马、特征識(shí)別侥猬、文字識(shí)別

動(dòng)態(tài)識(shí)別:

動(dòng)態(tài)監(jiān)測(cè)人臉,動(dòng)態(tài)進(jìn)行添加

55k2.gif

Demo下載地址

https://github.com/bigsen/Vision_Demo
https://github.com/bigsen/Vision_Track

https://github.com/NilStack/HelloVision
https://github.com/jeffreybergier/Blog-Getting-Started-with-Vision

參考資料:

http://www.reibang.com/p/174b7b67acc9
http://www.reibang.com/p/e371099f12bd
https://github.com/NilStack/HelloVision
https://developer.apple.com/documentation/vision
https://github.com/jeffreybergier/Blog-Getting-Started-with-Vision
https://tech.iheart.com/iheart-wwdc-familiar-faces-1093fe751d9e
http://yulingtianxia.com/blog/2017/06/19/Core-ML-and-Vision-Framework-on-iOS-11/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末捐韩,一起剝皮案震驚了整個(gè)濱河市退唠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荤胁,老刑警劉巖瞧预,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異仅政,居然都是意外死亡垢油,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門圆丹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滩愁,“玉大人,你說我怎么就攤上這事辫封∠跬鳎” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵倦微,是天一觀的道長(zhǎng)妻味。 經(jīng)常有香客問我,道長(zhǎng)欣福,這世上最難降的妖魔是什么责球? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上雏逾,老公的妹妹穿的比我還像新娘嘉裤。我一直安慰自己,他們只是感情好栖博,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布屑宠。 她就那樣靜靜地躺著,像睡著了一般笛匙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上犀变,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天妹孙,我揣著相機(jī)與錄音,去河邊找鬼获枝。 笑死蠢正,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的省店。 我是一名探鬼主播嚣崭,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼懦傍!你這毒婦竟也來了雹舀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤粗俱,失蹤者是張志新(化名)和其女友劉穎说榆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寸认,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡签财,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了偏塞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唱蒸。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖灸叼,靈堂內(nèi)的尸體忽然破棺而出神汹,到底是詐尸還是另有隱情,我是刑警寧澤古今,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布慎冤,位于F島的核電站,受9級(jí)特大地震影響沧卢,放射性物質(zhì)發(fā)生泄漏蚁堤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望披诗。 院中可真熱鬧撬即,春花似錦、人聲如沸呈队。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宪摧。三九已至粒竖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間几于,已是汗流浹背蕊苗。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沿彭,地道東北人朽砰。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像喉刘,于是被迫代替她去往敵國(guó)和親瞧柔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 學(xué)習(xí)需要持之以恒睦裳,不做記錄的學(xué)習(xí)就和不以結(jié)婚為目的去談戀愛一樣造锅。 感覺自己學(xué)習(xí)的路途就是一路在耍流氓,沒有做筆記的...
    Synemin閱讀 6,630評(píng)論 0 5
  • 本篇文章十分的長(zhǎng)廉邑,大概有2萬7千字左右备绽。 一、發(fā)展史 1鬓催、人臉識(shí)別的理解: 人臉識(shí)別(Face Recogniti...
    放飛人夜閱讀 19,988評(píng)論 8 123
  • 產(chǎn)品版本 Android3.4.1 產(chǎn)品定位&賣點(diǎn) 適合城市短途出行的無樁共享單車 場(chǎng)景&用戶&需求 用戶乘坐公共...
    Qonyyyy閱讀 3,034評(píng)論 0 0
  • 今晚宇驾,亞冠聯(lián)賽上海上港和浦和紅鉆倍靡,比分1:1收?qǐng)觥2槐靥^在意球場(chǎng)的比分课舍,也不必太在意球場(chǎng)氛圍塌西。來看球,是來散心筝尾,...
    肉頭鬼閱讀 161評(píng)論 0 0
  • 沒有書店的地方算不上好地方;再者捡需,每個(gè)人的生命中,都有最艱難的一年筹淫,將人生變得美好而遼闊站辉。 書中的A.J.因?yàn)槠拮?..
    一只被嚇過的喵閱讀 170評(píng)論 0 0