滁州做網(wǎng)站公司南通百度網(wǎng)站快速優(yōu)化
? ? ? ?人體肢體動作捕捉在動漫影視制作、游戲CG 動畫、實時模型驅動中有著廣泛的應用,利用 ARKit,無須額外的硬件設備即可實現(xiàn) 2D和3D人體一系列關節(jié)和骨骼的動態(tài)捕捉,由于移動AR 的便攜性及低成本,必將促進相關產(chǎn)業(yè)的發(fā)展。
ARBody TrackingConfiguration
? ? ? ARKit 配置類 ARBodyTrackingConfiguration 專用于 2D、3D人體肢體檢測捕捉,同時,該配置類也可以設置實現(xiàn) 2D 圖像檢測和平面檢測,構建對現(xiàn)實環(huán)境的跟蹤。為更真實地渲染虛擬元素,ARBodyTrackingConfiguration 還支持 HDR(High Dynamic Range Imaging,高動態(tài)范圍成像)環(huán)境反射功能。其主要屬性如下表所示。
屬性名 | 描述 |
automaticSkeletonScaleEstimationEnabled | 布爾值,指定 ARKit是否進行人體骨骼尺寸評估,設置為true 時,ARKit會根據(jù)人體距離攝像頭的遠近調整所驅動的模型大小,使其更匹配 |
isAutoFocusEnabled | 設置是否自動對焦 |
planeDetection | 在進行人體肢體檢測跟蹤時是否進行平面檢測,可以設置為水平(horizontal)或者垂直(vertical),或者兩者都設置。設置該值后就會啟動平面檢測功能 |
automaticImageScaleEstimationEnabled | 自動評估檢測到的2D圖像的尺寸,這在設置2D 圖像跟蹤時有效 |
detectionImages | 參考圖像庫 |
maximum NumberOfTrackedImages | 最大可同時跟蹤的2D 圖像數(shù)量 |
wantsHDREnvironment Textures | 是否使用HDR 環(huán)境紋理反射,使用后渲染的虛擬元素更真實 |
environment Texturing | 環(huán)境紋理來源,可設置為自動(automatic)、手動(manual)、無(none)三者之一,當設置為手動時,需要提供環(huán)境紋理圖 |
? ? ? 通常,在實現(xiàn)人體肢體檢測和人形遮擋功能時,還需要設置 frameSemantics 語義屬性,使用ARBoodyTrackingConfiguration 配置類進行人體肢體檢測和動作捕捉時,frameSemantics 語義屬性值只能設置 bodyDetection(默認值)。frameSemantics 語義屬性中 bodyDetection 用于肢體檢測跟蹤,后兩個用于人形遮擋,personSegmentation現(xiàn)實屏幕空間的人形分離,而 personSegmentation WithDepth則是帶有深度信息的人形分離。
2D人體姿態(tài)估計
? ? ? 在ARKit 中,2D人體姿態(tài)估計是指對攝像頭采集的視頻圖像中人像在屏幕空間中的姿態(tài)進行估計,通常使用人體骨骼關節(jié)點來描述人體姿態(tài)。近年來,隨著深度學習技術的發(fā)展,人體骨骼關節(jié)點檢測效率與效果不斷提升,已經(jīng)開始廣泛應用于計算機視覺的相關領域。2D人體姿態(tài)檢測估計在視頻安防、動作分類、行為檢測、人機交互、體育科學中有著廣闊的應用前景。
人體骨骼關節(jié)點檢測
? ? ?人體骨骼關節(jié)點檢測(Pose Estimation)主要檢測人體的一些關鍵節(jié)點,如關節(jié)、頭部、手掌等,通過關節(jié)點描述人體骨骼及姿態(tài)信息。人體骨骼關節(jié)點檢測在計算機視覺人體姿態(tài)檢測相關領域的研究中起到了基礎性的作用,是智能視頻監(jiān)控、病人監(jiān)護系統(tǒng)、人機交互、虛擬現(xiàn)實、智能家居、智能安防、運動員輔助訓練等應用的基礎性算法。
? ? ? 在實際應用中,由于人體具有相當?shù)娜嵝?#xff0c;會出現(xiàn)各種姿態(tài)和形狀,人體任何一個部位的微小變化都會產(chǎn)生一種新的姿態(tài),同時其關節(jié)點的可見性受穿著、姿態(tài)、視角等影響非常大,而且還受到光照、遮擋等環(huán)境影響。除此之外,2D人體關節(jié)點和3D人體關節(jié)點在視覺上會有明顯的差異,身體不同部位都會有視覺上的縮短效應(Fore Shortening),使得人體骨骼關節(jié)點檢測成為計算機視覺領域中一個極具挑戰(zhàn)性的課題。
使用2D 人體姿態(tài)估計
? ? ?在 ARKit 中,我們不必關心底層的人體骨骼關節(jié)點檢測算法,也不必自己去調用這些算法,在運行使用ARBodyTrackingConfiguration 配置的ARSession 之后,基于攝像頭圖像的2D人體姿態(tài)估計任務就會啟動。
? ? ? 2D人體姿態(tài)檢測基于屏幕空間,獲取的人體姿態(tài)信息沒有深度值。在 ARKit 檢測到屏幕空間中的人形后,可以通過 ARFrame. detectedBody 獲取一個 ARBody2D 對象,也就是說 ARKit 目前對屏幕空間中的2D人體,只支持單個人形檢測。ARBody2D對象描述了檢測到的人形結構信息,其結構如下圖所示。
? ? ?通過圖可以看到,在使用 session(_ session: ARSession,didUpdate frame: ARFrame)方法獲取ARFrame 中表示 2D人體的 ARBody2D 對象后,就可以使用其 skeleton. jointLandmarks 獲取所有關節(jié)點位置信息,也可以通過其 skeleton. definition.jointNames 獲取所有關節(jié)點名稱。jointLandmarks 是一個包含所有關節(jié)點位置信息的數(shù)組,我們可以通過索引值檢索某個關節(jié)點的位置,也可以通過 skeleton.landmark(for: ARSkeleton. JointName(rawValue: jointName))方法取指定關節(jié)點名稱的位置信息。
? ? ?2D人體姿態(tài)估計是在屏幕空間中對攝像頭采集的圖像進行逐幀分析,解算出的關節(jié)點位置也是在屏幕空間中的歸一化坐標,以屏幕左上角(0,0)右下角為(1,1),如下圖所示。
? ? 為了描述人體骨骼關節(jié)點,ARKit 新建了一個 ARSkeleton 類,該類包含一個人體關節(jié)點(Joint)集合及關節(jié)之間關系的定義,該類預定義了8個關節(jié)點,分別是 head、 leftFoot、 left Hand、 leftShoulder.hannnt riahtHand.rightShoulder、root.這是在應用開發(fā)中使用最多的關節(jié)點,2D和3D人體肢體都包含這些關節(jié)點,因此我們可以通過這些預定義的節(jié)點名字快速找到骨骼節(jié)點位置。ARSkeleton 類是ARSkeleton2D 和 ARSkeleton3D類的父類。
? ? ? ARSkeleton2D 類繼承自 ARSkeleton,其 jointLandmarks 包含了所有2D關節(jié)點的位置信息,也可以通過該類的landmark(forJointNamed:)方法獲取某個名字關節(jié)點的位置,此方法需要傳遞關節(jié)點的原始名稱(rawValue)而不是 ARSkeleton 預定義的關節(jié)點名(預定義關節(jié)點名可以通過其.rawValue 獲取原始名稱)。jointLandmarks 是 simd_float2 類型數(shù)組,因此我們也可以直接通過下標獲取特定的關節(jié)點位置信息,下標方法取值比使用 landmark(forJointNamed:)快得多,特別是對每幀都要執(zhí)行的循環(huán)操作,可以節(jié)省很多時間。獲取特定節(jié)點名稱的索引值可以通過 definition.index(for:)方法實現(xiàn)。除此之外,還可以通過 ARSkeleton2D的isJointTracked(_:)方法查詢每一個關節(jié)點在當前幀的檢測跟蹤情況,還可以獲取每一個節(jié)點的父節(jié)點。
骨骼關節(jié)點名稱 | 索引 | 父節(jié)點名稱 | 索引 |
invalid | -1 | 無 | |
head_ joint | 0 | neck_1 joint | 1 |
neck_ 1_joint | 1 | root | 16 |
right_ shoulder_1 _joint | 2 | neck_1_joint | 1 |
right_ forearm_joint | 3 | right_shoulder_1_joint | 2 |
right_hand _joint | 4 | right_ forearm_joint | 3 |
left_shoulder_1_joint | 5 | neck_1 _joint | 1 |
left_forearm_joint | 6 | 5 | |
left_hand joint | 7 | left forearm_joint | 6 |
right_upLeg_joint | 8 | root | 16 |
right_leg joint | 9 | right_upLeg_joint | 8 |
right_foot_ joint | 10 | right_leg joint | 9 |
left_ upLeg_joint | 11 | root | 16 |
left_leg joint | 12 | left_upLeg_joint | 11 |
left_foot joint | 13 | left_leg joint | 12 |
right_eye joint | 14 | head _joint | 0 |
left_eye_joint | 15 | head_joint | 0 |
root | 16 | Invalid | -1 |
right_ear_joint | 17 | right_eye joint | 14 |
left-ear- joint | 18 | left_eye_joint | 15 |
? ? ?ARKit 2D 人體骨骼關節(jié)點定義及它們之間的關聯(lián)關系如上表所示,通過表可以看到,在ARKit 中,檢測到的2D人體共包含19個關節(jié)點(root 節(jié)點代表了整個 ARBody2D 對象,不計算在內時包含18個關節(jié)點),這些關節(jié)點相互之間有很強的相關性,存在緊密的父子連接關系,通過節(jié)點之間的相互關系,就可以畫出各骨骼節(jié)點之間的連結圖。
? ? ?下面演示利用 ARKit 檢測到的2D人體骨骼關節(jié)點信息,將每一個關節(jié)點用一個圓圈標示出來,具體代碼如下
//
// BodyTrackingView.swift
// ARKitDeamo
//
// Created by zhaoquan du on 2024/2/1.
//import SwiftUI
import ARKit
import RealityKitstruct BodyTrackingView: View {var body: some View {BodyTrackingViewContainer().edgesIgnoringSafeArea(.all).navigationTitle("人體骨架2D檢測")}
}struct BodyTrackingViewContainer:UIViewRepresentable {func makeUIView(context: Context) ->ARView {let arView = ARView(frame: .zero)return arView}func updateUIView(_ uiView: UIViewType, context: Context) {guard ARBodyTrackingConfiguration.isSupported else {return}context.coordinator.arView = uiViewlet config = ARBodyTrackingConfiguration()config.frameSemantics = .bodyDetectionconfig.automaticSkeletonScaleEstimationEnabled = trueuiView.session.delegate = context.coordinatoruiView.session.run(config)}func makeCoordinator() -> Coordinator {Coordinator()}class Coordinator: NSObject,ARSessionDelegate {var arView : ARView? = nillet circleWidth: CGFloat = 10let circleHeight: CGFloat = 10var isPrinted = falsefunc session(_ session: ARSession, didUpdate frame: ARFrame) {guard let arView = arView else {return}//清除骨骼圓圈arView.layer.sublayers?.compactMap({$0 as? CAShapeLayer}).forEach({$0.removeFromSuperlayer()})guard let detectedBody = frame.detectedBody else {return}guard let orientation = arView.window?.windowScene?.interfaceOrientation else {return}let transform = frame.displayTransform(for: orientation, viewportSize: arView.frame.size)detectedBody.skeleton.jointLandmarks.forEach { landmark inlet normalizeCenter = CGPoint(x: CGFloat(landmark.x), y: CGFloat(landmark.y)).applying(transform)let center = normalizeCenter.applying(.identity.scaledBy(x: arView.frame.width, y: arView.frame.height))let rect = CGRect(x: center.x - circleWidth/2, y: center.y - circleWidth/2, width: circleWidth, height: circleHeight)let circleLayer = CAShapeLayer()circleLayer.path = UIBezierPath(ovalIn: rect).cgPatharView.layer.addSublayer(circleLayer)}if !isPrinted {let jointNames = detectedBody.skeleton.definition.jointNamesfor name in jointNames {let landmark = detectedBody.skeleton.landmark(for: ARSkeleton.JointName(rawValue: name))let index = detectedBody.skeleton.definition.index(for: ARSkeleton.JointName(rawValue: name))print("\(name),\(String(describing: landmark)),the index is \(index) parent index is \(detectedBody.skeleton.definition.parentIndices[index])")}print("last: \(ARSkeleton2D.JointName.rightShoulder.rawValue)")isPrinted = true}}}}
? ? ? 代碼中實現(xiàn)的主要功能是在每一個檢測到的2D人體關節(jié)點位置畫一個圓圈,效果如圖所示。
? ? ??????代碼很多語句都是執(zhí)行畫圖操作,但也演示了 ARKit 2D 人體檢測使用的幾個重要功能:
? (1)演示了如何獲取屏幕空間中的 ARBody2D對象,為確保代碼在沒有檢測到2D人體時也能正確執(zhí)行,我們使用了 guard 語句。
? (2)演示了如何獲取2D 人體所有骨骼關節(jié)點名字集合,以及各關節(jié)點索引及其父節(jié)點索引。
? (3)演示了如何利用關節(jié)點名字獲取該關節(jié)點在屏幕空間中的位置信息。
? ? 如前所述,使用索引值獲取特定的關節(jié)點位置信息比使用關節(jié)點名字快得多,代碼清演示了利用關節(jié)點名字獲取對應索引值,在實際開發(fā)中,可以直接使用前表中各關節(jié)點的索引值以提高性能。
具體代碼地址:GitHub - duzhaoquan/ARkitDemo