├── .clang-format ├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .github ├── actions │ └── setup │ │ └── action.yml └── workflows │ ├── ci.yml │ └── docdeploy.yml ├── .gitignore ├── .gitmodules ├── .nvmrc ├── .prettierrc.js ├── .watchmanconfig ├── .yarn ├── patches │ ├── react-native-vision-camera-npm-3.9.2-3b35d90475.patch │ ├── react-native-vision-camera-npm-4.0.1-7ecdf9d15a.patch │ ├── react-native-vision-camera-npm-4.0.5-0f2bdc9daa.patch │ └── react-native-vision-camera-patch-cc9d789186.patch ├── plugins │ └── @yarnpkg │ │ ├── plugin-interactive-tools.cjs │ │ └── plugin-workspace-tools.cjs └── releases │ └── yarn-3.6.1.cjs ├── .yarnrc.yml ├── ASSIGNMENT.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── ReactNativeMediaPipe.podspec ├── android ├── CMakeLists.txt ├── build.gradle ├── gradle.properties └── src │ └── main │ ├── AndroidManifest.xml │ ├── AndroidManifestNew.xml │ └── java │ └── com │ └── reactnativemediapipe │ ├── MediapipePackage.kt │ ├── MediapipeViewManager.kt │ ├── facelandmarkdetection │ ├── ConvertHelpers.kt │ ├── FaceLandmarkDetectionFrameProcessorPlugin.kt │ ├── FaceLandmarkDetectionModule.kt │ └── FaceLandmarkDetectorHelper.kt │ ├── objectdetection │ ├── ConvertHelpers.kt │ ├── ObjectDetectionFrameProcessorPlugin.kt │ ├── ObjectDetectionModule.kt │ └── ObjectDetectorHelper.kt │ ├── posedetection │ ├── ConvertHelpers.kt │ ├── PoseDetectionFrameProcessorPlugin.kt │ ├── PoseDetectionModule.kt │ └── PoseDetectorHelper.kt │ └── shared │ ├── ConvertHelpers.kt │ ├── MediaHelper.kt │ └── OrientationHelpers.kt ├── babel.config.js ├── docsite ├── .gitignore ├── README.md ├── babel.config.js ├── docs │ ├── _coming-soon.md │ ├── api_pages │ │ ├── _category_.json │ │ ├── face-detection.md │ │ ├── face-landmark-detection.md │ │ ├── gesture-recognition.md │ │ ├── hand-landmark-detection.md │ │ ├── image-classification.md │ │ ├── image-embedding.md │ │ ├── image-segmentation.md │ │ ├── interactive-segmentation.md │ │ ├── object-detection.md │ │ └── pose-landmark-detection.md │ ├── intro.md │ └── troubleshooting_guides │ │ ├── _category_.json │ │ └── long_path_issue.md ├── docusaurus.config.ts ├── package.json ├── sidebars.ts ├── src │ ├── components │ │ └── HomepageFeatures │ │ │ ├── index.tsx │ │ │ └── styles.module.css │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.module.css │ │ ├── index.tsx │ │ └── markdown-page.md ├── static │ ├── .nojekyll │ └── img │ │ ├── docusaurus-social-card.jpg │ │ ├── docusaurus.png │ │ ├── react-native-mediapipe-favicon.ico │ │ ├── rnmp_logo.png │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ └── undraw_docusaurus_tree.svg └── tsconfig.json ├── examples ├── .gitignore ├── README.md ├── facelandmarkdetection │ ├── .bundle │ │ └── config │ ├── .watchmanconfig │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ ├── android │ │ ├── app │ │ │ ├── build.gradle │ │ │ ├── debug.keystore │ │ │ ├── download_tasks.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── facelandmarkdetection │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ └── MainApplication.kt │ │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── app.json │ ├── babel.config.js │ ├── index.js │ ├── ios │ │ ├── .xcode.env │ │ ├── Podfile │ │ ├── Podfile.lock │ │ ├── RunScripts │ │ │ └── download_models.sh │ │ ├── facelandmarkdetection.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── facelandmarkdetection.xcscheme │ │ ├── facelandmarkdetection.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── facelandmarkdetection │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.mm │ │ │ ├── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ ├── 1024.png │ │ │ │ │ ├── 120 1.png │ │ │ │ │ ├── 120.png │ │ │ │ │ ├── 180.png │ │ │ │ │ ├── 40.png │ │ │ │ │ ├── 58.png │ │ │ │ │ ├── 60.png │ │ │ │ │ ├── 80.png │ │ │ │ │ ├── 87.png │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── LaunchScreen.storyboard │ │ │ ├── PrivacyInfo.xcprivacy │ │ │ └── main.m │ │ └── facelandmarkdetectionTests │ │ │ ├── Info.plist │ │ │ └── facelandmarkdetectionTests.m │ ├── jest.config.js │ ├── metro.config.js │ ├── package.json │ ├── react-native.config.js │ ├── src │ │ ├── App.tsx │ │ ├── CameraStream.tsx │ │ ├── Drawing.tsx │ │ ├── Photo.tsx │ │ ├── Settings.tsx │ │ ├── app-settings.ts │ │ ├── colors.ts │ │ └── navigation.ts │ └── tsconfig.json ├── objectdetection │ ├── .bundle │ │ └── config │ ├── .watchmanconfig │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ ├── __mocks__ │ │ ├── react-native-vision.camera.js │ │ └── react-native-worklets-core.js │ ├── android │ │ ├── app │ │ │ ├── build.gradle │ │ │ ├── debug.keystore │ │ │ ├── download_models.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── objectdetection │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ └── MainApplication.kt │ │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── app.json │ ├── babel.config.js │ ├── index.js │ ├── ios │ │ ├── .xcode.env │ │ ├── Podfile │ │ ├── Podfile.lock │ │ ├── RunScripts │ │ │ └── download_models.sh │ │ ├── objectdetection.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── objectdetection.xcscheme │ │ ├── objectdetection.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── objectdetection │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.mm │ │ │ ├── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ ├── 1024.png │ │ │ │ │ ├── 120 1.png │ │ │ │ │ ├── 120.png │ │ │ │ │ ├── 180.png │ │ │ │ │ ├── 40.png │ │ │ │ │ ├── 58.png │ │ │ │ │ ├── 60.png │ │ │ │ │ ├── 80.png │ │ │ │ │ ├── 87.png │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── LaunchScreen.storyboard │ │ │ └── main.m │ │ └── objectdetectionTests │ │ │ ├── Info.plist │ │ │ └── objectdetectionTests.m │ ├── jest.config.js │ ├── metro.config.js │ ├── package.json │ ├── react-native.config.js │ ├── src │ │ ├── App.tsx │ │ ├── CameraStream.tsx │ │ ├── Drawing.tsx │ │ ├── Photo.tsx │ │ ├── Settings.tsx │ │ ├── app-settings.ts │ │ ├── colors.ts │ │ └── navigation.ts │ └── tsconfig.json └── posedetection │ ├── .bundle │ └── config │ ├── .watchmanconfig │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ ├── android │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── download_tasks.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── posedetection │ │ │ │ ├── MainActivity.kt │ │ │ │ └── MainApplication.kt │ │ │ └── res │ │ │ ├── drawable │ │ │ └── rn_edit_text_material.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle │ ├── app.json │ ├── babel.config.js │ ├── index.js │ ├── ios │ ├── .xcode.env │ ├── Podfile │ ├── Podfile.lock │ ├── RunScripts │ │ └── download_models.sh │ ├── posedetection.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── posedetection.xcscheme │ ├── posedetection.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── posedetection │ │ ├── AppDelegate.h │ │ ├── AppDelegate.mm │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ ├── PrivacyInfo.xcprivacy │ │ └── main.m │ └── posedetectionTests │ │ ├── Info.plist │ │ └── posedetectionTests.m │ ├── jest.config.js │ ├── metro.config.js │ ├── package.json │ ├── react-native.config.js │ ├── src │ ├── App.tsx │ ├── CameraStream.tsx │ ├── Drawing.tsx │ ├── Photo.tsx │ ├── Settings.tsx │ ├── app-settings.ts │ └── navigation.ts │ └── tsconfig.json ├── ios ├── Mediapipe-Bridging-Header.h ├── MediapipeViewManager.m ├── MediapipeViewManager.swift ├── ReactNativeMediaPipe.h ├── facelandmarkdetection │ ├── FaceLandmarkDetectionFrameProcessorPlugin.m │ ├── FaceLandmarkDetectionFrameProcessorPlugin.swift │ ├── FaceLandmarkDetectionModule.m │ ├── FaceLandmarkDetectionModule.swift │ ├── FaceLandmarkDetectorHelper.swift │ └── FldConvertHelpers.swift ├── objectdetection │ ├── ConvertHelpers.swift │ ├── ObjectDetectionFrameProcessorPlugin.m │ ├── ObjectDetectionFrameProcessorPlugin.swift │ ├── ObjectDetectionModule.m │ ├── ObjectDetectionModule.swift │ └── ObjectDetectorHelper.swift ├── posedetection │ ├── PdConvertHelpers.swift │ ├── PoseDetectionFrameProcessorPlugin.m │ ├── PoseDetectionFrameProcessorPlugin.swift │ ├── PoseDetectionModule.m │ ├── PoseDetectionModule.swift │ └── PoseDetectorHelper.swift └── shared │ ├── ConvertHelper.swift │ ├── MediaHelper.swift │ └── OrientationHelper.swift ├── lefthook.yml ├── package-lock.json ├── package.json ├── src ├── __tests__ │ ├── convert.test.ts │ └── index.test.tsx ├── faceLandmarkDetection │ └── index.ts ├── index.ts ├── objectDetection │ └── index.ts ├── poseDetection │ └── index.ts └── shared │ ├── convert.ts │ ├── mediapipeCamera.tsx │ └── types.ts ├── tools ├── long-paths-enabled.reg └── windows │ └── ninja.exe ├── tsconfig.build.json ├── tsconfig.json ├── tsconfig.shared.json ├── turbo.json └── yarn.lock /.clang-format: -------------------------------------------------------------------------------- 1 | # Config for clang-format version 16 2 | 3 | # Standard 4 | BasedOnStyle: llvm 5 | Standard: c++14 6 | 7 | # Indentation 8 | IndentWidth: 2 9 | ColumnLimit: 140 10 | 11 | # Includes 12 | SortIncludes: true 13 | SortUsingDeclarations: true 14 | 15 | # Pointer and reference alignment 16 | PointerAlignment: Left 17 | ReferenceAlignment: Left 18 | ReflowComments: true 19 | 20 | # Line breaking options 21 | BreakBeforeBraces: Attach 22 | BreakConstructorInitializers: BeforeColon 23 | AllowShortFunctionsOnASingleLine: Empty 24 | IndentCaseLabels: true 25 | NamespaceIndentation: Inner 26 | 27 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Setup Node.js and install dependencies 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - name: Setup Node.js 8 | uses: actions/setup-node@v3 9 | with: 10 | node-version-file: .nvmrc 11 | 12 | - name: Cache dependencies 13 | id: yarn-cache 14 | uses: actions/cache@v3 15 | with: 16 | path: | 17 | **/node_modules 18 | .yarn/install-state.gz 19 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} 20 | restore-keys: | 21 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 22 | ${{ runner.os }}-yarn- 23 | 24 | - name: Install dependencies 25 | if: steps.yarn-cache.outputs.cache-hit != 'true' 26 | run: yarn install --immutable 27 | shell: bash 28 | -------------------------------------------------------------------------------- /.github/workflows/docdeploy.yml: -------------------------------------------------------------------------------- 1 | name: docdeploy 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths: 7 | - 'docsite/**' 8 | jobs: 9 | deploy-docsite: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: Build Docusaurus website 14 | run: | 15 | cd docsite 16 | yarn install 17 | yarn run build 18 | - name: Deploy to GitHub Pages 19 | if: success() 20 | uses: crazy-max/ghaction-github-pages@v4 21 | with: 22 | target_branch: gh-pages 23 | build_dir: docsite/build 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | jsconfig.json 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | .xcode.env.local 32 | 33 | # TypeScript cache 34 | *.tsbuildinfo 35 | 36 | # Android/IJ 37 | # 38 | .classpath 39 | .cxx 40 | .gradle 41 | .idea 42 | .project 43 | .settings 44 | local.properties 45 | android.iml 46 | 47 | # node.js 48 | # 49 | node_modules/ 50 | npm-debug.log 51 | yarn-debug.log 52 | yarn-error.log 53 | 54 | # BUCK 55 | buck-out/ 56 | \.buckd/ 57 | android/app/libs 58 | android/keystores/debug.keystore 59 | 60 | # Yarn 61 | .yarn/* 62 | !.yarn/patches 63 | !.yarn/plugins 64 | !.yarn/releases 65 | !.yarn/sdks 66 | !.yarn/versions 67 | 68 | # Expo 69 | .expo/ 70 | 71 | # Turborepo 72 | .turbo/ 73 | 74 | # generated by bob 75 | lib/ 76 | 77 | # jest 78 | coverage/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/.gitmodules -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: true, 3 | parser: 'typescript', 4 | printWidth: 80, 5 | semi: true, 6 | tabWidth: 2, 7 | trailingComma: 'es5', 8 | }; 9 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.yarn/patches/react-native-vision-camera-npm-3.9.2-3b35d90475.patch: -------------------------------------------------------------------------------- 1 | diff --git a/android/build.gradle b/android/build.gradle 2 | index 88ea6a5b7b32dca55eeedc5b4bf255157742abdf..c1ba2dd18f2b1af7d880f5cf9c27d08638ac0221 100644 3 | --- a/android/build.gradle 4 | +++ b/android/build.gradle 5 | @@ -1,5 +1,6 @@ 6 | import java.nio.file.Paths 7 | import com.android.Version 8 | +import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform 9 | 10 | def agpVersion = Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger() 11 | def androidManifestPath = agpVersion >= 7 ? 'src/main/AndroidManifest.xml' : 'src/hasNamespace/AndroidManifest.xml' 12 | @@ -72,11 +73,27 @@ static def findNodeModules(baseDir) { 13 | 14 | def nodeModules = findNodeModules(projectDir) 15 | 16 | +static def findTools(baseDir) { 17 | + def basePath = baseDir.toPath().normalize() 18 | + while (basePath) { 19 | + def toolsPath = Paths.get(basePath.toString(), "tools") 20 | + if (toolsPath.toFile().exists()) { 21 | + return toolsPath.toString() 22 | + } 23 | + basePath = basePath.getParent() 24 | + } 25 | + throw new GradleException("react-native-vision-camera: Failed to find tools/ path!") 26 | +} 27 | + 28 | +def toolsDir = findTools(projectDir) 29 | + 30 | def hasWorklets = !safeExtGetBool('VisionCamera_disableFrameProcessors', false) && findProject(":react-native-worklets-core") != null 31 | logger.warn("[VisionCamera] react-native-worklets-core ${hasWorklets ? "found" : "not found"}, Frame Processors ${hasWorklets ? "enabled" : "disabled"}!") 32 | 33 | def enableCodeScanner = safeExtGetBool('VisionCamera_enableCodeScanner', false) 34 | 35 | +def os = DefaultNativePlatform.currentOperatingSystem; 36 | + 37 | repositories { 38 | google() 39 | mavenCentral() 40 | @@ -118,9 +135,17 @@ android { 41 | externalNativeBuild { 42 | cmake { 43 | cppFlags "-O2 -frtti -fexceptions -Wall -Wno-unused-variable -fstack-protector-all" 44 | - arguments "-DANDROID_STL=c++_shared", 45 | - "-DNODE_MODULES_DIR=${nodeModules}", 46 | - "-DENABLE_FRAME_PROCESSORS=${hasWorklets ? "ON" : "OFF"}" 47 | + if (os.isWindows()) { 48 | + arguments "-DANDROID_STL=c++_shared", 49 | + "-DNODE_MODULES_DIR=${nodeModules}", 50 | + "-DENABLE_FRAME_PROCESSORS=${hasWorklets ? "ON" : "OFF"}", 51 | + "-DCMAKE_MAKE_PROGRAM=${toolsDir}\\windows\\ninja.exe", 52 | + "-DCMAKE_OBJECT_PATH_MAX=1024" 53 | + } else { 54 | + arguments "-DANDROID_STL=c++_shared", 55 | + "-DNODE_MODULES_DIR=${nodeModules}", 56 | + "-DENABLE_FRAME_PROCESSORS=${hasWorklets ? "ON" : "OFF"}" 57 | + } 58 | abiFilters (*reactNativeArchitectures()) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.yarn/patches/react-native-vision-camera-npm-4.0.1-7ecdf9d15a.patch: -------------------------------------------------------------------------------- 1 | diff --git a/android/build.gradle b/android/build.gradle 2 | index 3ef638b2b91d9d94a8f43222b6ffd953e57110fb..d507ff0fa8705e5bb794828d1940d81dd27cf969 100644 3 | --- a/android/build.gradle 4 | +++ b/android/build.gradle 5 | @@ -1,5 +1,6 @@ 6 | import java.nio.file.Paths 7 | import com.android.Version 8 | +import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform 9 | 10 | def agpVersion = Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger() 11 | def androidManifestPath = agpVersion >= 7 ? 'src/main/AndroidManifest.xml' : 'src/hasNamespace/AndroidManifest.xml' 12 | @@ -89,11 +90,27 @@ if (hasWorklets) { 13 | def enableCodeScanner = safeExtGetBool('VisionCamera_enableCodeScanner', false) 14 | logger.warn("[VisionCamera] VisionCamera_enableCodeScanner is set to $enableCodeScanner!") 15 | 16 | +static def findTools(baseDir) { 17 | + def basePath = baseDir.toPath().normalize() 18 | + while (basePath) { 19 | + def toolsPath = Paths.get(basePath.toString(), "tools") 20 | + if (toolsPath.toFile().exists()) { 21 | + return toolsPath.toString() 22 | + } 23 | + basePath = basePath.getParent() 24 | + } 25 | + throw new GradleException("react-native-vision-camera: Failed to find tools/ path!") 26 | +} 27 | + 28 | +def toolsDir = findTools(projectDir) 29 | + 30 | repositories { 31 | google() 32 | mavenCentral() 33 | } 34 | 35 | +def os = DefaultNativePlatform.currentOperatingSystem; 36 | + 37 | android { 38 | if (agpVersion >= 7) { 39 | namespace "com.mrousavy.camera" 40 | @@ -130,9 +147,17 @@ android { 41 | externalNativeBuild { 42 | cmake { 43 | cppFlags "-O2 -frtti -fexceptions -Wall -Wno-unused-variable -fstack-protector-all" 44 | - arguments "-DANDROID_STL=c++_shared", 45 | - "-DNODE_MODULES_DIR=${nodeModules}", 46 | - "-DENABLE_FRAME_PROCESSORS=${enableFrameProcessors ? "ON" : "OFF"}" 47 | + if (os.isWindows()) { 48 | + arguments "-DANDROID_STL=c++_shared", 49 | + "-DNODE_MODULES_DIR=${nodeModules}", 50 | + "-DENABLE_FRAME_PROCESSORS=${hasWorklets ? "ON" : "OFF"}", 51 | + "-DCMAKE_MAKE_PROGRAM=${toolsDir}\\windows\\ninja.exe", 52 | + "-DCMAKE_OBJECT_PATH_MAX=1024" 53 | + } else { 54 | + arguments "-DANDROID_STL=c++_shared", 55 | + "-DNODE_MODULES_DIR=${nodeModules}", 56 | + "-DENABLE_FRAME_PROCESSORS=${hasWorklets ? "ON" : "OFF"}" 57 | + } 58 | abiFilters (*reactNativeArchitectures()) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.yarn/patches/react-native-vision-camera-patch-cc9d789186.patch: -------------------------------------------------------------------------------- 1 | diff --git a/android/src/main/java/com/mrousavy/camera/frameprocessors/VisionCameraProxy.kt b/android/src/main/java/com/mrousavy/camera/frameprocessors/VisionCameraProxy.kt 2 | index d697befefc1a1d5b8f21ae9b2925161d03b79306..8de418b0b3196000fa09990b1658bb4196a5c4f9 100644 3 | --- a/android/src/main/java/com/mrousavy/camera/frameprocessors/VisionCameraProxy.kt 4 | +++ b/android/src/main/java/com/mrousavy/camera/frameprocessors/VisionCameraProxy.kt 5 | @@ -7,12 +7,14 @@ import com.facebook.jni.HybridData 6 | import com.facebook.proguard.annotations.DoNotStrip 7 | import com.facebook.react.bridge.ReactApplicationContext 8 | import com.facebook.react.bridge.UiThreadUtil 9 | +import com.facebook.react.common.annotations.FrameworkAPI 10 | import com.facebook.react.turbomodule.core.CallInvokerHolderImpl 11 | import com.facebook.react.uimanager.UIManagerHelper 12 | import com.mrousavy.camera.core.ViewNotFoundError 13 | import com.mrousavy.camera.react.CameraView 14 | import java.lang.ref.WeakReference 15 | 16 | +@OptIn(FrameworkAPI::class) 17 | @Suppress("KotlinJniMissingFunction") // we use fbjni. 18 | class VisionCameraProxy(private val reactContext: ReactApplicationContext) { 19 | companion object { 20 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | nmHoistingLimits: workspaces 3 | 4 | plugins: 5 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 6 | spec: "@yarnpkg/plugin-interactive-tools" 7 | - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs 8 | spec: "@yarnpkg/plugin-workspace-tools" 9 | 10 | yarnPath: .yarn/releases/yarn-3.6.1.cjs 11 | -------------------------------------------------------------------------------- /ASSIGNMENT.md: -------------------------------------------------------------------------------- 1 | # Assignment 2 | 3 | Add your github alias to this file 4 | 5 | ## add below this line: 6 | 7 | adamandwise - Adam Wise 8 | 9 | sukanvisapearyoo - Sukanvisa Pearyoo 10 | 11 | jazmin915- Jazmin Gonzalez 12 | michellrodriguez08 - Michell Rodriguez 13 | shackerman - Jack Ruiz 14 | 15 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Charles Parker 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-mediapipe 2 | 3 | A React Native Camera and Player for MediaPipe applications. 4 | 5 | * [Documentation](https://cdiddy77.github.io/react-native-mediapipe/) 6 | 7 | ## Requirements 8 | * Gradle minimum SDK 24 or higher 9 | * Android-SDK Version 26 or higher 10 | * iOS 12 or higher 11 | 12 | ## Features 13 | * 🎥 Video streaming from a react-native app to a media pipe 14 | * 🔍 AI Object Detection 15 | * 🧩 Works as a react-native component 16 | 17 | ## Getting Started 18 | 19 | 1) Install react-native-mediapipe from npm: 20 | ```sh 21 | npm install react-native-mediapipe react-native-vision-camera react-native-worklets-core 22 | ``` 23 | or Install react-native-mediapipe from yarn: 24 | ```sh 25 | yarn add react-native-mediapipe react-native-vision-camera react-native-worklets-core 26 | ``` 27 | 28 | ```js 29 | import { MediaPipeCamera } from "react-native-mediapipe"; 30 | ``` 31 | 32 | 2) In your babel.config.js file 33 | ``` 34 | module.exports = { 35 | presets: ['module:@react-native/babel-present'], 36 | plugins: [['react-native-worklets-core/plugin']], 37 | } 38 | ``` 39 | 40 | 3) In your gradle/build.gradle file 41 | ``` 42 | buildscript { 43 | ext { 44 | ... 45 | minSdkVersion = 24 (Make sure that this is at least 24) 46 | ... 47 | } 48 | ... 49 | } 50 | ``` 51 | 4) If you're on IOS: 52 | In your info.plist file in the outermost tag: 53 | ``` 54 | NSCameraUsageDescription 55 | $(PRODUCT_NAME) needs access to your Camera. 56 | 57 | 58 | NSMicrophoneUsageDescription 59 | $(PRODUCT_NAME) needs access to your Microphone. 60 | ``` 61 | then in your terminal: 62 | ``` 63 | cd ios 64 | bundle install (you only need to do this once) 65 | pod install 66 | ``` 67 | 68 | 69 | 4) If you're on Android: 70 | In your AndroidManifest.xml file inside the tag: 71 | ``` 72 | 73 | 74 | 75 | 76 | ``` 77 | 78 | 79 | ## Contributing 80 | 81 | See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. 82 | 83 | Join the [Community](https://discord.gg/ApuAzVnAaX) here! 84 | 85 | ## License 86 | 87 | MIT 88 | 89 | See the [License file](LICENSE) for more information. 90 | 91 | --- 92 | 93 | Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) 94 | -------------------------------------------------------------------------------- /ReactNativeMediaPipe.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 4 | folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' 5 | 6 | Pod::Spec.new do |s| 7 | s.name = "ReactNativeMediaPipe" 8 | s.version = package["version"] 9 | s.summary = package["description"] 10 | s.homepage = package["homepage"] 11 | s.license = package["license"] 12 | s.authors = package["author"] 13 | 14 | s.platforms = { :ios => min_ios_version_supported } 15 | s.source = { :git => "https://github.com/cdiddy77/react-native-mediapipe.git", :tag => "#{s.version}" } 16 | 17 | s.source_files = "ios/**/*.{h,m,mm,swift}" 18 | 19 | s.dependency "MediaPipeTasksVision", "0.10.12" 20 | s.dependency "VisionCamera" 21 | 22 | # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. 23 | # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79. 24 | if respond_to?(:install_modules_dependencies, true) 25 | install_modules_dependencies(s) 26 | else 27 | s.dependency "React-Core" 28 | 29 | # Don't install the dependencies when we run `pod install` in the old architecture. 30 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then 31 | s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" 32 | s.pod_target_xcconfig = { 33 | "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", 34 | "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", 35 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" 36 | } 37 | s.dependency "React-RCTFabric" 38 | s.dependency "React-Codegen" 39 | s.dependency "RCT-Folly" 40 | s.dependency "RCTRequired" 41 | s.dependency "RCTTypeSafety" 42 | s.dependency "ReactCommon/turbomodule/core" 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /android/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(ResizeConvertLib) 2 | cmake_minimum_required(VERSION 3.9.0) 3 | 4 | set (PACKAGE_NAME "ResizeConvertLib") 5 | set (BUILD_DIR ${CMAKE_SOURCE_DIR}/build) 6 | set (CMAKE_VERBOSE_MAKEFILE ON) 7 | set (CMAKE_CXX_STANDARD 17) 8 | 9 | # Third party libraries (Prefabs) 10 | find_package(fbjni REQUIRED CONFIG) 11 | find_library(LOG_LIB log) 12 | 13 | # libyuv 14 | add_subdirectory(../libyuv libyuv) 15 | 16 | add_library(${PACKAGE_NAME} SHARED 17 | src/main/cpp/ResizeConvert.cpp 18 | src/main/cpp/JImage.cpp 19 | src/main/cpp/JImagePlane.cpp 20 | src/main/cpp/ResizeConvertLib.cpp 21 | ) 22 | 23 | # Specifies a path to native header files. 24 | target_include_directories( 25 | ${PACKAGE_NAME} PRIVATE 26 | src/main/cpp 27 | ../libyuv/include 28 | ) 29 | 30 | target_link_libraries( 31 | ${PACKAGE_NAME} 32 | ${LOG_LIB} # <-- Logcat logger 33 | android # <-- Android JNI core 34 | fbjni::fbjni # <-- fbjni 35 | yuv # <-- libyuv 36 | ) 37 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | Mediapipe_kotlinVersion=1.7.0 2 | Mediapipe_minSdkVersion=21 3 | Mediapipe_targetSdkVersion=31 4 | Mediapipe_compileSdkVersion=31 5 | Mediapipe_ndkversion=21.4.7075529 6 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifestNew.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativemediapipe/MediapipePackage.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemediapipe 2 | 3 | import com.facebook.react.ReactPackage 4 | import com.facebook.react.bridge.NativeModule 5 | import com.facebook.react.bridge.ReactApplicationContext 6 | import com.facebook.react.uimanager.ViewManager 7 | import com.mrousavy.camera.frameprocessors.FrameProcessorPluginRegistry 8 | import com.reactnativemediapipe.facelandmarkdetection.FaceLandmarkDetectionFrameProcessorPlugin 9 | import com.reactnativemediapipe.facelandmarkdetection.FaceLandmarkDetectionModule 10 | import com.reactnativemediapipe.objectdetection.ObjectDetectionFrameProcessorPlugin 11 | import com.reactnativemediapipe.objectdetection.ObjectDetectionModule 12 | import com.reactnativemediapipe.posedetection.PoseDetectionFrameProcessorPlugin 13 | import com.reactnativemediapipe.posedetection.PoseDetectionModule 14 | 15 | 16 | class MediapipePackage : ReactPackage { 17 | companion object { 18 | init { 19 | FrameProcessorPluginRegistry.addFrameProcessorPlugin("objectDetection") { _, _ -> 20 | ObjectDetectionFrameProcessorPlugin() 21 | } 22 | FrameProcessorPluginRegistry.addFrameProcessorPlugin("faceLandmarkDetection") { _, _ -> 23 | FaceLandmarkDetectionFrameProcessorPlugin() 24 | } 25 | FrameProcessorPluginRegistry.addFrameProcessorPlugin("poseDetection") { _, _ -> 26 | PoseDetectionFrameProcessorPlugin() 27 | } 28 | } 29 | } 30 | 31 | override fun createNativeModules(reactContext: ReactApplicationContext): List { 32 | return listOf( 33 | ObjectDetectionModule(reactContext), 34 | FaceLandmarkDetectionModule(reactContext), 35 | PoseDetectionModule(reactContext) 36 | ) 37 | } 38 | 39 | override fun createViewManagers(reactContext: ReactApplicationContext): List> { 40 | return listOf(MediapipeViewManager()) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativemediapipe/MediapipeViewManager.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemediapipe 2 | 3 | import android.graphics.Color 4 | import android.view.View 5 | import com.facebook.react.uimanager.SimpleViewManager 6 | import com.facebook.react.uimanager.ThemedReactContext 7 | import com.facebook.react.uimanager.annotations.ReactProp 8 | 9 | class MediapipeViewManager : SimpleViewManager() { 10 | override fun getName() = "MediapipeView" 11 | 12 | override fun createViewInstance(reactContext: ThemedReactContext): View { 13 | return View(reactContext) 14 | } 15 | 16 | @ReactProp(name = "color") 17 | fun setColor(view: View, color: String) { 18 | view.setBackgroundColor(Color.parseColor(color)) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativemediapipe/facelandmarkdetection/FaceLandmarkDetectionFrameProcessorPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemediapipe.facelandmarkdetection 2 | 3 | import com.google.mediapipe.framework.image.MediaImageBuilder 4 | import com.mrousavy.camera.frameprocessors.Frame 5 | import com.mrousavy.camera.frameprocessors.FrameProcessorPlugin 6 | import com.reactnativemediapipe.shared.imageOrientation 7 | 8 | class FaceLandmarkDetectionFrameProcessorPlugin() : FrameProcessorPlugin() { 9 | 10 | companion object { 11 | private const val TAG = "FaceLandmarkDetectionFrameProcessorPlugin" 12 | } 13 | 14 | override fun callback(frame: Frame, params: MutableMap?): Any? { 15 | val detectorHandle = (params?.get("detectorHandle") as? Double) ?: return false 16 | val detector = FaceLandmarkDetectorMap.detectorMap[detectorHandle.toInt()] ?: return false 17 | val orientation = params["orientation"] as String 18 | val mappedOrientation = imageOrientation(orientation) 19 | mappedOrientation ?: return false 20 | 21 | val mpImage = MediaImageBuilder(frame.image).build() 22 | detector.detectLiveStream(mpImage, mappedOrientation) 23 | return true 24 | } 25 | 26 | private enum class PixelFormat { 27 | RGB, 28 | BGR, 29 | ARGB, 30 | RGBA, 31 | BGRA, 32 | ABGR; 33 | 34 | companion object { 35 | fun fromString(string: String): PixelFormat = 36 | when (string) { 37 | "rgb" -> RGB 38 | "rgba" -> RGBA 39 | "argb" -> ARGB 40 | "bgra" -> BGRA 41 | "bgr" -> BGR 42 | "abgr" -> ABGR 43 | else -> throw Error("Invalid PixelFormat! ($string)") 44 | } 45 | } 46 | } 47 | 48 | private enum class DataType { 49 | UINT8, 50 | FLOAT32; 51 | 52 | companion object { 53 | fun fromString(string: String): DataType = 54 | when (string) { 55 | "uint8" -> UINT8 56 | "float32" -> FLOAT32 57 | else -> throw Error("Invalid DataType! ($string)") 58 | } 59 | } 60 | } 61 | } 62 | 63 | private enum class Rotation(val degrees: Int) { 64 | Rotation0(0), 65 | Rotation90(90), 66 | Rotation180(180), 67 | Rotation270(270); 68 | 69 | companion object { 70 | fun fromString(value: String): Rotation = 71 | when (value) { 72 | "0deg" -> Rotation0 73 | "90deg" -> Rotation90 74 | "180deg" -> Rotation180 75 | "270deg" -> Rotation270 76 | else -> throw Error("Invalid rotation value! ($value)") 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativemediapipe/posedetection/ConvertHelpers.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemediapipe.posedetection 2 | 3 | import com.facebook.react.bridge.Arguments 4 | import com.facebook.react.bridge.WritableMap 5 | import com.facebook.react.bridge.WritableNativeArray 6 | import com.facebook.react.bridge.WritableNativeMap 7 | import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarkerResult 8 | import com.reactnativemediapipe.shared.landmarkToWritableMap 9 | import com.reactnativemediapipe.shared.normalizedLandmarkToWritableMap 10 | 11 | 12 | fun convertResultBundleToWritableMap(resultBundle: PoseDetectorHelper.ResultBundle): WritableMap { 13 | val map = Arguments.createMap() 14 | val resultsArray = Arguments.createArray() 15 | resultBundle.results.forEach { result -> 16 | resultsArray.pushMap(poseLandmarkerResultToWritableMap(result)) 17 | } 18 | map.putArray("results", resultsArray) 19 | map.putInt("inputImageHeight", resultBundle.inputImageHeight) 20 | map.putInt("inputImageWidth", resultBundle.inputImageWidth) 21 | map.putDouble("inferenceTime", resultBundle.inferenceTime.toDouble()) 22 | return map 23 | } 24 | 25 | fun poseLandmarkerResultToWritableMap(result: PoseLandmarkerResult): WritableMap { 26 | val resultMap = WritableNativeMap() 27 | val landmarksArray = WritableNativeArray() 28 | val worldLandmarksArray = WritableNativeArray() 29 | result.landmarks().forEach { landmarks -> 30 | val landmarkArray = WritableNativeArray() 31 | landmarks.forEach { it -> landmarkArray.pushMap(normalizedLandmarkToWritableMap(it)) } 32 | landmarksArray.pushArray(landmarkArray) 33 | } 34 | 35 | result.worldLandmarks().forEach { worldLandmarks -> 36 | val worldLandmarkArray = WritableNativeArray() 37 | worldLandmarks.forEach { it -> worldLandmarkArray.pushMap(landmarkToWritableMap(it)) } 38 | worldLandmarksArray.pushArray(worldLandmarkArray) 39 | } 40 | 41 | 42 | resultMap.putArray("landmarks", landmarksArray) 43 | resultMap.putArray("worldLandmarks", worldLandmarksArray) 44 | resultMap.putArray("segmentationMask", WritableNativeArray()) 45 | 46 | return resultMap 47 | } 48 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativemediapipe/shared/ConvertHelpers.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemediapipe.shared 2 | 3 | import com.facebook.react.bridge.WritableMap 4 | import com.facebook.react.bridge.WritableNativeArray 5 | import com.facebook.react.bridge.WritableNativeMap 6 | import com.google.mediapipe.tasks.components.containers.Landmark 7 | import com.google.mediapipe.tasks.components.containers.NormalizedLandmark 8 | import com.mrousavy.camera.core.types.Orientation 9 | 10 | // Converts NormalizedLandmark to WritableMap 11 | fun normalizedLandmarkToWritableMap(landmark: NormalizedLandmark): WritableMap { 12 | val map = WritableNativeMap() 13 | map.putDouble("x", landmark.x().toDouble()) 14 | map.putDouble("y", landmark.y().toDouble()) 15 | map.putDouble("z", landmark.z().toDouble()) 16 | return map 17 | } 18 | 19 | fun landmarkToWritableMap(landmark: Landmark): WritableMap { 20 | val map = WritableNativeMap() 21 | map.putDouble("x", landmark.x().toDouble()) 22 | map.putDouble("y", landmark.y().toDouble()) 23 | map.putDouble("z", landmark.z().toDouble()) 24 | return map 25 | } 26 | 27 | // Converts TransformMatrix to WritableMap 28 | fun transformMatrixToWritableMap(matrix: FloatArray): WritableMap { 29 | val map = WritableNativeMap() 30 | val dataArray = WritableNativeArray() 31 | 32 | for (value in matrix) { 33 | dataArray.pushDouble(value.toDouble()) 34 | } 35 | 36 | map.putInt("rows", 4) 37 | map.putInt("columns", 4) 38 | map.putArray("data", dataArray) 39 | return map 40 | } 41 | 42 | fun orientationToDegrees(orientation: Orientation): Int = 43 | when (orientation) { 44 | Orientation.PORTRAIT -> 0 45 | Orientation.LANDSCAPE_LEFT -> 90 46 | Orientation.PORTRAIT_UPSIDE_DOWN -> 180 47 | Orientation.LANDSCAPE_RIGHT -> -90 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativemediapipe/shared/MediaHelper.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemediapipe.shared 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.BitmapFactory 5 | 6 | sealed class MediaLoadingError(message: String) : Exception(message) { 7 | object InvalidURL : MediaLoadingError("Provided string is not a valid URL.") 8 | object UnableToLoadData : MediaLoadingError("Could not load data from the URL.") 9 | object UnableToCreateImage : MediaLoadingError("Data loaded is not a valid image.") 10 | object UnableToCreateVideoAsset : MediaLoadingError("Data loaded is not a valid video.") 11 | } 12 | 13 | 14 | fun loadBitmapFromPath(fileUrl: String): Bitmap { 15 | var filePath: String 16 | if (fileUrl.startsWith("file://")) { 17 | filePath = fileUrl.substring(7) 18 | } else { 19 | filePath = fileUrl 20 | } 21 | val result = BitmapFactory.decodeFile(filePath) 22 | result?.let { 23 | return it 24 | } 25 | throw MediaLoadingError.UnableToLoadData; 26 | } 27 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativemediapipe/shared/OrientationHelpers.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemediapipe.shared 2 | 3 | import com.mrousavy.camera.core.types.Orientation 4 | 5 | fun imageOrientation(orientation: String): Orientation? { 6 | return when (orientation) { 7 | "portrait" -> Orientation.PORTRAIT 8 | "portrait-upside-down" -> Orientation.PORTRAIT_UPSIDE_DOWN 9 | "landscape-left" -> Orientation.LANDSCAPE_LEFT 10 | "landscape-right" -> Orientation.LANDSCAPE_RIGHT 11 | else -> null 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /docsite/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docsite/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /docsite/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docsite/docs/_coming-soon.md: -------------------------------------------------------------------------------- 1 | **Frame by frame, Coming Soon!** 📸 Our team of coding wizards 🧙‍♂️🧙‍♀️ are working hard to get this classifier working just right! 2 | 3 | In the meantime, if you have any questions feel free to join the community on [discord](https://discord.gg/2HPuUda3z4)! 🎉 4 | -------------------------------------------------------------------------------- /docsite/docs/api_pages/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "API", 3 | "position": 2, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "This API reference documentation provides detailed information for each of the classifiers in the react native media-pipe library." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docsite/docs/api_pages/face-detection.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # Face Detection 6 | 7 | Detects one or multiple faces and its movements in real time. 8 | 9 | For more details or to demo it, visit 10 | [MediaPipe - Face Detection](https://mediapipe-studio.webapps.google.com/studio/demo/face_detector) 11 | 12 | --- 13 | import ComingSoon from '../_coming-soon.md'; 14 | 15 | -------------------------------------------------------------------------------- /docsite/docs/api_pages/gesture-recognition.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Gesture Recognition 6 | 7 | Recognizes and identifies hand gestures on images and videos. 8 | 9 | For more details or to demo it, visit 10 | [MediaPipe - Gesture Recognition](https://mediapipe-studio.webapps.google.com/studio/demo/gesture_recognizer) 11 | 12 | --- 13 | import ComingSoon from '../_coming-soon.md'; 14 | 15 | -------------------------------------------------------------------------------- /docsite/docs/api_pages/hand-landmark-detection.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Hand Landmark Detection 6 | 7 | Detects hands and their movements in an image or video. 8 | 9 | For more details or to demo it, visit 10 | [MediaPipe - Hand Landmark Detection](https://mediapipe-studio.webapps.google.com/studio/demo/hand_landmarker) 11 | 12 | --- 13 | import ComingSoon from '../_coming-soon.md'; 14 | 15 | -------------------------------------------------------------------------------- /docsite/docs/api_pages/image-classification.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Image Classification 6 | 7 | Identifies and categorizes content in images. 8 | 9 | For more details or to demo it, visit 10 | [MediaPipe - Image Classification](https://mediapipe-studio.webapps.google.com/studio/demo/image_classifier) 11 | 12 | --- 13 | import ComingSoon from '../_coming-soon.md'; 14 | 15 | -------------------------------------------------------------------------------- /docsite/docs/api_pages/image-embedding.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 10 3 | --- 4 | 5 | # Image Embedding 6 | 7 | Changes a selected image into an embedded one. 8 | 9 | For more details or to demo it, visit 10 | [MediaPipe - Image Embedding](https://mediapipe-studio.webapps.google.com/studio/demo/image_embedder) 11 | 12 | --- 13 | import ComingSoon from '../_coming-soon.md'; 14 | 15 | -------------------------------------------------------------------------------- /docsite/docs/api_pages/image-segmentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Image Segmentation 6 | 7 | Identifies objects in images and creates silhouettes of them. 8 | 9 | For more details or to demo it, visit 10 | [MediaPipe - Image Segmentation](https://mediapipe-studio.webapps.google.com/studio/demo/image_segmenter) 11 | 12 | 13 | --- 14 | import ComingSoon from '../_coming-soon.md'; 15 | 16 | -------------------------------------------------------------------------------- /docsite/docs/api_pages/interactive-segmentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | --- 4 | 5 | # Interactive Segmentation 6 | 7 | Creates a silhouette of an chosen object on an image. 8 | 9 | For more details or to demo it, visit 10 | [MediaPipe - Interactive Segmentation](https://mediapipe-studio.webapps.google.com/studio/demo/interactive_segmenter) 11 | 12 | 13 | --- 14 | import ComingSoon from '../_coming-soon.md'; 15 | 16 | -------------------------------------------------------------------------------- /docsite/docs/troubleshooting_guides/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Troubleshooting", 3 | "position": 3, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Troubleshooting guide for common errors when working with the react native media-pipe library." 7 | } 8 | } -------------------------------------------------------------------------------- /docsite/docs/troubleshooting_guides/long_path_issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Long Path Issue On Windows 10 6 | 7 | If you are encountering an error with Ninja on Windows due to long paths not being enabled typically means that the path to your project or files is too long for Ninja to handle. Windows has a limitation on the maximum length of file paths, and if your project's path exceeds this limit, Ninja may fail to execute properly. 8 | 9 | To resolve this, you can either enable long paths in Windows or try moving your project to a shorter path. 10 | 11 | ## How To Enable Long Paths 12 | 13 | To enable the new long path behavior on your machine: 14 | 15 | - Use the registry key 16 | **Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled (Type: REG_DWORD)** must exist and be set to 1. 17 | In order for all apps on the system to recognize the value of the key, a reboot might be required because some processes may have started before the key was set. 18 | 19 | - Using PowerShell 20 | You can also enable long paths by using the PowerShell command from a terminal window with elevated privileges: 21 | 22 | ```bash 23 | New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" ` 24 | -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force 25 | ``` 26 | ## For More Information or Help on Long Paths 27 | 28 | https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry#enable-long-paths-in-windows-10-version-1607-and-later 29 | -------------------------------------------------------------------------------- /docsite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docsite", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@cmfcmf/docusaurus-search-local": "^1.1.0", 19 | "@docusaurus/core": "3.2.0", 20 | "@docusaurus/preset-classic": "3.2.0", 21 | "@mdx-js/react": "^3.0.0", 22 | "clsx": "^2.0.0", 23 | "prism-react-renderer": "^2.3.0", 24 | "react": "^18.0.0", 25 | "react-dom": "^18.0.0" 26 | }, 27 | "devDependencies": { 28 | "@docusaurus/module-type-aliases": "3.2.0", 29 | "@docusaurus/tsconfig": "3.2.0", 30 | "@docusaurus/types": "3.2.0", 31 | "typescript": "^5.3.3" 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.5%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 3 chrome version", 41 | "last 3 firefox version", 42 | "last 5 safari version" 43 | ] 44 | }, 45 | "engines": { 46 | "node": ">=18.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docsite/sidebars.ts: -------------------------------------------------------------------------------- 1 | import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; 2 | 3 | /** 4 | * Creating a sidebar enables you to: 5 | - create an ordered group of docs 6 | - render a sidebar for each doc of that group 7 | - provide next/previous navigation 8 | 9 | The sidebars can be generated from the filesystem, or explicitly defined here. 10 | 11 | Create as many sidebars as you want. 12 | */ 13 | const sidebars: SidebarsConfig = { 14 | // By default, Docusaurus generates a sidebar from the docs folder structure 15 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 16 | 17 | // But you can create a sidebar manually 18 | /* 19 | tutorialSidebar: [ 20 | 'intro', 21 | 'hello', 22 | { 23 | type: 'category', 24 | label: 'Tutorial', 25 | items: ['tutorial-basics/create-a-document'], 26 | }, 27 | ], 28 | */ 29 | }; 30 | 31 | export default sidebars; -------------------------------------------------------------------------------- /docsite/src/components/HomepageFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | // the way the standard docusaurus file use .require upsets the linter, turn that warning off 2 | /* eslint @typescript-eslint/no-var-requires: "off" */ 3 | /* eslint @typescript-eslint/no-unsafe-assignment: "off" */ 4 | 5 | import clsx from "clsx"; 6 | import Heading from "@theme/Heading"; 7 | import styles from "./styles.module.css"; 8 | 9 | type FeatureItem = { 10 | title: string; 11 | Svg?: React.ComponentType>; 12 | linkLabel: string; 13 | link: string; 14 | }; 15 | 16 | const FeatureList: FeatureItem[] = [ 17 | { 18 | title: "Installation", 19 | linkLabel: 20 | "Getting Started: Integrate React Native MediaPipe into your project.", 21 | link: "/react-native-mediapipe/docs/intro", 22 | }, 23 | { 24 | title: "Object Detection", 25 | linkLabel: 26 | "Getting Started: Track and categorize objects using your mobile camera.", 27 | link: "/react-native-mediapipe/docs/api_pages/object-detection", 28 | }, 29 | { 30 | title: "Face Landmark Detection", 31 | linkLabel: 32 | "Getting Started: Captures main facial points and expressions in real-time.", 33 | link: "/react-native-mediapipe/docs/api_pages/face-landmark-detection", 34 | }, 35 | ]; 36 | 37 | function Feature({ title, Svg, link, linkLabel }: FeatureItem) { 38 | return ( 39 |
40 |
41 | {Svg && } 42 |
43 |
44 | {title} 45 | 46 |

