基于Mediapipe_Unity_Plugin實現手勢識別

?GitHub - homuler/MediaPipeUnityPlugin: Unity plugin to run MediaPipehttps://github.com/homuler/MediaPipeUnityPlugin

實現了以下:

public enum HandGesture
{
? ? None,
? ? Stop,
? ? ThumbsUp,
? ? Victory,
? ? OK,
? ? OpenHand
}

核心腳本:

// Copyright (c) 2023 homuler
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.using System.Collections;
using Mediapipe.Tasks.Vision.HandLandmarker;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;namespace Mediapipe.Unity.Sample.HandLandmarkDetection
{public class HandLandmarkerRunner : VisionTaskApiRunner<HandLandmarker>{[SerializeField] private HandLandmarkerResultAnnotationController _handLandmarkerResultAnnotationController;private Experimental.TextureFramePool _textureFramePool;public readonly HandLandmarkDetectionConfig config = new HandLandmarkDetectionConfig();public UnityAction<HandLandmarkerResult> ProcessHandLandmark;public override void Stop(){base.Stop();_textureFramePool?.Dispose();_textureFramePool = null;}protected override IEnumerator Run(){Debug.Log($"Delegate = {config.Delegate}");Debug.Log($"Image Read Mode = {config.ImageReadMode}");Debug.Log($"Running Mode = {config.RunningMode}");Debug.Log($"NumHands = {config.NumHands}");Debug.Log($"MinHandDetectionConfidence = {config.MinHandDetectionConfidence}");Debug.Log($"MinHandPresenceConfidence = {config.MinHandPresenceConfidence}");Debug.Log($"MinTrackingConfidence = {config.MinTrackingConfidence}");yield return AssetLoader.PrepareAssetAsync(config.ModelPath);var options = config.GetHandLandmarkerOptions(config.RunningMode == Tasks.Vision.Core.RunningMode.LIVE_STREAM ? OnHandLandmarkDetectionOutput : null);taskApi = HandLandmarker.CreateFromOptions(options, GpuManager.GpuResources);var imageSource = ImageSourceProvider.ImageSource;yield return imageSource.Play();if (!imageSource.isPrepared){Debug.LogError("Failed to start ImageSource, exiting...");yield break;}// Use RGBA32 as the input format.// TODO: When using GpuBuffer, MediaPipe assumes that the input format is BGRA, so maybe the following code needs to be fixed._textureFramePool = new Experimental.TextureFramePool(imageSource.textureWidth, imageSource.textureHeight, TextureFormat.RGBA32, 10);// NOTE: The screen will be resized later, keeping the aspect ratio.screen.Initialize(imageSource);SetupAnnotationController(_handLandmarkerResultAnnotationController, imageSource);var transformationOptions = imageSource.GetTransformationOptions();var flipHorizontally = transformationOptions.flipHorizontally;var flipVertically = transformationOptions.flipVertically;var imageProcessingOptions = new Tasks.Vision.Core.ImageProcessingOptions(rotationDegrees: (int)transformationOptions.rotationAngle);AsyncGPUReadbackRequest req = default;var waitUntilReqDone = new WaitUntil(() => req.done);var waitForEndOfFrame = new WaitForEndOfFrame();var result = HandLandmarkerResult.Alloc(options.numHands);// NOTE: we can share the GL context of the render thread with MediaPipe (for now, only on Android)var canUseGpuImage = SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3 && GpuManager.GpuResources != null;using var glContext = canUseGpuImage ? GpuManager.GetGlContext() : null;while (true){if (isPaused){yield return new WaitWhile(() => isPaused);}if (!_textureFramePool.TryGetTextureFrame(out var textureFrame)){yield return new WaitForEndOfFrame();continue;}// Build the input ImageImage image;switch (config.ImageReadMode){case ImageReadMode.GPU:if (!canUseGpuImage){throw new System.Exception("ImageReadMode.GPU is not supported");}textureFrame.ReadTextureOnGPU(imageSource.GetCurrentTexture(), flipHorizontally, flipVertically);image = textureFrame.BuildGPUImage(glContext);// TODO: Currently we wait here for one frame to make sure the texture is fully copied to the TextureFrame before sending it to MediaPipe.// This usually works but is not guaranteed. Find a proper way to do this. See: https://github.com/homuler/MediaPipeUnityPlugin/pull/1311yield return waitForEndOfFrame;break;case ImageReadMode.CPU:yield return waitForEndOfFrame;textureFrame.ReadTextureOnCPU(imageSource.GetCurrentTexture(), flipHorizontally, flipVertically);image = textureFrame.BuildCPUImage();textureFrame.Release();break;case ImageReadMode.CPUAsync:default:req = textureFrame.ReadTextureAsync(imageSource.GetCurrentTexture(), flipHorizontally, flipVertically);yield return waitUntilReqDone;if (req.hasError){Debug.LogWarning($"Failed to read texture from the image source");continue;}image = textureFrame.BuildCPUImage();textureFrame.Release();break;}switch (taskApi.runningMode){case Tasks.Vision.Core.RunningMode.IMAGE:if (taskApi.TryDetect(image, imageProcessingOptions, ref result)){_handLandmarkerResultAnnotationController.DrawNow(result);}else{_handLandmarkerResultAnnotationController.DrawNow(default);}break;case Tasks.Vision.Core.RunningMode.VIDEO:if (taskApi.TryDetectForVideo(image, GetCurrentTimestampMillisec(), imageProcessingOptions, ref result)){_handLandmarkerResultAnnotationController.DrawNow(result);}else{_handLandmarkerResultAnnotationController.DrawNow(default);}break;case Tasks.Vision.Core.RunningMode.LIVE_STREAM:taskApi.DetectAsync(image, GetCurrentTimestampMillisec(), imageProcessingOptions);break;}}}private void OnHandLandmarkDetectionOutput(HandLandmarkerResult result, Image image, long timestamp){_handLandmarkerResultAnnotationController.DrawLater(result);ProcessHandLandmark?.Invoke(result);}}
}

對于ProcessHandLandmark?.Invoke(result);進行處理手部21個關鍵點的三維坐標信息。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/94471.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/94471.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/94471.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android 項目構建編譯概述

主要內容是Android AOSP源碼的管理方式&#xff0c;項目源碼的構建和編譯&#xff0c;用到比如git、repo、gerrit一些命令工具&#xff0c;以及使用Soong編譯系統&#xff0c;編寫Android.bp文件的格式樣式。 1. Android操作系統堆棧概述 Android 是一個針對多種不同設備類型打…

Python爬蟲08_Requests聚焦批量爬取圖片

一、Requests聚焦批量爬取圖片 import re import requests import os import timeurl https://www.douban.com/ userAgent {User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0}#獲取整個瀏覽頁面 page_text requests.get(urlur…

Spring Cloud系列—簡介

目錄 1 單體架構 2 集群與分布式 3 微服務架構 4 Spring Cloud 5 Spring Cloud環境和工程搭建 5.1 服務拆分 5.2 示例 5.2.1 數據庫配置 5.2.2 父子項目創建 5.2.3 order_service子項目結構配置 5.2.4 product_service子項目結構配置 5.2.5 服務之間的遠程調用 5.…

【普中STM32精靈開發攻略】--第 1 章 如何使用本攻略

學習本開發攻略主要參考的文檔有《STM32F1xx 中文參考手冊》和《Cortex M3權威指南(中文)》&#xff0c;這兩本都是 ST 官方手冊&#xff0c;尤其是《STM32F1xx 中文參考手冊》&#xff0c;里面包含了 STM32F1 內部所有外設介紹&#xff0c;非常詳細。大家在學習 STM32F103的時…

【Docker】RK3576-Debian上使用Docker安裝Ubuntu22.04+ROS2

1、簡述 RK3576自帶Debian12系統,如果要使用ROS2,可以在Debian上直接安裝ROS2,缺點是有的ROS包需要源碼編譯;當然最好是使用Ubuntu系統,可以使用Docker安裝,或者構建Ubuntu系統,替換Debian系統。 推薦使用Docker來安裝Ubuntu22.04,這里會有個疑問,是否可以直接使用Do…

解決docker load加載tar鏡像報json no such file or directory的錯誤

在使用docker加載離線鏡像文件時&#xff0c;出現了json no such file or directory的錯誤&#xff0c;剛開始以為是壓縮包拷貝壞了&#xff0c;重新拷貝了以后還是出現了問題。經過網上查找方案&#xff0c;并且自己實踐&#xff0c;采用下面的簡單方法就可以搞定。 歸結為一句…

《協作畫布的深層架構:React與TypeScript構建多人實時繪圖應用的核心邏輯》

多人在線協作繪圖應用的構建不僅是技術棧的簡單組合,更是對實時性、一致性與用戶體驗的多維挑戰。基于React與TypeScript開發這類應用,需要在圖形繪制的基礎功能之外,解決多用戶并發操作的同步難題、狀態回溯的邏輯沖突以及大規模協作的性能瓶頸。每一層架構的設計,都需兼顧…

智慧社區(八)——社區人臉識別出入管理系統設計與實現

在社區安全管理日益智能化的背景下&#xff0c;傳統的人工登記方式已難以滿足高效、精準的管理需求。本文將詳細介紹一套基于人臉識別技術的社區出入管理系統&#xff0c;該系統通過整合騰訊云 AI 接口、數據庫設計與業務邏輯&#xff0c;實現了居民出入自動識別、記錄追蹤與訪…

嵌入式開發學習———Linux環境下IO進程線程學習(四)

進程相關函數fork創建一個子進程&#xff0c;子進程復制父進程的地址空間。父進程返回子進程PID&#xff0c;子進程返回0。pid_t pid fork(); if (pid 0) { /* 子進程代碼 */ } else { /* 父進程代碼 */ }getpid獲取當前進程的PID。pid_t pid getpid();getppid獲取父進程的P…

標記-清除算法中的可達性判定與Chrome DevTools內存分析實踐

引言 在現代前端開發中&#xff0c;內存管理是保證應用性能與用戶體驗的核心技術之一。作為JavaScript運行時的基礎機制&#xff0c;標記-清除算法(Mark-and-Sweep) 通過可達性判定決定哪些內存需要回收&#xff0c;而Chrome DevTools提供的Memory工具則為開發者提供了深度的內…

微算法科技(NASDAQ:MLGO)基于量子重加密技術構建區塊鏈數據共享解決方案

隨著信息技術的飛速發展&#xff0c;數據已成為數字經濟時代的核心生產要素。數據的共享和安全往往是一對難以調和的矛盾。傳統的加密方法在面對日益強大的計算能力和復雜的網絡攻擊時&#xff0c;安全性受到了挑戰。微算法科技(NASDAQ&#xff1a;MLGO)通過引入量子重加密技術…

FastAPI快速入門P2:與SpringBoot比較

歡迎來到啾啾的博客&#x1f431;。 記錄學習點滴。分享工作思考和實用技巧&#xff0c;偶爾也分享一些雜談&#x1f4ac;。 有很多很多不足的地方&#xff0c;歡迎評論交流&#xff0c;感謝您的閱讀和評論&#x1f604;。 目錄引言1 FastAPI事件管理2 類的使用2.1 初始化方法對…

SAP-ABAP: Open SQL集合函數COUNT(統計行數)、SUM(數值求和)、AVG(平均值)、MAX/MIN(極值)深度指南

SAP Open SQL集合函數深度指南 1. 核心價值與特性函數作用關鍵特性COUNT統計行數用COUNT(*)包含NULL值行&#xff0c;COUNT(字段)排除NULLSUM數值求和自動過濾NULL值&#xff0c;結果類型與源字段相同AVG平均值必須用TYPE f接收&#xff0c;否則四舍五入導致精度丟失MAX/MIN極值…

【docker】UnionFS聯合操作系統

Linux 的 Namespace、CGroups 和 UnionFS 三大技術支撐了 Docker 的實現。 一、為什么需要聯合文件系統&#xff1f;在傳統操作系統中&#xff0c;每個文件系統都是獨立的孤島。但當我們需要&#xff1a;合并多個目錄的內容保持基礎系統不變的同時進行修改高效共享重復文件內容…

CTF-XXE 漏洞解題思路總結

一、XXE 漏洞簡介XXE (XML External Entity) 漏洞允許攻擊者通過構造惡意的 XML 輸入&#xff0c;強迫服務器的 XML 解析器執行非預期的操作。在 CTF 場景中&#xff0c;最常見的利用方式是讓解析器讀取服務器上的敏感文件&#xff0c;并將其內容返回給攻擊者。二、核心攻擊載荷…

GitLab:一站式 DevOps 平臺的全方位解析

GitLab&#xff1a;一站式 DevOps 平臺的全方位解析 在當今數字化時代&#xff0c;軟件研發的效率與質量直接決定企業的市場競爭力。GitLab 作為全球領先的 DevOps 平臺&#xff0c;憑借 “從構思到部署” 的全流程管理能力&#xff0c;已成為無數企業加速軟件交付的核心工具。…

Flink富函數:一種更靈活、可擴展的方式來定義數據流的處理邏輯

本文重點 Flink中的富函數類是一組用于處理數據流的函數接口和實現類。富函數類提供了一種更靈活和可擴展的方式來定義數據流的處理邏輯。 富函數類 富函數類是DataStream API提供的一個函數類的接口,所有的Flink函數類都有其Rich版本。富函數類一般是以抽象類的形式出現的。…

【STM32】HAL庫中的實現(四):RTC (實時時鐘)

&#x1f552;HAL庫中的實現&#xff1a;RTC&#xff08;Real-Time Clock&#xff09;實時時鐘RTC 是 STM32 的低功耗實時時鐘模塊&#xff0c;常用于&#xff1a; 實時時間維護&#xff08;年月日時分秒&#xff09;定時喚醒日志時間戳鬧鐘功能RTC&#xff08;實時時鐘&#x…

Pauli 矩陣指數函數展開為顯式矩陣 e^A -> B

要展開表達式 為普通矩陣&#xff0c;其中 是 Pauli 矩陣&#xff0c; 是單位向量&#xff0c; 是實數。以下是詳細推導步驟&#xff1a;1. Pauli 矩陣的性質Pauli 矩陣定義為&#xff1a;它們滿足以下關系&#xff1a;?其中 是 Kronecker delta&#xff0c;? 是 Levi-…

【Algorithm | 0x03 搜索與圖論】DFS

DFS基礎知識典型例題例1&#xff1a;n皇后問題例2&#xff1a;拍照例3&#xff1a;理發基礎知識 核心原理&#xff1a;一條路走到黑 示意圖&#xff1a;其含義表示&#xff0c;在這個圖中頂層是第0層&#xff0c;也就是后面dfs的入口&#xff0c;一般從dfs(0)開始操作。 模版&a…