iOS - 蘋果的Vision綜合實踐

iOS11引入的Vision Framework,這幾年在不斷的添加新能力。今年新增的能力比較多有滑,蘋果直接整了一個完整的App和文檔,來綜合的展示新的視覺能力嵌削,文章本身是對這個demo App和文檔的解讀和翻譯毛好,demo app的鏈接在文末。

丟沙包游戲

丟沙包游戲

這個游戲貌似是老美很常見的一個游戲苛秕,主要元素是:

  1. 一個人肌访,幾個沙包
  2. 一個帶有洞的木板(2*4英尺大小的木板,6英寸直徑的洞)
  3. 游戲規(guī)則就是人站在25英尺外扔沙包
  4. 碰到木板或者進洞就算得分

Action & Vision

蘋果以丟沙包這個游戲為例艇劫,寫了一個名字叫Action & Vision的App吼驶,通過iOS的視覺能力來幫助用戶分析游戲行為和統(tǒng)計分數(shù)。實際運行效果如下。

Action & Vision

業(yè)務流程和代碼

  1. Vision基礎
    所有Vision能力蟹演,命名都是一個VNXXXRequest风钻,比如VNDetectHumanBodyPoseRequest。每當我們需要使用一個能力酒请,我們需要創(chuàng)建一個request骡技,并且使用一個VNImageRequestHandler,來輸入圖片羞反,以及需要使用的[request]能力數(shù)組布朦,最后,我們調(diào)用handle.perform(request)苟弛,來執(zhí)行實際的預測喝滞,并沖request中獲取結(jié)果,即一個observation.
// 創(chuàng)建request
private let detectPlayerRequest = VNDetectHumanBodyPoseRequest()
// 輸入圖片并執(zhí)行request
let visionHandler = VNImageRequestHandler(cmSampleBuffer: buffer, orientation: orientation, options: [:])
// 獲取結(jié)果
let results = self.detectTrajectoryRequest.results as? [VNTrajectoryObservation] 
  1. 游戲前的定位和分析膏秫。
    1.1 首先需要識別木板的位置右遭,蘋果使用了Create ML自己創(chuàng)建了一個模型,來識別木板缤削。
    1.2 然后通過VNDetectContoursRequest窘哈,來確定木板的邊緣,確定像素和實際物體長寬的對應關(guān)系亭敢,來確定洞在木板和圖片中的位置滚婉。因為在1.1中已經(jīng)識別了木板,實際使用VNDetectContoursRequest的過程是帅刀,把1.1中識別的木板的bouding box拿到让腹,在使用VNDetectContoursRequest時指定regionOfInterest,減少噪聲提高效率扣溺。
        let contoursRequest = VNDetectContoursRequest()
        contoursRequest.regionOfInterest = boardBoundingBox.visionRect
  1. 確定畫面的穩(wěn)定性
    之前的普遍做法是骇窍,使用陀螺儀,隔一段時間計算陀螺儀的參數(shù)diff是否大于一個自己的閾值锥余,來判斷用戶或者畫面是否穩(wěn)定「鼓桑現(xiàn)在可以使用蘋果提供的新API - VNTranslationalImageRegistrationRequest,用判斷兩張圖仿射變換xy的距離來判斷畫面的穩(wěn)定性驱犹。

利用VNTranslationalImageRegistrationRequest獲取反射變換transform

    private func checkSceneStability(_ controller: CameraViewController, _ buffer: CMSampleBuffer, _ orientation: CGImagePropertyOrientation) throws {
        guard let previousBuffer = self.previousSampleBuffer else {
            self.previousSampleBuffer = buffer
            return
        }
        let registrationRequest = VNTranslationalImageRegistrationRequest(targetedCMSampleBuffer: buffer)
        try sceneStabilityRequestHandler.perform([registrationRequest], on: previousBuffer, orientation: orientation)
        self.previousSampleBuffer = buffer
        if let alignmentObservation = registrationRequest.results?.first as? VNImageTranslationAlignmentObservation {
            let transform = alignmentObservation.alignmentTransform
            sceneStabilityHistoryPoints.append(CGPoint(x: transform.tx, y: transform.ty))
        }
    }

判斷transform x嘲恍,y,確定畫面是否穩(wěn)定