{linkLabel}

47 |
48 |
49 |
50 | ); 51 | } 52 | 53 | export default function HomepageFeatures(): JSX.Element { 54 | return ( 55 |
56 |
57 |
58 | {FeatureList.map((props, idx) => ( 59 | 60 | ))} 61 |
62 |
63 |
64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /docsite/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /docsite/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | -------------------------------------------------------------------------------- /docsite/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /docsite/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 3 | import Layout from '@theme/Layout'; 4 | 5 | import HomepageFeatures from '@site/src/components/HomepageFeatures'; 6 | import Heading from '@theme/Heading'; 7 | 8 | import styles from './index.module.css'; 9 | 10 | function HomepageHeader() { 11 | const {siteConfig} = useDocusaurusContext(); 12 | return ( 13 |
14 |
15 | 16 | {siteConfig.title} 17 | 18 |

{siteConfig.tagline}

19 |
20 |
21 | ); 22 | } 23 | 24 | export default function Home(): JSX.Element { 25 | const {siteConfig} = useDocusaurusContext(); 26 | return ( 27 | 30 | 31 |
32 | 33 |
34 |
35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /docsite/src/pages/markdown-page.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown page example 3 | --- 4 | 5 | # Markdown page example 6 | 7 | You don't need React to write simple standalone pages. 8 | -------------------------------------------------------------------------------- /docsite/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/docsite/static/.nojekyll -------------------------------------------------------------------------------- /docsite/static/img/docusaurus-social-card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/docsite/static/img/docusaurus-social-card.jpg -------------------------------------------------------------------------------- /docsite/static/img/docusaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/docsite/static/img/docusaurus.png -------------------------------------------------------------------------------- /docsite/static/img/react-native-mediapipe-favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/docsite/static/img/react-native-mediapipe-favicon.ico -------------------------------------------------------------------------------- /docsite/static/img/rnmp_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/docsite/static/img/rnmp_logo.png -------------------------------------------------------------------------------- /docsite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@docusaurus/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "strictNullChecks": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | Pods/ 3 | *.tflite 4 | *.task 5 | 6 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | ## How to create a new example 4 | 5 | ```sh 6 | npx npx @react-native-community/cli@latest init examplename 7 | cd examplename 8 | yarn 9 | bundle install 10 | cd ios 11 | pod install 12 | cd .. 13 | yarn add react-native-vision-camera react-native-worklets-core 14 | yarn add -D babel-plugin-module-resolver 15 | cd ios && pod install 16 | 17 | ``` 18 | ### modify various build files 19 | 20 | per [RNVC getting started - update the min sdk for android](https://react-native-vision-camera.com/docs/guides/#installing-the-library) 21 | - android/build.gradle buildscript.ext.minSdkVersion = 26 22 | 23 | per [RNVC getting started - updating manifests](https://react-native-vision-camera.com/docs/guides/#updating-manifests) 24 | 25 | - update Info.plist 26 | - update AndroidManifest.xml 27 | 28 | ### Modify the source code 29 | 30 | - Edit `tsconfig.json` to what it is 31 | - Create `src` directory. Move `App.tsx` to `src` 32 | - Edit `index.js` import App statement 33 | - Edit `App.tsx` to what it is 34 | - Edit `babel.config.js` to what it is 35 | - Edit `metro.config.js` to what it is 36 | - Edit `react-native.config.js` to what it is 37 | - Delete `prettierrc.js`, `eslintrc.js`, `.gitignore` 38 | 39 | ### Add the model file download stuff 40 | 41 | Lift from [This PR](https://github.com/cdiddy77/react-native-mediapipe/pull/85) and from the appropriate example from [the MediaPipe examples](https://github.com/googlesamples/mediapipe/blob/9d0624bb1cf1baa8ac31991748d69ec219aa3535/examples) 42 | 43 | ### add boilerplate code for tabs/icons/etc 44 | 45 | ```sh 46 | yarn add @react-native-community/slider @react-native-picker/picker @react-navigation/bottom-tabs @react-navigation/native @shopify/react-native-skia react-native-image-crop-picker react-native-picker-select react-native-safe-area-context react-native-screens react-native-vector-icons 47 | yarn add -D @types/react-native-vector-icons 48 | ``` 49 | 50 | - Follow special installation for react-native-vector-icons. Lift from [This PR](https://github.com/cdiddy77/react-native-mediapipe/pull/60) 51 | - copy various files from a different example `src` directory to the new `src` directory 52 | - app-settings.ts 53 | - App.tsx 54 | - CameraStream.tsx 55 | - Drawing.tsx 56 | - navigation.ts 57 | - Photo.tsx 58 | - Settings.tsx -------------------------------------------------------------------------------- /examples/facelandmarkdetection/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Updated to allow Ruby 3.0+ (including 3.1, 3.2, etc.) 4 | ruby ">= 3.0.0" 5 | 6 | # Add explicit logger requirement 7 | gem 'logger', '~> 1.5.0' 8 | # https://github.com/facebook/react-native/issues/48746#issuecomment-2602408458 9 | gem 'concurrent-ruby', '1.3.4' 10 | 11 | # Lock ActiveSupport to a compatible version 12 | gem 'activesupport', '6.1.7.5' # Exact version known to work 13 | 14 | # Cocoapods 1.15 introduced a bug which break the build. We will remove the upper 15 | # bound in the template on Cocoapods with next React Native release. 16 | gem 'cocoapods', '>= 1.13', '< 1.15' 17 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/debug.keystore -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/download_tasks.gradle: -------------------------------------------------------------------------------- 1 | 2 | task downloadTaskFile(type: Download) { 3 | src 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task' 4 | dest project.ext.ASSET_DIR + '/face_landmarker.task' 5 | overwrite false 6 | } 7 | 8 | preBuild.dependsOn downloadTaskFile 9 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/java/com/facelandmarkdetection/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.facelandmarkdetection 2 | 3 | import com.facebook.react.ReactActivity 4 | import com.facebook.react.ReactActivityDelegate 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate 7 | 8 | class MainActivity : ReactActivity() { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | override fun getMainComponentName(): String = "facelandmarkdetection" 15 | 16 | /** 17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 19 | */ 20 | override fun createReactActivityDelegate(): ReactActivityDelegate = 21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 22 | } 23 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/java/com/facelandmarkdetection/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.facelandmarkdetection 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.soloader.SoLoader 13 | 14 | class MainApplication : Application(), ReactApplication { 15 | 16 | override val reactNativeHost: ReactNativeHost = 17 | object : DefaultReactNativeHost(this) { 18 | override fun getPackages(): List = 19 | PackageList(this).packages.apply { 20 | // Packages that cannot be autolinked yet can be added manually here, for example: 21 | // add(MyReactNativePackage()) 22 | } 23 | 24 | override fun getJSMainModuleName(): String = "index" 25 | 26 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 27 | 28 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 29 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 30 | } 31 | 32 | override val reactHost: ReactHost 33 | get() = getDefaultReactHost(applicationContext, reactNativeHost) 34 | 35 | override fun onCreate() { 36 | super.onCreate() 37 | SoLoader.init(this, false) 38 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 39 | // If you opted-in for the New Architecture, we load the native entry point for this app. 40 | load() 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | facelandmarkdetection 3 | 4 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "34.0.0" 4 | minSdkVersion = 26 5 | compileSdkVersion = 34 6 | targetSdkVersion = 34 7 | ndkVersion = "26.1.10909125" 8 | kotlinVersion = "1.9.22" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | classpath("de.undercouch:gradle-download-task:4.1.2") 19 | } 20 | } 21 | 22 | apply plugin: "com.facebook.react.rootproject" 23 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Use this property to specify which architecture you want to build. 28 | # You can also override it from the CLI using 29 | # ./gradlew -PreactNativeArchitectures=x86_64 30 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 31 | 32 | # Use this property to enable support to the new architecture. 33 | # This will allow you to use TurboModules and the Fabric render in 34 | # your application. You should enable this flag either if you want 35 | # to write custom TurboModules/Fabric components OR use libraries that 36 | # are providing them. 37 | newArchEnabled=false 38 | 39 | # Use this property to enable or disable the Hermes JS engine. 40 | # If set to false, you will be using JSC instead. 41 | hermesEnabled=true 42 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'facelandmarkdetection' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/@react-native/gradle-plugin') 5 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "facelandmarkdetection", 3 | "displayName": "facelandmarkdetection" 4 | } 5 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const pak = require("../../package.json"); 3 | 4 | module.exports = { 5 | presets: ["module:@react-native/babel-preset"], 6 | plugins: [ 7 | "react-native-reanimated/plugin", 8 | ["react-native-worklets-core/plugin"], 9 | [ 10 | "module-resolver", 11 | { 12 | extensions: [".tsx", ".ts", ".js", ".json"], 13 | alias: { 14 | [pak.name]: path.join(__dirname, "../..", pak.source), 15 | }, 16 | }, 17 | ], 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './src/App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Resolve react_native_pods.rb with node to allow for hoisting 2 | require Pod::Executable.execute_command('node', ['-p', 3 | 'require.resolve( 4 | "react-native/scripts/react_native_pods.rb", 5 | {paths: [process.argv[1]]}, 6 | )', __dir__]).strip 7 | 8 | platform :ios, min_ios_version_supported 9 | prepare_react_native_project! 10 | 11 | linkage = ENV['USE_FRAMEWORKS'] 12 | if linkage != nil 13 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 14 | use_frameworks! :linkage => linkage.to_sym 15 | end 16 | 17 | target 'facelandmarkdetection' do 18 | config = use_native_modules! 19 | 20 | use_react_native!( 21 | :path => config[:reactNativePath], 22 | # An absolute path to your application root. 23 | :app_path => "#{Pod::Config.instance.installation_root}/.." 24 | ) 25 | 26 | target 'facelandmarkdetectionTests' do 27 | inherit! :complete 28 | # Pods for testing 29 | end 30 | 31 | post_install do |installer| 32 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 33 | react_native_post_install( 34 | installer, 35 | config[:reactNativePath], 36 | :mac_catalyst_enabled => false, 37 | # :ccache_enabled => true 38 | ) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/RunScripts/download_models.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2023 The MediaPipe Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | # Download face_landmarker.task from the internet if it's not exist. 18 | MODEL_FILE=./facelandmarkdetection/face_landmarker.task 19 | if test -f "$MODEL_FILE"; then 20 | echo "INFO: face_landmarker.task existed. Skip downloading and use the local task." 21 | else 22 | curl -o ${MODEL_FILE} https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task 23 | if [ $? -ne 0 ]; then 24 | echo "ERROR: Failed to download face_landmarker.task." 25 | exit 1 26 | fi 27 | echo "INFO: Downloaded face_landmarker.task to $MODEL_FILE ." 28 | fi 29 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | @implementation AppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 8 | { 9 | self.moduleName = @"facelandmarkdetection"; 10 | // You can add your custom initial props in the dictionary below. 11 | // They will be passed down to the ViewController used by React Native. 12 | self.initialProps = @{}; 13 | 14 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 15 | } 16 | 17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 18 | { 19 | return [self bundleURL]; 20 | } 21 | 22 | - (NSURL *)bundleURL 23 | { 24 | #if DEBUG 25 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 26 | #else 27 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 28 | #endif 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/120 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/120 1.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "40.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "60.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "58.png", 17 | "idiom" : "iphone", 18 | "scale" : "2x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "87.png", 23 | "idiom" : "iphone", 24 | "scale" : "3x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "80.png", 29 | "idiom" : "iphone", 30 | "scale" : "2x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "filename" : "120.png", 35 | "idiom" : "iphone", 36 | "scale" : "3x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "120 1.png", 41 | "idiom" : "iphone", 42 | "scale" : "2x", 43 | "size" : "60x60" 44 | }, 45 | { 46 | "filename" : "180.png", 47 | "idiom" : "iphone", 48 | "scale" : "3x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "1024.png", 53 | "idiom" : "ios-marketing", 54 | "scale" : "1x", 55 | "size" : "1024x1024" 56 | } 57 | ], 58 | "info" : { 59 | "author" : "xcode", 60 | "version" : 1 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | facelandmarkdetection 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSAllowsLocalNetworking 32 | 33 | 34 | NSCameraUsageDescription 35 | $(PRODUCT_NAME) needs access to your Camera. 36 | NSLocationWhenInUseUsageDescription 37 | 38 | NSMicrophoneUsageDescription 39 | $(PRODUCT_NAME) needs access to your Microphone. 40 | NSPhotoLibraryUsageDescription 41 | Enable inference on images and videos 42 | UIAppFonts 43 | 44 | Ionicons.ttf 45 | 46 | UILaunchStoryboardName 47 | LaunchScreen 48 | UIRequiredDeviceCapabilities 49 | 50 | arm64 51 | 52 | UISupportedInterfaceOrientations 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationLandscapeLeft 56 | UIInterfaceOrientationLandscapeRight 57 | 58 | UIViewControllerBasedStatusBarAppearance 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryUserDefaults 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | CA92.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategorySystemBootTime 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | 35F9.1 29 | 30 | 31 | 32 | NSPrivacyCollectedDataTypes 33 | 34 | NSPrivacyTracking 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetection/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetectionTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/ios/facelandmarkdetectionTests/facelandmarkdetectionTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface facelandmarkdetectionTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation facelandmarkdetectionTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config"); 2 | const path = require("path"); 3 | const escape = require("escape-string-regexp"); 4 | const exclusionList = require("metro-config/src/defaults/exclusionList"); 5 | const pak = require("../../package.json"); 6 | 7 | const root = path.resolve(__dirname, "../.."); 8 | const modules = Object.keys({ ...pak.peerDependencies }); 9 | 10 | /** 11 | * Metro configuration 12 | * https://facebook.github.io/metro/docs/configuration 13 | * 14 | * @type {import('metro-config').MetroConfig} 15 | */ 16 | const config = { 17 | watchFolders: [root], 18 | 19 | // We need to make sure that only one version is loaded for peerDependencies 20 | // So we block them at the root, and alias them to the versions in example's node_modules 21 | resolver: { 22 | blacklistRE: exclusionList( 23 | modules.map( 24 | (m) => 25 | new RegExp(`^${escape(path.join(root, "node_modules", m))}\\/.*$`) 26 | ) 27 | ), 28 | 29 | extraNodeModules: modules.reduce((acc, name) => { 30 | acc[name] = path.join(__dirname, "node_modules", name); 31 | return acc; 32 | }, {}), 33 | }, 34 | 35 | transformer: { 36 | getTransformOptions: async () => ({ 37 | transform: { 38 | experimentalImportSupport: false, 39 | inlineRequires: true, 40 | }, 41 | }), 42 | }, 43 | }; 44 | 45 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); 46 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "facelandmarkdetection", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "adb-reverse": "adb reverse tcp:8081 tcp:8081", 7 | "android": "react-native run-android", 8 | "ios": "react-native run-ios", 9 | "build:android": "cd android && ./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a", 10 | "build:ios": "cd ios && xcodebuild -workspace facelandmarkdetection.xcworkspace -scheme facelandmarkdetection -configuration Debug -sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO", 11 | "lint": "eslint .", 12 | "start": "react-native start", 13 | "test": "jest" 14 | }, 15 | "dependencies": { 16 | "@react-native-community/slider": "^4.5.2", 17 | "@react-native-picker/picker": "^2.7.5", 18 | "@react-navigation/bottom-tabs": "^6.5.20", 19 | "@react-navigation/native": "^6.1.17", 20 | "@shopify/react-native-skia": "^1.0.5", 21 | "react": "18.2.0", 22 | "react-native": "0.74.1", 23 | "react-native-image-crop-picker": "^0.40.2", 24 | "react-native-picker-select": "^9.1.3", 25 | "react-native-reanimated": "^3.16.2", 26 | "react-native-safe-area-context": "^4.10.0", 27 | "react-native-screens": "^3.30.1", 28 | "react-native-vector-icons": "^10.0.3", 29 | "react-native-vision-camera": "^4.0.3", 30 | "react-native-worklets-core": "^1.3.0" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.20.0", 34 | "@babel/preset-env": "^7.20.0", 35 | "@babel/runtime": "^7.20.0", 36 | "@react-native/babel-preset": "0.74.83", 37 | "@react-native/eslint-config": "0.74.83", 38 | "@react-native/metro-config": "0.74.83", 39 | "@react-native/typescript-config": "0.74.83", 40 | "@types/react": "^18.2.6", 41 | "@types/react-native-vector-icons": "^6.4.18", 42 | "@types/react-test-renderer": "^18.0.0", 43 | "babel-jest": "^29.6.3", 44 | "babel-plugin-module-resolver": "^5.0.2", 45 | "eslint": "^8.19.0", 46 | "jest": "^29.6.3", 47 | "prettier": "2.8.8", 48 | "react-test-renderer": "18.2.0", 49 | "typescript": "^5.3.3" 50 | }, 51 | "engines": { 52 | "node": ">=18" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/react-native.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const pak = require("../../package.json"); 3 | 4 | module.exports = { 5 | assets: ["./assets/models"], // Adjust the path according to your assets structure 6 | 7 | dependencies: { 8 | [pak.name]: { 9 | root: path.join(__dirname, "../.."), 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/src/Drawing.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Canvas, Points, type SkPoint } from "@shopify/react-native-skia"; 3 | import { type StyleProp, type ViewStyle } from "react-native"; 4 | import { useSharedValue, useDerivedValue } from "react-native-reanimated"; 5 | import type { SharedValue } from "react-native-reanimated"; 6 | 7 | export interface FaceDrawFrameProps { 8 | connections: SharedValue; 9 | style?: StyleProp; 10 | } 11 | 12 | export const FaceDrawFrame: React.FC = React.memo( 13 | ({ connections, style }) => { 14 | // Use derived value for reactive updates 15 | const points = useDerivedValue(() => { 16 | return connections.value; 17 | }, [connections]); 18 | 19 | return ( 20 | 21 | 28 | 36 | 37 | ); 38 | }, 39 | ); 40 | 41 | FaceDrawFrame.displayName = "FaceDrawFrame"; 42 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/src/app-settings.ts: -------------------------------------------------------------------------------- 1 | import type { Delegate } from "react-native-mediapipe"; 2 | import * as React from "react"; 3 | 4 | export type AppSettings = { 5 | maxResults: number; 6 | threshold: number; 7 | processor: Delegate; 8 | model: string; 9 | }; 10 | 11 | export const SettingsContext = React.createContext< 12 | | { 13 | settings: AppSettings; 14 | setSettings: React.Dispatch>; 15 | } 16 | | undefined 17 | >(undefined); 18 | 19 | export const useSettings = () => { 20 | const context = React.useContext(SettingsContext); 21 | if (!context) { 22 | throw new Error("useSettings must be used within a SettingsProvider"); 23 | } 24 | return context; 25 | }; 26 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/src/colors.ts: -------------------------------------------------------------------------------- 1 | export const CustomColors = { 2 | teal: "#2C8395", 3 | elecBlue: "#5FCCF5", 4 | backgroundGrayBlue: "#EAF5F9", 5 | deepSkyBlue: "#00BFFF", 6 | lightGray: "#F3F3F3", 7 | }; -------------------------------------------------------------------------------- /examples/facelandmarkdetection/src/navigation.ts: -------------------------------------------------------------------------------- 1 | export type RootTabParamList = { 2 | CameraStream: undefined; 3 | Photo: undefined; 4 | Settings: undefined; 5 | }; 6 | -------------------------------------------------------------------------------- /examples/facelandmarkdetection/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.shared", 3 | "compilerOptions": { 4 | "rootDir": "../..", 5 | "paths": { 6 | "react-native-mediapipe": [ 7 | "../../src/index" 8 | ] 9 | }, 10 | "composite": true 11 | }, 12 | "exclude": [ 13 | "node_modules" 14 | ], 15 | "include": [ 16 | "src", 17 | "../../src" 18 | ] 19 | } -------------------------------------------------------------------------------- /examples/objectdetection/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /examples/objectdetection/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /examples/objectdetection/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | # Cocoapods 1.15 introduced a bug which break the build. We will remove the upper 7 | # bound in the template on Cocoapods with next React Native release. 8 | gem 'cocoapods', '>= 1.13', '< 1.15' 9 | gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' 10 | -------------------------------------------------------------------------------- /examples/objectdetection/__mocks__/react-native-vision.camera.js: -------------------------------------------------------------------------------- 1 | // __mocks__/react-native-vision-camera.js 2 | 3 | export default { 4 | // Mock any functions or properties you use from the vision camera here 5 | // For example: 6 | getCameraPermissionStatus: jest.fn(), 7 | // Add more mocked functions or properties as needed 8 | }; 9 | -------------------------------------------------------------------------------- /examples/objectdetection/__mocks__/react-native-worklets-core.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/__mocks__/react-native-worklets-core.js -------------------------------------------------------------------------------- /examples/objectdetection/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/debug.keystore -------------------------------------------------------------------------------- /examples/objectdetection/android/app/download_models.gradle: -------------------------------------------------------------------------------- 1 | task downloadModelFile0(type: Download) { 2 | src 'https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/float32/1/efficientdet_lite0.tflite' 3 | dest project.ext.ASSET_DIR + '/efficientdet-lite0.tflite' 4 | overwrite false 5 | } 6 | 7 | task downloadModelFile1(type: Download) { 8 | src 'https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite2/float32/1/efficientdet_lite2.tflite' 9 | dest project.ext.ASSET_DIR + '/efficientdet-lite2.tflite' 10 | overwrite false 11 | } 12 | 13 | task downloadModelFile2(type: Download) { 14 | src 'https://storage.googleapis.com/mediapipe-models/object_detector/ssd_mobilenet_v2/float32/1/ssd_mobilenet_v2.tflite' 15 | dest project.ext.ASSET_DIR + '/ssd-mobilenet-v2.tflite' 16 | overwrite false 17 | } 18 | 19 | preBuild.dependsOn downloadModelFile0, downloadModelFile1, downloadModelFile2 20 | -------------------------------------------------------------------------------- /examples/objectdetection/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/java/com/objectdetection/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.objectdetection 2 | 3 | import com.facebook.react.ReactActivity 4 | import com.facebook.react.ReactActivityDelegate 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate 7 | 8 | import android.os.Bundle 9 | 10 | class MainActivity : ReactActivity() { 11 | 12 | /** 13 | * Returns the name of the main component registered from JavaScript. This is used to schedule 14 | * rendering of the component. 15 | */ 16 | override fun getMainComponentName(): String = "objectdetection" 17 | 18 | /** 19 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 20 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 21 | */ 22 | override fun createReactActivityDelegate(): ReactActivityDelegate = 23 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 24 | 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(null) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/java/com/objectdetection/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.objectdetection 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.react.flipper.ReactNativeFlipper 13 | import com.facebook.soloader.SoLoader 14 | 15 | class MainApplication : Application(), ReactApplication { 16 | 17 | override val reactNativeHost: ReactNativeHost = 18 | object : DefaultReactNativeHost(this) { 19 | override fun getPackages(): List = 20 | PackageList(this).packages.apply { 21 | // Packages that cannot be autolinked yet can be added manually here, for example: 22 | // add(MyReactNativePackage()) 23 | } 24 | 25 | override fun getJSMainModuleName(): String = "index" 26 | 27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 28 | 29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 31 | } 32 | 33 | override val reactHost: ReactHost 34 | get() = getDefaultReactHost(this.applicationContext, reactNativeHost) 35 | 36 | override fun onCreate() { 37 | super.onCreate() 38 | SoLoader.init(this, false) 39 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 40 | // If you opted-in for the New Architecture, we load the native entry point for this app. 41 | load() 42 | } 43 | ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | objectdetection 3 | 4 | -------------------------------------------------------------------------------- /examples/objectdetection/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/objectdetection/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "34.0.0" 4 | minSdkVersion = 26 5 | compileSdkVersion = 34 6 | targetSdkVersion = 34 7 | ndkVersion = "25.1.8937393" 8 | kotlinVersion = "1.8.0" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | classpath("de.undercouch:gradle-download-task:4.1.2") 19 | } 20 | } 21 | 22 | apply plugin: "com.facebook.react.rootproject" 23 | -------------------------------------------------------------------------------- /examples/objectdetection/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Use this property to specify which architecture you want to build. 28 | # You can also override it from the CLI using 29 | # ./gradlew -PreactNativeArchitectures=x86_64 30 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 31 | 32 | # Use this property to enable support to the new architecture. 33 | # This will allow you to use TurboModules and the Fabric render in 34 | # your application. You should enable this flag either if you want 35 | # to write custom TurboModules/Fabric components OR use libraries that 36 | # are providing them. 37 | newArchEnabled=false 38 | 39 | # Use this property to enable or disable the Hermes JS engine. 40 | # If set to false, you will be using JSC instead. 41 | hermesEnabled=true 42 | -------------------------------------------------------------------------------- /examples/objectdetection/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/objectdetection/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /examples/objectdetection/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'objectdetection' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/@react-native/gradle-plugin') 5 | -------------------------------------------------------------------------------- /examples/objectdetection/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "objectdetection", 3 | "displayName": "objectdetection" 4 | } 5 | -------------------------------------------------------------------------------- /examples/objectdetection/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const pak = require("../../package.json"); 3 | 4 | module.exports = { 5 | presets: ["module:@react-native/babel-preset"], 6 | plugins: [ 7 | ["react-native-worklets-core/plugin"], 8 | [ 9 | "module-resolver", 10 | { 11 | extensions: [".tsx", ".ts", ".js", ".json"], 12 | alias: { 13 | [pak.name]: path.join(__dirname, "../..", pak.source), 14 | }, 15 | }, 16 | ], 17 | ], 18 | }; 19 | -------------------------------------------------------------------------------- /examples/objectdetection/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import { AppRegistry } from "react-native"; 6 | import App from "./src/App"; 7 | import { name as appName } from "./app.json"; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Resolve react_native_pods.rb with node to allow for hoisting 2 | require Pod::Executable.execute_command('node', ['-p', 3 | 'require.resolve( 4 | "react-native/scripts/react_native_pods.rb", 5 | {paths: [process.argv[1]]}, 6 | )', __dir__]).strip 7 | 8 | platform :ios, min_ios_version_supported 9 | prepare_react_native_project! 10 | 11 | # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. 12 | # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded 13 | # 14 | # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` 15 | # ```js 16 | # module.exports = { 17 | # dependencies: { 18 | # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), 19 | # ``` 20 | flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled 21 | 22 | linkage = ENV['USE_FRAMEWORKS'] 23 | if linkage != nil 24 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 25 | use_frameworks! :linkage => linkage.to_sym 26 | end 27 | 28 | target 'objectdetection' do 29 | config = use_native_modules! 30 | 31 | use_react_native!( 32 | :path => config[:reactNativePath], 33 | # Enables Flipper. 34 | # 35 | # Note that if you have use_frameworks! enabled, Flipper will not work and 36 | # you should disable the next line. 37 | :flipper_configuration => flipper_config, 38 | # An absolute path to your application root. 39 | :app_path => "#{Pod::Config.instance.installation_root}/.." 40 | ) 41 | 42 | target 'objectdetectionTests' do 43 | inherit! :complete 44 | # Pods for testing 45 | end 46 | 47 | post_install do |installer| 48 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 49 | react_native_post_install( 50 | installer, 51 | config[:reactNativePath], 52 | :mac_catalyst_enabled => false 53 | ) 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/RunScripts/download_models.sh: -------------------------------------------------------------------------------- 1 | echo "INFO: Downloading models for iOS." 2 | 3 | # Download efficientnet-lite0.tflite from the internet if doesn't exist. 4 | TFLITE_FILE=./objectdetection/efficientdet-lite0.tflite 5 | if test -f "$TFLITE_FILE"; then 6 | echo "INFO: efficientdet_lite0.tflite exists. Skip downloading and use the local model." 7 | else 8 | curl -o ${TFLITE_FILE} https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/float32/1/efficientdet_lite0.tflite 9 | if [ $? -ne 0 ]; then 10 | echo "ERROR: Failed to download $TFLITE_FILE." 11 | exit 1 12 | fi 13 | echo "INFO: Downloaded efficientdet_lite0.tflite to $TFLITE_FILE ." 14 | fi 15 | 16 | # Download efficientnet-lite2.tflite from the internet if doesn't exist. 17 | TFLITE_FILE=./objectdetection/efficientdet-lite2.tflite 18 | if test -f "$TFLITE_FILE"; then 19 | echo "INFO: efficientdet_lite0.tflite exists. Skip downloading and use the local model." 20 | else 21 | curl -o ${TFLITE_FILE} https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite2/float32/1/efficientdet_lite2.tflite 22 | if [ $? -ne 0 ]; then 23 | echo "ERROR: Failed to download $TFLITE_FILE." 24 | exit 1 25 | fi 26 | echo "INFO: Downloaded efficientdet_lite0.tflite to $TFLITE_FILE ." 27 | fi 28 | 29 | # Download ssd_mobilenet-v2.tflite from the internet if doesn't exist. 30 | TFLITE_FILE=./objectdetection/ssd-mobilenet-v2.tflite 31 | if test -f "$TFLITE_FILE"; then 32 | echo "INFO: ssd_mobilenet_v2.tflite exists. Skip downloading and use the local model." 33 | else 34 | curl -o ${TFLITE_FILE} https://storage.googleapis.com/mediapipe-models/object_detector/ssd_mobilenet_v2.tflite/float32/1/ssd_mobilenet_v2.tflite 35 | if [ $? -ne 0 ]; then 36 | echo "ERROR: Failed to download $TFLITE_FILE." 37 | exit 1 38 | fi 39 | echo "INFO: Downloaded ssd_mobilenet_v2.tflite to $TFLITE_FILE ." 40 | fi 41 | 42 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | @implementation AppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 8 | { 9 | self.moduleName = @"objectdetection"; 10 | // You can add your custom initial props in the dictionary below. 11 | // They will be passed down to the ViewController used by React Native. 12 | self.initialProps = @{}; 13 | 14 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 15 | } 16 | 17 | 18 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 19 | { 20 | return [self getBundleURL]; 21 | } 22 | 23 | - (NSURL *)getBundleURL 24 | { 25 | #if DEBUG 26 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 27 | #else 28 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 29 | #endif 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/120 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/120 1.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "40.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "60.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "58.png", 17 | "idiom" : "iphone", 18 | "scale" : "2x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "87.png", 23 | "idiom" : "iphone", 24 | "scale" : "3x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "80.png", 29 | "idiom" : "iphone", 30 | "scale" : "2x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "filename" : "120 1.png", 35 | "idiom" : "iphone", 36 | "scale" : "3x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "120.png", 41 | "idiom" : "iphone", 42 | "scale" : "2x", 43 | "size" : "60x60" 44 | }, 45 | { 46 | "filename" : "180.png", 47 | "idiom" : "iphone", 48 | "scale" : "3x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "1024.png", 53 | "idiom" : "ios-marketing", 54 | "scale" : "1x", 55 | "size" : "1024x1024" 56 | } 57 | ], 58 | "info" : { 59 | "author" : "xcode", 60 | "version" : 1 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | objectdetection 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSAllowsLocalNetworking 32 | 33 | 34 | NSCameraUsageDescription 35 | $(PRODUCT_NAME) needs access to your Camera. 36 | NSLocationWhenInUseUsageDescription 37 | 38 | NSMicrophoneUsageDescription 39 | $(PRODUCT_NAME) needs access to your Microphone. 40 | NSPhotoLibraryUsageDescription 41 | Enable inference on images and videos 42 | UIAppFonts 43 | 44 | Ionicons.ttf 45 | 46 | UILaunchStoryboardName 47 | 48 | UIRequiredDeviceCapabilities 49 | 50 | armv7 51 | 52 | UISupportedInterfaceOrientations 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationLandscapeLeft 56 | UIInterfaceOrientationLandscapeRight 57 | 58 | UIViewControllerBasedStatusBarAppearance 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetection/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetectionTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/objectdetection/ios/objectdetectionTests/objectdetectionTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface objectdetectionTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation objectdetectionTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /examples/objectdetection/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /examples/objectdetection/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config"); 2 | const path = require("path"); 3 | const escape = require("escape-string-regexp"); 4 | const exclusionList = require("metro-config/src/defaults/exclusionList"); 5 | const pak = require("../../package.json"); 6 | 7 | const root = path.resolve(__dirname, "../.."); 8 | const modules = Object.keys({ ...pak.peerDependencies }); 9 | 10 | /** 11 | * Metro configuration 12 | * https://facebook.github.io/metro/docs/configuration 13 | * 14 | * @type {import('metro-config').MetroConfig} 15 | */ 16 | const config = { 17 | watchFolders: [root], 18 | 19 | // We need to make sure that only one version is loaded for peerDependencies 20 | // So we block them at the root, and alias them to the versions in example's node_modules 21 | resolver: { 22 | blacklistRE: exclusionList( 23 | modules.map( 24 | (m) => 25 | new RegExp(`^${escape(path.join(root, "node_modules", m))}\\/.*$`) 26 | ) 27 | ), 28 | 29 | extraNodeModules: modules.reduce((acc, name) => { 30 | acc[name] = path.join(__dirname, "node_modules", name); 31 | return acc; 32 | }, {}), 33 | }, 34 | 35 | transformer: { 36 | getTransformOptions: async () => ({ 37 | transform: { 38 | experimentalImportSupport: false, 39 | inlineRequires: true, 40 | }, 41 | }), 42 | }, 43 | }; 44 | 45 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); 46 | -------------------------------------------------------------------------------- /examples/objectdetection/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "objectdetection", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "adb-reverse": "adb reverse tcp:8081 tcp:8081", 7 | "android": "react-native run-android", 8 | "ios": "react-native run-ios", 9 | "build:android": "cd android && ./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a", 10 | "build:ios": "cd ios && xcodebuild -workspace objectdetection.xcworkspace -scheme objectdetection -configuration Debug -sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO", 11 | "lint": "eslint .", 12 | "start": "react-native start", 13 | "test": "jest" 14 | }, 15 | "dependencies": { 16 | "@react-native-community/slider": "^4.5.2", 17 | "@react-native-picker/picker": "^2.7.5", 18 | "@react-navigation/bottom-tabs": "^6.5.20", 19 | "@react-navigation/native": "^6.1.17", 20 | "@shopify/react-native-skia": "^1.0.5", 21 | "react": "18.2.0", 22 | "react-native": "0.73.6", 23 | "react-native-image-crop-picker": "^0.40.2", 24 | "react-native-picker-select": "^9.1.3", 25 | "react-native-safe-area-context": "^4.10.0", 26 | "react-native-screens": "^3.30.1", 27 | "react-native-vector-icons": "^10.0.3", 28 | "react-native-vision-camera": "^4.0.3", 29 | "react-native-worklets-core": "^1.3.0" 30 | }, 31 | "devDependencies": { 32 | "@babel/core": "^7.20.0", 33 | "@babel/preset-env": "^7.20.0", 34 | "@babel/runtime": "^7.20.0", 35 | "@react-native/babel-preset": "0.73.21", 36 | "@react-native/eslint-config": "0.73.2", 37 | "@react-native/metro-config": "0.73.5", 38 | "@react-native/typescript-config": "0.73.1", 39 | "@types/react": "^18.2.6", 40 | "@types/react-native-vector-icons": "^6.4.18", 41 | "@types/react-test-renderer": "^18.0.0", 42 | "babel-jest": "^29.6.3", 43 | "babel-plugin-module-resolver": "^5.0.0", 44 | "eslint": "^8.19.0", 45 | "jest": "^29.6.3", 46 | "prettier": "2.8.8", 47 | "react-test-renderer": "18.2.0", 48 | "typescript": "^5.3.3" 49 | }, 50 | "engines": { 51 | "node": ">=18" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /examples/objectdetection/react-native.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const pak = require("../../package.json"); 3 | 4 | module.exports = { 5 | assets: ["./assets/models"], // Adjust the path according to your assets structure 6 | 7 | dependencies: { 8 | [pak.name]: { 9 | root: path.join(__dirname, "../.."), 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /examples/objectdetection/src/app-settings.ts: -------------------------------------------------------------------------------- 1 | import type { Delegate } from "react-native-mediapipe"; 2 | import * as React from "react"; 3 | 4 | export type AppSettings = { 5 | maxResults: number; 6 | threshold: number; 7 | processor: Delegate; 8 | model: string; 9 | }; 10 | 11 | export const SettingsContext = React.createContext< 12 | | { 13 | settings: AppSettings; 14 | setSettings: React.Dispatch>; 15 | } 16 | | undefined 17 | >(undefined); 18 | 19 | export const useSettings = () => { 20 | const context = React.useContext(SettingsContext); 21 | if (!context) { 22 | throw new Error("useSettings must be used within a SettingsProvider"); 23 | } 24 | return context; 25 | }; 26 | -------------------------------------------------------------------------------- /examples/objectdetection/src/colors.ts: -------------------------------------------------------------------------------- 1 | export const CustomColors = { 2 | teal: "#2C8395", 3 | elecBlue: "#5FCCF5", 4 | backgroundGrayBlue: "#EAF5F9", 5 | deepSkyBlue: "#00BFFF", 6 | lightGray: "#F3F3F3", 7 | }; -------------------------------------------------------------------------------- /examples/objectdetection/src/navigation.ts: -------------------------------------------------------------------------------- 1 | export type RootTabParamList = { 2 | CameraStream: undefined; 3 | Photo: undefined; 4 | Settings: undefined; 5 | }; 6 | -------------------------------------------------------------------------------- /examples/objectdetection/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.shared", 3 | "compilerOptions": { 4 | "rootDir": "../..", 5 | "paths": { 6 | "react-native-mediapipe": [ 7 | "../../src/index" 8 | ] 9 | }, 10 | "composite": true 11 | }, 12 | "exclude": [ 13 | "node_modules" 14 | ], 15 | "include": [ 16 | "src", 17 | "../../src" 18 | ] 19 | } -------------------------------------------------------------------------------- /examples/posedetection/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /examples/posedetection/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /examples/posedetection/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | # Cocoapods 1.15 introduced a bug which break the build. We will remove the upper 7 | # bound in the template on Cocoapods with next React Native release. 8 | gem 'cocoapods', '>= 1.13', '< 1.15' 9 | gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' 10 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/debug.keystore -------------------------------------------------------------------------------- /examples/posedetection/android/app/download_tasks.gradle: -------------------------------------------------------------------------------- 1 | task downloadTaskFile(type: Download) { 2 | src 'https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_heavy/float16/1/pose_landmarker_heavy.task' 3 | dest project.ext.ASSET_DIR + '/pose_landmarker_heavy.task' 4 | overwrite false 5 | } 6 | 7 | task downloadTaskFile1(type: Download) { 8 | src 'https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_full/float16/1/pose_landmarker_full.task' 9 | dest project.ext.ASSET_DIR + '/pose_landmarker_full.task' 10 | overwrite false 11 | } 12 | 13 | task downloadTaskFile2(type: Download) { 14 | src 'https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task' 15 | dest project.ext.ASSET_DIR + '/pose_landmarker_lite.task' 16 | overwrite false 17 | } 18 | 19 | preBuild.dependsOn downloadTaskFile, downloadTaskFile1, downloadTaskFile2 20 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/java/com/posedetection/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.posedetection 2 | 3 | import com.facebook.react.ReactActivity 4 | import com.facebook.react.ReactActivityDelegate 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate 7 | 8 | class MainActivity : ReactActivity() { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | override fun getMainComponentName(): String = "posedetection" 15 | 16 | /** 17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 19 | */ 20 | override fun createReactActivityDelegate(): ReactActivityDelegate = 21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 22 | } 23 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/java/com/posedetection/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.posedetection 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.soloader.SoLoader 13 | 14 | class MainApplication : Application(), ReactApplication { 15 | 16 | override val reactNativeHost: ReactNativeHost = 17 | object : DefaultReactNativeHost(this) { 18 | override fun getPackages(): List = 19 | PackageList(this).packages.apply { 20 | // Packages that cannot be autolinked yet can be added manually here, for example: 21 | // add(MyReactNativePackage()) 22 | } 23 | 24 | override fun getJSMainModuleName(): String = "index" 25 | 26 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 27 | 28 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 29 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 30 | } 31 | 32 | override val reactHost: ReactHost 33 | get() = getDefaultReactHost(applicationContext, reactNativeHost) 34 | 35 | override fun onCreate() { 36 | super.onCreate() 37 | SoLoader.init(this, false) 38 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 39 | // If you opted-in for the New Architecture, we load the native entry point for this app. 40 | load() 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | posedetection 3 | 4 | -------------------------------------------------------------------------------- /examples/posedetection/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/posedetection/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "34.0.0" 4 | minSdkVersion = 26 5 | compileSdkVersion = 34 6 | targetSdkVersion = 34 7 | ndkVersion = "26.1.10909125" 8 | kotlinVersion = "1.9.22" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | classpath("de.undercouch:gradle-download-task:4.1.2") 19 | } 20 | } 21 | 22 | apply plugin: "com.facebook.react.rootproject" 23 | -------------------------------------------------------------------------------- /examples/posedetection/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Use this property to specify which architecture you want to build. 28 | # You can also override it from the CLI using 29 | # ./gradlew -PreactNativeArchitectures=x86_64 30 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 31 | 32 | # Use this property to enable support to the new architecture. 33 | # This will allow you to use TurboModules and the Fabric render in 34 | # your application. You should enable this flag either if you want 35 | # to write custom TurboModules/Fabric components OR use libraries that 36 | # are providing them. 37 | newArchEnabled=false 38 | 39 | # Use this property to enable or disable the Hermes JS engine. 40 | # If set to false, you will be using JSC instead. 41 | hermesEnabled=true 42 | -------------------------------------------------------------------------------- /examples/posedetection/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/examples/posedetection/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/posedetection/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /examples/posedetection/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'posedetection' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/@react-native/gradle-plugin') 5 | -------------------------------------------------------------------------------- /examples/posedetection/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "posedetection", 3 | "displayName": "posedetection" 4 | } 5 | -------------------------------------------------------------------------------- /examples/posedetection/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const pak = require("../../package.json"); 3 | 4 | module.exports = { 5 | presets: ["module:@react-native/babel-preset"], 6 | plugins: [ 7 | [ 8 | "module-resolver", 9 | { 10 | extensions: [".tsx", ".ts", ".js", ".json"], 11 | alias: { 12 | [pak.name]: path.join(__dirname, "../..", pak.source), 13 | }, 14 | }, 15 | ], 16 | ["react-native-reanimated/plugin"], 17 | ["react-native-worklets-core/plugin"], 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /examples/posedetection/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './src/App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /examples/posedetection/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /examples/posedetection/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Resolve react_native_pods.rb with node to allow for hoisting 2 | require Pod::Executable.execute_command('node', ['-p', 3 | 'require.resolve( 4 | "react-native/scripts/react_native_pods.rb", 5 | {paths: [process.argv[1]]}, 6 | )', __dir__]).strip 7 | 8 | platform :ios, min_ios_version_supported 9 | prepare_react_native_project! 10 | 11 | linkage = ENV['USE_FRAMEWORKS'] 12 | if linkage != nil 13 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 14 | use_frameworks! :linkage => linkage.to_sym 15 | end 16 | 17 | target 'posedetection' do 18 | config = use_native_modules! 19 | 20 | use_react_native!( 21 | :path => config[:reactNativePath], 22 | # An absolute path to your application root. 23 | :app_path => "#{Pod::Config.instance.installation_root}/.." 24 | ) 25 | 26 | target 'posedetectionTests' do 27 | inherit! :complete 28 | # Pods for testing 29 | end 30 | 31 | post_install do |installer| 32 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 33 | react_native_post_install( 34 | installer, 35 | config[:reactNativePath], 36 | :mac_catalyst_enabled => false, 37 | # :ccache_enabled => true 38 | ) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /examples/posedetection/ios/RunScripts/download_models.sh: -------------------------------------------------------------------------------- 1 | 2 | # Download pose_landmarker_lite.task from the internet if it's not exist. 3 | TASK_FILE=./posedetection/pose_landmarker_lite.task 4 | if test -f "$TASK_FILE"; then 5 | echo "INFO: pose_landmarker_lite.task existed. Skip downloading and use the local model." 6 | else 7 | curl -o ${TASK_FILE} https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/latest/pose_landmarker_lite.task 8 | echo "INFO: Downloaded pose_landmarker_lite.task to $TASK_FILE ." 9 | fi 10 | 11 | # Download pose_landmarker_full.task from the internet if it's not exist. 12 | TASK_FILE=./posedetection/pose_landmarker_full.task 13 | if test -f "$TASK_FILE"; then 14 | echo "INFO: pose_landmarker_full.task existed. Skip downloading and use the local model." 15 | else 16 | curl -o ${TASK_FILE} https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_full/float16/latest/pose_landmarker_full.task 17 | echo "INFO: Downloaded pose_landmarker_full.task to $TASK_FILE ." 18 | fi 19 | 20 | # Download pose_landmarker_heavy.task from the internet if it's not exist. 21 | TASK_FILE=./posedetection/pose_landmarker_heavy.task 22 | if test -f "$TASK_FILE"; then 23 | echo "INFO: pose_landmarker_heavy.task existed. Skip downloading and use the local model." 24 | else 25 | curl -o ${TASK_FILE} https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_heavy/float16/latest/pose_landmarker_heavy.task 26 | echo "INFO: Downloaded pose_landmarker_heavy.task to $TASK_FILE ." 27 | fi 28 | 29 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | @implementation AppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 8 | { 9 | self.moduleName = @"posedetection"; 10 | // You can add your custom initial props in the dictionary below. 11 | // They will be passed down to the ViewController used by React Native. 12 | self.initialProps = @{}; 13 | 14 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 15 | } 16 | 17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 18 | { 19 | return [self bundleURL]; 20 | } 21 | 22 | - (NSURL *)bundleURL 23 | { 24 | #if DEBUG 25 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 26 | #else 27 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 28 | #endif 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | posedetection 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | 30 | NSAllowsArbitraryLoads 31 | 32 | NSAllowsLocalNetworking 33 | 34 | 35 | NSLocationWhenInUseUsageDescription 36 | 37 | UILaunchStoryboardName 38 | LaunchScreen 39 | UIRequiredDeviceCapabilities 40 | 41 | arm64 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | UIViewControllerBasedStatusBarAppearance 50 | 51 | NSCameraUsageDescription 52 | $(PRODUCT_NAME) needs access to your Camera. 53 | UIAppFonts 54 | 55 | Ionicons.ttf 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | 3B52.1 13 | C617.1 14 | 15 | 16 | 17 | NSPrivacyAccessedAPIType 18 | NSPrivacyAccessedAPICategoryUserDefaults 19 | NSPrivacyAccessedAPITypeReasons 20 | 21 | CA92.1 22 | 23 | 24 | 25 | NSPrivacyAccessedAPIType 26 | NSPrivacyAccessedAPICategorySystemBootTime 27 | NSPrivacyAccessedAPITypeReasons 28 | 29 | 35F9.1 30 | 31 | 32 | 33 | NSPrivacyCollectedDataTypes 34 | 35 | NSPrivacyTracking 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetection/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetectionTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/posedetection/ios/posedetectionTests/posedetectionTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface posedetectionTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation posedetectionTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /examples/posedetection/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /examples/posedetection/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config"); 2 | const path = require("path"); 3 | const escape = require("escape-string-regexp"); 4 | const exclusionList = require("metro-config/src/defaults/exclusionList"); 5 | const pak = require("../../package.json"); 6 | 7 | const root = path.resolve(__dirname, "../.."); 8 | const modules = Object.keys({ ...pak.peerDependencies }); 9 | 10 | /** 11 | * Metro configuration 12 | * https://facebook.github.io/metro/docs/configuration 13 | * 14 | * @type {import('metro-config').MetroConfig} 15 | */ 16 | const config = { 17 | watchFolders: [root], 18 | 19 | // We need to make sure that only one version is loaded for peerDependencies 20 | // So we block them at the root, and alias them to the versions in example's node_modules 21 | resolver: { 22 | blacklistRE: exclusionList( 23 | modules.map( 24 | (m) => 25 | new RegExp(`^${escape(path.join(root, "node_modules", m))}\\/.*$`) 26 | ) 27 | ), 28 | 29 | extraNodeModules: modules.reduce((acc, name) => { 30 | acc[name] = path.join(__dirname, "node_modules", name); 31 | return acc; 32 | }, {}), 33 | }, 34 | 35 | transformer: { 36 | getTransformOptions: async () => ({ 37 | transform: { 38 | experimentalImportSupport: false, 39 | inlineRequires: true, 40 | }, 41 | }), 42 | }, 43 | }; 44 | 45 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); 46 | -------------------------------------------------------------------------------- /examples/posedetection/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "posedetection", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "adb-reverse": "adb reverse tcp:8081 tcp:8081", 7 | "android": "react-native run-android", 8 | "ios": "react-native run-ios", 9 | "build:android": "cd android && ./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a", 10 | "build:ios": "cd ios && xcodebuild -workspace posedetection.xcworkspace -scheme posedetection -configuration Debug -sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO", 11 | "lint": "eslint .", 12 | "start": "react-native start", 13 | "test": "jest" 14 | }, 15 | "dependencies": { 16 | "@react-native-community/slider": "^4.5.2", 17 | "@react-native-picker/picker": "^2.7.7", 18 | "@react-navigation/bottom-tabs": "^6.5.20", 19 | "@react-navigation/native": "^6.1.17", 20 | "@shopify/react-native-skia": "^1.3.6", 21 | "react": "18.2.0", 22 | "react-native": "0.74.2", 23 | "react-native-image-crop-picker": "^0.41.2", 24 | "react-native-picker-select": "^9.1.3", 25 | "react-native-reanimated": "^3.12.1", 26 | "react-native-safe-area-context": "^4.10.5", 27 | "react-native-screens": "^3.32.0", 28 | "react-native-vector-icons": "^10.1.0", 29 | "react-native-vision-camera": "^4.5.3", 30 | "react-native-worklets-core": "^1.3.3" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.20.0", 34 | "@babel/preset-env": "^7.20.0", 35 | "@babel/runtime": "^7.20.0", 36 | "@react-native/babel-preset": "0.74.84", 37 | "@react-native/eslint-config": "0.74.84", 38 | "@react-native/metro-config": "0.74.84", 39 | "@react-native/typescript-config": "0.74.84", 40 | "@types/react": "^18.2.6", 41 | "@types/react-native-vector-icons": "^6.4.18", 42 | "@types/react-test-renderer": "^18.0.0", 43 | "babel-jest": "^29.6.3", 44 | "babel-plugin-module-resolver": "^5.0.2", 45 | "eslint": "^8.19.0", 46 | "jest": "^29.6.3", 47 | "prettier": "2.8.8", 48 | "react-test-renderer": "18.2.0", 49 | "typescript": "^5.3.3" 50 | }, 51 | "engines": { 52 | "node": ">=18" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/posedetection/react-native.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const pak = require("../../package.json"); 3 | 4 | module.exports = { 5 | assets: ["./assets/models"], // Adjust the path according to your assets structure 6 | 7 | dependencies: { 8 | [pak.name]: { 9 | root: path.join(__dirname, "../.."), 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /examples/posedetection/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { CameraStream } from "./CameraStream"; 3 | import { Photo } from "./Photo"; 4 | import { Settings } from "./Settings"; 5 | import { NavigationContainer, type RouteProp } from "@react-navigation/native"; 6 | import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; 7 | import { type RootTabParamList } from "./navigation"; 8 | import Ionicons from "react-native-vector-icons/Ionicons"; 9 | import type { AppSettings } from "./app-settings"; 10 | import { Delegate } from "react-native-mediapipe"; 11 | import { SettingsContext } from "./app-settings"; 12 | 13 | const Tab = createBottomTabNavigator(); 14 | 15 | type TabBarIconProps = { 16 | focused: boolean; 17 | color: string; 18 | size: number; 19 | route: RouteProp; 20 | }; 21 | 22 | const RenderTabBarIcon: React.FC = ({ 23 | focused, 24 | color, 25 | size, 26 | route, 27 | }) => { 28 | let iconName; 29 | 30 | if (route.name === "CameraStream") { 31 | iconName = focused ? "camera" : "camera-outline"; 32 | } else if (route.name === "Photo") { 33 | iconName = focused ? "document" : "document-outline"; 34 | } else { 35 | // if (route.name === "Settings") 36 | iconName = focused ? "cog" : "cog-outline"; 37 | } 38 | 39 | return ; 40 | }; 41 | 42 | function App() { 43 | const [settings, setSettings] = React.useState({ 44 | maxResults: 5, 45 | threshold: 20, 46 | processor: Delegate.GPU, 47 | model: "pose_landmarker_lite", 48 | }); 49 | 50 | return ( 51 | 52 | 53 | ({ 56 | tabBarIcon: ({ focused, color, size }) => { 57 | return RenderTabBarIcon({ focused, color, size, route }); 58 | }, 59 | tabBarActiveTintColor: "tomato", 60 | tabBarInactiveTintColor: "gray", 61 | })} 62 | > 63 | 68 | 73 | 78 | 79 | 80 | 81 | ); 82 | } 83 | 84 | export default App; 85 | -------------------------------------------------------------------------------- /examples/posedetection/src/Drawing.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Canvas, Points, type SkPoint } from "@shopify/react-native-skia"; 3 | import { type StyleProp, type ViewStyle } from "react-native"; 4 | import type { SharedValue } from "react-native-reanimated"; 5 | 6 | export interface PoseDrawFrameProps { 7 | connections: SharedValue; 8 | style?: StyleProp; 9 | } 10 | export const PoseDrawFrame: React.FC = (props) => { 11 | return ( 12 | 13 | 20 | 28 | 29 | ); 30 | }; 31 | 32 | const COLOR_NAMES = [ 33 | "Coral", 34 | "DarkCyan", 35 | "DeepSkyBlue", 36 | "ForestGreen", 37 | "GoldenRod", 38 | "MediumOrchid", 39 | "SteelBlue", 40 | "Tomato", 41 | "Turquoise", 42 | "SlateGray", 43 | "DodgerBlue", 44 | "FireBrick", 45 | "Gold", 46 | "HotPink", 47 | "LimeGreen", 48 | "Navy", 49 | "OrangeRed", 50 | "RoyalBlue", 51 | "SeaGreen", 52 | "Violet", 53 | ] as const; 54 | 55 | export type ColorName = (typeof COLOR_NAMES)[number]; 56 | -------------------------------------------------------------------------------- /examples/posedetection/src/app-settings.ts: -------------------------------------------------------------------------------- 1 | import type { Delegate } from "react-native-mediapipe"; 2 | import * as React from "react"; 3 | 4 | export type AppSettings = { 5 | maxResults: number; 6 | threshold: number; 7 | processor: Delegate; 8 | model: string; 9 | }; 10 | 11 | export const SettingsContext = React.createContext< 12 | | { 13 | settings: AppSettings; 14 | setSettings: React.Dispatch>; 15 | } 16 | | undefined 17 | >(undefined); 18 | 19 | export const useSettings = () => { 20 | const context = React.useContext(SettingsContext); 21 | if (!context) { 22 | throw new Error("useSettings must be used within a SettingsProvider"); 23 | } 24 | return context; 25 | }; 26 | -------------------------------------------------------------------------------- /examples/posedetection/src/navigation.ts: -------------------------------------------------------------------------------- 1 | export type RootTabParamList = { 2 | CameraStream: undefined; 3 | Photo: undefined; 4 | Settings: undefined; 5 | }; 6 | -------------------------------------------------------------------------------- /examples/posedetection/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.shared", 3 | "compilerOptions": { 4 | "rootDir": "../..", 5 | "paths": { 6 | "react-native-mediapipe": [ 7 | "../../src/index" 8 | ] 9 | }, 10 | "composite": true 11 | }, 12 | "exclude": [ 13 | "node_modules" 14 | ], 15 | "include": [ 16 | "src", 17 | "../../src" 18 | ] 19 | } -------------------------------------------------------------------------------- /ios/Mediapipe-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | -------------------------------------------------------------------------------- /ios/MediapipeViewManager.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface RCT_EXTERN_MODULE(MediapipeViewManager, RCTViewManager) 4 | 5 | RCT_EXPORT_VIEW_PROPERTY(color, NSString) 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /ios/MediapipeViewManager.swift: -------------------------------------------------------------------------------- 1 | @objc(MediapipeViewManager) 2 | class MediapipeViewManager: RCTViewManager { 3 | 4 | override func view() -> (MediapipeView) { 5 | return MediapipeView() 6 | } 7 | 8 | @objc override static func requiresMainQueueSetup() -> Bool { 9 | return false 10 | } 11 | } 12 | 13 | class MediapipeView : UIView { 14 | 15 | @objc var color: String = "" { 16 | didSet { 17 | self.backgroundColor = hexStringToUIColor(hexColor: color) 18 | } 19 | } 20 | 21 | func hexStringToUIColor(hexColor: String) -> UIColor { 22 | let stringScanner = Scanner(string: hexColor) 23 | 24 | if(hexColor.hasPrefix("#")) { 25 | stringScanner.scanLocation = 1 26 | } 27 | var color: UInt32 = 0 28 | stringScanner.scanHexInt32(&color) 29 | 30 | let r = CGFloat(Int(color >> 16) & 0x000000FF) 31 | let g = CGFloat(Int(color >> 8) & 0x000000FF) 32 | let b = CGFloat(Int(color) & 0x000000FF) 33 | 34 | return UIColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: 1) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ios/ReactNativeMediaPipe.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReactNativeMediaPipe.h 3 | // Pods 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | #ifndef ReactNativeMediaPipe_h 9 | #define ReactNativeMediaPipe_h 10 | 11 | 12 | #endif /* ReactNativeMediaPipe_h */ 13 | -------------------------------------------------------------------------------- /ios/facelandmarkdetection/FaceLandmarkDetectionFrameProcessorPlugin.m: -------------------------------------------------------------------------------- 1 | // 2 | // FrameProcessorPlugins.m 3 | // react-native-mediapipe 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | #import 9 | 10 | #import 11 | #import 12 | 13 | #import "ReactNativeMediaPipe-Swift.h" 14 | 15 | @interface FaceLandmarkDetectionFrameProcessorPlugin (FrameProcessorPluginLoader) 16 | @end 17 | 18 | @implementation FaceLandmarkDetectionFrameProcessorPlugin (FrameProcessorPluginLoader) 19 | + (void) load { 20 | [FrameProcessorPluginRegistry addFrameProcessorPlugin:@"faceLandmarkDetection" 21 | withInitializer:^FrameProcessorPlugin*(VisionCameraProxyHolder* proxy, NSDictionary* options) { 22 | return [[FaceLandmarkDetectionFrameProcessorPlugin alloc] initWithProxy:proxy withOptions:options]; 23 | }]; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /ios/facelandmarkdetection/FaceLandmarkDetectionFrameProcessorPlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FaceLandmarkDetectionFrameProcessorPlugin.swift 3 | // react-native-mediapipe 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | import Foundation 9 | import Vision 10 | 11 | @objc(FaceLandmarkDetectionFrameProcessorPlugin) 12 | public class FaceLandmarkDetectionFrameProcessorPlugin: FrameProcessorPlugin { 13 | public override init(proxy: VisionCameraProxyHolder, options: [AnyHashable: Any]! = [:]) { 14 | super.init(proxy: proxy, options: options) 15 | } 16 | 17 | public override func callback(_ frame: Frame, withArguments arguments: [AnyHashable: Any]?) -> Any { 18 | guard let detectorHandleValue = arguments?["detectorHandle"] as? Double else { 19 | return false 20 | } 21 | // get the orientation argument. If its nil, return false 22 | guard let orientation = arguments?["orientation"] as? String else { 23 | return false 24 | } 25 | // convert the orientation string to a UIImage.Orientation 26 | guard let uiOrientation = uiImageOrientation(from: orientation) else { 27 | return false 28 | } 29 | 30 | // Now that we have a valid Double, attempt to retrieve the detector using it 31 | guard let detector = FaceLandmarkDetectionModule.detectorMap[Int(detectorHandleValue)] else { 32 | return false 33 | } 34 | 35 | let buffer = frame.buffer 36 | detector.detectAsync( 37 | sampleBuffer: buffer, 38 | orientation: uiOrientation, 39 | timeStamps: Int(Date().timeIntervalSince1970 * 1000)) 40 | return true 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ios/facelandmarkdetection/FaceLandmarkDetectionModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // FaceLandmarkDetectionModule.m 3 | // react-native-mediapipe 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | #import 9 | #import "React/RCTBridgeModule.h" 10 | #import "React/RCTEventEmitter.h" 11 | 12 | @interface RCT_EXTERN_REMAP_MODULE(FaceLandmarkDetection, FaceLandmarkDetectionModule, RCTEventEmitter) 13 | RCT_EXTERN_METHOD( 14 | createDetector:(NSInteger)numFaces 15 | withMinFaceDetectionConfidence:(nonnull NSNumber *)minFaceDetectionConfidence 16 | withMinFacePresenceConfidence:(nonnull NSNumber *)minFacePresenceConfidence 17 | withMinTrackingConfidence:(nonnull NSNumber *)minTrackingConfidence 18 | withModel:(nonnull NSString *)model 19 | withDelegate:(NSInteger)delegate 20 | withRunningMode:(NSInteger)runningMode 21 | resolver:(RCTPromiseResolveBlock)resolve 22 | rejecter:(RCTPromiseRejectBlock)reject 23 | ) 24 | 25 | RCT_EXTERN_METHOD(releaseDetector:(NSInteger)handle 26 | resolver:(RCTPromiseResolveBlock)resolve 27 | rejecter:(RCTPromiseRejectBlock)reject 28 | ) 29 | 30 | RCT_EXTERN_METHOD(detectOnImage:(nonnull NSString *)imagePath 31 | withNumFaces:(NSInteger)numFaces 32 | withMinFaceDetectionConfidence:(nonnull NSNumber *)minFaceDetectionConfidence 33 | withMinFacePresenceConfidence:(nonnull NSNumber *)minFacePresenceConfidence 34 | withMinTrackingConfidence:(nonnull NSNumber *)minTrackingConfidence 35 | withModel:(nonnull NSString *)model 36 | withDelegate:(NSInteger)delegate 37 | resolver:(RCTPromiseResolveBlock)resolve 38 | rejecter:(RCTPromiseRejectBlock)reject 39 | ) 40 | 41 | RCT_EXTERN_METHOD(detectOnVideo:(nonnull NSString *)videoPath 42 | withNumFaces:(NSInteger)numFaces 43 | withMinFaceDetectionConfidence:(nonnull NSNumber *)minFaceDetectionConfidence 44 | withMinFacePresenceConfidence:(nonnull NSNumber *)minFacePresenceConfidence 45 | withMinTrackingConfidence:(nonnull NSNumber *)minTrackingConfidence 46 | withModel:(nonnull NSString *)model 47 | withDelegate:(NSInteger)delegate 48 | resolver:(RCTPromiseResolveBlock)resolve 49 | rejecter:(RCTPromiseRejectBlock)reject 50 | ) 51 | @end 52 | 53 | -------------------------------------------------------------------------------- /ios/facelandmarkdetection/FldConvertHelpers.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import MediaPipeTasksVision 3 | import React 4 | 5 | func convertFldResultBundleToDictionary(_ resultBundle: FaceLandmarkDetectionResultBundle) -> [String: Any] { 6 | var map = [String: Any]() 7 | 8 | // Results 9 | let resultsArray = resultBundle.faceLandmarkDetectorResults.map { result -> [String: Any] in 10 | var resultMap = [String: Any]() 11 | resultMap["timestampMs"] = result?.timestampInMilliseconds 12 | 13 | 14 | let landmarks = result?.faceLandmarks.map { $0.map(normalizedLandmarkToDictionary) } 15 | let matrices = result?.facialTransformationMatrixes.map(transformMatrixToDictionary) 16 | let blendshapes = result?.faceBlendshapes.map(classificationsToDictionary) 17 | 18 | return [ 19 | "faceLandmarks": landmarks ?? [], 20 | "faceBlendshapes": blendshapes ?? [], 21 | "facialTransformationMatrixes": matrices ?? [] 22 | ] 23 | } 24 | map["results"] = resultsArray 25 | 26 | // Image properties 27 | map["inputImageHeight"] = resultBundle.size.height 28 | map["inputImageWidth"] = resultBundle.size.width 29 | // map["inputImageRotation"] = resultBundle. 30 | map["inferenceTime"] = resultBundle.inferenceTime 31 | 32 | return map 33 | } 34 | 35 | // Converts Classifications to a Dictionary 36 | func classificationsToDictionary(_ classification: Classifications) -> [String: Any] { 37 | let categories = classification.categories.map { 38 | [ 39 | "categoryName": $0.categoryName ?? "", 40 | "displayName": $0.displayName ?? "", 41 | "score": $0.score 42 | ] 43 | } 44 | var dict = [ 45 | "headIndex": classification.headIndex, 46 | "categories": categories 47 | ] as [String : Any] 48 | if let headName = classification.headName { 49 | dict["headName"] = headName 50 | } 51 | return dict 52 | } 53 | 54 | func connectorsToArray(_ connections:[Connection]) ->[[String: Any]] { 55 | return connections.map { 56 | [ 57 | "start": $0.start, 58 | "end": $0.end 59 | ] 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /ios/objectdetection/ConvertHelpers.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import MediaPipeTasksVision 3 | import React 4 | 5 | // Convert Category to NSDictionary 6 | func convertCategoryToDictionary(_ category: ResultCategory) -> [String: Any] { 7 | var map = [String: Any]() 8 | map["score"] = category.score 9 | map["index"] = category.index 10 | map["categoryName"] = category.categoryName 11 | map["displayName"] = category.displayName 12 | return map 13 | } 14 | 15 | // Convert Detection to NSDictionary 16 | func convertDetectionToDictionary(_ detection: Detection) -> [String: Any] { 17 | var map = [String: Any]() 18 | 19 | // Categories 20 | let categoriesArray = detection.categories.map { convertCategoryToDictionary($0) } 21 | map["categories"] = categoriesArray 22 | 23 | // Keypoints 24 | let keypointsArray = detection.keypoints?.compactMap { keypoint -> [String: Any]? in 25 | var keypointMap = [String: Any]() 26 | keypointMap["x"] = keypoint.location.x 27 | keypointMap["y"] = keypoint.location.y 28 | 29 | keypointMap["label"] = keypoint.label 30 | keypointMap["score"] = keypoint.score 31 | return keypointMap 32 | } 33 | map["keypoints"] = keypointsArray 34 | map["boundingBox"] = convertRectFToDictionary(detection.boundingBox) 35 | 36 | return map 37 | } 38 | 39 | // Convert RectF to NSDictionary 40 | func convertRectFToDictionary(_ rectF: CGRect) -> [String: Any] { 41 | return [ 42 | "left": rectF.minX, 43 | "top": rectF.minY, 44 | "right": rectF.maxX, 45 | "bottom": rectF.maxY 46 | ] 47 | } 48 | 49 | // Convert ResultBundle to NSDictionary 50 | func convertResultBundleToDictionary(_ resultBundle: ObjectDetectionResultBundle) -> [String: Any] { 51 | var map = [String: Any]() 52 | 53 | // Results 54 | let resultsArray = resultBundle.objectDetectorResults.map { result -> [String: Any] in 55 | var resultMap = [String: Any]() 56 | resultMap["timestampMs"] = result?.timestampInMilliseconds 57 | 58 | // Detections 59 | let detectionsArray = result?.detections.map { convertDetectionToDictionary($0) } 60 | resultMap["detections"] = detectionsArray 61 | return resultMap 62 | } 63 | map["results"] = resultsArray 64 | 65 | // Image properties 66 | map["inputImageHeight"] = resultBundle.size.height 67 | map["inputImageWidth"] = resultBundle.size.width 68 | // map["inputImageRotation"] = resultBundle. 69 | map["inferenceTime"] = resultBundle.inferenceTime 70 | 71 | return map 72 | } 73 | -------------------------------------------------------------------------------- /ios/objectdetection/ObjectDetectionFrameProcessorPlugin.m: -------------------------------------------------------------------------------- 1 | // 2 | // FrameProcessorPlugins.m 3 | // react-native-mediapipe 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | #import 9 | 10 | #import 11 | #import 12 | 13 | #import "ReactNativeMediaPipe-Swift.h" 14 | 15 | @interface ObjectDetectionFrameProcessorPlugin (FrameProcessorPluginLoader) 16 | @end 17 | 18 | @implementation ObjectDetectionFrameProcessorPlugin (FrameProcessorPluginLoader) 19 | + (void) load { 20 | [FrameProcessorPluginRegistry addFrameProcessorPlugin:@"objectDetection" 21 | withInitializer:^FrameProcessorPlugin*(VisionCameraProxyHolder* proxy, NSDictionary* options) { 22 | return [[ObjectDetectionFrameProcessorPlugin alloc] initWithProxy:proxy withOptions:options]; 23 | }]; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /ios/objectdetection/ObjectDetectionFrameProcessorPlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectDetectionFrameProcessorPlugin.swift 3 | // react-native-mediapipe 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | import Foundation 9 | import Vision 10 | 11 | 12 | @objc(ObjectDetectionFrameProcessorPlugin) 13 | public class ObjectDetectionFrameProcessorPlugin: FrameProcessorPlugin { 14 | public override init(proxy: VisionCameraProxyHolder, options: [AnyHashable: Any]! = [:]) { 15 | super.init(proxy: proxy, options: options) 16 | } 17 | 18 | public override func callback(_ frame: Frame, withArguments arguments: [AnyHashable: Any]?) -> Any 19 | { 20 | guard let detectorHandleValue = arguments?["detectorHandle"] as? Double else { 21 | return false 22 | } 23 | 24 | // Now that we have a valid Double, attempt to retrieve the detector using it 25 | guard let detector = ObjectDetectionModule.detectorMap[Int(detectorHandleValue)] else { 26 | return false 27 | } 28 | 29 | let buffer = frame.buffer 30 | detector.detectAsync( 31 | sampleBuffer: buffer, 32 | orientation: frame.orientation, 33 | timeStamps: Int(Date().timeIntervalSince1970 * 1000)) 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ios/objectdetection/ObjectDetectionModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectDetectionModule.m 3 | // react-native-mediapipe 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | #import 9 | #import "React/RCTBridgeModule.h" 10 | #import "React/RCTEventEmitter.h" 11 | 12 | @interface RCT_EXTERN_REMAP_MODULE(ObjectDetection, ObjectDetectionModule, RCTEventEmitter) 13 | RCT_EXTERN_METHOD( 14 | createDetector:(nonnull NSNumber *)threshold 15 | withMaxResults:(NSInteger)maxResults 16 | withDelegate:(NSInteger)delegate 17 | withModel:(nonnull NSString *)model 18 | withRunningMode:(NSInteger)runningMode 19 | resolver:(RCTPromiseResolveBlock)resolve 20 | rejecter:(RCTPromiseRejectBlock)reject 21 | ) 22 | 23 | RCT_EXTERN_METHOD(releaseDetector:(NSInteger)handle 24 | resolver:(RCTPromiseResolveBlock)resolve 25 | rejecter:(RCTPromiseRejectBlock)reject 26 | ) 27 | 28 | RCT_EXTERN_METHOD(detectOnImage:(nonnull NSString *)imagePath 29 | withThreshold:(nonnull NSNumber *)threshold 30 | withMaxResults:(NSInteger)maxResults 31 | withDelegate:(NSInteger)delegate 32 | withModel:(nonnull NSString *)model 33 | resolver:(RCTPromiseResolveBlock)resolve 34 | rejecter:(RCTPromiseRejectBlock)reject 35 | ) 36 | 37 | RCT_EXTERN_METHOD(detectOnVideo:(nonnull NSString *)videoPath 38 | withThreshold:(nonnull NSNumber *)threshold 39 | withMaxResults:(NSInteger)maxResults 40 | withDelegate:(NSInteger)delegate 41 | withModel:(nonnull NSString *)model 42 | resolver:(RCTPromiseResolveBlock)resolve 43 | rejecter:(RCTPromiseRejectBlock)reject 44 | ) 45 | @end 46 | 47 | -------------------------------------------------------------------------------- /ios/posedetection/PdConvertHelpers.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import MediaPipeTasksVision 3 | import React 4 | 5 | func convertPdResultBundleToDictionary(_ resultBundle: PoseDetectionResultBundle) -> [String: Any] { 6 | var map = [String: Any]() 7 | 8 | // Results 9 | let resultsArray = resultBundle.poseDetectorResults.map { result -> [String: Any] in 10 | var resultMap = [String: Any]() 11 | resultMap["timestampMs"] = result?.timestampInMilliseconds 12 | 13 | 14 | let landmarks = result?.landmarks.map { $0.map(normalizedLandmarkToDictionary) } 15 | let worldLandmarks = result?.worldLandmarks.map { $0.map(landmarkToDictionary) } 16 | // this is typically a float for every frame. Too much. It can never go over the boundary 17 | // let segmentationMasks = result?.segmentationMasks.map { maskToDictionary($0) } 18 | 19 | return [ 20 | "landmarks": landmarks ?? [], 21 | "worldLandmarks": worldLandmarks ?? [], 22 | "segmentationMasks": [] 23 | ] 24 | } 25 | map["results"] = resultsArray 26 | 27 | // Image properties 28 | map["inputImageHeight"] = resultBundle.size.height 29 | map["inputImageWidth"] = resultBundle.size.width 30 | // map["inputImageRotation"] = resultBundle. 31 | map["inferenceTime"] = resultBundle.inferenceTime 32 | 33 | return map 34 | } 35 | 36 | -------------------------------------------------------------------------------- /ios/posedetection/PoseDetectionFrameProcessorPlugin.m: -------------------------------------------------------------------------------- 1 | // 2 | // FrameProcessorPlugins.m 3 | // react-native-mediapipe 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | #import 9 | 10 | #import 11 | #import 12 | 13 | #import "ReactNativeMediaPipe-Swift.h" 14 | 15 | @interface PoseDetectionFrameProcessorPlugin (FrameProcessorPluginLoader) 16 | @end 17 | 18 | @implementation PoseDetectionFrameProcessorPlugin (FrameProcessorPluginLoader) 19 | + (void) load { 20 | [FrameProcessorPluginRegistry addFrameProcessorPlugin:@"poseDetection" 21 | withInitializer:^FrameProcessorPlugin*(VisionCameraProxyHolder* proxy, NSDictionary* options) { 22 | return [[PoseDetectionFrameProcessorPlugin alloc] initWithProxy:proxy withOptions:options]; 23 | }]; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /ios/posedetection/PoseDetectionFrameProcessorPlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PoseDetectionFrameProcessorPlugin.swift 3 | // react-native-mediapipe 4 | // 5 | // Created by Charles Parker on 3/24/24. 6 | // 7 | 8 | import Foundation 9 | import Vision 10 | 11 | @objc(PoseDetectionFrameProcessorPlugin) 12 | public class PoseDetectionFrameProcessorPlugin: FrameProcessorPlugin { 13 | public override init(proxy: VisionCameraProxyHolder, options: [AnyHashable: Any]! = [:]) { 14 | super.init(proxy: proxy, options: options) 15 | } 16 | 17 | public override func callback(_ frame: Frame, withArguments arguments: [AnyHashable: Any]?) -> Any 18 | { 19 | guard let detectorHandleValue = arguments?["detectorHandle"] as? Double else { 20 | return false 21 | } 22 | // get the orientation argument. If its nil, return false 23 | guard let orientation = arguments?["orientation"] as? String else { 24 | return false 25 | } 26 | // convert the orientation string to a UIImage.Orientation 27 | guard let uiOrientation = uiImageOrientation(from: orientation) else { 28 | return false 29 | } 30 | 31 | 32 | // Now that we have a valid Double, attempt to retrieve the detector using it 33 | guard let detector = PoseDetectionModule.detectorMap[Int(detectorHandleValue)] else { 34 | return false 35 | } 36 | 37 | let buffer = frame.buffer 38 | detector.detectAsync( 39 | sampleBuffer: buffer, 40 | orientation: uiOrientation, 41 | timeStamps: Int(Date().timeIntervalSince1970 * 1000)) 42 | return true 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ios/shared/ConvertHelper.swift: -------------------------------------------------------------------------------- 1 | import MediaPipeTasksVision 2 | 3 | func convertIntToDelegate(_ value: Int) -> Delegate { 4 | switch value { 5 | case 0: 6 | return .CPU 7 | case 1: 8 | return .GPU 9 | default: 10 | return .CPU 11 | } 12 | } 13 | 14 | func normalizedLandmarkToDictionary(_ landmark: NormalizedLandmark) -> [String: Any] { 15 | var dict = [ 16 | "x": landmark.x, 17 | "y": landmark.y, 18 | "z": landmark.z 19 | ] 20 | if let visibility = landmark.visibility { 21 | dict["visibility"] = visibility.floatValue 22 | } 23 | if let presence = landmark.presence { 24 | dict["presence"] = presence.floatValue 25 | } 26 | return dict 27 | } 28 | 29 | func landmarkToDictionary(_ landmark: Landmark) -> [String: Any] { 30 | var dict = [ 31 | "x": landmark.x, 32 | "y": landmark.y, 33 | "z": landmark.z 34 | ] 35 | if let visibility = landmark.visibility { 36 | dict["visibility"] = visibility.floatValue 37 | } 38 | if let presence = landmark.presence { 39 | dict["presence"] = presence.floatValue 40 | } 41 | return dict 42 | } 43 | 44 | // Converts TransformMatrix to a Dictionary 45 | func transformMatrixToDictionary(_ matrix: TransformMatrix) -> [String: Any] { 46 | var data = [Float]() 47 | for row in 0.. [String: Any] { 60 | var dictionary: [String: Any] = [ 61 | "width": mask.width, 62 | "height": mask.height, 63 | "dataType": mask.dataType.rawValue 64 | ] 65 | 66 | switch mask.dataType { 67 | case .uInt8: 68 | let data = Array(UnsafeBufferPointer(start: mask.uint8Data, count: mask.width * mask.height)) 69 | dictionary["uint8Data"] = data 70 | case .float32: 71 | let data = Array(UnsafeBufferPointer(start: mask.float32Data, count: mask.width * mask.height)) 72 | dictionary["float32Data"] = data 73 | @unknown default: 74 | fatalError() 75 | } 76 | 77 | return dictionary 78 | } 79 | 80 | -------------------------------------------------------------------------------- /ios/shared/MediaHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MediaHelper.swift 3 | // CocoaAsyncSocket 4 | // 5 | // Created by Charles Parker on 5/12/24. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | enum MediaLoadingError: Error, LocalizedError { 12 | case invalidURL 13 | case unableToLoadData 14 | case unableToCreateImage 15 | case unableToCreateVideoAsset 16 | 17 | var errorDescription: String? { 18 | switch self { 19 | case .invalidURL: 20 | return "Provided string is not a valid URL." 21 | case .unableToLoadData: 22 | return "Could not load data from the URL." 23 | case .unableToCreateImage: 24 | return "Data loaded is not a valid image." 25 | case .unableToCreateVideoAsset: 26 | return "Data loaded is not a valid video." 27 | } 28 | } 29 | } 30 | 31 | func loadImageFromPath(from path: String) throws -> UIImage { 32 | // ensure its a url 33 | var imageUrl: String 34 | if path.starts(with: "file://") { 35 | imageUrl = path 36 | } else { 37 | imageUrl = "file://" + path 38 | } 39 | 40 | guard let url = URL(string: imageUrl) else { 41 | throw MediaLoadingError.invalidURL 42 | } 43 | guard let data = try? Data(contentsOf: url) else { 44 | throw MediaLoadingError.unableToLoadData 45 | } 46 | guard let image = UIImage(data: data) else { 47 | throw MediaLoadingError.unableToCreateImage 48 | } 49 | return image 50 | } 51 | -------------------------------------------------------------------------------- /ios/shared/OrientationHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OrientationHelper.swift 3 | // Pods 4 | // 5 | // Created by Charles Parker on 9/17/24. 6 | // 7 | 8 | import UIKit 9 | 10 | func uiImageOrientation(from orientation: String) -> UIImage.Orientation? { 11 | switch orientation { 12 | case "portrait": 13 | return .up 14 | case "portrait-upside-down": 15 | return .down 16 | case "landscape-left": 17 | return .right 18 | case "landscape-right": 19 | return .left 20 | default: 21 | return nil 22 | } 23 | } -------------------------------------------------------------------------------- /lefthook.yml: -------------------------------------------------------------------------------- 1 | pre-commit: 2 | parallel: true 3 | commands: 4 | lint: 5 | glob: "*.{js,ts,jsx,tsx}" 6 | run: npx eslint {staged_files} 7 | types: 8 | glob: "*.{js,ts, jsx, tsx}" 9 | run: npx tsc --noEmit 10 | types-docsite: 11 | glob: "*.{js,ts, jsx, tsx}" 12 | run: npx tsc --noEmit --project docsite 13 | commit-msg: 14 | parallel: true 15 | commands: 16 | commitlint: 17 | run: npx commitlint --edit 18 | -------------------------------------------------------------------------------- /src/__tests__/index.test.tsx: -------------------------------------------------------------------------------- 1 | it("write a test", () => { 2 | expect(true).toBe(true); 3 | }); 4 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./objectDetection"; 2 | export * from "./poseDetection"; 3 | export * from "./faceLandmarkDetection"; 4 | export * from "./shared/mediapipeCamera"; 5 | export * from "./shared/convert"; 6 | export * from "./shared/types"; 7 | -------------------------------------------------------------------------------- /src/shared/mediapipeCamera.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, forwardRef } from "react"; 2 | import { type ViewStyle, Text } from "react-native"; 3 | import { 4 | Camera, 5 | useCameraDevice, 6 | type CameraPosition, 7 | type CameraProps, 8 | } from "react-native-vision-camera"; 9 | import type { MediaPipeSolution } from "./types"; 10 | 11 | export type MediapipeCameraProps = { 12 | style: ViewStyle; 13 | solution: MediaPipeSolution; 14 | activeCamera?: CameraPosition; 15 | resizeMode?: CameraProps["resizeMode"]; 16 | }; 17 | 18 | export const MediapipeCamera = forwardRef( 19 | ( 20 | { 21 | style, 22 | solution: { 23 | cameraDeviceChangeHandler, 24 | cameraViewLayoutChangeHandler, 25 | cameraOrientationChangedHandler, 26 | resizeModeChangeHandler, 27 | frameProcessor, 28 | }, 29 | activeCamera = "front", 30 | resizeMode = "cover", 31 | }, 32 | ref 33 | ) => { 34 | const device = useCameraDevice(activeCamera); 35 | 36 | useEffect(() => { 37 | if (device) { 38 | cameraDeviceChangeHandler(device); 39 | } 40 | }, [cameraDeviceChangeHandler, device]); 41 | 42 | useEffect(() => { 43 | resizeModeChangeHandler(resizeMode); 44 | }, [resizeModeChangeHandler, resizeMode]); 45 | 46 | if (device == null) { 47 | return Loading...; 48 | } 49 | 50 | return ( 51 | 63 | ); 64 | } 65 | ); 66 | -------------------------------------------------------------------------------- /tools/long-paths-enabled.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem] 4 | "LongPathsEnabled"=dword:00000001 5 | -------------------------------------------------------------------------------- /tools/windows/ninja.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdiddy77/react-native-mediapipe/cdd0dafd87c362097a364fdca8d06fcdb2f7ff3f/tools/windows/ninja.exe -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "exclude": [ 4 | "docsite" 5 | ] 6 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.shared", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "paths": { 6 | "react-native-mediapipe": [ 7 | "./src/index" 8 | ] 9 | }, 10 | "composite": true 11 | }, 12 | "exclude": [ 13 | ".eslintrc.js", 14 | "babel.config.js", 15 | "react-native.config.js", 16 | "docsite", 17 | ] 18 | } -------------------------------------------------------------------------------- /tsconfig.shared.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowUnreachableCode": false, 4 | "allowUnusedLabels": false, 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "jsx": "react-native", 8 | "lib": [ 9 | "esnext" 10 | ], 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "noFallthroughCasesInSwitch": true, 14 | "noImplicitReturns": true, 15 | "noImplicitUseStrict": false, 16 | "noStrictGenericChecks": false, 17 | "noUncheckedIndexedAccess": false, 18 | "resolveJsonModule": true, 19 | "skipLibCheck": true, 20 | "strict": true, 21 | "target": "esnext", 22 | "verbatimModuleSyntax": true 23 | } 24 | } -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "pipeline": { 4 | "build:android": { 5 | "inputs": [ 6 | "package.json", 7 | "android", 8 | "!android/build", 9 | "src/*.ts", 10 | "src/*.tsx", 11 | "examples/*/package.json", 12 | "examples/*/android", 13 | "!examples/*/android/.gradle", 14 | "!examples/*/android/build", 15 | "!examples/*/android/app/build" 16 | ], 17 | "outputs": [] 18 | }, 19 | "build:ios": { 20 | "inputs": [ 21 | "package.json", 22 | "*.podspec", 23 | "ios", 24 | "src/*.ts", 25 | "src/*.tsx", 26 | "examples/*/package.json", 27 | "examples/*/ios", 28 | "!examples/*/ios/build", 29 | "!examples/*/ios/Pods" 30 | ], 31 | "outputs": [] 32 | } 33 | } 34 | } --------------------------------------------------------------------------------