2 |
3 |
24 | Requirements • Usage • Installation • Contribution • Contact • License 25 |
26 | 27 | ## Requirements 28 | 29 | - visionOS 1.0+ 30 | - Xcode 15.2+ 31 | - Swift 5.9+ 32 | 33 | ## Usage 34 | 35 | `HandVector 2.0` supports two kinds of gesture matching methods, which differ in their calculation principles and are suitable for different scenarios. They can also be mixed used together in a project: 36 | 37 | * **Cosine Similarity**: This method matches each joint of the specified fingers precisely, using the matrix information of each joint relative to its parent joint, resulting in high accuracy. Advantages: High precision, applicable to fingers and wrists; Disadvantages: Poor interpretability, difficult to adjust the range. 38 | * **FingerShape**: Referencing Unity's [XRHands](https://docs.unity3d.com/Packages/com.unity.xr.hands@1.5/manual/index.html) framework, this method simplifies the finger shape into five parameters: `baseCurl` (curl at the base of the finger), `tipCurl` (curl at the tip of the finger), `fullCurl` (overall curl of the finger), `pinch` (distance of pinching with the thumb), and `spread` (degree of separation from the adjacent outer finger). Advantages: The values are easy to understand and convenient to control and adjust; Disadvantages: Does not fully utilize joint pose information, thus not as precise, and is only applicable to five fingers. 39 | 40 | 41 | This upgrade also includes a reorganization of the file structure, with some classes and structures being renamed for clearer functionality. Therefore, it is not compatible with the previous major version API. 42 | 43 |  44 | 45 | ### 1. Cosine Similarity Gesture Matching 46 | `HandVector` supports matching built-in gestures as well as recording and saving custom gestures for later use. Currently, there are 8 built-in gestures: 👆✌️✋👌✊🤘🤙🫱🏿🫲🏻 47 | > 🫱🏿🫲🏻: Grab, grasp 48 | #### a. Matching Built-in Gestures 49 |  50 | 51 | ```swift 52 | 53 | import HandVector 54 | 55 | 56 | 57 | //Get current Hand info from `HandTrackingProvider` , and convert to `HVHandInfo` 58 | 59 | for await update in handTracking.anchorUpdates { 60 | 61 | switch update.event { 62 | 63 | case .added, .updated: 64 | 65 | let anchor = update.anchor 66 | 67 | guard anchor.isTracked else { continue } 68 | 69 | let handInfo = latestHandTracking.generateHandInfo(from: anchor) 70 | 71 | case .removed: 72 | 73 | ... 74 | 75 | } 76 | 77 | } 78 | 79 | 80 | 81 | //Load built-in gesture from json file 82 | 83 | let builtinHands = HVHandInfo.builtinHandInfo 84 | 85 | //Calculate the similarity with the built-in gestures, `.fiveFingers` indicates matching only the 5 fingers, ignoring the wrist and palm. 86 | 87 | builtinHands.forEach { (key, value) in 88 | 89 | leftScores[key] = latestHandTracking.leftHandVector?.similarity(of: .fiveFingers, to: value) 90 | 91 | rightScores[key] = latestHandTracking.rightHandVector?.similarity(of: .fiveFingers, to: value) 92 | 93 | } 94 | 95 | ``` 96 | 97 | the score should be in `[-1.0,1.0]`, `1.0` means fully matched and both are left or right hands, `-1.0 `means fully matched but one is left hand, another is right hand, and `0` means not matched. 98 | 99 | #### b. Record custom gesture and match it 100 | 101 | 102 | 103 |  104 | 105 | 106 | 107 | Record a custom gesture and save it as a JSON string using `HVHandJsonModel`: 108 | 109 | 110 | 111 | ```swift 112 | 113 | if let left = model.latestHandTracking.leftHandVector { 114 | 115 | let para = HVHandJsonModel.generateJsonModel(name: "YourHand", handVector: left) 116 | 117 | jsonString = para.toJson() 118 | 119 | //Save jsonString to disk or network 120 | 121 | ... 122 | 123 | } 124 | 125 | ``` 126 | 127 | 128 | 129 | Next, convert the saved JSON string into the `HVHandInfo` type for gesture matching: 130 | 131 | 132 | 133 | ```swift 134 | 135 | //Convert from JSON string 136 | 137 | let handInfo = jsonStr.toModel(HVHandJsonModel.self)!.convertToHVHandInfo() 138 | 139 | //Load JSON file from disk, and convert 140 | 141 | let handInfo = HVHandJsonModel.loadHandJsonModel(fileName: "YourJsonFileName")!.convertToHVHandInfo() 142 | 143 | 144 | 145 | //Using the `HVHandInfo` type for gesture matching allows you to calculate the similarity for each finger individually. 146 | 147 | if let handInfo { 148 | 149 | averageAndEachLeftScores = latestHandTracking.leftHandVector?.averageAndEachSimilarities(of: .fiveFingers, to: recordHand) 150 | 151 | averageAndEachRightScores = latestHandTracking.rightHandVector?.averageAndEachSimilarities(of: .fiveFingers, to: recordHand) 152 | 153 | } 154 | 155 | 156 | 157 | ``` 158 | 159 | 160 | 161 | ### 2.Finger Shape Parameter 162 | 163 | 164 | 165 |  166 | 167 | 168 | 169 | This method draws significant reference from the well-known XR gesture framework in Unity: [XRHands](https://docs.unity3d.com/Packages/com.unity.xr.hands@1.5/manual/index.html). 170 | 171 | 172 | 173 |  174 | 175 | 176 | 177 | The definitions of the related parameters are similar: 178 | * **baseCurl**: The degree of curl at the root joint of the finger. For the thumb, it is the `IntermediateBase` joint, and for the other fingers, it is the `Knuckle` joint, with a range of 0 to 1. 179 | 180 |  181 | 182 | 183 | 184 | * **tipCurl**:The degree of curl at the upper joint of the finger. For the thumb, it is the `IntermediateTip` joint, and for the other fingers, it is the average value of the `IntermediateBase` and `IntermediateTip` joints, with a range of 0 to 1. 185 | 186 |  187 | 188 | * **fullCurl**:The average value of baseCurl and tipCurl, with a range of 0 to 1. 189 | 190 |  191 | 192 | * **pinch**:The distance from the tip of the thumb, with a range of 0 to 1. For the thumb, this parameter is `nil`. 193 | 194 |  195 | 196 | * **spread**:Only the horizontal spread angle is calculated, with a range of 0 to 1. For the little finger, this parameter is `nil`. 197 | 198 |  199 | 200 | Regarding the differences between the three types of curl degrees, you can refer to the following image: 201 | 202 |  203 | 204 | ### 3. Test hand gesture on Mac simulator 205 | 206 | The test method of`HandVector` is inspired by [VisionOS Simulator hands](https://github.com/BenLumenDigital/VisionOS-SimHands), it allow you to test hand tracking on visionOS simulator: 207 | 208 | It uses 2 things: 209 | 210 | 1. A macOS helper app, with a bonjour service 211 | 2. A Swift class for your VisionOS project which connects to the bonjour service (It comes with this package, and automatically receives and converts to the corresponding gesture; HandVector 2.0 version has updated mathematical "black magic" to achieve the new matching algorithm.) 212 | 213 | #### macOS Helper App 214 | 215 | The helper app uses Google MediaPipes for 3D hand tracking. This is a very basic setup - it uses a WKWebView to run the Google sample code, and that passed the hand data as JSON into native Swift. 216 | 217 | The Swift code then spits out the JSON over a Bonjour service. 218 | 219 | > If hand tracking can't start for a long time(Start button still can't be pressed), please check your network to google MediaPipes. 220 | 221 |  222 | 223 | ### And many more... 224 | 225 | To go further, take a look at the documentation and the demo project. 226 | 227 | *Note: All contributions are welcome* 228 | 229 | ## Installation 230 | 231 | #### Swift Package Manager 232 | 233 | To integrate using Apple's Swift package manager, without Xcode integration, add the following as a dependency to your `Package.swift`: 234 | 235 | ``` 236 | .package(url: "https://github.com/XanderXu/HandVector.git", .upToNextMajor(from: "2.0.0")) 237 | ``` 238 | 239 | #### Manually 240 | 241 | [Download](https://github.com/XanderXu/HandVector/archive/master.zip) the project and copy the `HandVector` folder into your project to use it. 242 | 243 | ## Contribution 244 | 245 | Contributions are welcomed and encouraged *♡*. 246 | 247 | ## Contact 248 | 249 | Xander: API 搬运工 250 | 251 | * [https://twitter.com/XanderARKit](https://twitter.com/XanderARKit) 252 | * [https://github.com/XanderXu](https://github.com/XanderXu) 253 | 254 | - [https://juejin.cn/user/2629687543092056](https://juejin.cn/user/2629687543092056) 255 | 256 | 257 | 258 | ## License 259 | 260 | HandVector is released under an MIT license. See [LICENSE](./LICENSE) for more information. 261 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
21 | 环境要求 • 用法 • 安装 • 贡献 • 联系方式 • 许可证 22 |
23 | 24 | 25 | ## 环境要求 26 | 27 | - visionOS 1.0+ 28 | - Xcode 15.2+ 29 | - Swift 5.9+ 30 | 31 | ## 用法 32 | 33 | `HandVector 2.0` 支持两种手势匹配方法,它们计算理念不同,适用不同情况,也可一起混合使用: 34 | 35 | * **余弦相似度Cosine Similarity**:完全匹配指定手指的每个关节,使用每个关节点相对于父关节的矩阵信息,精准度高。优点:精度高,可适用手指与手腕;缺点:可解释性差,难以调整范围。 36 | * **手指形状参数FingerShape**:参考 Unity 的 [XRHands](https://docs.unity3d.com/Packages/com.unity.xr.hands@1.5/manual/index.html) 框架,将手指形状化简为: `指根卷曲度 baseCurl`、 `指尖卷曲度 tipCurl`、 `整体卷曲度 fullCurl`、 `(与拇指)捏合度 pinch`、 `(与外侧相邻手指)分离度 spread` 5 个参数。优点:数值方便理解,方便控制与调整;缺点:未充分利用关节位姿信息,精度不够高,且只适用 5 根手指。 37 | 38 | 本次升级也同时整理了文件结构,重命名了部分类和结构体,作用更清晰,所以与之间大版本 API 不兼容。 39 | 40 |  41 | 42 | ### 1.余弦相似度手势匹配 43 | 44 | `HandVector` 支持匹配内置的手势,也支持自行录制保存自定义手势。目前内置的手势有 8 种:👆✌️✋👌✊🤘🤙🫱🏿🫲🏻 45 | 46 | > 🫱🏿🫲🏻:握、抓住 47 | 48 | #### a.匹配内置的手势 49 | 50 |  51 | 52 | 追踪双手关节的姿态,并与内置的手势相比较,得出它们的相似度。 53 | 54 | ```swift 55 | import HandVector 56 | 57 | //从 HandTrackingProvider 中获取当前手部信息,并转换为 `HVHandInfo` 58 | for await update in handTracking.anchorUpdates { 59 | switch update.event { 60 | case .added, .updated: 61 | let anchor = update.anchor 62 | guard anchor.isTracked else { continue } 63 | let handInfo = latestHandTracking.generateHandInfo(from: anchor) 64 | case .removed: 65 | ... 66 | } 67 | } 68 | 69 | //从 json 文件中加载内置的手势 70 | let builtinHands = HVHandInfo.builtinHandInfo 71 | //计算与内置手势的相似度,`.fiveFingers`表示只匹配 5 根手指,忽略手腕和手掌 72 | builtinHands.forEach { (key, value) in 73 | leftScores[key] = latestHandTracking.leftHandVector?.similarity(of: .fiveFingers, to: value) 74 | rightScores[key] = latestHandTracking.rightHandVector?.similarity(of: .fiveFingers, to: value) 75 | } 76 | ``` 77 | 78 | 相似度得分在 `[-1.0,1.0]` 之间, `1.0` 含义为手势完全匹配并且左右手也匹配, `-1.0 ` 含义为手势完全匹配但一个是左手一个是右手, `0` 含义为完全不匹配。 79 | 80 | #### b. 录制自定义的新手势并匹配它 81 | 82 |  83 | 84 | 录制自定义手势,并利用 `HVHandJsonModel` 保存为 JSON 字符串: 85 | 86 | ```swift 87 | if let left = model.latestHandTracking.leftHandVector { 88 | let para = HVHandJsonModel.generateJsonModel(name: "YourHand", handVector: left) 89 | jsonString = para.toJson() 90 | //保存 jsonString 到磁盘或网络 91 | ... 92 | } 93 | ``` 94 | 95 | 然后,将保存的 JSON 字符串转换为 `HVHandInfo` 类型进行手势匹配: 96 | 97 | ```swift 98 | //从 JSON 字符串转换 99 | let handInfo = jsonStr.toModel(HVHandJsonModel.self)!.convertToHVHandInfo() 100 | //从磁盘加载 JSON 并转换 101 | let handInfo = HVHandJsonModel.loadHandJsonModel(fileName: "YourJsonFileName")!.convertToHVHandInfo() 102 | 103 | //用 `HVHandInfo` 类型进行手势匹配,可以将每根手指单独计算相似度 104 | if let handInfo { 105 | averageAndEachLeftScores = latestHandTracking.leftHandVector?.averageAndEachSimilarities(of: .fiveFingers, to: recordHand) 106 | averageAndEachRightScores = latestHandTracking.rightHandVector?.averageAndEachSimilarities(of: .fiveFingers, to: recordHand) 107 | } 108 | 109 | ``` 110 | 111 | ### 2.手指形状参数FingerShape 112 | 113 |  114 | 115 | 该方法重点参考了 Unity 中知名 XR 手势框架:[XRHands](https://docs.unity3d.com/Packages/com.unity.xr.hands@1.5/manual/index.html) 。 116 | 117 |  118 | 119 | 相关参数的定义也类似: 120 | 121 | * **指根卷曲度 baseCurl**:手指根部关节的卷曲度,大拇指为 `IntermediateBase` 关节,其余手指为 `Knuckle` 关节,范围 0~1 122 | 123 |  124 | 125 | * **指尖卷曲度 tipCurl**:手指上部关节的卷曲度,大拇指为 `IntermediateTip` 关节,其余手指为 `IntermediateBase` 和 `IntermediateTip` 两个关节的平均值,范围 0~1 126 | 127 |  128 | 129 | * **整体卷曲度 fullCurl**:baseCurl 与 tipCurl 的平均值,范围 0~1 130 | 131 |  132 | 133 | * **(与拇指)捏合度 pinch**:计算与拇指指尖的距离,范围 0~1,拇指该参数为 `nil` 134 | 135 |  136 | 137 | * **(与外侧相邻手指)分离度 spread**:只计算水平方向上的夹角,范围 0~1,小拇指该参数为 `nil` 138 | 139 |  140 | 141 | 关于三个不同的卷曲度有什么区别,可以参考下图: 142 | 143 |  144 | 145 | ### 3. 在模拟器上测试 146 | 147 | `HandVector` 中的模拟器测试方法来自于 [VisionOS Simulator hands](https://github.com/BenLumenDigital/VisionOS-SimHands) 项目, 它提供了一种可以在模拟器上测试手部追踪的方法: 148 | 149 | 它分为 2 部分: 150 | 151 | 1. 一个 macOS 工具 app, 带有 bonjour 网络服务 152 | 2. 一个 Swift 类,用来在你的项目中连接到 bonjour 服务(本 package 中已自带,并自动接收转换为对应手势,HandVector 2.0 版本中更新了大量数学“黑魔法”来实现新的匹配算法) 153 | 154 | #### macOS Helper App 155 | 156 | 这个工具 app 使用了 Google 的 MediaPipes 来实现 3D 手势追踪。工具中只是一段非常简单的代码——它使用一个WKWebView 来运行 Google 的示例代码,并将捕获到的手部数据作用 JSON 传递到原生 Swift 代码中。 157 | 158 | 然后通过 Swift 代码将 JSON 信息通过 Bonjour 服务广播出去。 159 | 160 | > 如果手势识别长时间无法启动(按钮一直无法点击),请检查网络是否能连接到 google MediaPipes。(中国用户请特别注意网络) 161 | 162 |  163 | 164 | ### 其他... 165 | 166 | 更多详情,请查看 demo 工程。 167 | 168 | 169 | 170 | ## 安装 171 | 172 | #### Swift Package Manager 173 | 174 | 要使用苹果的 Swift Package Manager 集成,将以下内容作为依赖添加到你的 `Package.swift`: 175 | 176 | ``` 177 | .package(url: "https://github.com/XanderXu/HandVector.git", .upToNextMajor(from: "2.0.0")) 178 | ``` 179 | 180 | #### 手动 181 | 182 | [下载](https://github.com/XanderXu/HandVector/archive/master.zip) 项目,然后复制 `HandVector` 文件夹到你的工程中就可以使用了。 183 | 184 | ## 贡献 185 | 186 | 欢迎贡献代码 *♡*. 187 | 188 | ## 联系我 189 | 190 | Xander: API 搬运工 191 | 192 | * [https://twitter.com/XanderARKit](https://twitter.com/XanderARKit) 193 | * [https://github.com/XanderXu](https://github.com/XanderXu) 194 | 195 | - [https://juejin.cn/user/2629687543092056](https://juejin.cn/user/2629687543092056) 196 | 197 | 198 | 199 | ## 许可证 200 | 201 | HandVector 是在 MIT license 下发布的。更多信息可以查看 [LICENSE](./LICENSE)。 202 | -------------------------------------------------------------------------------- /READMEv1/README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
15 | Requirements • Usage • Installation • Contribution • Contact • License 16 |
17 | 18 | ## Requirements 19 | 20 | - visionOS 1.0+ 21 | - Xcode 15.2+ 22 | - Swift 5.9+ 23 | 24 | ## Usage 25 | 26 | Your can run demo in package to see how to use it, and also can try an Vision Pro App. And also can see the App in App Store whitch uses `HandVector` to match gesture: 27 | 28 | 1. [FingerEmoji](https://apps.apple.com/us/app/fingeremoji/id6476075901) : FingerEmoji Let your finger dance with Emoji, you can Hit the emoji card by hand with the same gesture. 29 | 30 |  31 | 32 | 2. [SkyGestures](https://apps.apple.com/us/app/skygestures/id6499123392): **[SkyGestures](https://github.com/zlinoliver/SkyGestures)** is an innovative app that uses hand gestures to control DJI Tello drones via the Vision Pro platform. It's [Open Source](https://github.com/zlinoliver/SkyGestures) now. 33 | 34 |  35 | 36 | 37 | 38 | ### 1. Match builtin hand gesture: OK 39 | 40 |  41 | 42 | `HandVector` allows you to track your hands, and calculate the similarity between your current hand to another recorded hand gesture: 43 | 44 | ```swift 45 | import HandVector 46 | 47 | //load recorded hand gesture from json file 48 | model.handEmojiDict = HandEmojiParameter.generateParametersDict(fileName: "HandEmojiTotalJson")! 49 | guard let okVector = model.handEmojiDict["👌"]?.convertToHandVectorMatcher(), let leftOKVector = okVector.left else { return } 50 | 51 | //update current handTracking from HandTrackingProvider 52 | for await update in handTracking.anchorUpdates { 53 | switch update.event { 54 | case .added, .updated: 55 | let anchor = update.anchor 56 | guard anchor.isTracked else { continue } 57 | await latestHandTracking.updateHand(from: anchor) 58 | case .removed: 59 | ... 60 | } 61 | } 62 | 63 | 64 | //calculate the similarity 65 | let leftScore = model.latestHandTracking.leftHandVector?.similarity(to: leftOKVector) ?? 0 66 | model.leftScore = Int(abs(leftScore) * 100) 67 | let rightScore = model.latestHandTracking.rightHandVector?.similarity(to: leftOKVector) ?? 0 68 | model.rightScore = Int(abs(rightScore) * 100) 69 | ``` 70 | 71 | the score should be in `[-1.0,1.0]`, `1.0` means fully matched and both are left or right hands, `-1.0 `means fully matched but one is left hand, another is right hand, and `0` means not matched. 72 | 73 | ### 2. Record a new gesture and match 74 | 75 |  76 | 77 | `HandVector` allows you to record your custom hands gesture, and save as JSON string: 78 | 79 | ```swift 80 | let para = HandEmojiParameter.generateParameters(name: "both", leftHandVector: model.latestHandTracking.leftHandVector, rightHandVector: model.latestHandTracking.rightHandVector) 81 | model.recordHand = para 82 | 83 | jsonString = para?.toJson() 84 | ``` 85 | 86 | And then, you can turn this JSON string to `HandVectorMatcher`,so you can use it to match your gesture now: 87 | 88 | ```swift 89 | guard let targetVector = model.recordHand?.convertToHandVectorMatcher(), targetVector.left != nil || targetVector.right != nil else { return } 90 | 91 | let targetLeft = targetVector.left ?? targetVector.right 92 | let targetRight = targetVector.right ?? targetVector.left 93 | 94 | let leftScore = model.latestHandTracking.leftHandVector?.similarity(of: HandVectorMatcher.allFingers, to: targetLeft!) ?? 0 95 | model.leftScore = Int(abs(leftScore) * 100) 96 | let rightScore = model.latestHandTracking.rightHandVector?.similarity(of: HandVectorMatcher.allFingers, to: targetRight!) ?? 0 97 | model.rightScore = Int(abs(rightScore) * 100) 98 | ``` 99 | 100 | 101 | 102 | ### 3. Test hand gesture on Mac simulator 103 | 104 | The test method of`HandVector` is inspired by [VisionOS Simulator hands](https://github.com/BenLumenDigital/VisionOS-SimHands), it allow you to test hand tracking on visionOS simulator: 105 | 106 | It uses 2 things: 107 | 108 | 1. A macOS helper app, with a bonjour service 109 | 2. A Swift class for your VisionOS project which connects to the bonjour service (already in this package, and already turn JSON data to hand gestures) 110 | 111 | #### macOS Helper App 112 | 113 | The helper app uses Google MediaPipes for 3D hand tracking. This is a very basic setup - it uses a WKWebView to run the Google sample code, and that passed the hand data as JSON into native Swift. 114 | 115 | The Swift code then spits out the JSON over a Bonjour service. 116 | 117 | > If hand tracking can't start for a long time(Start button still can't be pressed), please check your network to google MediaPipes. 118 | 119 |  120 | 121 | ### And many more... 122 | 123 | To go further, take a look at the documentation and the demo project. 124 | 125 | *Note: All contributions are welcome* 126 | 127 | ## Installation 128 | 129 | #### Swift Package Manager 130 | 131 | To integrate using Apple's Swift package manager, without Xcode integration, add the following as a dependency to your `Package.swift`: 132 | 133 | ``` 134 | .package(url: "https://github.com/XanderXu/HandVector.git", .upToNextMajor(from: "0.3.0")) 135 | ``` 136 | 137 | #### Manually 138 | 139 | [Download](https://github.com/XanderXu/HandVector/archive/master.zip) the project and copy the `HandVector` folder into your project to use it. 140 | 141 | ## Contribution 142 | 143 | Contributions are welcomed and encouraged *♡*. 144 | 145 | ## Contact 146 | 147 | Xander: API 搬运工 148 | 149 | * [https://twitter.com/XanderARKit](https://twitter.com/XanderARKit) 150 | * [https://github.com/XanderXu](https://github.com/XanderXu) 151 | 152 | - [https://juejin.cn/user/2629687543092056](https://juejin.cn/user/2629687543092056) 153 | 154 | 155 | 156 | ## License 157 | 158 | HandVector is released under an MIT license. See [LICENSE](./LICENSE) for more information. 159 | -------------------------------------------------------------------------------- /READMEv1/README_CN.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
16 | 环境要求 • 用法 • 安装 • 贡献 • 联系方式 • 许可证 17 |
18 | 19 | 20 | ## 环境要求 21 | 22 | - visionOS 1.0+ 23 | - Xcode 15.2+ 24 | - Swift 5.9+ 25 | 26 | ## 用法 27 | 28 | 你可以下载运行软件包中的 demo 工程来查看如何使用,也可以从 App Store 中下载使用了 **HandVector** 的 App 来查看功能演示: 29 | 30 | 1. [FingerEmoji](https://apps.apple.com/us/app/fingeremoji/id6476075901) : FingerEmoji 让你的手指与 Emoji 共舞,你可以做出相同的手势并撞击 Emoji 卡片得分。 31 | 32 |  33 | 34 | 2. [SkyGestures](https://apps.apple.com/us/app/skygestures/id6499123392): **[SkyGestures](https://github.com/zlinoliver/SkyGestures)** 使用 Vision Pro 上的手势来控制大疆 DJI Tello 无人机,并且目前它已经 [开源](https://github.com/zlinoliver/SkyGestures) 了! 35 | 36 |  37 | 38 | 39 | 40 | ### 1.匹配内置的 OK 手势 41 | 42 |  43 | 44 | `HandVector` 可以让你追踪双手关节的姿态,并与先前记录下的手势相比较,得出它们的相似度: 45 | 46 | ```swift 47 | import HandVector 48 | 49 | //从 json 文件中加载先前记录下的手势 50 | model.handEmojiDict = HandEmojiParameter.generateParametersDict(fileName: "HandEmojiTotalJson")! 51 | guard let okVector = model.handEmojiDict["👌"]?.convertToHandVectorMatcher(), let leftOKVector = okVector.left else { return } 52 | 53 | //从 HandTrackingProvider 中获取当前手势,并更新 54 | for await update in handTracking.anchorUpdates { 55 | switch update.event { 56 | case .added, .updated: 57 | let anchor = update.anchor 58 | guard anchor.isTracked else { continue } 59 | await latestHandTracking.updateHand(from: anchor) 60 | case .removed: 61 | ... 62 | } 63 | } 64 | 65 | 66 | //计算相似度 67 | let leftScore = model.latestHandTracking.leftHandVector?.similarity(to: leftOKVector) ?? 0 68 | model.leftScore = Int(abs(leftScore) * 100) 69 | let rightScore = model.latestHandTracking.rightHandVector?.similarity(to: leftOKVector) ?? 0 70 | model.rightScore = Int(abs(rightScore) * 100) 71 | ``` 72 | 73 | 相似度得分在 `[-1.0,1.0]` 之间, `1.0` 含义为手势完全匹配并且左右手也匹配, `-1.0 ` 含义为手势完全匹配但一个是左手一个是右手, `0` 含义为完全不匹配。 74 | 75 | ### 2. 录制自定义的新手势并匹配它 76 | 77 |  78 | 79 | `HandVector` 允许你录制你的自定义手势,并保存为 JSON 字符串: 80 | 81 | ```swift 82 | let para = HandEmojiParameter.generateParameters(name: "both", leftHandVector: model.latestHandTracking.leftHandVector, rightHandVector: model.latestHandTracking.rightHandVector) 83 | model.recordHand = para 84 | 85 | jsonString = para?.toJson() 86 | ``` 87 | 88 | 然后,你还可以将 JSON 字符串转换为 `HandVectorMatcher` 类型,这样就可以进行手势匹配了: 89 | 90 | ```swift 91 | guard let targetVector = model.recordHand?.convertToHandVectorMatcher(), targetVector.left != nil || targetVector.right != nil else { return } 92 | 93 | let targetLeft = targetVector.left ?? targetVector.right 94 | let targetRight = targetVector.right ?? targetVector.left 95 | 96 | let leftScore = model.latestHandTracking.leftHandVector?.similarity(of: HandVectorMatcher.allFingers, to: targetLeft!) ?? 0 97 | model.leftScore = Int(abs(leftScore) * 100) 98 | let rightScore = model.latestHandTracking.rightHandVector?.similarity(of: HandVectorMatcher.allFingers, to: targetRight!) ?? 0 99 | model.rightScore = Int(abs(rightScore) * 100) 100 | ``` 101 | 102 | 103 | 104 | ### 3. 在模拟器上测试 105 | 106 | `HandVector` 中的模拟器测试方法来自于 [VisionOS Simulator hands](https://github.com/BenLumenDigital/VisionOS-SimHands) 项目, 它提供了一种可以在模拟器上测试手部追踪的方法: 107 | 108 | 它分为 2 部分: 109 | 110 | 1. 一个 macOS 工具 app, 带有 bonjour 网络服务 111 | 2. 一个 Swift 类,用来在你的项目中连接到 bonjour 服务(本 package 中已自带,并自动接收转换为对应手势) 112 | 113 | #### macOS Helper App 114 | 115 | 这个工具 app 使用了 Google 的 MediaPipes 来实现 3D 手势追踪。工具中只是一段非常简单的代码——它使用一个WKWebView 来运行 Google 的示例代码,并将捕获到的手部数据作用 JSON 传递到原生 Swift 代码中。 116 | 117 | 然后通过 Swift 代码将 JSON 信息通过 Bonjour 服务广播出去。 118 | 119 | > 如果手势识别长时间无法启动(按钮一直无法点击),请检查网络是否能连接到 google MediaPipes。(中国用户请特别注意网络) 120 | 121 |  122 | 123 | ### 其他... 124 | 125 | 更多详情,请查看 demo 工程。 126 | 127 | 128 | 129 | ## 安装 130 | 131 | #### Swift Package Manager 132 | 133 | 要使用苹果的 Swift Package Manager 集成,将以下内容作为依赖添加到你的 `Package.swift`: 134 | 135 | ``` 136 | .package(url: "https://github.com/XanderXu/HandVector.git", .upToNextMajor(from: "0.3.0")) 137 | ``` 138 | 139 | #### 手动 140 | 141 | [下载](https://github.com/XanderXu/HandVector/archive/master.zip) 项目,然后复制 `HandVector` 文件夹到你的工程中就可以使用了。 142 | 143 | ## 贡献 144 | 145 | 欢迎贡献代码 *♡*. 146 | 147 | ## 联系我 148 | 149 | Xander: API 搬运工 150 | 151 | * [https://twitter.com/XanderARKit](https://twitter.com/XanderARKit) 152 | * [https://github.com/XanderXu](https://github.com/XanderXu) 153 | 154 | - [https://juejin.cn/user/2629687543092056](https://juejin.cn/user/2629687543092056) 155 | 156 | 157 | 158 | ## 许可证 159 | 160 | HandVector 是在 MIT license 下发布的。更多信息可以查看 [LICENSE](./LICENSE)。 161 | -------------------------------------------------------------------------------- /READMEv1/Resources/960x540mv.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/READMEv1/Resources/960x540mv.webp -------------------------------------------------------------------------------- /READMEv1/Resources/HandVectorLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/READMEv1/Resources/HandVectorLogo.png -------------------------------------------------------------------------------- /READMEv1/Resources/handVectorDemoMatchOK.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/READMEv1/Resources/handVectorDemoMatchOK.gif -------------------------------------------------------------------------------- /READMEv1/Resources/handVectorDemoRecordMatch.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/READMEv1/Resources/handVectorDemoRecordMatch.gif -------------------------------------------------------------------------------- /READMEv1/Resources/handVectorTest.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/READMEv1/Resources/handVectorTest.gif -------------------------------------------------------------------------------- /READMEv1/Resources/skygestures_demo1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/READMEv1/Resources/skygestures_demo1.gif -------------------------------------------------------------------------------- /Resources/FingerShapFullCurl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/FingerShapFullCurl.png -------------------------------------------------------------------------------- /Resources/FingerShapeBaseCurl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/FingerShapeBaseCurl.png -------------------------------------------------------------------------------- /Resources/FingerShapeDifferenceCurl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/FingerShapeDifferenceCurl.png -------------------------------------------------------------------------------- /Resources/FingerShapePinch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/FingerShapePinch.png -------------------------------------------------------------------------------- /Resources/FingerShapeSpread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/FingerShapeSpread.png -------------------------------------------------------------------------------- /Resources/FingerShapeTipCurl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/FingerShapeTipCurl.png -------------------------------------------------------------------------------- /Resources/FingerShaper.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/FingerShaper.gif -------------------------------------------------------------------------------- /Resources/HandVectorFileStructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/HandVectorFileStructure.png -------------------------------------------------------------------------------- /Resources/HandVectorLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/HandVectorLogo.png -------------------------------------------------------------------------------- /Resources/MatchAllBuiltin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/MatchAllBuiltin.gif -------------------------------------------------------------------------------- /Resources/RecordAndMatch.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/RecordAndMatch.gif -------------------------------------------------------------------------------- /Resources/UntityXRHandsCoverImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/UntityXRHandsCoverImage.png -------------------------------------------------------------------------------- /Resources/handVectorTest.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XanderXu/HandVector/efd0d2f0f2dfe4d1f98e4ad0817df24e28a0a59d/Resources/handVectorTest.gif -------------------------------------------------------------------------------- /Sources/HandVector/Extensions/Codable+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Codable+Extensions.swift 3 | // HandVector 4 | // 5 | // Created by 许同学 on 2023/11/30. 6 | // 7 | 8 | import Foundation 9 | 10 | 11 | extension Encodable { 12 | func toJson(encoding: String.Encoding = .utf8) -> String? { 13 | guard let data = try? JSONEncoder().encode(self) else { return nil } 14 | return String(data: data, encoding: encoding) 15 | } 16 | } 17 | extension String { 18 | func toModel