var sceneStability: SceneStabilityResult {
        // Determine if we have enough evidence of stability.
        guard sceneStabilityHistoryPoints.count > sceneStabilityRequiredHistoryLength else {
            return .unknown
        }
        
        // Calculate the moving average by adding up values of stored points
        // returned by VNTranslationalImageRegistrationRequest for both axis
        var movingAverage = CGPoint.zero
        movingAverage.x = sceneStabilityHistoryPoints.map { $0.x }.reduce(.zero, +)
        movingAverage.y = sceneStabilityHistoryPoints.map { $0.y }.reduce(.zero, +)
        // Get the moving distance by adding absolute moving average values of individual axis
        let distance = abs(movingAverage.x) + abs(movingAverage.y)
        // If the distance is not significant enough to affect the game analysis (less that 10 points),
        // we declare the scene being stable
        return (distance < 10 ? .stable : .unstable)
    }
  1. 識別進入畫面的玩家(人體識別)
    使用VNDetectHumanBodyPoseRequest來獲取人體和姿勢數(shù)據(jù)雄驹。
    3.1 根據(jù)observation.confidence結(jié)果佃牛,判斷是否有人,根據(jù)observation.recognizedPoints医舆,把points的結(jié)果合并吁脱,返回人的CGRect桑涎。
    3.2 轉(zhuǎn)換一下recognizedPoints的格式,根據(jù)部分點位兼贡,畫出人的姿態(tài)。


    人的姿態(tài)

這個recognizedPoints實際的數(shù)據(jù)是這樣的

left_hand_joint
[0.201963; 0.587417]

然后你需要賽選幾個你想要繪制的點娃胆,使用bezier path將他們鏈接遍希,繪制,然后更新他們的位置里烦。

3.3 姿勢檢測凿蒜,基本原理是通過create ML訓練一個模型來分來。步驟是:獲取一張圖胁黑,獲取圖中人的姿勢結(jié)果废封,也就是通過VNDetectHumanBodyPoseRequest獲取到observation,observation中有姿勢相關(guān)的point丧蘸,將他們構(gòu)造一個MLMultiArray作為輸入漂洋,使用core ML跑模型,來進行姿勢分類力喷。

  1. 檢測投擲沙包的拋物線
    使用VNDetectTrajectoriesRequest來檢測拋物線軌跡刽漂。因為拋物線是多個點組成的,所以一個VNDetectTrajectoriesRequest實例需要一系列的視頻幀來多次執(zhí)行弟孟,獲取到足夠多的點贝咙,然后執(zhí)行完成回調(diào)。Demo中把這些拋物線的點連成一條曲線拂募,繪制出來庭猩。


    拋物線
private lazy var detectTrajectoryRequest: VNDetectTrajectoriesRequest! =
                        VNDetectTrajectoriesRequest(frameAnalysisSpacing: .zero, trajectoryLength: GameConstants.trajectoryLength)
try visionHandler.perform([self.detectTrajectoryRequest])
let results = self.detectTrajectoryRequest.results as? [VNTrajectoryObservation]
let trajectory = UIBezierPath()
        for point in points.dropFirst() {
            trajectory.addLine(to: point.location)
        }
// 然后繪制 draw path

Building a Feature-Rich App for Sports Analysis
丟沙包 - Cornhole

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市陈症,隨后出現(xiàn)的幾起案子蔼水,更是在濱河造成了極大的恐慌,老刑警劉巖爬凑,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徙缴,死亡現(xiàn)場離奇詭異,居然都是意外死亡嘁信,警方通過查閱死者的電腦和手機于样,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來潘靖,“玉大人穿剖,你說我怎么就攤上這事∝砸纾” “怎么了糊余?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵秀又,是天一觀的道長。 經(jīng)常有香客問我贬芥,道長吐辙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任蘸劈,我火速辦了婚禮昏苏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘威沫。我一直安慰自己贤惯,他們只是感情好,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布棒掠。 她就那樣靜靜地躺著孵构,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烟很。 梳的紋絲不亂的頭發(fā)上颈墅,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音溯职,去河邊找鬼精盅。 笑死,一個胖子當著我的面吹牛谜酒,可吹牛的內(nèi)容都是我干的叹俏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼僻族,長吁一口氣:“原來是場噩夢啊……” “哼粘驰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起述么,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蝌数,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后度秘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顶伞,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年剑梳,在試婚紗的時候發(fā)現(xiàn)自己被綠了唆貌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡垢乙,死狀恐怖锨咙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情追逮,我是刑警寧澤酪刀,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布粹舵,位于F島的核電站,受9級特大地震影響骂倘,放射性物質(zhì)發(fā)生泄漏眼滤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一稠茂、第九天 我趴在偏房一處隱蔽的房頂上張望柠偶。 院中可真熱鬧,春花似錦睬关、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至料睛,卻和暖如春丐箩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恤煞。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工屎勘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人居扒。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓概漱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親喜喂。 傳聞我的和親對象是個殘疾皇子瓤摧,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355