Compare commits
+1
-1
@@ -1 +1 @@
|
|||||||
5.2.0
|
6.1.1
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Build/Installation Issue"
|
|
||||||
about: Use this template for build/installation issues
|
|
||||||
labels: type:build/install
|
|
||||||
|
|
||||||
---
|
|
||||||
<em>Please make sure that this is a build/installation issue and also refer to the [troubleshooting](https://google.github.io/mediapipe/getting_started/troubleshooting.html) documentation before raising any issues.</em>
|
|
||||||
|
|
||||||
**System information** (Please provide as much relevant information as possible)
|
|
||||||
- OS Platform and Distribution (e.g. Linux Ubuntu 16.04, Android 11, iOS 14.4):
|
|
||||||
- Compiler version (e.g. gcc/g++ 8 /Apple clang version 12.0.0):
|
|
||||||
- Programming Language and version ( e.g. C++ 14, Python 3.6, Java ):
|
|
||||||
- Installed using virtualenv? pip? Conda? (if python):
|
|
||||||
- [MediaPipe version](https://github.com/google/mediapipe/releases):
|
|
||||||
- Bazel version:
|
|
||||||
- XCode and Tulsi versions (if iOS):
|
|
||||||
- Android SDK and NDK versions (if android):
|
|
||||||
- Android [AAR](https://google.github.io/mediapipe/getting_started/android_archive_library.html) ( if android):
|
|
||||||
- OpenCV version (if running on desktop):
|
|
||||||
|
|
||||||
**Describe the problem**:
|
|
||||||
|
|
||||||
|
|
||||||
**[Provide the exact sequence of commands / steps that you executed before running into the problem](https://google.github.io/mediapipe/getting_started/getting_started.html):**
|
|
||||||
|
|
||||||
**Complete Logs:**
|
|
||||||
Include Complete Log information or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached:
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Tasks Issue"
|
|
||||||
about: Use this template for assistance with using MediaPipe Tasks (developers.google.com/mediapipe/solutions) to deploy on-device ML solutions (e.g. gesture recognition etc.) on supported platforms.
|
|
||||||
labels: type:support
|
|
||||||
|
|
||||||
---
|
|
||||||
<em>Please make sure that this is a [Tasks](https://developers.google.com/mediapipe/solutions) issue.<em>
|
|
||||||
|
|
||||||
**System information** (Please provide as much relevant information as possible)
|
|
||||||
- Have I written custom code (as opposed to using a stock example script provided in MediaPipe):
|
|
||||||
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04, Android 11, iOS 14.4):
|
|
||||||
- MediaPipe Tasks SDK version:
|
|
||||||
- Task name (e.g. Object detection, Gesture recognition etc.):
|
|
||||||
- Programming Language and version ( e.g. C++, Python, Java):
|
|
||||||
|
|
||||||
**Describe the expected behavior:**
|
|
||||||
|
|
||||||
**Standalone code you may have used to try to get what you need :**
|
|
||||||
|
|
||||||
If there is a problem, provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab, GitHub repo link or anything that we can use to reproduce the problem:
|
|
||||||
|
|
||||||
**Other info / Complete Logs :**
|
|
||||||
Include any logs or source code that would be helpful to
|
|
||||||
diagnose the problem. If including tracebacks, please include the full
|
|
||||||
traceback. Large logs and files should be attached:
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Model Maker Issue"
|
|
||||||
about: Use this template for assistance with using MediaPipe Model Maker (developers.google.com/mediapipe/solutions) to create custom on-device ML solutions.
|
|
||||||
labels: type:support
|
|
||||||
|
|
||||||
---
|
|
||||||
<em>Please make sure that this is a [Model Maker](https://developers.google.com/mediapipe/solutions) issue.<em>
|
|
||||||
|
|
||||||
**System information** (Please provide as much relevant information as possible)
|
|
||||||
- Have I written custom code (as opposed to using a stock example script provided in MediaPipe):
|
|
||||||
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04):
|
|
||||||
- Python version (e.g. 3.8):
|
|
||||||
- [MediaPipe Model Maker version](https://pypi.org/project/mediapipe-model-maker/):
|
|
||||||
- Task name (e.g. Image classification, Gesture recognition etc.):
|
|
||||||
|
|
||||||
**Describe the expected behavior:**
|
|
||||||
|
|
||||||
**Standalone code you may have used to try to get what you need :**
|
|
||||||
|
|
||||||
If there is a problem, provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab, GitHub repo link or anything that we can use to reproduce the problem:
|
|
||||||
|
|
||||||
**Other info / Complete Logs :**
|
|
||||||
Include any logs or source code that would be helpful to
|
|
||||||
diagnose the problem. If including tracebacks, please include the full
|
|
||||||
traceback. Large logs and files should be attached:
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Solution (legacy) Issue"
|
|
||||||
about: Use this template for assistance with a specific Mediapipe solution (google.github.io/mediapipe/solutions) such as "Pose", including inference model usage/training, solution-specific calculators etc.
|
|
||||||
labels: type:support
|
|
||||||
|
|
||||||
---
|
|
||||||
<em>Please make sure that this is a [solution](https://google.github.io/mediapipe/solutions/solutions.html) issue.<em>
|
|
||||||
|
|
||||||
**System information** (Please provide as much relevant information as possible)
|
|
||||||
- Have I written custom code (as opposed to using a stock example script provided in Mediapipe):
|
|
||||||
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04, Android 11, iOS 14.4):
|
|
||||||
- [MediaPipe version](https://github.com/google/mediapipe/releases):
|
|
||||||
- Bazel version:
|
|
||||||
- Solution (e.g. FaceMesh, Pose, Holistic):
|
|
||||||
- Programming Language and version ( e.g. C++, Python, Java):
|
|
||||||
|
|
||||||
**Describe the expected behavior:**
|
|
||||||
|
|
||||||
**Standalone code you may have used to try to get what you need :**
|
|
||||||
|
|
||||||
If there is a problem, provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab/repo link /any notebook:
|
|
||||||
|
|
||||||
**Other info / Complete Logs :**
|
|
||||||
Include any logs or source code that would be helpful to
|
|
||||||
diagnose the problem. If including tracebacks, please include the full
|
|
||||||
traceback. Large logs and files should be attached:
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Studio Issue"
|
|
||||||
about: Use this template for assistance with the MediaPipe Studio application.
|
|
||||||
labels: type:support
|
|
||||||
|
|
||||||
---
|
|
||||||
<em>Please make sure that this is a MediaPipe Studio issue.<em>
|
|
||||||
|
|
||||||
**System information** (Please provide as much relevant information as possible)
|
|
||||||
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04, Android 11, iOS 14.4):
|
|
||||||
- Browser and Version
|
|
||||||
- Any microphone or camera hardware
|
|
||||||
- URL that shows the problem
|
|
||||||
|
|
||||||
**Describe the expected behavior:**
|
|
||||||
|
|
||||||
**Other info / Complete Logs :**
|
|
||||||
Include any js console logs that would be helpful to diagnose the problem.
|
|
||||||
Large logs and files should be attached:
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Documentation Issue"
|
|
||||||
about: Use this template for documentation related issues
|
|
||||||
labels: type:docs
|
|
||||||
|
|
||||||
---
|
|
||||||
Thank you for submitting a MediaPipe documentation issue.
|
|
||||||
The MediaPipe docs are open source! To get involved, read the documentation Contributor Guide
|
|
||||||
## URL(s) with the issue:
|
|
||||||
|
|
||||||
Please provide a link to the documentation entry, for example: https://github.com/google/mediapipe/blob/master/docs/solutions/face_mesh.md#models
|
|
||||||
|
|
||||||
## Description of issue (what needs changing):
|
|
||||||
|
|
||||||
Kinds of documentation problems:
|
|
||||||
|
|
||||||
### Clear description
|
|
||||||
|
|
||||||
For example, why should someone use this method? How is it useful?
|
|
||||||
|
|
||||||
### Correct links
|
|
||||||
|
|
||||||
Is the link to the source code correct?
|
|
||||||
|
|
||||||
### Parameters defined
|
|
||||||
Are all parameters defined and formatted correctly?
|
|
||||||
|
|
||||||
### Returns defined
|
|
||||||
|
|
||||||
Are return values defined?
|
|
||||||
|
|
||||||
### Raises listed and defined
|
|
||||||
|
|
||||||
Are the errors defined? For example,
|
|
||||||
|
|
||||||
### Usage example
|
|
||||||
|
|
||||||
Is there a usage example?
|
|
||||||
|
|
||||||
See the API guide:
|
|
||||||
on how to write testable usage examples.
|
|
||||||
|
|
||||||
### Request visuals, if applicable
|
|
||||||
|
|
||||||
Are there currently visuals? If not, will it clarify the content?
|
|
||||||
|
|
||||||
### Submit a pull request?
|
|
||||||
|
|
||||||
Are you planning to also submit a pull request to fix the issue? See the docs
|
|
||||||
https://github.com/google/mediapipe/blob/master/CONTRIBUTING.md
|
|
||||||
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bug Issue"
|
|
||||||
about: Use this template for reporting a bug
|
|
||||||
labels: type:bug
|
|
||||||
|
|
||||||
---
|
|
||||||
<em>Please make sure that this is a bug and also refer to the [troubleshooting](https://google.github.io/mediapipe/getting_started/troubleshooting.html), FAQ documentation before raising any issues.</em>
|
|
||||||
|
|
||||||
**System information** (Please provide as much relevant information as possible)
|
|
||||||
|
|
||||||
- Have I written custom code (as opposed to using a stock example script provided in MediaPipe):
|
|
||||||
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04, Android 11, iOS 14.4):
|
|
||||||
- Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device:
|
|
||||||
- Browser and version (e.g. Google Chrome, Safari) if the issue happens on browser:
|
|
||||||
- Programming Language and version ( e.g. C++, Python, Java):
|
|
||||||
- [MediaPipe version](https://github.com/google/mediapipe/releases):
|
|
||||||
- Bazel version (if compiling from source):
|
|
||||||
- Solution ( e.g. FaceMesh, Pose, Holistic ):
|
|
||||||
- Android Studio, NDK, SDK versions (if issue is related to building in Android environment):
|
|
||||||
- Xcode & Tulsi version (if issue is related to building for iOS):
|
|
||||||
|
|
||||||
**Describe the current behavior:**
|
|
||||||
|
|
||||||
**Describe the expected behavior:**
|
|
||||||
|
|
||||||
**Standalone code to reproduce the issue:**
|
|
||||||
Provide a reproducible test case that is the bare minimum necessary to replicate the problem. If possible, please share a link to Colab/repo link /any notebook:
|
|
||||||
|
|
||||||
**Other info / Complete Logs :**
|
|
||||||
Include any logs or source code that would be helpful to
|
|
||||||
diagnose the problem. If including tracebacks, please include the full
|
|
||||||
traceback. Large logs and files should be attached
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Feature Request"
|
|
||||||
about: Use this template for raising a feature request
|
|
||||||
labels: type:feature
|
|
||||||
|
|
||||||
---
|
|
||||||
<em>Please make sure that this is a feature request.</em>
|
|
||||||
|
|
||||||
**System information** (Please provide as much relevant information as possible)
|
|
||||||
|
|
||||||
- MediaPipe Solution (you are using):
|
|
||||||
- Programming language : C++/typescript/Python/Objective C/Android Java
|
|
||||||
- Are you willing to contribute it (Yes/No):
|
|
||||||
|
|
||||||
|
|
||||||
**Describe the feature and the current behavior/state:**
|
|
||||||
|
|
||||||
**Will this change the current api? How?**
|
|
||||||
|
|
||||||
**Who will benefit with this feature?**
|
|
||||||
|
|
||||||
**Please specify the use cases for this feature:**
|
|
||||||
|
|
||||||
**Any Other info:**
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
name: Documentation issue
|
||||||
|
description: Use this template for documentation related issues. If this doesn’t look right, choose a different type.
|
||||||
|
labels: 'type:doc-bug'
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: link
|
||||||
|
attributes:
|
||||||
|
value: Thank you for submitting a MediaPipe documentation issue. The MediaPipe docs are open source! To get involved, read the documentation Contributor Guide
|
||||||
|
- type: markdown
|
||||||
|
id: url
|
||||||
|
attributes:
|
||||||
|
value: URL(s) with the issue Please provide a link to the documentation entry, for example https://github.com/google/mediapipe/blob/master/docs/solutions/face_mesh.md#models
|
||||||
|
- type: input
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description of issue (what needs changing)
|
||||||
|
description: Kinds of documentation problems
|
||||||
|
- type: input
|
||||||
|
id: clear_desc
|
||||||
|
attributes:
|
||||||
|
label: Clear description
|
||||||
|
description: For example, why should someone use this method? How is it useful?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: link
|
||||||
|
attributes:
|
||||||
|
label: Correct links
|
||||||
|
description: Is the link to the source code correct?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: parameter
|
||||||
|
attributes:
|
||||||
|
label: Parameters defined
|
||||||
|
description: Are all parameters defined and formatted correctly?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: returns
|
||||||
|
attributes:
|
||||||
|
label: Returns defined
|
||||||
|
description: Are return values defined?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: raises
|
||||||
|
attributes:
|
||||||
|
label: Raises listed and defined
|
||||||
|
description: Are the errors defined? For example,
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: usage
|
||||||
|
attributes:
|
||||||
|
label: Usage example
|
||||||
|
description: Is there a usage example? See the API guide-on how to write testable usage examples.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: visual
|
||||||
|
attributes:
|
||||||
|
label: Request visuals, if applicable
|
||||||
|
description: Are there currently visuals? If not, will it clarify the content?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: pull
|
||||||
|
attributes:
|
||||||
|
label: Submit a pull request?
|
||||||
|
description: Are you planning to also submit a pull request to fix the issue? See the [docs](https://github.com/google/mediapipe/blob/master/CONTRIBUTING.md)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
name: Solution(Legacy) Issue
|
||||||
|
description: Use this template for assistance with a specific Mediapipe solution (google.github.io/mediapipe/solutions) such as "Pose", including inference model usage/training, solution-specific calculators etc.
|
||||||
|
labels: 'type:support'
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: linkmodel
|
||||||
|
attributes:
|
||||||
|
value: Please make sure that this is a [solution](https://google.github.io/mediapipe/solutions/solutions.html) issue.
|
||||||
|
- type: dropdown
|
||||||
|
id: customcode_model
|
||||||
|
attributes:
|
||||||
|
label: Have I written custom code (as opposed to using a stock example script provided in MediaPipe)
|
||||||
|
options:
|
||||||
|
- 'Yes'
|
||||||
|
- 'No'
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: os_model
|
||||||
|
attributes:
|
||||||
|
label: OS Platform and Distribution
|
||||||
|
placeholder: e.g. Linux Ubuntu 16.04, Android 11, iOS 14.4
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: mediapipe_version
|
||||||
|
attributes:
|
||||||
|
label: MediaPipe version
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: bazel_version
|
||||||
|
attributes:
|
||||||
|
label: Bazel version
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: Solution
|
||||||
|
placeholder: e.g. FaceMesh, Pose, Holistic
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: programminglang
|
||||||
|
attributes:
|
||||||
|
label: Programming Language and version
|
||||||
|
placeholder: e.g. C++, Python, Java
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: current_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the actual behavior
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: expected_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the expected behaviour
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened_model
|
||||||
|
attributes:
|
||||||
|
label: Standalone code/steps you may have used to try to get what you need
|
||||||
|
description: If there is a problem, provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab, GitHub repo link or anything that we can use to reproduce the problem
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: other_info
|
||||||
|
attributes:
|
||||||
|
label: Other info / Complete Logs
|
||||||
|
description: Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
name: Bug Issues
|
||||||
|
description: Use this template for reporting a bug. If this doesn’t look right, choose a different type.
|
||||||
|
labels: 'type:bug'
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: link
|
||||||
|
attributes:
|
||||||
|
value: Please make sure that this is a bug and also refer to the [troubleshooting](https://google.github.io/mediapipe/getting_started/troubleshooting.html), FAQ documentation before raising any issues.
|
||||||
|
- type: dropdown
|
||||||
|
id: customcode_model
|
||||||
|
attributes:
|
||||||
|
label: Have I written custom code (as opposed to using a stock example script provided in MediaPipe)
|
||||||
|
options:
|
||||||
|
- 'Yes'
|
||||||
|
- 'No'
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: os
|
||||||
|
attributes:
|
||||||
|
label: OS Platform and Distribution
|
||||||
|
description:
|
||||||
|
placeholder: e.g. Linux Ubuntu 16.04, Android 11, iOS 14.4
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: mobile_device
|
||||||
|
attributes:
|
||||||
|
label: Mobile device if the issue happens on mobile device
|
||||||
|
description:
|
||||||
|
placeholder: e.g. iPhone 8, Pixel 2, Samsung Galaxy
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: browser_version
|
||||||
|
attributes:
|
||||||
|
label: Browser and version if the issue happens on browser
|
||||||
|
placeholder: e.g. Google Chrome 109.0.5414.119, Safari 16.3
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: programminglang
|
||||||
|
attributes:
|
||||||
|
label: Programming Language and version
|
||||||
|
placeholder: e.g. C++, Python, Java
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: mediapipever
|
||||||
|
attributes:
|
||||||
|
label: MediaPipe version
|
||||||
|
description:
|
||||||
|
placeholder: e.g. 0.8.11, 0.9.1
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: bazelver
|
||||||
|
attributes:
|
||||||
|
label: Bazel version
|
||||||
|
description:
|
||||||
|
placeholder: e.g. 5.0, 5.1
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: Solution
|
||||||
|
placeholder: e.g. FaceMesh, Pose, Holistic
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: sdkndkversion
|
||||||
|
attributes:
|
||||||
|
label: Android Studio, NDK, SDK versions (if issue is related to building in Android environment)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: xcode_ver
|
||||||
|
attributes:
|
||||||
|
label: Xcode & Tulsi version (if issue is related to building for iOS)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: current_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the actual behavior
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expected_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the expected behaviour
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened_model
|
||||||
|
attributes:
|
||||||
|
label: Standalone code/steps you may have used to try to get what you need
|
||||||
|
description: If there is a problem, provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab, GitHub repo link or anything that we can use to reproduce the problem
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: other_info
|
||||||
|
attributes:
|
||||||
|
label: Other info / Complete Logs
|
||||||
|
description: Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
name: Build/Install Issue
|
||||||
|
description: Use this template to report build/install issue
|
||||||
|
labels: 'type:build/install'
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: link
|
||||||
|
attributes:
|
||||||
|
value: Please make sure that this is a build/installation issue and also refer to the [troubleshooting](https://google.github.io/mediapipe/getting_started/troubleshooting.html) documentation before raising any issues.
|
||||||
|
- type: input
|
||||||
|
id: os
|
||||||
|
attributes:
|
||||||
|
label: OS Platform and Distribution
|
||||||
|
description:
|
||||||
|
placeholder: e.g. Linux Ubuntu 16.04, Android 11, iOS 14.4
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: compilerversion
|
||||||
|
attributes:
|
||||||
|
label: Compiler version
|
||||||
|
description:
|
||||||
|
placeholder: e.g. gcc/g++ 8 /Apple clang version 12.0.0
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: programminglang
|
||||||
|
attributes:
|
||||||
|
label: Programming Language and version
|
||||||
|
description:
|
||||||
|
placeholder: e.g. C++ 14, Python 3.6, Java
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: virtualenv
|
||||||
|
attributes:
|
||||||
|
label: Installed using virtualenv? pip? Conda?(if python)
|
||||||
|
description:
|
||||||
|
placeholder:
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: mediapipever
|
||||||
|
attributes:
|
||||||
|
label: MediaPipe version
|
||||||
|
description:
|
||||||
|
placeholder: e.g. 0.8.11, 0.9.1
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: bazelver
|
||||||
|
attributes:
|
||||||
|
label: Bazel version
|
||||||
|
description:
|
||||||
|
placeholder: e.g. 5.0, 5.1
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: xcodeversion
|
||||||
|
attributes:
|
||||||
|
label: XCode and Tulsi versions (if iOS)
|
||||||
|
description:
|
||||||
|
placeholder:
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: sdkndkversion
|
||||||
|
attributes:
|
||||||
|
label: Android SDK and NDK versions (if android)
|
||||||
|
description:
|
||||||
|
placeholder:
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: dropdown
|
||||||
|
id: androidaar
|
||||||
|
attributes:
|
||||||
|
label: Android AAR (if android)
|
||||||
|
options:
|
||||||
|
- 'Yes'
|
||||||
|
- 'No'
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: opencvversion
|
||||||
|
attributes:
|
||||||
|
label: OpenCV version (if running on desktop)
|
||||||
|
description:
|
||||||
|
placeholder:
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: Describe the problem
|
||||||
|
description: Provide the exact sequence of commands / steps that you executed before running into the [problem](https://google.github.io/mediapipe/getting_started/getting_started.html)
|
||||||
|
placeholder: Tell us what you see!
|
||||||
|
value: "A bug happened!"
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: code-to-reproduce
|
||||||
|
attributes:
|
||||||
|
label: Complete Logs
|
||||||
|
description: Include Complete Log information or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached
|
||||||
|
placeholder: Tell us what you see!
|
||||||
|
value:
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
name: Feature Request Issues
|
||||||
|
description: Use this template for raising a feature request. If this doesn’t look right, choose a different type.
|
||||||
|
labels: 'type:feature'
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: linkmodel
|
||||||
|
attributes:
|
||||||
|
value: Please make sure that this is a feature request.
|
||||||
|
- type: input
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: MediaPipe Solution (you are using)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: pgmlang
|
||||||
|
attributes:
|
||||||
|
label: Programming language
|
||||||
|
placeholder: C++/typescript/Python/Objective C/Android Java
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: dropdown
|
||||||
|
id: willingcon
|
||||||
|
attributes:
|
||||||
|
label: Are you willing to contribute it
|
||||||
|
options:
|
||||||
|
- 'Yes'
|
||||||
|
- 'No'
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: behaviour
|
||||||
|
attributes:
|
||||||
|
label: Describe the feature and the current behaviour/state
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: api_change
|
||||||
|
attributes:
|
||||||
|
label: Will this change the current API? How?
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: benifit
|
||||||
|
attributes:
|
||||||
|
label: Who will benefit with this feature?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: use_case
|
||||||
|
attributes:
|
||||||
|
label: Please specify the use cases for this feature
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: info_other
|
||||||
|
attributes:
|
||||||
|
label: Any Other info
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
name: Model Maker Issues
|
||||||
|
description: Use this template for assistance with using MediaPipe Model Maker (developers.google.com/mediapipe/solutions) to create custom on-device ML solutions.
|
||||||
|
labels: 'type:modelmaker'
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: linkmodel
|
||||||
|
attributes:
|
||||||
|
value: Please make sure that this is a [Model Maker](https://developers.google.com/mediapipe/solutions) issue
|
||||||
|
- type: dropdown
|
||||||
|
id: customcode_model
|
||||||
|
attributes:
|
||||||
|
label: Have I written custom code (as opposed to using a stock example script provided in MediaPipe)
|
||||||
|
options:
|
||||||
|
- 'Yes'
|
||||||
|
- 'No'
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: os_model
|
||||||
|
attributes:
|
||||||
|
label: OS Platform and Distribution
|
||||||
|
placeholder: e.g. Linux Ubuntu 16.04, Android 11, iOS 14.4
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: pythonver
|
||||||
|
attributes:
|
||||||
|
label: Python Version
|
||||||
|
placeholder: e.g. 3.7, 3.8
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: modelmakerver
|
||||||
|
attributes:
|
||||||
|
label: MediaPipe Model Maker version
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: taskname
|
||||||
|
attributes:
|
||||||
|
label: Task name (e.g. Image classification, Gesture recognition etc.)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: current_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the actual behavior
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expected_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the expected behaviour
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened_model
|
||||||
|
attributes:
|
||||||
|
label: Standalone code/steps you may have used to try to get what you need
|
||||||
|
description: If there is a problem, provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab, GitHub repo link or anything that we can use to reproduce the problem
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: other_info
|
||||||
|
attributes:
|
||||||
|
label: Other info / Complete Logs
|
||||||
|
description: Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
name: Studio Issues
|
||||||
|
description: Use this template for assistance with the MediaPipe Studio application. If this doesn’t look right, choose a different type.
|
||||||
|
labels: 'type:support'
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: linkmodel
|
||||||
|
attributes:
|
||||||
|
value: Please make sure that this is a MediaPipe Studio issue.
|
||||||
|
- type: input
|
||||||
|
id: os_model
|
||||||
|
attributes:
|
||||||
|
label: OS Platform and Distribution
|
||||||
|
placeholder: e.g. Linux Ubuntu 16.04, Android 11, iOS 14.4
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: browserver
|
||||||
|
attributes:
|
||||||
|
label: Browser and Version
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: hardware
|
||||||
|
attributes:
|
||||||
|
label: Any microphone or camera hardware
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: url
|
||||||
|
attributes:
|
||||||
|
label: URL that shows the problem
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: current_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the actual behavior
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: expected_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the expected behaviour
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened_model
|
||||||
|
attributes:
|
||||||
|
label: Standalone code/steps you may have used to try to get what you need
|
||||||
|
description: If there is a problem, provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab, GitHub repo link or anything that we can use to reproduce the problem
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
id: other_info
|
||||||
|
attributes:
|
||||||
|
label: Other info / Complete Logs
|
||||||
|
description: Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
name: Task Issue
|
||||||
|
description: Use this template for assistance with using MediaPipe Tasks (developers.google.com/mediapipe/solutions) to deploy on-device ML solutions (e.g. gesture recognition etc.) on supported platforms
|
||||||
|
labels: 'type:task'
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
id: linkmodel
|
||||||
|
attributes:
|
||||||
|
value: Please make sure that this is a [Tasks](https://developers.google.com/mediapipe/solutions) issue.
|
||||||
|
- type: dropdown
|
||||||
|
id: customcode_model
|
||||||
|
attributes:
|
||||||
|
label: Have I written custom code (as opposed to using a stock example script provided in MediaPipe)
|
||||||
|
options:
|
||||||
|
- 'Yes'
|
||||||
|
- 'No'
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: os_model
|
||||||
|
attributes:
|
||||||
|
label: OS Platform and Distribution
|
||||||
|
placeholder: e.g. Linux Ubuntu 16.04, Android 11, iOS 14.4
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: task-sdk-version
|
||||||
|
attributes:
|
||||||
|
label: MediaPipe Tasks SDK version
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: taskname
|
||||||
|
attributes:
|
||||||
|
label: Task name (e.g. Image classification, Gesture recognition etc.)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: programminglang
|
||||||
|
attributes:
|
||||||
|
label: Programming Language and version (e.g. C++, Python, Java)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: current_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the actual behavior
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expected_model
|
||||||
|
attributes:
|
||||||
|
label: Describe the expected behaviour
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened_model
|
||||||
|
attributes:
|
||||||
|
label: Standalone code/steps you may have used to try to get what you need
|
||||||
|
description: If there is a problem, provide a reproducible test case that is the bare minimum necessary to generate the problem. If possible, please share a link to Colab, GitHub repo link or anything that we can use to reproduce the problem
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: other_info
|
||||||
|
attributes:
|
||||||
|
label: Other info / Complete Logs
|
||||||
|
description: Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
+1
-1
@@ -61,7 +61,7 @@ RUN pip3 install tf_slim
|
|||||||
RUN ln -s /usr/bin/python3 /usr/bin/python
|
RUN ln -s /usr/bin/python3 /usr/bin/python
|
||||||
|
|
||||||
# Install bazel
|
# Install bazel
|
||||||
ARG BAZEL_VERSION=5.2.0
|
ARG BAZEL_VERSION=6.1.1
|
||||||
RUN mkdir /bazel && \
|
RUN mkdir /bazel && \
|
||||||
wget --no-check-certificate -O /bazel/installer.sh "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/b\
|
wget --no-check-certificate -O /bazel/installer.sh "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/b\
|
||||||
azel-${BAZEL_VERSION}-installer-linux-x86_64.sh" && \
|
azel-${BAZEL_VERSION}-installer-linux-x86_64.sh" && \
|
||||||
|
|||||||
@@ -199,3 +199,20 @@
|
|||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
|
===========================================================================
|
||||||
|
For files under tasks/cc/text/language_detector/custom_ops/utils/utf/
|
||||||
|
===========================================================================
|
||||||
|
/*
|
||||||
|
* The authors of this software are Rob Pike and Ken Thompson.
|
||||||
|
* Copyright (c) 2002 by Lucent Technologies.
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose without fee is hereby granted, provided that this entire notice
|
||||||
|
* is included in all copies of any software which is or includes a copy
|
||||||
|
* or modification of this software and in all copies of the supporting
|
||||||
|
* documentation for such software.
|
||||||
|
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||||
|
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||||
|
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
|||||||
@@ -6,6 +6,20 @@ nav_order: 1
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
*This notice and web page will be removed on June 1, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
## Live ML anywhere
|
## Live ML anywhere
|
||||||
@@ -19,6 +33,8 @@ ML solutions for live and streaming media.
|
|||||||
 | 
|
 | 
|
||||||
***Ready-to-use solutions***: *Cutting-edge ML solutions demonstrating full power of the framework* | ***Free and open source***: *Framework and solutions both under Apache 2.0, fully extensible and customizable*
|
***Ready-to-use solutions***: *Cutting-edge ML solutions demonstrating full power of the framework* | ***Free and open source***: *Framework and solutions both under Apache 2.0, fully extensible and customizable*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## ML solutions in MediaPipe
|
## ML solutions in MediaPipe
|
||||||
|
|
||||||
Face Detection | Face Mesh | Iris | Hands | Pose | Holistic
|
Face Detection | Face Mesh | Iris | Hands | Pose | Holistic
|
||||||
|
|||||||
@@ -10,33 +10,31 @@ bind(
|
|||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "bazel_skylib",
|
name = "bazel_skylib",
|
||||||
type = "tar.gz",
|
sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
|
||||||
urls = [
|
urls = [
|
||||||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz",
|
"https://storage.googleapis.com/mirror.tensorflow.org/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
|
||||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz",
|
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
|
||||||
],
|
],
|
||||||
sha256 = "1c531376ac7e5a180e0237938a2536de0c54d93f5c278634818e0efc952dd56c",
|
|
||||||
)
|
)
|
||||||
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
|
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
|
||||||
bazel_skylib_workspace()
|
bazel_skylib_workspace()
|
||||||
load("@bazel_skylib//lib:versions.bzl", "versions")
|
load("@bazel_skylib//lib:versions.bzl", "versions")
|
||||||
versions.check(minimum_bazel_version = "3.7.2")
|
versions.check(minimum_bazel_version = "3.7.2")
|
||||||
|
|
||||||
# ABSL cpp library lts_2021_03_24, patch 2.
|
# ABSL cpp library lts_2023_01_25.
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "com_google_absl",
|
name = "com_google_absl",
|
||||||
urls = [
|
urls = [
|
||||||
"https://github.com/abseil/abseil-cpp/archive/refs/tags/20220623.1.tar.gz",
|
"https://github.com/abseil/abseil-cpp/archive/refs/tags/20230125.0.tar.gz",
|
||||||
],
|
],
|
||||||
# Remove after https://github.com/abseil/abseil-cpp/issues/326 is solved.
|
|
||||||
patches = [
|
patches = [
|
||||||
"@//third_party:com_google_absl_f863b622fe13612433fdf43f76547d5edda0c93001.diff"
|
"@//third_party:com_google_absl_windows_patch.diff"
|
||||||
],
|
],
|
||||||
patch_args = [
|
patch_args = [
|
||||||
"-p1",
|
"-p1",
|
||||||
],
|
],
|
||||||
strip_prefix = "abseil-cpp-20220623.1",
|
strip_prefix = "abseil-cpp-20230125.0",
|
||||||
sha256 = "91ac87d30cc6d79f9ab974c51874a704de9c2647c40f6932597329a282217ba8"
|
sha256 = "3ea49a7d97421b88a8c48a0de16c16048e17725c7ec0f1d3ea2683a2a75adc21"
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
@@ -56,6 +54,76 @@ load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependen
|
|||||||
|
|
||||||
rules_foreign_cc_dependencies()
|
rules_foreign_cc_dependencies()
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "com_google_protobuf",
|
||||||
|
sha256 = "87407cd28e7a9c95d9f61a098a53cf031109d451a7763e7dd1253abf8b4df422",
|
||||||
|
strip_prefix = "protobuf-3.19.1",
|
||||||
|
urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.1.tar.gz"],
|
||||||
|
patches = [
|
||||||
|
"@//third_party:com_google_protobuf_fixes.diff"
|
||||||
|
],
|
||||||
|
patch_args = [
|
||||||
|
"-p1",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Load Zlib before initializing TensorFlow and the iOS build rules to guarantee
|
||||||
|
# that the target @zlib//:mini_zlib is available
|
||||||
|
http_archive(
|
||||||
|
name = "zlib",
|
||||||
|
build_file = "@//third_party:zlib.BUILD",
|
||||||
|
sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1",
|
||||||
|
strip_prefix = "zlib-1.2.11",
|
||||||
|
urls = [
|
||||||
|
"http://mirror.bazel.build/zlib.net/fossils/zlib-1.2.11.tar.gz",
|
||||||
|
"http://zlib.net/fossils/zlib-1.2.11.tar.gz", # 2017-01-15
|
||||||
|
],
|
||||||
|
patches = [
|
||||||
|
"@//third_party:zlib.diff",
|
||||||
|
],
|
||||||
|
patch_args = [
|
||||||
|
"-p1",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# iOS basic build deps.
|
||||||
|
http_archive(
|
||||||
|
name = "build_bazel_rules_apple",
|
||||||
|
sha256 = "3e2c7ae0ddd181c4053b6491dad1d01ae29011bc322ca87eea45957c76d3a0c3",
|
||||||
|
url = "https://github.com/bazelbuild/rules_apple/releases/download/2.1.0/rules_apple.2.1.0.tar.gz",
|
||||||
|
patches = [
|
||||||
|
# Bypass checking ios unit test runner when building MP ios applications.
|
||||||
|
"@//third_party:build_bazel_rules_apple_bypass_test_runner_check.diff"
|
||||||
|
],
|
||||||
|
patch_args = [
|
||||||
|
"-p1",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@build_bazel_rules_apple//apple:repositories.bzl",
|
||||||
|
"apple_rules_dependencies",
|
||||||
|
)
|
||||||
|
apple_rules_dependencies()
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@build_bazel_rules_swift//swift:repositories.bzl",
|
||||||
|
"swift_rules_dependencies",
|
||||||
|
)
|
||||||
|
swift_rules_dependencies()
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@build_bazel_rules_swift//swift:extras.bzl",
|
||||||
|
"swift_rules_extra_dependencies",
|
||||||
|
)
|
||||||
|
swift_rules_extra_dependencies()
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@build_bazel_apple_support//lib:repositories.bzl",
|
||||||
|
"apple_support_dependencies",
|
||||||
|
)
|
||||||
|
apple_support_dependencies()
|
||||||
|
|
||||||
# This is used to select all contents of the archives for CMake-based packages to give CMake access to them.
|
# This is used to select all contents of the archives for CMake-based packages to give CMake access to them.
|
||||||
all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])"""
|
all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])"""
|
||||||
|
|
||||||
@@ -135,27 +203,18 @@ http_archive(
|
|||||||
urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.1.tar.gz"],
|
urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.1.tar.gz"],
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
load("@//third_party/flatbuffers:workspace.bzl", flatbuffers = "repo")
|
||||||
name = "com_google_protobuf",
|
|
||||||
sha256 = "87407cd28e7a9c95d9f61a098a53cf031109d451a7763e7dd1253abf8b4df422",
|
|
||||||
strip_prefix = "protobuf-3.19.1",
|
|
||||||
urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.19.1.tar.gz"],
|
|
||||||
patches = [
|
|
||||||
"@//third_party:com_google_protobuf_fixes.diff"
|
|
||||||
],
|
|
||||||
patch_args = [
|
|
||||||
"-p1",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
load("//third_party/flatbuffers:workspace.bzl", flatbuffers = "repo")
|
|
||||||
flatbuffers()
|
flatbuffers()
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "com_google_audio_tools",
|
name = "com_google_audio_tools",
|
||||||
strip_prefix = "multichannel-audio-tools-master",
|
strip_prefix = "multichannel-audio-tools-1f6b1319f13282eda6ff1317be13de67f4723860",
|
||||||
urls = ["https://github.com/google/multichannel-audio-tools/archive/master.zip"],
|
urls = ["https://github.com/google/multichannel-audio-tools/archive/1f6b1319f13282eda6ff1317be13de67f4723860.zip"],
|
||||||
|
sha256 = "fe346e1aee4f5069c4cbccb88706a9a2b2b4cf98aeb91ec1319be77e07dd7435",
|
||||||
repo_mapping = {"@com_github_glog_glog" : "@com_github_glog_glog_no_gflags"},
|
repo_mapping = {"@com_github_glog_glog" : "@com_github_glog_glog_no_gflags"},
|
||||||
|
# TODO: Fix this in AudioTools directly
|
||||||
|
patches = ["@//third_party:com_google_audio_tools_fixes.diff"],
|
||||||
|
patch_args = ["-p1"]
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
@@ -174,7 +233,7 @@ http_archive(
|
|||||||
"https://github.com/google/sentencepiece/archive/1.0.0.zip",
|
"https://github.com/google/sentencepiece/archive/1.0.0.zip",
|
||||||
],
|
],
|
||||||
patches = [
|
patches = [
|
||||||
"//third_party:com_google_sentencepiece_no_gflag_no_gtest.diff",
|
"@//third_party:com_google_sentencepiece_no_gflag_no_gtest.diff",
|
||||||
],
|
],
|
||||||
patch_args = ["-p1"],
|
patch_args = ["-p1"],
|
||||||
repo_mapping = {"@com_google_glog" : "@com_github_glog_glog_no_gflags"},
|
repo_mapping = {"@com_google_glog" : "@com_github_glog_glog_no_gflags"},
|
||||||
@@ -188,8 +247,8 @@ http_archive(
|
|||||||
"https://github.com/tensorflow/text/archive/v2.2.0.zip",
|
"https://github.com/tensorflow/text/archive/v2.2.0.zip",
|
||||||
],
|
],
|
||||||
patches = [
|
patches = [
|
||||||
"//third_party:tensorflow_text_remove_tf_deps.diff",
|
"@//third_party:tensorflow_text_remove_tf_deps.diff",
|
||||||
"//third_party:tensorflow_text_a0f49e63.diff",
|
"@//third_party:tensorflow_text_a0f49e63.diff",
|
||||||
],
|
],
|
||||||
patch_args = ["-p1"],
|
patch_args = ["-p1"],
|
||||||
repo_mapping = {"@com_google_re2": "@com_googlesource_code_re2"},
|
repo_mapping = {"@com_google_re2": "@com_googlesource_code_re2"},
|
||||||
@@ -271,7 +330,7 @@ new_local_repository(
|
|||||||
# For local MacOS builds, the path should point to an opencv@3 installation.
|
# For local MacOS builds, the path should point to an opencv@3 installation.
|
||||||
# If you edit the path here, you will also need to update the corresponding
|
# If you edit the path here, you will also need to update the corresponding
|
||||||
# prefix in "opencv_macos.BUILD".
|
# prefix in "opencv_macos.BUILD".
|
||||||
path = "/usr/local",
|
path = "/usr/local", # e.g. /usr/local/Cellar for HomeBrew
|
||||||
)
|
)
|
||||||
|
|
||||||
new_local_repository(
|
new_local_repository(
|
||||||
@@ -320,63 +379,6 @@ http_archive(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Load Zlib before initializing TensorFlow and the iOS build rules to guarantee
|
|
||||||
# that the target @zlib//:mini_zlib is available
|
|
||||||
http_archive(
|
|
||||||
name = "zlib",
|
|
||||||
build_file = "//third_party:zlib.BUILD",
|
|
||||||
sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1",
|
|
||||||
strip_prefix = "zlib-1.2.11",
|
|
||||||
urls = [
|
|
||||||
"http://mirror.bazel.build/zlib.net/fossils/zlib-1.2.11.tar.gz",
|
|
||||||
"http://zlib.net/fossils/zlib-1.2.11.tar.gz", # 2017-01-15
|
|
||||||
],
|
|
||||||
patches = [
|
|
||||||
"@//third_party:zlib.diff",
|
|
||||||
],
|
|
||||||
patch_args = [
|
|
||||||
"-p1",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
# iOS basic build deps.
|
|
||||||
http_archive(
|
|
||||||
name = "build_bazel_rules_apple",
|
|
||||||
sha256 = "f94e6dddf74739ef5cb30f000e13a2a613f6ebfa5e63588305a71fce8a8a9911",
|
|
||||||
url = "https://github.com/bazelbuild/rules_apple/releases/download/1.1.3/rules_apple.1.1.3.tar.gz",
|
|
||||||
patches = [
|
|
||||||
# Bypass checking ios unit test runner when building MP ios applications.
|
|
||||||
"@//third_party:build_bazel_rules_apple_bypass_test_runner_check.diff"
|
|
||||||
],
|
|
||||||
patch_args = [
|
|
||||||
"-p1",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@build_bazel_rules_apple//apple:repositories.bzl",
|
|
||||||
"apple_rules_dependencies",
|
|
||||||
)
|
|
||||||
apple_rules_dependencies()
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@build_bazel_rules_swift//swift:repositories.bzl",
|
|
||||||
"swift_rules_dependencies",
|
|
||||||
)
|
|
||||||
swift_rules_dependencies()
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@build_bazel_rules_swift//swift:extras.bzl",
|
|
||||||
"swift_rules_extra_dependencies",
|
|
||||||
)
|
|
||||||
swift_rules_extra_dependencies()
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@build_bazel_apple_support//lib:repositories.bzl",
|
|
||||||
"apple_support_dependencies",
|
|
||||||
)
|
|
||||||
apple_support_dependencies()
|
|
||||||
|
|
||||||
# More iOS deps.
|
# More iOS deps.
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
@@ -456,9 +458,9 @@ http_archive(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# TensorFlow repo should always go after the other external dependencies.
|
# TensorFlow repo should always go after the other external dependencies.
|
||||||
# TF on 2022-08-10.
|
# TF on 2023-03-08.
|
||||||
_TENSORFLOW_GIT_COMMIT = "af1d5bc4fbb66d9e6cc1cf89503014a99233583b"
|
_TENSORFLOW_GIT_COMMIT = "24f7ee636d62e1f8d8330357f8bbd65956dfb84d"
|
||||||
_TENSORFLOW_SHA256 = "f85a5443264fc58a12d136ca6a30774b5bc25ceaf7d114d97f252351b3c3a2cb"
|
_TENSORFLOW_SHA256 = "7f8a96dd99215c0cdc77230d3dbce43e60102b64a89203ad04aa09b0a187a4bd"
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "org_tensorflow",
|
name = "org_tensorflow",
|
||||||
urls = [
|
urls = [
|
||||||
@@ -500,8 +502,8 @@ cc_crosstool(name = "crosstool")
|
|||||||
# Node dependencies
|
# Node dependencies
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
sha256 = "5aae76dced38f784b58d9776e4ab12278bc156a9ed2b1d9fcd3e39921dc88fda",
|
sha256 = "94070eff79305be05b7699207fbac5d2608054dd53e6109f7d00d923919ff45a",
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.7.1/rules_nodejs-5.7.1.tar.gz"],
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.8.2/rules_nodejs-5.8.2.tar.gz"],
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_nodejs//:repositories.bzl", "build_bazel_rules_nodejs_dependencies")
|
load("@build_bazel_rules_nodejs//:repositories.bzl", "build_bazel_rules_nodejs_dependencies")
|
||||||
@@ -512,8 +514,8 @@ load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install
|
|||||||
node_repositories()
|
node_repositories()
|
||||||
yarn_install(
|
yarn_install(
|
||||||
name = "npm",
|
name = "npm",
|
||||||
package_json = "//:package.json",
|
package_json = "@//:package.json",
|
||||||
yarn_lock = "//:yarn.lock",
|
yarn_lock = "@//:yarn.lock",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Protobuf for Node dependencies
|
# Protobuf for Node dependencies
|
||||||
@@ -539,8 +541,48 @@ load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_
|
|||||||
rules_proto_dependencies()
|
rules_proto_dependencies()
|
||||||
rules_proto_toolchains()
|
rules_proto_toolchains()
|
||||||
|
|
||||||
load("//third_party:external_files.bzl", "external_files")
|
load("@//third_party:external_files.bzl", "external_files")
|
||||||
external_files()
|
external_files()
|
||||||
|
|
||||||
load("//third_party:wasm_files.bzl", "wasm_files")
|
load("@//third_party:wasm_files.bzl", "wasm_files")
|
||||||
wasm_files()
|
wasm_files()
|
||||||
|
|
||||||
|
# Halide
|
||||||
|
|
||||||
|
new_local_repository(
|
||||||
|
name = "halide",
|
||||||
|
build_file = "@//third_party/halide:BUILD.bazel",
|
||||||
|
path = "third_party/halide"
|
||||||
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "linux_halide",
|
||||||
|
sha256 = "d290fadf3f358c94aacf43c883de6468bb98883e26116920afd491ec0e440cd2",
|
||||||
|
strip_prefix = "Halide-15.0.1-x86-64-linux",
|
||||||
|
urls = ["https://github.com/halide/Halide/releases/download/v15.0.1/Halide-15.0.1-x86-64-linux-4c63f1befa1063184c5982b11b6a2cc17d4e5815.tar.gz"],
|
||||||
|
build_file = "@//third_party:halide.BUILD",
|
||||||
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "macos_x86_64_halide",
|
||||||
|
sha256 = "48ff073ac1aee5c4aca941a4f043cac64b38ba236cdca12567e09d803594a61c",
|
||||||
|
strip_prefix = "Halide-15.0.1-x86-64-osx",
|
||||||
|
urls = ["https://github.com/halide/Halide/releases/download/v15.0.1/Halide-15.0.1-x86-64-osx-4c63f1befa1063184c5982b11b6a2cc17d4e5815.tar.gz"],
|
||||||
|
build_file = "@//third_party:halide.BUILD",
|
||||||
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "macos_arm_64_halide",
|
||||||
|
sha256 = "db5d20d75fa7463490fcbc79c89f0abec9c23991f787c8e3e831fff411d5395c",
|
||||||
|
strip_prefix = "Halide-15.0.1-arm-64-osx",
|
||||||
|
urls = ["https://github.com/halide/Halide/releases/download/v15.0.1/Halide-15.0.1-arm-64-osx-4c63f1befa1063184c5982b11b6a2cc17d4e5815.tar.gz"],
|
||||||
|
build_file = "@//third_party:halide.BUILD",
|
||||||
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "windows_halide",
|
||||||
|
sha256 = "61fd049bd75ee918ac6c30d0693aac6048f63f8d1fc4db31001573e58eae8dae",
|
||||||
|
strip_prefix = "Halide-15.0.1-x86-64-windows",
|
||||||
|
urls = ["https://github.com/halide/Halide/releases/download/v15.0.1/Halide-15.0.1-x86-64-windows-4c63f1befa1063184c5982b11b6a2cc17d4e5815.zip"],
|
||||||
|
build_file = "@//third_party:halide.BUILD",
|
||||||
|
)
|
||||||
|
|||||||
+3
-5
@@ -4,12 +4,10 @@ py_binary(
|
|||||||
name = "build_py_api_docs",
|
name = "build_py_api_docs",
|
||||||
srcs = ["build_py_api_docs.py"],
|
srcs = ["build_py_api_docs.py"],
|
||||||
deps = [
|
deps = [
|
||||||
"//mediapipe",
|
|
||||||
"//third_party/py/absl:app",
|
"//third_party/py/absl:app",
|
||||||
"//third_party/py/absl/flags",
|
"//third_party/py/absl/flags",
|
||||||
"//third_party/py/tensorflow_docs",
|
"//third_party/py/mediapipe",
|
||||||
"//third_party/py/tensorflow_docs/api_generator:generate_lib",
|
"//third_party/py/tensorflow_docs/api_generator:generate_lib",
|
||||||
"//third_party/py/tensorflow_docs/api_generator:public_api",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,11 +16,11 @@ py_binary(
|
|||||||
srcs = ["build_java_api_docs.py"],
|
srcs = ["build_java_api_docs.py"],
|
||||||
data = [
|
data = [
|
||||||
"//third_party/android/sdk:api/26.txt",
|
"//third_party/android/sdk:api/26.txt",
|
||||||
"//third_party/java/doclava/current:doclava.jar",
|
"//third_party/java/doclava:doclet.jar",
|
||||||
"//third_party/java/jsilver:jsilver_jar",
|
"//third_party/java/jsilver:jsilver_jar",
|
||||||
],
|
],
|
||||||
env = {
|
env = {
|
||||||
"DOCLAVA_JAR": "$(location //third_party/java/doclava/current:doclava.jar)",
|
"DOCLAVA_JAR": "$(location //third_party/java/doclava:doclet.jar)",
|
||||||
"JSILVER_JAR": "$(location //third_party/java/jsilver:jsilver_jar)",
|
"JSILVER_JAR": "$(location //third_party/java/jsilver:jsilver_jar)",
|
||||||
},
|
},
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="refresh" content="0;url={{ page.target }}"/>
|
||||||
|
<link rel="canonical" href="{{ page.target }}"/>
|
||||||
|
<title>Redirecting</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>This page now lives on https://developers.google.com/mediapipe/. If you aren't automatically
|
||||||
|
redirected, follow this
|
||||||
|
<a href="{{ page.target }}">link</a>.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,704 @@
|
|||||||
|
---
|
||||||
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/framework_concepts/graphs_cpp
|
||||||
|
title: Building Graphs in C++
|
||||||
|
parent: Graphs
|
||||||
|
nav_order: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
# Building Graphs in C++
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
1. TOC
|
||||||
|
{:toc}
|
||||||
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
C++ graph builder is a powerful tool for:
|
||||||
|
|
||||||
|
* Building complex graphs
|
||||||
|
* Parametrizing graphs (e.g. setting a delegate on `InferenceCalculator`,
|
||||||
|
enabling/disabling parts of the graph)
|
||||||
|
* Deduplicating graphs (e.g. instead of CPU and GPU dedicated graphs in pbtxt
|
||||||
|
you can have a single code that constructs required graphs, sharing as much
|
||||||
|
as possible)
|
||||||
|
* Supporting optional graph inputs/outputs
|
||||||
|
* Customizing graphs per platform
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
Let's see how C++ graph builder can be used for a simple graph:
|
||||||
|
|
||||||
|
```proto
|
||||||
|
# Graph inputs.
|
||||||
|
input_stream: "input_tensors"
|
||||||
|
input_side_packet: "model"
|
||||||
|
|
||||||
|
# Graph outputs.
|
||||||
|
output_stream: "output_tensors"
|
||||||
|
|
||||||
|
node {
|
||||||
|
calculator: "InferenceCalculator"
|
||||||
|
input_stream: "TENSORS:input_tensors"
|
||||||
|
input_side_packet: "MODEL:model"
|
||||||
|
output_stream: "TENSORS:output_tensors"
|
||||||
|
node_options: {
|
||||||
|
[type.googleapis.com/mediapipe.InferenceCalculatorOptions] {
|
||||||
|
# Requesting GPU delegate.
|
||||||
|
delegate { gpu {} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Function to build the above `CalculatorGraphConfig` may look like:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Graph inputs.
|
||||||
|
Stream<std::vector<Tensor>> input_tensors =
|
||||||
|
graph.In(0).SetName("input_tensors").Cast<std::vector<Tensor>>();
|
||||||
|
SidePacket<TfLiteModelPtr> model =
|
||||||
|
graph.SideIn(0).SetName("model").Cast<TfLiteModelPtr>();
|
||||||
|
|
||||||
|
auto& inference_node = graph.AddNode("InferenceCalculator");
|
||||||
|
auto& inference_opts =
|
||||||
|
inference_node.GetOptions<InferenceCalculatorOptions>();
|
||||||
|
// Requesting GPU delegate.
|
||||||
|
inference_opts.mutable_delegate()->mutable_gpu();
|
||||||
|
input_tensors.ConnectTo(inference_node.In("TENSORS"));
|
||||||
|
model.ConnectTo(inference_node.SideIn("MODEL"));
|
||||||
|
Stream<std::vector<Tensor>> output_tensors =
|
||||||
|
inference_node.Out("TENSORS").Cast<std::vector<Tensor>>();
|
||||||
|
|
||||||
|
// Graph outputs.
|
||||||
|
output_tensors.SetName("output_tensors").ConnectTo(graph.Out(0));
|
||||||
|
|
||||||
|
// Get `CalculatorGraphConfig` to pass it into `CalculatorGraph`
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Short summary:
|
||||||
|
|
||||||
|
* Use `Graph::In/SideIn` to get graph inputs as `Stream/SidePacket`
|
||||||
|
* Use `Node::Out/SideOut` to get node outputs as `Stream/SidePacket`
|
||||||
|
* Use `Stream/SidePacket::ConnectTo` to connect streams and side packets to
|
||||||
|
node inputs (`Node::In/SideIn`) and graph outputs (`Graph::Out/SideOut`)
|
||||||
|
* There's a "shortcut" operator `>>` that you can use instead of
|
||||||
|
`ConnectTo` function (E.g. `x >> node.In("IN")`).
|
||||||
|
* `Stream/SidePacket::Cast` is used to cast stream or side packet of `AnyType`
|
||||||
|
(E.g. `Stream<AnyType> in = graph.In(0);`) to a particular type
|
||||||
|
* Using actual types instead of `AnyType` sets you on a better path for
|
||||||
|
unleashing graph builder capabilities and improving your graphs
|
||||||
|
readability.
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### Utility Functions
|
||||||
|
|
||||||
|
Let's extract inference construction code into a dedicated utility function to
|
||||||
|
help for readability and code reuse:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Updates graph to run inference.
|
||||||
|
Stream<std::vector<Tensor>> RunInference(
|
||||||
|
Stream<std::vector<Tensor>> tensors, SidePacket<TfLiteModelPtr> model,
|
||||||
|
const InferenceCalculatorOptions::Delegate& delegate, Graph& graph) {
|
||||||
|
auto& inference_node = graph.AddNode("InferenceCalculator");
|
||||||
|
auto& inference_opts =
|
||||||
|
inference_node.GetOptions<InferenceCalculatorOptions>();
|
||||||
|
*inference_opts.mutable_delegate() = delegate;
|
||||||
|
tensors.ConnectTo(inference_node.In("TENSORS"));
|
||||||
|
model.ConnectTo(inference_node.SideIn("MODEL"));
|
||||||
|
return inference_node.Out("TENSORS").Cast<std::vector<Tensor>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Graph inputs.
|
||||||
|
Stream<std::vector<Tensor>> input_tensors =
|
||||||
|
graph.In(0).SetName("input_tensors").Cast<std::vector<Tensor>>();
|
||||||
|
SidePacket<TfLiteModelPtr> model =
|
||||||
|
graph.SideIn(0).SetName("model").Cast<TfLiteModelPtr>();
|
||||||
|
|
||||||
|
InferenceCalculatorOptions::Delegate delegate;
|
||||||
|
delegate.mutable_gpu();
|
||||||
|
Stream<std::vector<Tensor>> output_tensors =
|
||||||
|
RunInference(input_tensors, model, delegate, graph);
|
||||||
|
|
||||||
|
// Graph outputs.
|
||||||
|
output_tensors.SetName("output_tensors").ConnectTo(graph.Out(0));
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As a result, `RunInference` provides a clear interface stating what are the
|
||||||
|
inputs/outputs and their types.
|
||||||
|
|
||||||
|
It can be easily reused, e.g. it's only a few lines if you want to run an extra
|
||||||
|
model inference:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Run first inference.
|
||||||
|
Stream<std::vector<Tensor>> output_tensors =
|
||||||
|
RunInference(input_tensors, model, delegate, graph);
|
||||||
|
// Run second inference on the output of the first one.
|
||||||
|
Stream<std::vector<Tensor>> extra_output_tensors =
|
||||||
|
RunInference(output_tensors, extra_model, delegate, graph);
|
||||||
|
```
|
||||||
|
|
||||||
|
And you don't need to duplicate names and tags (`InferenceCalculator`,
|
||||||
|
`TENSORS`, `MODEL`) or introduce dedicated constants here and there - those
|
||||||
|
details are localized to `RunInference` function.
|
||||||
|
|
||||||
|
Tip: extracting `RunInference` and similar functions to dedicated modules (e.g.
|
||||||
|
inference.h/cc which depends on the inference calculator) enables reuse in
|
||||||
|
graphs construction code and helps automatically pull in calculator dependencies
|
||||||
|
(e.g. no need to manually add `:inference_calculator` dep, just let your IDE
|
||||||
|
include `inference.h` and build cleaner pull in corresponding dependency).
|
||||||
|
|
||||||
|
### Utility Classes
|
||||||
|
|
||||||
|
And surely, it's not only about functions, in some cases it's beneficial to
|
||||||
|
introduce utility classes which can help making your graph construction code
|
||||||
|
more readable and less error prone.
|
||||||
|
|
||||||
|
MediaPipe offers `PassThroughCalculator` calculator, which is simply passing
|
||||||
|
through its inputs:
|
||||||
|
|
||||||
|
```
|
||||||
|
input_stream: "float_value"
|
||||||
|
input_stream: "int_value"
|
||||||
|
input_stream: "bool_value"
|
||||||
|
|
||||||
|
output_stream: "passed_float_value"
|
||||||
|
output_stream: "passed_int_value"
|
||||||
|
output_stream: "passed_bool_value"
|
||||||
|
|
||||||
|
node {
|
||||||
|
calculator: "PassThroughCalculator"
|
||||||
|
input_stream: "float_value"
|
||||||
|
input_stream: "int_value"
|
||||||
|
input_stream: "bool_value"
|
||||||
|
# The order must be the same as for inputs (or you can use explicit indexes)
|
||||||
|
output_stream: "passed_float_value"
|
||||||
|
output_stream: "passed_int_value"
|
||||||
|
output_stream: "passed_bool_value"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's see the straightforward C++ construction code to create the above graph:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Graph inputs.
|
||||||
|
Stream<float> float_value = graph.In(0).SetName("float_value").Cast<float>();
|
||||||
|
Stream<int> int_value = graph.In(1).SetName("int_value").Cast<int>();
|
||||||
|
Stream<bool> bool_value = graph.In(2).SetName("bool_value").Cast<bool>();
|
||||||
|
|
||||||
|
auto& pass_node = graph.AddNode("PassThroughCalculator");
|
||||||
|
float_value.ConnectTo(pass_node.In("")[0]);
|
||||||
|
int_value.ConnectTo(pass_node.In("")[1]);
|
||||||
|
bool_value.ConnectTo(pass_node.In("")[2]);
|
||||||
|
Stream<float> passed_float_value = pass_node.Out("")[0].Cast<float>();
|
||||||
|
Stream<int> passed_int_value = pass_node.Out("")[1].Cast<int>();
|
||||||
|
Stream<bool> passed_bool_value = pass_node.Out("")[2].Cast<bool>();
|
||||||
|
|
||||||
|
// Graph outputs.
|
||||||
|
passed_float_value.SetName("passed_float_value").ConnectTo(graph.Out(0));
|
||||||
|
passed_int_value.SetName("passed_int_value").ConnectTo(graph.Out(1));
|
||||||
|
passed_bool_value.SetName("passed_bool_value").ConnectTo(graph.Out(2));
|
||||||
|
|
||||||
|
// Get `CalculatorGraphConfig` to pass it into `CalculatorGraph`
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
While `pbtxt` representation maybe error prone (when we have many inputs to pass
|
||||||
|
through), C++ code looks even worse: repeated empty tags and `Cast` calls. Let's
|
||||||
|
see how we can do better by introducing a `PassThroughNodeBuilder`:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
class PassThroughNodeBuilder {
|
||||||
|
public:
|
||||||
|
explicit PassThroughNodeBuilder(Graph& graph)
|
||||||
|
: node_(graph.AddNode("PassThroughCalculator")) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Stream<T> PassThrough(Stream<T> stream) {
|
||||||
|
stream.ConnectTo(node_.In(index_));
|
||||||
|
return node_.Out(index_++).Cast<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int index_ = 0;
|
||||||
|
GenericNode& node_;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
And now graph construction code can look like:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Graph inputs.
|
||||||
|
Stream<float> float_value = graph.In(0).SetName("float_value").Cast<float>();
|
||||||
|
Stream<int> int_value = graph.In(1).SetName("int_value").Cast<int>();
|
||||||
|
Stream<bool> bool_value = graph.In(2).SetName("bool_value").Cast<bool>();
|
||||||
|
|
||||||
|
PassThroughNodeBuilder pass_node_builder(graph);
|
||||||
|
Stream<float> passed_float_value = pass_node_builder.PassThrough(float_value);
|
||||||
|
Stream<int> passed_int_value = pass_node_builder.PassThrough(int_value);
|
||||||
|
Stream<bool> passed_bool_value = pass_node_builder.PassThrough(bool_value);
|
||||||
|
|
||||||
|
// Graph outputs.
|
||||||
|
passed_float_value.SetName("passed_float_value").ConnectTo(graph.Out(0));
|
||||||
|
passed_int_value.SetName("passed_int_value").ConnectTo(graph.Out(1));
|
||||||
|
passed_bool_value.SetName("passed_bool_value").ConnectTo(graph.Out(2));
|
||||||
|
|
||||||
|
// Get `CalculatorGraphConfig` to pass it into `CalculatorGraph`
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can't have incorrect order or index in your pass through construction
|
||||||
|
code and save some typing by guessing the type for `Cast` from the `PassThrough`
|
||||||
|
input.
|
||||||
|
|
||||||
|
Tip: the same as for the `RunInference` function, extracting
|
||||||
|
`PassThroughNodeBuilder` and similar utility classes into dedicated modules
|
||||||
|
enables reuse in graph construction code and helps to automatically pull in the
|
||||||
|
corresponding calculator dependencies.
|
||||||
|
|
||||||
|
## Dos and Don'ts
|
||||||
|
|
||||||
|
### Define graph inputs at the very beginning if possible
|
||||||
|
|
||||||
|
```c++ {.bad}
|
||||||
|
Stream<D> RunSomething(Stream<A> a, Stream<B> b, Graph& graph) {
|
||||||
|
Stream<C> c = graph.In(2).SetName("c").Cast<C>(); // Bad.
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
Stream<A> a = graph.In(0).SetName("a").Cast<A>();
|
||||||
|
// 10/100/N lines of code.
|
||||||
|
Stream<B> b = graph.In(1).SetName("b").Cast<B>() // Bad.
|
||||||
|
Stream<D> d = RunSomething(a, b, graph);
|
||||||
|
// ...
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above code:
|
||||||
|
|
||||||
|
* It can be hard to guess how many inputs you have in the graph.
|
||||||
|
* Can be error prone overall and hard to maintain in future (e.g. is it a
|
||||||
|
correct index? name? what if some inputs are removed or made optional?
|
||||||
|
etc.).
|
||||||
|
* `RunSomething` reuse is limited because other graphs may have different
|
||||||
|
inputs
|
||||||
|
|
||||||
|
Instead, define your graph inputs at the very beginning of your graph builder:
|
||||||
|
|
||||||
|
```c++ {.good}
|
||||||
|
Stream<D> RunSomething(Stream<A> a, Stream<B> b, Stream<C> c, Graph& graph) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Inputs.
|
||||||
|
Stream<A> a = graph.In(0).SetName("a").Cast<A>();
|
||||||
|
Stream<B> b = graph.In(1).SetName("b").Cast<B>();
|
||||||
|
Stream<C> c = graph.In(2).SetName("c").Cast<C>();
|
||||||
|
|
||||||
|
// 10/100/N lines of code.
|
||||||
|
Stream<D> d = RunSomething(a, b, c, graph);
|
||||||
|
// ...
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `std::optional` if you have an input stream or side packet that is not
|
||||||
|
always defined and put it at the very beginning:
|
||||||
|
|
||||||
|
```c++ {.good}
|
||||||
|
std::optional<Stream<A>> a;
|
||||||
|
if (needs_a) {
|
||||||
|
a = graph.In(0).SetName(a).Cast<A>();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: of course, there can be exceptions - for example, there can be a use case
|
||||||
|
where calling `RunSomething1(..., graph)`, ..., `RunSomethingN(..., graph)` is
|
||||||
|
**intended to add new inputs**, so afterwards you can iterate over them and feed
|
||||||
|
only added inputs into the graph. However, in any case, try to make it easy for
|
||||||
|
readers to find out what graph inputs it has or may have.
|
||||||
|
|
||||||
|
### Define graph outputs at the very end
|
||||||
|
|
||||||
|
```c++ {.bad}
|
||||||
|
void RunSomething(Stream<Input> input, Graph& graph) {
|
||||||
|
// ...
|
||||||
|
node.Out("OUTPUT_F")
|
||||||
|
.SetName("output_f").ConnectTo(graph.Out(2)); // Bad.
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// 10/100/N lines of code.
|
||||||
|
node.Out("OUTPUT_D")
|
||||||
|
.SetName("output_d").ConnectTo(graph.Out(0)); // Bad.
|
||||||
|
// 10/100/N lines of code.
|
||||||
|
node.Out("OUTPUT_E")
|
||||||
|
.SetName("output_e").ConnectTo(graph.Out(1)); // Bad.
|
||||||
|
// 10/100/N lines of code.
|
||||||
|
RunSomething(input, graph);
|
||||||
|
// ...
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above code:
|
||||||
|
|
||||||
|
* It can be hard to guess how many outputs you have in the graph.
|
||||||
|
* Can be error prone overall and hard to maintain in future (e.g. is it a
|
||||||
|
correct index? name? what if some outpus are removed or made optional?
|
||||||
|
etc.).
|
||||||
|
* `RunSomething` reuse is limited as other graphs may have different outputs
|
||||||
|
|
||||||
|
Instead, define your graph outputs at the very end of your graph builder:
|
||||||
|
|
||||||
|
```c++ {.good}
|
||||||
|
Stream<F> RunSomething(Stream<Input> input, Graph& graph) {
|
||||||
|
// ...
|
||||||
|
return node.Out("OUTPUT_F").Cast<F>();
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// 10/100/N lines of code.
|
||||||
|
Stream<D> d = node.Out("OUTPUT_D").Cast<D>();
|
||||||
|
// 10/100/N lines of code.
|
||||||
|
Stream<E> e = node.Out("OUTPUT_E").Cast<E>();
|
||||||
|
// 10/100/N lines of code.
|
||||||
|
Stream<F> f = RunSomething(input, graph);
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// Outputs.
|
||||||
|
d.SetName("output_d").ConnectTo(graph.Out(0));
|
||||||
|
e.SetName("output_e").ConnectTo(graph.Out(1));
|
||||||
|
f.SetName("output_f").ConnectTo(graph.Out(2));
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keep nodes decoupled from each other
|
||||||
|
|
||||||
|
In MediaPipe, packet streams and side packets are as meaningful as processing
|
||||||
|
nodes. And any node input requirements and output products are expressed clearly
|
||||||
|
and independently in terms of the streams and side packets it consumes and
|
||||||
|
produces.
|
||||||
|
|
||||||
|
```c++ {.bad}
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Inputs.
|
||||||
|
Stream<A> a = graph.In(0).Cast<A>();
|
||||||
|
|
||||||
|
auto& node1 = graph.AddNode("Calculator1");
|
||||||
|
a.ConnectTo(node1.In("INPUT"));
|
||||||
|
|
||||||
|
auto& node2 = graph.AddNode("Calculator2");
|
||||||
|
node1.Out("OUTPUT").ConnectTo(node2.In("INPUT")); // Bad.
|
||||||
|
|
||||||
|
auto& node3 = graph.AddNode("Calculator3");
|
||||||
|
node1.Out("OUTPUT").ConnectTo(node3.In("INPUT_B")); // Bad.
|
||||||
|
node2.Out("OUTPUT").ConnectTo(node3.In("INPUT_C")); // Bad.
|
||||||
|
|
||||||
|
auto& node4 = graph.AddNode("Calculator4");
|
||||||
|
node1.Out("OUTPUT").ConnectTo(node4.In("INPUT_B")); // Bad.
|
||||||
|
node2.Out("OUTPUT").ConnectTo(node4.In("INPUT_C")); // Bad.
|
||||||
|
node3.Out("OUTPUT").ConnectTo(node4.In("INPUT_D")); // Bad.
|
||||||
|
|
||||||
|
// Outputs.
|
||||||
|
node1.Out("OUTPUT").SetName("b").ConnectTo(graph.Out(0)); // Bad.
|
||||||
|
node2.Out("OUTPUT").SetName("c").ConnectTo(graph.Out(1)); // Bad.
|
||||||
|
node3.Out("OUTPUT").SetName("d").ConnectTo(graph.Out(2)); // Bad.
|
||||||
|
node4.Out("OUTPUT").SetName("e").ConnectTo(graph.Out(3)); // Bad.
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above code:
|
||||||
|
|
||||||
|
* Nodes are coupled to each other, e.g. `node4` knows where its inputs are
|
||||||
|
coming from (`node1`, `node2`, `node3`) and it complicates refactoring,
|
||||||
|
maintenance and code reuse
|
||||||
|
* Such usage pattern is a downgrade from proto representation, where nodes
|
||||||
|
are decoupled by default.
|
||||||
|
* `node#.Out("OUTPUT")` calls are duplicated and readability suffers as you
|
||||||
|
could use cleaner names instead and also provide an actual type.
|
||||||
|
|
||||||
|
So, to fix the above issues you can write the following graph construction code:
|
||||||
|
|
||||||
|
```c++ {.good}
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Inputs.
|
||||||
|
Stream<A> a = graph.In(0).Cast<A>();
|
||||||
|
|
||||||
|
// `node1` usage is limited to 3 lines below.
|
||||||
|
auto& node1 = graph.AddNode("Calculator1");
|
||||||
|
a.ConnectTo(node1.In("INPUT"));
|
||||||
|
Stream<B> b = node1.Out("OUTPUT").Cast<B>();
|
||||||
|
|
||||||
|
// `node2` usage is limited to 3 lines below.
|
||||||
|
auto& node2 = graph.AddNode("Calculator2");
|
||||||
|
b.ConnectTo(node2.In("INPUT"));
|
||||||
|
Stream<C> c = node2.Out("OUTPUT").Cast<C>();
|
||||||
|
|
||||||
|
// `node3` usage is limited to 4 lines below.
|
||||||
|
auto& node3 = graph.AddNode("Calculator3");
|
||||||
|
b.ConnectTo(node3.In("INPUT_B"));
|
||||||
|
c.ConnectTo(node3.In("INPUT_C"));
|
||||||
|
Stream<D> d = node3.Out("OUTPUT").Cast<D>();
|
||||||
|
|
||||||
|
// `node4` usage is limited to 5 lines below.
|
||||||
|
auto& node4 = graph.AddNode("Calculator4");
|
||||||
|
b.ConnectTo(node4.In("INPUT_B"));
|
||||||
|
c.ConnectTo(node4.In("INPUT_C"));
|
||||||
|
d.ConnectTo(node4.In("INPUT_D"));
|
||||||
|
Stream<E> e = node4.Out("OUTPUT").Cast<E>();
|
||||||
|
|
||||||
|
// Outputs.
|
||||||
|
b.SetName("b").ConnectTo(graph.Out(0));
|
||||||
|
c.SetName("c").ConnectTo(graph.Out(1));
|
||||||
|
d.SetName("d").ConnectTo(graph.Out(2));
|
||||||
|
e.SetName("e").ConnectTo(graph.Out(3));
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, if needed, you can easily remove `node1` and make `b` a graph input and no
|
||||||
|
updates are needed to `node2`, `node3`, `node4` (same as in proto representation
|
||||||
|
by the way), because they are decoupled from each other.
|
||||||
|
|
||||||
|
Overall, the above code replicates the proto graph more closely:
|
||||||
|
|
||||||
|
```proto
|
||||||
|
input_stream: "a"
|
||||||
|
|
||||||
|
node {
|
||||||
|
calculator: "Calculator1"
|
||||||
|
input_stream: "INPUT:a"
|
||||||
|
output_stream: "OUTPUT:b"
|
||||||
|
}
|
||||||
|
|
||||||
|
node {
|
||||||
|
calculator: "Calculator2"
|
||||||
|
input_stream: "INPUT:b"
|
||||||
|
output_stream: "OUTPUT:C"
|
||||||
|
}
|
||||||
|
|
||||||
|
node {
|
||||||
|
calculator: "Calculator3"
|
||||||
|
input_stream: "INPUT_B:b"
|
||||||
|
input_stream: "INPUT_C:c"
|
||||||
|
output_stream: "OUTPUT:d"
|
||||||
|
}
|
||||||
|
|
||||||
|
node {
|
||||||
|
calculator: "Calculator4"
|
||||||
|
input_stream: "INPUT_B:b"
|
||||||
|
input_stream: "INPUT_C:c"
|
||||||
|
input_stream: "INPUT_D:d"
|
||||||
|
output_stream: "OUTPUT:e"
|
||||||
|
}
|
||||||
|
|
||||||
|
output_stream: "b"
|
||||||
|
output_stream: "c"
|
||||||
|
output_stream: "d"
|
||||||
|
output_stream: "e"
|
||||||
|
```
|
||||||
|
|
||||||
|
On top of that, now you can extract utility functions for further reuse in other graphs:
|
||||||
|
|
||||||
|
```c++ {.good}
|
||||||
|
Stream<B> RunCalculator1(Stream<A> a, Graph& graph) {
|
||||||
|
auto& node = graph.AddNode("Calculator1");
|
||||||
|
a.ConnectTo(node.In("INPUT"));
|
||||||
|
return node.Out("OUTPUT").Cast<B>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<C> RunCalculator2(Stream<B> b, Graph& graph) {
|
||||||
|
auto& node = graph.AddNode("Calculator2");
|
||||||
|
b.ConnectTo(node.In("INPUT"));
|
||||||
|
return node.Out("OUTPUT").Cast<C>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<D> RunCalculator3(Stream<B> b, Stream<C> c, Graph& graph) {
|
||||||
|
auto& node = graph.AddNode("Calculator3");
|
||||||
|
b.ConnectTo(node.In("INPUT_B"));
|
||||||
|
c.ConnectTo(node.In("INPUT_C"));
|
||||||
|
return node.Out("OUTPUT").Cast<D>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<E> RunCalculator4(Stream<B> b, Stream<C> c, Stream<D> d, Graph& graph) {
|
||||||
|
auto& node = graph.AddNode("Calculator4");
|
||||||
|
b.ConnectTo(node.In("INPUT_B"));
|
||||||
|
c.ConnectTo(node.In("INPUT_C"));
|
||||||
|
d.ConnectTo(node.In("INPUT_D"));
|
||||||
|
return node.Out("OUTPUT").Cast<E>();
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Inputs.
|
||||||
|
Stream<A> a = graph.In(0).Cast<A>();
|
||||||
|
|
||||||
|
Stream<B> b = RunCalculator1(a, graph);
|
||||||
|
Stream<C> c = RunCalculator2(b, graph);
|
||||||
|
Stream<D> d = RunCalculator3(b, c, graph);
|
||||||
|
Stream<E> e = RunCalculator4(b, c, d, graph);
|
||||||
|
|
||||||
|
// Outputs.
|
||||||
|
b.SetName("b").ConnectTo(graph.Out(0));
|
||||||
|
c.SetName("c").ConnectTo(graph.Out(1));
|
||||||
|
d.SetName("d").ConnectTo(graph.Out(2));
|
||||||
|
e.SetName("e").ConnectTo(graph.Out(3));
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Separate nodes for better readability
|
||||||
|
|
||||||
|
```c++ {.bad}
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Inputs.
|
||||||
|
Stream<A> a = graph.In(0).Cast<A>();
|
||||||
|
auto& node1 = graph.AddNode("Calculator1");
|
||||||
|
a.ConnectTo(node1.In("INPUT"));
|
||||||
|
Stream<B> b = node1.Out("OUTPUT").Cast<B>();
|
||||||
|
auto& node2 = graph.AddNode("Calculator2");
|
||||||
|
b.ConnectTo(node2.In("INPUT"));
|
||||||
|
Stream<C> c = node2.Out("OUTPUT").Cast<C>();
|
||||||
|
auto& node3 = graph.AddNode("Calculator3");
|
||||||
|
b.ConnectTo(node3.In("INPUT_B"));
|
||||||
|
c.ConnectTo(node3.In("INPUT_C"));
|
||||||
|
Stream<D> d = node3.Out("OUTPUT").Cast<D>();
|
||||||
|
auto& node4 = graph.AddNode("Calculator4");
|
||||||
|
b.ConnectTo(node4.In("INPUT_B"));
|
||||||
|
c.ConnectTo(node4.In("INPUT_C"));
|
||||||
|
d.ConnectTo(node4.In("INPUT_D"));
|
||||||
|
Stream<E> e = node4.Out("OUTPUT").Cast<E>();
|
||||||
|
// Outputs.
|
||||||
|
b.SetName("b").ConnectTo(graph.Out(0));
|
||||||
|
c.SetName("c").ConnectTo(graph.Out(1));
|
||||||
|
d.SetName("d").ConnectTo(graph.Out(2));
|
||||||
|
e.SetName("e").ConnectTo(graph.Out(3));
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above code, it can be hard to grasp the idea where each node begins and
|
||||||
|
ends. To improve this and help your code readers, you can simply have blank
|
||||||
|
lines before and after each node:
|
||||||
|
|
||||||
|
```c++ {.good}
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Inputs.
|
||||||
|
Stream<A> a = graph.In(0).Cast<A>();
|
||||||
|
|
||||||
|
auto& node1 = graph.AddNode("Calculator1");
|
||||||
|
a.ConnectTo(node1.In("INPUT"));
|
||||||
|
Stream<B> b = node1.Out("OUTPUT").Cast<B>();
|
||||||
|
|
||||||
|
auto& node2 = graph.AddNode("Calculator2");
|
||||||
|
b.ConnectTo(node2.In("INPUT"));
|
||||||
|
Stream<C> c = node2.Out("OUTPUT").Cast<C>();
|
||||||
|
|
||||||
|
auto& node3 = graph.AddNode("Calculator3");
|
||||||
|
b.ConnectTo(node3.In("INPUT_B"));
|
||||||
|
c.ConnectTo(node3.In("INPUT_C"));
|
||||||
|
Stream<D> d = node3.Out("OUTPUT").Cast<D>();
|
||||||
|
|
||||||
|
auto& node4 = graph.AddNode("Calculator4");
|
||||||
|
b.ConnectTo(node4.In("INPUT_B"));
|
||||||
|
c.ConnectTo(node4.In("INPUT_C"));
|
||||||
|
d.ConnectTo(node4.In("INPUT_D"));
|
||||||
|
Stream<E> e = node4.Out("OUTPUT").Cast<E>();
|
||||||
|
|
||||||
|
// Outputs.
|
||||||
|
b.SetName("b").ConnectTo(graph.Out(0));
|
||||||
|
c.SetName("c").ConnectTo(graph.Out(1));
|
||||||
|
d.SetName("d").ConnectTo(graph.Out(2));
|
||||||
|
e.SetName("e").ConnectTo(graph.Out(3));
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, the above representation matches `CalculatorGraphConfig` proto
|
||||||
|
representation better.
|
||||||
|
|
||||||
|
If you extract nodes into utility functions, they are scoped within functions
|
||||||
|
already and it's clear where they begin and end, so it's completely fine to
|
||||||
|
have:
|
||||||
|
|
||||||
|
```c++ {.good}
|
||||||
|
CalculatorGraphConfig BuildGraph() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Inputs.
|
||||||
|
Stream<A> a = graph.In(0).Cast<A>();
|
||||||
|
|
||||||
|
Stream<B> b = RunCalculator1(a, graph);
|
||||||
|
Stream<C> c = RunCalculator2(b, graph);
|
||||||
|
Stream<D> d = RunCalculator3(b, c, graph);
|
||||||
|
Stream<E> e = RunCalculator4(b, c, d, graph);
|
||||||
|
|
||||||
|
// Outputs.
|
||||||
|
b.SetName("b").ConnectTo(graph.Out(0));
|
||||||
|
c.SetName("c").ConnectTo(graph.Out(1));
|
||||||
|
d.SetName("d").ConnectTo(graph.Out(2));
|
||||||
|
e.SetName("e").ConnectTo(graph.Out(3));
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/framework_concepts/calculators
|
||||||
title: Calculators
|
title: Calculators
|
||||||
parent: Framework Concepts
|
parent: Framework Concepts
|
||||||
nav_order: 1
|
nav_order: 1
|
||||||
@@ -12,6 +13,12 @@ nav_order: 1
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
Each calculator is a node of a graph. We describe how to create a new
|
Each calculator is a node of a graph. We describe how to create a new
|
||||||
calculator, how to initialize a calculator, how to perform its calculations,
|
calculator, how to initialize a calculator, how to perform its calculations,
|
||||||
input and output streams, timestamps, and options. Each node in the graph is
|
input and output streams, timestamps, and options. Each node in the graph is
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/framework_concepts/overview
|
||||||
title: Framework Concepts
|
title: Framework Concepts
|
||||||
nav_order: 5
|
nav_order: 5
|
||||||
has_children: true
|
has_children: true
|
||||||
@@ -13,6 +14,12 @@ has_toc: false
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## The basics
|
## The basics
|
||||||
|
|
||||||
### Packet
|
### Packet
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/framework_concepts/gpu
|
||||||
title: GPU
|
title: GPU
|
||||||
parent: Framework Concepts
|
parent: Framework Concepts
|
||||||
nav_order: 5
|
nav_order: 5
|
||||||
@@ -12,6 +13,12 @@ nav_order: 5
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
MediaPipe supports calculator nodes for GPU compute and rendering, and allows combining multiple GPU nodes, as well as mixing them with CPU based calculator nodes. There exist several GPU APIs on mobile platforms (eg, OpenGL ES, Metal and Vulkan). MediaPipe does not attempt to offer a single cross-API GPU abstraction. Individual nodes can be written using different APIs, allowing them to take advantage of platform specific features when needed.
|
MediaPipe supports calculator nodes for GPU compute and rendering, and allows combining multiple GPU nodes, as well as mixing them with CPU based calculator nodes. There exist several GPU APIs on mobile platforms (eg, OpenGL ES, Metal and Vulkan). MediaPipe does not attempt to offer a single cross-API GPU abstraction. Individual nodes can be written using different APIs, allowing them to take advantage of platform specific features when needed.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/framework_concepts/graphs
|
||||||
title: Graphs
|
title: Graphs
|
||||||
parent: Framework Concepts
|
parent: Framework Concepts
|
||||||
nav_order: 2
|
nav_order: 2
|
||||||
@@ -12,31 +13,37 @@ nav_order: 2
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
## GraphConfig
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
A `GraphConfig` is a specification that describes the topology and functionality
|
----
|
||||||
of a MediaPipe graph. In the specification, a node in the graph represents an
|
|
||||||
instance of a particular calculator. All the necessary configurations of the
|
## Graph
|
||||||
node, such its type, inputs and outputs must be described in the specification.
|
|
||||||
Description of the node can also include several optional fields, such as
|
A `CalculatorGraphConfig` proto specifies the topology and functionality of a
|
||||||
|
MediaPipe graph. Each `node` in the graph represents a particular calculator or
|
||||||
|
subgraph, and specifies necessary configurations, such as registered
|
||||||
|
calculator/subgraph type, inputs, outputs and optional fields, such as
|
||||||
node-specific options, input policy and executor, discussed in
|
node-specific options, input policy and executor, discussed in
|
||||||
[Synchronization](synchronization.md).
|
[Synchronization](synchronization.md).
|
||||||
|
|
||||||
`GraphConfig` has several other fields to configure the global graph-level
|
`CalculatorGraphConfig` has several other fields to configure global graph-level
|
||||||
settings, eg, graph executor configs, number of threads, and maximum queue size
|
settings, e.g. graph executor configs, number of threads, and maximum queue size
|
||||||
of input streams. Several graph-level settings are useful for tuning the
|
of input streams. Several graph-level settings are useful for tuning the
|
||||||
performance of the graph on different platforms (eg, desktop v.s. mobile). For
|
performance of the graph on different platforms (e.g., desktop v.s. mobile). For
|
||||||
instance, on mobile, attaching a heavy model-inference calculator to a separate
|
instance, on mobile, attaching a heavy model-inference calculator to a separate
|
||||||
executor can improve the performance of a real-time application since this
|
executor can improve the performance of a real-time application since this
|
||||||
enables thread locality.
|
enables thread locality.
|
||||||
|
|
||||||
Below is a trivial `GraphConfig` example where we have series of passthrough
|
Below is a trivial `CalculatorGraphConfig` example where we have series of
|
||||||
calculators :
|
passthrough calculators :
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
# This graph named main_pass_throughcals_nosubgraph.pbtxt contains 4
|
# This graph named main_pass_throughcals_nosubgraph.pbtxt contains 4
|
||||||
# passthrough calculators.
|
# passthrough calculators.
|
||||||
input_stream: "in"
|
input_stream: "in"
|
||||||
|
output_stream: "out"
|
||||||
node {
|
node {
|
||||||
calculator: "PassThroughCalculator"
|
calculator: "PassThroughCalculator"
|
||||||
input_stream: "in"
|
input_stream: "in"
|
||||||
@@ -55,17 +62,46 @@ node {
|
|||||||
node {
|
node {
|
||||||
calculator: "PassThroughCalculator"
|
calculator: "PassThroughCalculator"
|
||||||
input_stream: "out3"
|
input_stream: "out3"
|
||||||
output_stream: "out4"
|
output_stream: "out"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
MediaPipe offers an alternative `C++` representation for complex graphs (e.g. ML pipelines, handling model metadata, optional nodes, etc.). The above graph may look like:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
CalculatorGraphConfig BuildGraphConfig() {
|
||||||
|
Graph graph;
|
||||||
|
|
||||||
|
// Graph inputs
|
||||||
|
Stream<AnyType> in = graph.In(0).SetName("in");
|
||||||
|
|
||||||
|
auto pass_through_fn = [](Stream<AnyType> in,
|
||||||
|
Graph& graph) -> Stream<AnyType> {
|
||||||
|
auto& node = graph.AddNode("PassThroughCalculator");
|
||||||
|
in.ConnectTo(node.In(0));
|
||||||
|
return node.Out(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
Stream<AnyType> out1 = pass_through_fn(in, graph);
|
||||||
|
Stream<AnyType> out2 = pass_through_fn(out1, graph);
|
||||||
|
Stream<AnyType> out3 = pass_through_fn(out2, graph);
|
||||||
|
Stream<AnyType> out4 = pass_through_fn(out3, graph);
|
||||||
|
|
||||||
|
// Graph outputs
|
||||||
|
out4.SetName("out").ConnectTo(graph.Out(0));
|
||||||
|
|
||||||
|
return graph.GetConfig();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
See more details in [Building Graphs in C++](building_graphs_cpp.md)
|
||||||
|
|
||||||
## Subgraph
|
## Subgraph
|
||||||
|
|
||||||
To modularize a `CalculatorGraphConfig` into sub-modules and assist with re-use
|
To modularize a `CalculatorGraphConfig` into sub-modules and assist with re-use
|
||||||
of perception solutions, a MediaPipe graph can be defined as a `Subgraph`. The
|
of perception solutions, a MediaPipe graph can be defined as a `Subgraph`. The
|
||||||
public interface of a subgraph consists of a set of input and output streams
|
public interface of a subgraph consists of a set of input and output streams
|
||||||
similar to a calculator's public interface. The subgraph can then be included in
|
similar to a calculator's public interface. The subgraph can then be included in
|
||||||
an `CalculatorGraphConfig` as if it were a calculator. When a MediaPipe graph is
|
a `CalculatorGraphConfig` as if it were a calculator. When a MediaPipe graph is
|
||||||
loaded from a `CalculatorGraphConfig`, each subgraph node is replaced by the
|
loaded from a `CalculatorGraphConfig`, each subgraph node is replaced by the
|
||||||
corresponding graph of calculators. As a result, the semantics and performance
|
corresponding graph of calculators. As a result, the semantics and performance
|
||||||
of the subgraph is identical to the corresponding graph of calculators.
|
of the subgraph is identical to the corresponding graph of calculators.
|
||||||
@@ -151,7 +187,7 @@ protobuf specified for a MediaPipe calculator. These "graph options" can be
|
|||||||
specified where a graph is invoked, and used to populate calculator options and
|
specified where a graph is invoked, and used to populate calculator options and
|
||||||
subgraph options within the graph.
|
subgraph options within the graph.
|
||||||
|
|
||||||
In a CalculatorGraphConfig, graph options can be specified for a subgraph
|
In a `CalculatorGraphConfig`, graph options can be specified for a subgraph
|
||||||
exactly like calculator options, as shown below:
|
exactly like calculator options, as shown below:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -178,7 +214,7 @@ node {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In a CalculatorGraphConfig, graph options can be accepted and used to populate
|
In a `CalculatorGraphConfig`, graph options can be accepted and used to populate
|
||||||
calculator options, as shown below:
|
calculator options, as shown below:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -188,7 +224,7 @@ graph_options: {
|
|||||||
|
|
||||||
node: {
|
node: {
|
||||||
calculator: "ImageToTensorCalculator"
|
calculator: "ImageToTensorCalculator"
|
||||||
input_stream: "IMAGE:multi_backend_image"
|
input_stream: "IMAGE:image"
|
||||||
node_options: {
|
node_options: {
|
||||||
[type.googleapis.com/mediapipe.ImageToTensorCalculatorOptions] {
|
[type.googleapis.com/mediapipe.ImageToTensorCalculatorOptions] {
|
||||||
keep_aspect_ratio: true
|
keep_aspect_ratio: true
|
||||||
@@ -247,9 +283,9 @@ NOTE: The current approach is experimental and subject to change. We welcome
|
|||||||
your feedback.
|
your feedback.
|
||||||
|
|
||||||
Please use the `CalculatorGraphTest.Cycle` unit test in
|
Please use the `CalculatorGraphTest.Cycle` unit test in
|
||||||
`mediapipe/framework/calculator_graph_test.cc` as sample code. Shown
|
`mediapipe/framework/calculator_graph_test.cc` as sample code. Shown below is
|
||||||
below is the cyclic graph in the test. The `sum` output of the adder is the sum
|
the cyclic graph in the test. The `sum` output of the adder is the sum of the
|
||||||
of the integers generated by the integer source calculator.
|
integers generated by the integer source calculator.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/framework_concepts/packets
|
||||||
title: Packets
|
title: Packets
|
||||||
parent: Framework Concepts
|
parent: Framework Concepts
|
||||||
nav_order: 3
|
nav_order: 3
|
||||||
@@ -12,6 +13,12 @@ nav_order: 3
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
Calculators communicate by sending and receiving packets. Typically a single
|
Calculators communicate by sending and receiving packets. Typically a single
|
||||||
packet is sent along each input stream at each input timestamp. A packet can
|
packet is sent along each input stream at each input timestamp. A packet can
|
||||||
contain any kind of data, such as a single frame of video or a single integer
|
contain any kind of data, such as a single frame of video or a single integer
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/framework_concepts/realtime_streams
|
||||||
title: Real-time Streams
|
title: Real-time Streams
|
||||||
parent: Framework Concepts
|
parent: Framework Concepts
|
||||||
nav_order: 6
|
nav_order: 6
|
||||||
@@ -12,6 +13,12 @@ nav_order: 6
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Real-time timestamps
|
## Real-time timestamps
|
||||||
|
|
||||||
MediaPipe calculator graphs are often used to process streams of video or audio
|
MediaPipe calculator graphs are often used to process streams of video or audio
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/framework_concepts/synchronization
|
||||||
title: Synchronization
|
title: Synchronization
|
||||||
parent: Framework Concepts
|
parent: Framework Concepts
|
||||||
nav_order: 4
|
nav_order: 4
|
||||||
@@ -12,6 +13,12 @@ nav_order: 4
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Scheduling mechanics
|
## Scheduling mechanics
|
||||||
|
|
||||||
Data processing in a MediaPipe graph occurs inside processing nodes defined as
|
Data processing in a MediaPipe graph occurs inside processing nodes defined as
|
||||||
@@ -112,14 +119,14 @@ Warning: On the other hand, it is not guaranteed that an input packet will
|
|||||||
always be available for all streams.
|
always be available for all streams.
|
||||||
|
|
||||||
To explain how it works, we need to introduce the definition of a settled
|
To explain how it works, we need to introduce the definition of a settled
|
||||||
timestamp. We say that a timestamp in a stream is *settled* if it lower than the
|
timestamp. We say that a timestamp in a stream is *settled* if it is lower than
|
||||||
timestamp bound. In other words, a timestamp is settled for a stream once the
|
the timestamp bound. In other words, a timestamp is settled for a stream once
|
||||||
state of the input at that timestamp is irrevocably known: either there is a
|
the state of the input at that timestamp is irrevocably known: either there is a
|
||||||
packet, or there is the certainty that a packet with that timestamp will not
|
packet, or there is the certainty that a packet with that timestamp will not
|
||||||
arrive.
|
arrive.
|
||||||
|
|
||||||
Note: For this reason, MediaPipe also allows a stream producer to explicitly
|
Note: For this reason, MediaPipe also allows a stream producer to explicitly
|
||||||
advance the timestamp bound farther that what the last packet implies, i.e. to
|
advance the timestamp bound farther than what the last packet implies, i.e. to
|
||||||
provide a tighter bound. This can allow the downstream nodes to settle their
|
provide a tighter bound. This can allow the downstream nodes to settle their
|
||||||
inputs sooner.
|
inputs sooner.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/android
|
||||||
title: MediaPipe on Android
|
title: MediaPipe on Android
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
has_children: true
|
has_children: true
|
||||||
@@ -14,6 +15,12 @@ nav_order: 1
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
Please follow instructions below to build Android example apps in the supported
|
Please follow instructions below to build Android example apps in the supported
|
||||||
MediaPipe [solutions](../solutions/solutions.md). To learn more about these
|
MediaPipe [solutions](../solutions/solutions.md). To learn more about these
|
||||||
example apps, start from [Hello World! on Android](./hello_world_android.md).
|
example apps, start from [Hello World! on Android](./hello_world_android.md).
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/android_archive_library
|
||||||
title: MediaPipe Android Archive
|
title: MediaPipe Android Archive
|
||||||
parent: MediaPipe on Android
|
parent: MediaPipe on Android
|
||||||
grand_parent: Getting Started
|
grand_parent: Getting Started
|
||||||
@@ -13,6 +14,12 @@ nav_order: 3
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
***Experimental Only***
|
***Experimental Only***
|
||||||
|
|
||||||
The MediaPipe Android Archive (AAR) library is a convenient way to use MediaPipe
|
The MediaPipe Android Archive (AAR) library is a convenient way to use MediaPipe
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/
|
||||||
title: MediaPipe Android Solutions
|
title: MediaPipe Android Solutions
|
||||||
parent: MediaPipe on Android
|
parent: MediaPipe on Android
|
||||||
grand_parent: Getting Started
|
grand_parent: Getting Started
|
||||||
@@ -13,6 +14,12 @@ nav_order: 2
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
MediaPipe Android Solution APIs (currently in alpha) are available in:
|
MediaPipe Android Solution APIs (currently in alpha) are available in:
|
||||||
|
|
||||||
* [MediaPipe Face Detection](../solutions/face_detection#android-solution-api)
|
* [MediaPipe Face Detection](../solutions/face_detection#android-solution-api)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/
|
||||||
title: Building MediaPipe Examples
|
title: Building MediaPipe Examples
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
nav_exclude: true
|
nav_exclude: true
|
||||||
@@ -12,6 +13,12 @@ nav_exclude: true
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
### Android
|
### Android
|
||||||
|
|
||||||
Please see these [instructions](./android.md).
|
Please see these [instructions](./android.md).
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/cpp
|
||||||
title: MediaPipe in C++
|
title: MediaPipe in C++
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
has_children: true
|
has_children: true
|
||||||
@@ -14,6 +15,12 @@ nav_order: 5
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
Please follow instructions below to build C++ command-line example apps in the
|
Please follow instructions below to build C++ command-line example apps in the
|
||||||
supported MediaPipe [solutions](../solutions/solutions.md). To learn more about
|
supported MediaPipe [solutions](../solutions/solutions.md). To learn more about
|
||||||
these example apps, start from [Hello World! in C++](./hello_world_cpp.md).
|
these example apps, start from [Hello World! in C++](./hello_world_cpp.md).
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/faq
|
||||||
title: FAQ
|
title: FAQ
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
nav_order: 9
|
nav_order: 9
|
||||||
@@ -12,6 +13,12 @@ nav_order: 9
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
### How to convert ImageFrames and GpuBuffers
|
### How to convert ImageFrames and GpuBuffers
|
||||||
|
|
||||||
The Calculators [`ImageFrameToGpuBufferCalculator`] and
|
The Calculators [`ImageFrameToGpuBufferCalculator`] and
|
||||||
@@ -46,7 +53,7 @@ calculators need only to be *thread-compatible* and not *thread-safe*.
|
|||||||
In order to enable one calculator to process multiple inputs in parallel, there
|
In order to enable one calculator to process multiple inputs in parallel, there
|
||||||
are two possible approaches:
|
are two possible approaches:
|
||||||
|
|
||||||
1. Define multiple calulator nodes and dispatch input packets to all nodes.
|
1. Define multiple calculator nodes and dispatch input packets to all nodes.
|
||||||
2. Make the calculator thread-safe and configure its [`max_in_flight`] setting.
|
2. Make the calculator thread-safe and configure its [`max_in_flight`] setting.
|
||||||
|
|
||||||
The first approach can be followed using the calculators designed to distribute
|
The first approach can be followed using the calculators designed to distribute
|
||||||
@@ -59,7 +66,7 @@ The second approach allows up to [`max_in_flight`] invocations of the
|
|||||||
packets from [`CalculatorBase::Process`] are automatically ordered by timestamp
|
packets from [`CalculatorBase::Process`] are automatically ordered by timestamp
|
||||||
before they are passed along to downstream calculators.
|
before they are passed along to downstream calculators.
|
||||||
|
|
||||||
With either aproach, you must be aware that the calculator running in parallel
|
With either approach, you must be aware that the calculator running in parallel
|
||||||
cannot maintain internal state in the same way as a normal sequential
|
cannot maintain internal state in the same way as a normal sequential
|
||||||
calculator.
|
calculator.
|
||||||
|
|
||||||
@@ -88,12 +95,12 @@ while the application is running:
|
|||||||
The first approach has the advantage of leveraging [`CalculatorGraphConfig`]
|
The first approach has the advantage of leveraging [`CalculatorGraphConfig`]
|
||||||
processing tools such as "subgraphs". The second approach has the advantage of
|
processing tools such as "subgraphs". The second approach has the advantage of
|
||||||
allowing active calculators and packets to remain in-flight while settings
|
allowing active calculators and packets to remain in-flight while settings
|
||||||
change. Mediapipe contributors are currently investigating alternative approaches
|
change. MediaPipe contributors are currently investigating alternative approaches
|
||||||
to achieve both of these advantages.
|
to achieve both of these advantages.
|
||||||
|
|
||||||
### How to process realtime input streams
|
### How to process realtime input streams
|
||||||
|
|
||||||
The mediapipe framework can be used to process data streams either online or
|
The MediaPipe framework can be used to process data streams either online or
|
||||||
offline. For offline processing, packets are pushed into the graph as soon as
|
offline. For offline processing, packets are pushed into the graph as soon as
|
||||||
calculators are ready to process those packets. For online processing, one
|
calculators are ready to process those packets. For online processing, one
|
||||||
packet for each frame is pushed into the graph as that frame is recorded.
|
packet for each frame is pushed into the graph as that frame is recorded.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/
|
||||||
title: Getting Started
|
title: Getting Started
|
||||||
nav_order: 2
|
nav_order: 2
|
||||||
has_children: true
|
has_children: true
|
||||||
@@ -11,3 +12,9 @@ has_children: true
|
|||||||
1. TOC
|
1. TOC
|
||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/gpu_support
|
||||||
title: GPU Support
|
title: GPU Support
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
nav_order: 7
|
nav_order: 7
|
||||||
@@ -12,6 +13,12 @@ nav_order: 7
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## OpenGL ES Support
|
## OpenGL ES Support
|
||||||
|
|
||||||
MediaPipe supports OpenGL ES up to version 3.2 on Android/Linux and up to ES 3.0
|
MediaPipe supports OpenGL ES up to version 3.2 on Android/Linux and up to ES 3.0
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/hello_world_android
|
||||||
title: Hello World! on Android
|
title: Hello World! on Android
|
||||||
parent: MediaPipe on Android
|
parent: MediaPipe on Android
|
||||||
grand_parent: Getting Started
|
grand_parent: Getting Started
|
||||||
@@ -13,6 +14,12 @@ nav_order: 1
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
This codelab uses MediaPipe on an Android device.
|
This codelab uses MediaPipe on an Android device.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/hello_world_cpp
|
||||||
title: Hello World! in C++
|
title: Hello World! in C++
|
||||||
parent: MediaPipe in C++
|
parent: MediaPipe in C++
|
||||||
grand_parent: Getting Started
|
grand_parent: Getting Started
|
||||||
@@ -13,6 +14,12 @@ nav_order: 1
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
1. Ensure you have a working version of MediaPipe. See
|
1. Ensure you have a working version of MediaPipe. See
|
||||||
[installation instructions](./install.md).
|
[installation instructions](./install.md).
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/hello_world_ios
|
||||||
title: Hello World! on iOS
|
title: Hello World! on iOS
|
||||||
parent: MediaPipe on iOS
|
parent: MediaPipe on iOS
|
||||||
grand_parent: Getting Started
|
grand_parent: Getting Started
|
||||||
@@ -13,6 +14,12 @@ nav_order: 1
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
This codelab uses MediaPipe on an iOS device.
|
This codelab uses MediaPipe on an iOS device.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/help
|
||||||
title: Getting Help
|
title: Getting Help
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
nav_order: 8
|
nav_order: 8
|
||||||
@@ -12,6 +13,12 @@ nav_order: 8
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Technical questions
|
## Technical questions
|
||||||
|
|
||||||
For help with technical or algorithmic questions, visit
|
For help with technical or algorithmic questions, visit
|
||||||
@@ -37,8 +44,8 @@ If you open a GitHub issue, here is our policy:
|
|||||||
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:
|
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:
|
||||||
- **Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device**:
|
- **Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device**:
|
||||||
- **Bazel version**:
|
- **Bazel version**:
|
||||||
- **Android Studio, NDK, SDK versions (if issue is related to building in mobile dev enviroment)**:
|
- **Android Studio, NDK, SDK versions (if issue is related to building in mobile dev environment)**:
|
||||||
- **Xcode & Tulsi version (if issue is related to building in mobile dev enviroment)**:
|
- **Xcode & Tulsi version (if issue is related to building in mobile dev environment)**:
|
||||||
- **Exact steps to reproduce**:
|
- **Exact steps to reproduce**:
|
||||||
|
|
||||||
### Describe the problem
|
### Describe the problem
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/install
|
||||||
title: Installation
|
title: Installation
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
nav_order: 6
|
nav_order: 6
|
||||||
@@ -12,6 +13,12 @@ nav_order: 6
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
Note: To interoperate with OpenCV, OpenCV 3.x to 4.1 are preferred. OpenCV
|
Note: To interoperate with OpenCV, OpenCV 3.x to 4.1 are preferred. OpenCV
|
||||||
2.x currently works but interoperability support may be deprecated in the
|
2.x currently works but interoperability support may be deprecated in the
|
||||||
future.
|
future.
|
||||||
@@ -35,7 +42,7 @@ install --user six`.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd $HOME
|
$ cd $HOME
|
||||||
$ git clone https://github.com/google/mediapipe.git
|
$ git clone --depth 1 https://github.com/google/mediapipe.git
|
||||||
|
|
||||||
# Change directory into MediaPipe root directory
|
# Change directory into MediaPipe root directory
|
||||||
$ cd mediapipe
|
$ cd mediapipe
|
||||||
@@ -67,6 +74,13 @@ install --user six`.
|
|||||||
libopencv-video-dev
|
libopencv-video-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Note**. On Debian 11/Ubuntu 21.04 where OpenCV 4.5 is installed with
|
||||||
|
`libopencv-video-dev`, `libopencv-contrib-dev` should also be installed.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sudo apt-get install -y libopencv-contrib-dev
|
||||||
|
```
|
||||||
|
|
||||||
MediaPipe's [`opencv_linux.BUILD`] and [`WORKSPACE`] are already configured
|
MediaPipe's [`opencv_linux.BUILD`] and [`WORKSPACE`] are already configured
|
||||||
for OpenCV 2/3 and should work correctly on any architecture:
|
for OpenCV 2/3 and should work correctly on any architecture:
|
||||||
|
|
||||||
@@ -287,7 +301,7 @@ build issues.
|
|||||||
2. Checkout MediaPipe repository.
|
2. Checkout MediaPipe repository.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/google/mediapipe.git
|
$ git clone --depth 1 https://github.com/google/mediapipe.git
|
||||||
|
|
||||||
# Change directory into MediaPipe root directory
|
# Change directory into MediaPipe root directory
|
||||||
$ cd mediapipe
|
$ cd mediapipe
|
||||||
@@ -416,7 +430,7 @@ build issues.
|
|||||||
3. Checkout MediaPipe repository.
|
3. Checkout MediaPipe repository.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/google/mediapipe.git
|
$ git clone --depth 1 https://github.com/google/mediapipe.git
|
||||||
|
|
||||||
$ cd mediapipe
|
$ cd mediapipe
|
||||||
```
|
```
|
||||||
@@ -569,7 +583,7 @@ next section.
|
|||||||
|
|
||||||
Option 1. Follow
|
Option 1. Follow
|
||||||
[the official Bazel documentation](https://docs.bazel.build/versions/master/install-windows.html)
|
[the official Bazel documentation](https://docs.bazel.build/versions/master/install-windows.html)
|
||||||
to install Bazel 5.2.0 or higher.
|
to install Bazel 6.1.1 or higher.
|
||||||
|
|
||||||
Option 2. Follow the official
|
Option 2. Follow the official
|
||||||
[Bazel documentation](https://docs.bazel.build/versions/master/install-bazelisk.html)
|
[Bazel documentation](https://docs.bazel.build/versions/master/install-bazelisk.html)
|
||||||
@@ -590,7 +604,7 @@ next section.
|
|||||||
7. Checkout MediaPipe repository.
|
7. Checkout MediaPipe repository.
|
||||||
|
|
||||||
```
|
```
|
||||||
C:\Users\Username\mediapipe_repo> git clone https://github.com/google/mediapipe.git
|
C:\Users\Username\mediapipe_repo> git clone --depth 1 https://github.com/google/mediapipe.git
|
||||||
|
|
||||||
# Change directory into MediaPipe root directory
|
# Change directory into MediaPipe root directory
|
||||||
C:\Users\Username\mediapipe_repo> cd mediapipe
|
C:\Users\Username\mediapipe_repo> cd mediapipe
|
||||||
@@ -651,7 +665,7 @@ cameras. Alternatively, you use a video file as input.
|
|||||||
|
|
||||||
1. Follow the
|
1. Follow the
|
||||||
[instruction](https://docs.microsoft.com/en-us/windows/wsl/install-win10) to
|
[instruction](https://docs.microsoft.com/en-us/windows/wsl/install-win10) to
|
||||||
install Windows Sysystem for Linux (Ubuntu).
|
install Windows Subsystem for Linux (Ubuntu).
|
||||||
|
|
||||||
2. Install Windows ADB and start the ADB server in Windows.
|
2. Install Windows ADB and start the ADB server in Windows.
|
||||||
|
|
||||||
@@ -680,7 +694,7 @@ cameras. Alternatively, you use a video file as input.
|
|||||||
6. Checkout MediaPipe repository.
|
6. Checkout MediaPipe repository.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
username@DESKTOP-TMVLBJ1:~$ git clone https://github.com/google/mediapipe.git
|
username@DESKTOP-TMVLBJ1:~$ git clone --depth 1 https://github.com/google/mediapipe.git
|
||||||
|
|
||||||
username@DESKTOP-TMVLBJ1:~$ cd mediapipe
|
username@DESKTOP-TMVLBJ1:~$ cd mediapipe
|
||||||
```
|
```
|
||||||
@@ -771,7 +785,7 @@ This will use a Docker image that will isolate mediapipe's installation from the
|
|||||||
2. Build a docker image with tag "mediapipe".
|
2. Build a docker image with tag "mediapipe".
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/google/mediapipe.git
|
$ git clone --depth 1 https://github.com/google/mediapipe.git
|
||||||
$ cd mediapipe
|
$ cd mediapipe
|
||||||
$ docker build --tag=mediapipe .
|
$ docker build --tag=mediapipe .
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/ios
|
||||||
title: MediaPipe on iOS
|
title: MediaPipe on iOS
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
has_children: true
|
has_children: true
|
||||||
@@ -14,6 +15,12 @@ nav_order: 2
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
Please follow instructions below to build iOS example apps in the supported
|
Please follow instructions below to build iOS example apps in the supported
|
||||||
MediaPipe [solutions](../solutions/solutions.md). To learn more about these
|
MediaPipe [solutions](../solutions/solutions.md). To learn more about these
|
||||||
example apps, start from, start from
|
example apps, start from, start from
|
||||||
@@ -91,6 +98,10 @@ allows you to make use of automatic provisioning (see later section).
|
|||||||
This will install `Tulsi.app` inside the `Applications` directory in your
|
This will install `Tulsi.app` inside the `Applications` directory in your
|
||||||
home directory.
|
home directory.
|
||||||
|
|
||||||
|
**Note**: Please ensure the `xcode_version` in the
|
||||||
|
[`build_and_run.sh`](https://github.com/bazelbuild/tulsi/blob/b1d0108e6a93dbe8ab01529b2c607b6b651f0759/build_and_run.sh#L26)
|
||||||
|
file in tulsi repo is the same version as installed in your system.
|
||||||
|
|
||||||
2. Open `mediapipe/Mediapipe.tulsiproj` using the Tulsi app.
|
2. Open `mediapipe/Mediapipe.tulsiproj` using the Tulsi app.
|
||||||
|
|
||||||
Tip: If Tulsi displays an error saying "Bazel could not be found", press the
|
Tip: If Tulsi displays an error saying "Bazel could not be found", press the
|
||||||
@@ -109,8 +120,8 @@ allows you to make use of automatic provisioning (see later section).
|
|||||||
To install applications on an iOS device, you need a provisioning profile. There
|
To install applications on an iOS device, you need a provisioning profile. There
|
||||||
are two options:
|
are two options:
|
||||||
|
|
||||||
1. Automatic provisioning. This allows you to build and install an app to your
|
1. Automatic provisioning. This allows you to build and install an app on your
|
||||||
personal device. The provisining profile is managed by Xcode, and has to be
|
personal device. The provisioning profile is managed by Xcode, and has to be
|
||||||
updated often (it is valid for about a week).
|
updated often (it is valid for about a week).
|
||||||
|
|
||||||
2. Custom provisioning. This uses a provisioning profile associated with an
|
2. Custom provisioning. This uses a provisioning profile associated with an
|
||||||
@@ -175,7 +186,7 @@ Profiles"`. If there are none, generate and download a profile on
|
|||||||
Note: if you had previously set up automatic provisioning, you should remove the
|
Note: if you had previously set up automatic provisioning, you should remove the
|
||||||
`provisioning_profile.mobileprovision` symlink in each example's directory,
|
`provisioning_profile.mobileprovision` symlink in each example's directory,
|
||||||
since it will take precedence over the common one. You can also overwrite it
|
since it will take precedence over the common one. You can also overwrite it
|
||||||
with you own profile if you need a different profile for different apps.
|
with your own profile if you need a different profile for different apps.
|
||||||
|
|
||||||
1. Open `mediapipe/examples/ios/bundle_id.bzl`, and change the
|
1. Open `mediapipe/examples/ios/bundle_id.bzl`, and change the
|
||||||
`BUNDLE_ID_PREFIX` to a prefix associated with your provisioning profile.
|
`BUNDLE_ID_PREFIX` to a prefix associated with your provisioning profile.
|
||||||
@@ -192,7 +203,7 @@ Note: When you ask Xcode to run an app, by default it will use the Debug
|
|||||||
configuration. Some of our demos are computationally heavy; you may want to use
|
configuration. Some of our demos are computationally heavy; you may want to use
|
||||||
the Release configuration for better performance.
|
the Release configuration for better performance.
|
||||||
|
|
||||||
Note: Due to an imcoptibility caused by one of our dependencies, MediaPipe
|
Note: Due to an incompatibility caused by one of our dependencies, MediaPipe
|
||||||
cannot be used for apps running on the iPhone Simulator on Apple Silicon (M1).
|
cannot be used for apps running on the iPhone Simulator on Apple Silicon (M1).
|
||||||
|
|
||||||
Tip: To switch build configuration in Xcode, click on the target menu, choose
|
Tip: To switch build configuration in Xcode, click on the target menu, choose
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/
|
||||||
title: MediaPipe in JavaScript
|
title: MediaPipe in JavaScript
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
nav_order: 4
|
nav_order: 4
|
||||||
@@ -12,6 +13,12 @@ nav_order: 4
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We are moving to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe starting April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Ready-to-use JavaScript Solutions
|
## Ready-to-use JavaScript Solutions
|
||||||
|
|
||||||
MediaPipe currently offers the following solutions:
|
MediaPipe currently offers the following solutions:
|
||||||
@@ -29,11 +36,11 @@ Solution | NPM Package | Example
|
|||||||
Click on a solution link above for more information, including API and code
|
Click on a solution link above for more information, including API and code
|
||||||
snippets.
|
snippets.
|
||||||
|
|
||||||
### Supported plaforms:
|
### Supported platforms:
|
||||||
|
|
||||||
| Browser | Platform | Notes |
|
| Browser | Platform | Notes |
|
||||||
| ------- | ----------------------- | -------------------------------------- |
|
| ------- | ----------------------- | -------------------------------------- |
|
||||||
| Chrome | Android / Windows / Mac | Pixel 4 and older unsupported. Fuschia |
|
| Chrome | Android / Windows / Mac | Pixel 4 and older unsupported. Fuchsia |
|
||||||
| | | unsupported. |
|
| | | unsupported. |
|
||||||
| Chrome | iOS | Camera unavailable in Chrome on iOS. |
|
| Chrome | iOS | Camera unavailable in Chrome on iOS. |
|
||||||
| Safari | iPad/iPhone/Mac | iOS and Safari on iPad / iPhone / |
|
| Safari | iPad/iPhone/Mac | iOS and Safari on iPad / iPhone / |
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/
|
||||||
title: MediaPipe in Python
|
title: MediaPipe in Python
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
has_children: true
|
has_children: true
|
||||||
@@ -14,6 +15,12 @@ nav_order: 3
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Ready-to-use Python Solutions
|
## Ready-to-use Python Solutions
|
||||||
|
|
||||||
MediaPipe offers ready-to-use yet customizable Python solutions as a prebuilt
|
MediaPipe offers ready-to-use yet customizable Python solutions as a prebuilt
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
title: MediaPipe Python Framework
|
target: https://developers.google.com/mediapipe/framework/getting_started/python_framework
|
||||||
parent: MediaPipe in Python
|
parent: MediaPipe in Python
|
||||||
grand_parent: Getting Started
|
grand_parent: Getting Started
|
||||||
nav_order: 1
|
nav_order: 1
|
||||||
@@ -12,6 +12,11 @@ nav_order: 1
|
|||||||
1. TOC
|
1. TOC
|
||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
The MediaPipe Python framework grants direct access to the core components of
|
The MediaPipe Python framework grants direct access to the core components of
|
||||||
the MediaPipe C++ framework such as Timestamp, Packet, and CalculatorGraph,
|
the MediaPipe C++ framework such as Timestamp, Packet, and CalculatorGraph,
|
||||||
@@ -76,7 +81,7 @@ np.ndarray | mp::Matrix | create_ma
|
|||||||
Google Proto Message | Google Proto Message | create_proto(proto) | get_proto(packet)
|
Google Proto Message | Google Proto Message | create_proto(proto) | get_proto(packet)
|
||||||
List\[Proto\] | std::vector\<Proto\> | n/a | get_proto_list(packet)
|
List\[Proto\] | std::vector\<Proto\> | n/a | get_proto_list(packet)
|
||||||
|
|
||||||
It's not uncommon that users create custom C++ classes and and send those into
|
It's not uncommon that users create custom C++ classes and send those into
|
||||||
the graphs and calculators. To allow the custom classes to be used in Python
|
the graphs and calculators. To allow the custom classes to be used in Python
|
||||||
with MediaPipe, you may extend the Packet API for a new data type in the
|
with MediaPipe, you may extend the Packet API for a new data type in the
|
||||||
following steps:
|
following steps:
|
||||||
@@ -229,7 +234,7 @@ three stages: initialization and setup, graph run, and graph shutdown.
|
|||||||
output_packets.append(mp.packet_getter.get_str(packet)))
|
output_packets.append(mp.packet_getter.get_str(packet)))
|
||||||
```
|
```
|
||||||
|
|
||||||
Option 2. Initialize a CalculatorGraph with with a binary protobuf file, and
|
Option 2. Initialize a CalculatorGraph with a binary protobuf file, and
|
||||||
observe the output stream(s).
|
observe the output stream(s).
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/getting_started/troubleshooting
|
||||||
title: Troubleshooting
|
title: Troubleshooting
|
||||||
parent: Getting Started
|
parent: Getting Started
|
||||||
nav_order: 10
|
nav_order: 10
|
||||||
@@ -12,6 +13,12 @@ nav_order: 10
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Missing Python binary path
|
## Missing Python binary path
|
||||||
|
|
||||||
The error message:
|
The error message:
|
||||||
@@ -65,7 +72,7 @@ WARNING: Download from https://storage.googleapis.com/mirror.tensorflow.org/gith
|
|||||||
```
|
```
|
||||||
|
|
||||||
usually indicates that Bazel fails to download necessary dependency repositories
|
usually indicates that Bazel fails to download necessary dependency repositories
|
||||||
that MediaPipe needs. MedaiPipe has several dependency repositories that are
|
that MediaPipe needs. MediaPipe has several dependency repositories that are
|
||||||
hosted by Google sites. In some regions, you may need to set up a network proxy
|
hosted by Google sites. In some regions, you may need to set up a network proxy
|
||||||
or use a VPN to access those resources. You may also need to append
|
or use a VPN to access those resources. You may also need to append
|
||||||
`--host_jvm_args "-DsocksProxyHost=<ip address> -DsocksProxyPort=<port number>"`
|
`--host_jvm_args "-DsocksProxyHost=<ip address> -DsocksProxyPort=<port number>"`
|
||||||
|
|||||||
@@ -6,6 +6,20 @@ nav_order: 1
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
*This notice and web page will be removed on June 1, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
## Live ML anywhere
|
## Live ML anywhere
|
||||||
@@ -19,6 +33,8 @@ ML solutions for live and streaming media.
|
|||||||
 | 
|
 | 
|
||||||
***Ready-to-use solutions***: *Cutting-edge ML solutions demonstrating full power of the framework* | ***Free and open source***: *Framework and solutions both under Apache 2.0, fully extensible and customizable*
|
***Ready-to-use solutions***: *Cutting-edge ML solutions demonstrating full power of the framework* | ***Free and open source***: *Framework and solutions both under Apache 2.0, fully extensible and customizable*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## ML solutions in MediaPipe
|
## ML solutions in MediaPipe
|
||||||
|
|
||||||
Face Detection | Face Mesh | Iris | Hands | Pose | Holistic
|
Face Detection | Face Mesh | Iris | Hands | Pose | Holistic
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
MediaPipe
|
MediaPipe
|
||||||
=====================================
|
=====================================
|
||||||
Please see https://docs.mediapipe.dev.
|
Please see https://developers.google.com/mediapipe/
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/guide#legacy
|
||||||
title: AutoFlip (Saliency-aware Video Cropping)
|
title: AutoFlip (Saliency-aware Video Cropping)
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 14
|
nav_order: 14
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 14
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
We have ended support for this MediaPipe Legacy Solution as of March 1, 2023.
|
||||||
|
For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
AutoFlip is an automatic video cropping pipeline built on top of MediaPipe. This
|
AutoFlip is an automatic video cropping pipeline built on top of MediaPipe. This
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/guide#legacy
|
||||||
title: Box Tracking
|
title: Box Tracking
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 10
|
nav_order: 10
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 10
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
We have ended support for this MediaPipe Legacy Solution as of March 1, 2023.
|
||||||
|
For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
MediaPipe Box Tracking has been powering real-time tracking in
|
MediaPipe Box Tracking has been powering real-time tracking in
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/face_detector/
|
||||||
title: Face Detection
|
title: Face Detection
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 1
|
nav_order: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 1
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution is planned to be upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
MediaPipe Face Detection is an ultrafast face detection solution that comes with
|
MediaPipe Face Detection is an ultrafast face detection solution that comes with
|
||||||
@@ -54,6 +63,25 @@ used for its improved inference speed. Please refer to the
|
|||||||
[model cards](./models.md#face_detection) for details. Default to `0` if not
|
[model cards](./models.md#face_detection) for details. Default to `0` if not
|
||||||
specified.
|
specified.
|
||||||
|
|
||||||
|
Note: Not available for JavaScript (use "model" instead).
|
||||||
|
|
||||||
|
#### model
|
||||||
|
|
||||||
|
A string value to indicate which model should be used. Use "short" to
|
||||||
|
select a short-range model that works best for faces within 2 meters from the
|
||||||
|
camera, and "full" for a full-range model best for faces within 5 meters. For
|
||||||
|
the full-range option, a sparse model is used for its improved inference speed.
|
||||||
|
Please refer to the model cards for details. Default to empty string.
|
||||||
|
|
||||||
|
Note: Valid only for JavaScript solution.
|
||||||
|
|
||||||
|
#### selfie_mode
|
||||||
|
|
||||||
|
A boolean value to indicate whether to flip the images/video frames
|
||||||
|
horizontally or not. Default to `false`.
|
||||||
|
|
||||||
|
Note: Valid only for JavaScript solution.
|
||||||
|
|
||||||
#### min_detection_confidence
|
#### min_detection_confidence
|
||||||
|
|
||||||
Minimum confidence value (`[0.0, 1.0]`) from the face detection model for the
|
Minimum confidence value (`[0.0, 1.0]`) from the face detection model for the
|
||||||
@@ -146,9 +174,9 @@ Please first see general [introduction](../getting_started/javascript.md) on
|
|||||||
MediaPipe in JavaScript, then learn more in the companion [web demo](#resources)
|
MediaPipe in JavaScript, then learn more in the companion [web demo](#resources)
|
||||||
and the following usage example.
|
and the following usage example.
|
||||||
|
|
||||||
Supported configuration options:
|
Supported face detection options:
|
||||||
|
* [selfieMode](#selfie_mode)
|
||||||
* [modelSelection](#model_selection)
|
* [model](#model)
|
||||||
* [minDetectionConfidence](#min_detection_confidence)
|
* [minDetectionConfidence](#min_detection_confidence)
|
||||||
|
|
||||||
```html
|
```html
|
||||||
@@ -176,6 +204,7 @@ Supported configuration options:
|
|||||||
const videoElement = document.getElementsByClassName('input_video')[0];
|
const videoElement = document.getElementsByClassName('input_video')[0];
|
||||||
const canvasElement = document.getElementsByClassName('output_canvas')[0];
|
const canvasElement = document.getElementsByClassName('output_canvas')[0];
|
||||||
const canvasCtx = canvasElement.getContext('2d');
|
const canvasCtx = canvasElement.getContext('2d');
|
||||||
|
const drawingUtils = window;
|
||||||
|
|
||||||
function onResults(results) {
|
function onResults(results) {
|
||||||
// Draw the overlays.
|
// Draw the overlays.
|
||||||
@@ -199,7 +228,7 @@ const faceDetection = new FaceDetection({locateFile: (file) => {
|
|||||||
return `https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/${file}`;
|
return `https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/${file}`;
|
||||||
}});
|
}});
|
||||||
faceDetection.setOptions({
|
faceDetection.setOptions({
|
||||||
modelSelection: 0,
|
model: 'short',
|
||||||
minDetectionConfidence: 0.5
|
minDetectionConfidence: 0.5
|
||||||
});
|
});
|
||||||
faceDetection.onResults(onResults);
|
faceDetection.onResults(onResults);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/face_landmarker/
|
||||||
title: Face Mesh
|
title: Face Mesh
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 2
|
nav_order: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 2
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution is planned to be upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
MediaPipe Face Mesh is a solution that estimates 468 3D face landmarks in
|
MediaPipe Face Mesh is a solution that estimates 468 3D face landmarks in
|
||||||
@@ -133,7 +142,7 @@ about the model in this [paper](https://arxiv.org/abs/2006.10962).
|
|||||||
The [Face Landmark Model](#face-landmark-model) performs a single-camera face landmark
|
The [Face Landmark Model](#face-landmark-model) performs a single-camera face landmark
|
||||||
detection in the screen coordinate space: the X- and Y- coordinates are
|
detection in the screen coordinate space: the X- and Y- coordinates are
|
||||||
normalized screen coordinates, while the Z coordinate is relative and is scaled
|
normalized screen coordinates, while the Z coordinate is relative and is scaled
|
||||||
as the X coodinate under the
|
as the X coordinate under the
|
||||||
[weak perspective projection camera model](https://en.wikipedia.org/wiki/3D_projection#Weak_perspective_projection).
|
[weak perspective projection camera model](https://en.wikipedia.org/wiki/3D_projection#Weak_perspective_projection).
|
||||||
This format is well-suited for some applications, however it does not directly
|
This format is well-suited for some applications, however it does not directly
|
||||||
enable the full spectrum of augmented reality (AR) features like aligning a
|
enable the full spectrum of augmented reality (AR) features like aligning a
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/image_segmenter/
|
||||||
title: Hair Segmentation
|
title: Hair Segmentation
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 8
|
nav_order: 8
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 8
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of April 4, 2023, this solution was upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/vision/image_segmenter/)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Example Apps
|
## Example Apps
|
||||||
|
|||||||
+11
-2
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/hand_landmarker
|
||||||
title: Hands
|
title: Hands
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 4
|
nav_order: 4
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 4
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution was upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/vision/hand_landmarker)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The ability to perceive the shape and motion of hands can be a vital component
|
The ability to perceive the shape and motion of hands can be a vital component
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://github.com/google/mediapipe/blob/master/docs/solutions/holistic.md
|
||||||
title: Holistic
|
title: Holistic
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 6
|
nav_order: 6
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 6
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution is planned to be upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Live perception of simultaneous [human pose](./pose.md),
|
Live perception of simultaneous [human pose](./pose.md),
|
||||||
@@ -66,7 +75,7 @@ previous frame as a guide to the object region on the current one. However,
|
|||||||
during fast movements, the tracker can lose the target, which requires the
|
during fast movements, the tracker can lose the target, which requires the
|
||||||
detector to re-localize it in the image. MediaPipe Holistic uses
|
detector to re-localize it in the image. MediaPipe Holistic uses
|
||||||
[pose](./pose.md) prediction (on every frame) as an additional ROI prior to
|
[pose](./pose.md) prediction (on every frame) as an additional ROI prior to
|
||||||
reduce the response time of the pipeline when reacting to fast movements. This
|
reducing the response time of the pipeline when reacting to fast movements. This
|
||||||
also enables the model to retain semantic consistency across the body and its
|
also enables the model to retain semantic consistency across the body and its
|
||||||
parts by preventing a mixup between left and right hands or body parts of one
|
parts by preventing a mixup between left and right hands or body parts of one
|
||||||
person in the frame with another.
|
person in the frame with another.
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/guide#legacy
|
||||||
title: Instant Motion Tracking
|
title: Instant Motion Tracking
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 11
|
nav_order: 11
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 11
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
We have ended support for this MediaPipe Legacy Solution as of March 1, 2023.
|
||||||
|
For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Augmented Reality (AR) technology creates fun, engaging, and immersive user
|
Augmented Reality (AR) technology creates fun, engaging, and immersive user
|
||||||
|
|||||||
+13
-4
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/face_landmarker/
|
||||||
title: Iris
|
title: Iris
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 3
|
nav_order: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 3
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution is planned to be upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
A wide range of real-world applications, including computational photography
|
A wide range of real-world applications, including computational photography
|
||||||
@@ -38,7 +47,7 @@ camera, in real-time, without the need for specialized hardware. Through use of
|
|||||||
iris landmarks, the solution is also able to determine the metric distance
|
iris landmarks, the solution is also able to determine the metric distance
|
||||||
between the subject and the camera with relative error less than 10%. Note that
|
between the subject and the camera with relative error less than 10%. Note that
|
||||||
iris tracking does not infer the location at which people are looking, nor does
|
iris tracking does not infer the location at which people are looking, nor does
|
||||||
it provide any form of identity recognition. With the cross-platfrom capability
|
it provide any form of identity recognition. With the cross-platform capability
|
||||||
of the MediaPipe framework, MediaPipe Iris can run on most modern
|
of the MediaPipe framework, MediaPipe Iris can run on most modern
|
||||||
[mobile phones](#mobile), [desktops/laptops](#desktop) and even on the
|
[mobile phones](#mobile), [desktops/laptops](#desktop) and even on the
|
||||||
[web](#web).
|
[web](#web).
|
||||||
@@ -99,7 +108,7 @@ You can also find more details in this
|
|||||||
### Iris Landmark Model
|
### Iris Landmark Model
|
||||||
|
|
||||||
The iris model takes an image patch of the eye region and estimates both the eye
|
The iris model takes an image patch of the eye region and estimates both the eye
|
||||||
landmarks (along the eyelid) and iris landmarks (along ths iris contour). You
|
landmarks (along the eyelid) and iris landmarks (along this iris contour). You
|
||||||
can find more details in this [paper](https://arxiv.org/abs/2006.11341).
|
can find more details in this [paper](https://arxiv.org/abs/2006.11341).
|
||||||
|
|
||||||
 |
|
 |
|
||||||
|
|||||||
+11
-2
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/guide#legacy
|
||||||
title: KNIFT (Template-based Feature Matching)
|
title: KNIFT (Template-based Feature Matching)
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 13
|
nav_order: 13
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 13
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
We have ended support for this MediaPipe Legacy Solution as of March 1, 2023.
|
||||||
|
For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
MediaPipe KNIFT is a template-based feature matching solution using KNIFT
|
MediaPipe KNIFT is a template-based feature matching solution using KNIFT
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/guide#legacy
|
||||||
title: Dataset Preparation with MediaSequence
|
title: Dataset Preparation with MediaSequence
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 15
|
nav_order: 15
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 15
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
We have ended support for this MediaPipe Legacy Solution as of March 1, 2023.
|
||||||
|
For more information, see the new
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
MediaPipe is a useful and general framework for media processing that can
|
MediaPipe is a useful and general framework for media processing that can
|
||||||
@@ -85,7 +94,7 @@ process new data sets, in the documentation of
|
|||||||
|
|
||||||
MediaSequence uses SequenceExamples as the format of both inputs and
|
MediaSequence uses SequenceExamples as the format of both inputs and
|
||||||
outputs. Annotations are encoded as inputs in a SequenceExample of metadata
|
outputs. Annotations are encoded as inputs in a SequenceExample of metadata
|
||||||
that defines the labels and the path to the cooresponding video file. This
|
that defines the labels and the path to the corresponding video file. This
|
||||||
metadata is passed as input to the C++ `media_sequence_demo` binary, and the
|
metadata is passed as input to the C++ `media_sequence_demo` binary, and the
|
||||||
output is a SequenceExample filled with images and annotations ready for
|
output is a SequenceExample filled with images and annotations ready for
|
||||||
model training.
|
model training.
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/guide#legacy
|
||||||
title: Models and Model Cards
|
title: Models and Model Cards
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 30
|
nav_order: 30
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -12,6 +13,18 @@ nav_order: 30
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
We have ended support for
|
||||||
|
[these MediaPipe Legacy Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
as of March 1, 2023. All other
|
||||||
|
[MediaPipe Legacy Solutions will be upgraded](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
to a new MediaPipe Solution. The code repository and prebuilt binaries for all
|
||||||
|
MediaPipe Legacy Solutions will continue to be provided on an as-is basis.
|
||||||
|
We encourage you to check out the new MediaPipe Solutions at:
|
||||||
|
[https://developers.google.com/mediapipe/solutions](https://developers.google.com/mediapipe/solutions)*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
### [Face Detection](https://google.github.io/mediapipe/solutions/face_detection)
|
### [Face Detection](https://google.github.io/mediapipe/solutions/face_detection)
|
||||||
|
|
||||||
* Short-range model (best for faces within 2 meters from the camera):
|
* Short-range model (best for faces within 2 meters from the camera):
|
||||||
@@ -94,6 +107,8 @@ one over the other.
|
|||||||
|
|
||||||
* [TFLite model](https://storage.googleapis.com/mediapipe-assets/ssdlite_object_detection.tflite)
|
* [TFLite model](https://storage.googleapis.com/mediapipe-assets/ssdlite_object_detection.tflite)
|
||||||
* [TFLite model quantized for EdgeTPU/Coral](https://github.com/google/mediapipe/tree/master/mediapipe/examples/coral/models/object-detector-quantized_edgetpu.tflite)
|
* [TFLite model quantized for EdgeTPU/Coral](https://github.com/google/mediapipe/tree/master/mediapipe/examples/coral/models/object-detector-quantized_edgetpu.tflite)
|
||||||
|
* [TensorFlow model](https://storage.googleapis.com/mediapipe-assets/object_detection_saved_model/archive.zip)
|
||||||
|
* [Model information](https://storage.googleapis.com/mediapipe-assets/object_detection_saved_model/README.md)
|
||||||
|
|
||||||
### [Objectron](https://google.github.io/mediapipe/solutions/objectron)
|
### [Objectron](https://google.github.io/mediapipe/solutions/objectron)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/object_detector/
|
||||||
title: Object Detection
|
title: Object Detection
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 9
|
nav_order: 9
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 9
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution was upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/vision/object_detector/)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Example Apps
|
## Example Apps
|
||||||
@@ -108,9 +117,9 @@ on how to build MediaPipe examples.
|
|||||||
* With a TensorFlow Model
|
* With a TensorFlow Model
|
||||||
|
|
||||||
This uses the
|
This uses the
|
||||||
[TensorFlow model](https://github.com/google/mediapipe/tree/master/mediapipe/models/object_detection_saved_model)
|
[TensorFlow model](https://storage.googleapis.com/mediapipe-assets/object_detection_saved_model/archive.zip)
|
||||||
( see also
|
( see also
|
||||||
[model info](https://github.com/google/mediapipe/tree/master/mediapipe/models/object_detection_saved_model/README.md)),
|
[model info](https://storage.googleapis.com/mediapipe-assets/object_detection_saved_model/README.md)),
|
||||||
and the pipeline is implemented in this
|
and the pipeline is implemented in this
|
||||||
[graph](https://github.com/google/mediapipe/tree/master/mediapipe/graphs/object_detection/object_detection_mobile_cpu.pbtxt).
|
[graph](https://github.com/google/mediapipe/tree/master/mediapipe/graphs/object_detection/object_detection_mobile_cpu.pbtxt).
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
---
|
||||||
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/object_detector
|
||||||
|
title: Object Detection
|
||||||
|
parent: MediaPipe Legacy Solutions
|
||||||
|
nav_order: 9
|
||||||
|
---
|
||||||
|
|
||||||
|
# MediaPipe Object Detection
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
<details close markdown="block">
|
||||||
|
<summary>
|
||||||
|
Table of contents
|
||||||
|
</summary>
|
||||||
|
{: .text-delta }
|
||||||
|
1. TOC
|
||||||
|
{:toc}
|
||||||
|
</details>
|
||||||
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution was upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/vision/object_detector)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
### TensorFlow model
|
||||||
|
|
||||||
|
The model is trained on [MSCOCO 2014](http://cocodataset.org) dataset using [TensorFlow Object Detection API](https://github.com/tensorflow/models/tree/master/research/object_detection). It is a MobileNetV2-based SSD model with 0.5 depth multiplier. Detailed training configuration is in the provided `pipeline.config`. The model is a relatively compact model which has `0.171 mAP` to achieve real-time performance on mobile devices. You can compare it with other models from the [TensorFlow detection model zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/tf1_detection_zoo.md).
|
||||||
|
|
||||||
|
|
||||||
|
### TFLite model
|
||||||
|
|
||||||
|
The TFLite model is converted from the TensorFlow above. The steps needed to convert the model are similar to [this tutorial](https://medium.com/tensorflow/training-and-serving-a-realtime-mobile-object-detector-in-30-minutes-with-cloud-tpus-b78971cf1193) with minor modifications. Assuming now we have a trained TensorFlow model which includes the checkpoint files and the training configuration file, for example the files provided in this repo:
|
||||||
|
|
||||||
|
* `model.ckpt.index`
|
||||||
|
* `model.ckpt.meta`
|
||||||
|
* `model.ckpt.data-00000-of-00001`
|
||||||
|
* `pipeline.config`
|
||||||
|
|
||||||
|
Make sure you have installed these [python libraries](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/tf1.md). Then to get the frozen graph, run the `export_tflite_ssd_graph.py` script from the `models/research` directory with this command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ PATH_TO_MODEL=path/to/the/model
|
||||||
|
$ bazel run object_detection:export_tflite_ssd_graph -- \
|
||||||
|
--pipeline_config_path ${PATH_TO_MODEL}/pipeline.config \
|
||||||
|
--trained_checkpoint_prefix ${PATH_TO_MODEL}/model.ckpt \
|
||||||
|
--output_directory ${PATH_TO_MODEL} \
|
||||||
|
--add_postprocessing_op=False
|
||||||
|
```
|
||||||
|
|
||||||
|
The exported model contains two files:
|
||||||
|
|
||||||
|
* `tflite_graph.pb`
|
||||||
|
* `tflite_graph.pbtxt`
|
||||||
|
|
||||||
|
The difference between this step and the one in [the tutorial](https://medium.com/tensorflow/training-and-serving-a-realtime-mobile-object-detector-in-30-minutes-with-cloud-tpus-b78971cf1193) is that we set `add_postprocessing_op` to False. In MediaPipe, we have provided all the calculators needed for post-processing such that we can exclude the custom TFLite ops for post-processing in the original graph, e.g., non-maximum suppression. This enables the flexibility to integrate with different post-processing algorithms and implementations.
|
||||||
|
|
||||||
|
Optional: You can install and use the [graph tool](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/graph_transforms) to inspect the input/output of the exported model:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ bazel run graph_transforms:summarize_graph -- \
|
||||||
|
--in_graph=${PATH_TO_MODEL}/tflite_graph.pb
|
||||||
|
```
|
||||||
|
|
||||||
|
You should be able to see the input image size of the model is 320x320 and the outputs of the model are:
|
||||||
|
|
||||||
|
* `raw_outputs/box_encodings`
|
||||||
|
* `raw_outputs/class_predictions`
|
||||||
|
|
||||||
|
The last step is to convert the model to TFLite. You can look at [this guide](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/g3doc/r1/convert/cmdline_examples.md) for more detail. For this example, you just need to run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ tflite_convert -- \
|
||||||
|
--graph_def_file=${PATH_TO_MODEL}/tflite_graph.pb \
|
||||||
|
--output_file=${PATH_TO_MODEL}/model.tflite \
|
||||||
|
--input_format=TENSORFLOW_GRAPHDEF \
|
||||||
|
--output_format=TFLITE \
|
||||||
|
--inference_type=FLOAT \
|
||||||
|
--input_shapes=1,320,320,3 \
|
||||||
|
--input_arrays=normalized_input_image_tensor \
|
||||||
|
--output_arrays=raw_outputs/box_encodings,raw_outputs/class_predictions
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you have the TFLite model `model.tflite` ready to use with MediaPipe Object Detection graphs. Please see the examples for more detail.
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/guide#legacy
|
||||||
title: Objectron (3D Object Detection)
|
title: Objectron (3D Object Detection)
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 12
|
nav_order: 12
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 12
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
We have ended support for this MediaPipe Legacy Solution as of March 1, 2023.
|
||||||
|
For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
MediaPipe Objectron is a mobile real-time 3D object detection solution for
|
MediaPipe Objectron is a mobile real-time 3D object detection solution for
|
||||||
@@ -170,7 +179,7 @@ and a
|
|||||||
The detection subgraph performs ML inference only once every few frames to
|
The detection subgraph performs ML inference only once every few frames to
|
||||||
reduce computation load, and decodes the output tensor to a FrameAnnotation that
|
reduce computation load, and decodes the output tensor to a FrameAnnotation that
|
||||||
contains nine keypoints: the 3D bounding box's center and its eight vertices.
|
contains nine keypoints: the 3D bounding box's center and its eight vertices.
|
||||||
The tracking subgraph runs every frame, using the box traker in
|
The tracking subgraph runs every frame, using the box tracker in
|
||||||
[MediaPipe Box Tracking](./box_tracking.md) to track the 2D box tightly
|
[MediaPipe Box Tracking](./box_tracking.md) to track the 2D box tightly
|
||||||
enclosing the projection of the 3D bounding box, and lifts the tracked 2D
|
enclosing the projection of the 3D bounding box, and lifts the tracked 2D
|
||||||
keypoints to 3D with
|
keypoints to 3D with
|
||||||
@@ -613,7 +622,7 @@ z_ndc = 1 / Z
|
|||||||
|
|
||||||
### Pixel Space
|
### Pixel Space
|
||||||
|
|
||||||
In this API we set upper-left coner of an image as the origin of pixel
|
In this API we set upper-left corner of an image as the origin of pixel
|
||||||
coordinate. One can convert from NDC to pixel space as follows:
|
coordinate. One can convert from NDC to pixel space as follows:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
+13
-3
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/pose_landmarker/
|
||||||
title: Pose
|
title: Pose
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
has_children: true
|
has_children: true
|
||||||
has_toc: false
|
has_toc: false
|
||||||
nav_order: 5
|
nav_order: 5
|
||||||
@@ -20,6 +21,14 @@ nav_order: 5
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution is planned to be upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/vision/pose_landmarker/)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Human pose estimation from video plays a critical role in various applications
|
Human pose estimation from video plays a critical role in various applications
|
||||||
@@ -134,7 +143,7 @@ The landmark model in MediaPipe Pose predicts the location of 33 pose landmarks
|
|||||||
:----------------------------------------------------------------------------------------------: |
|
:----------------------------------------------------------------------------------------------: |
|
||||||
*Fig 4. 33 pose landmarks.* |
|
*Fig 4. 33 pose landmarks.* |
|
||||||
|
|
||||||
Optionally, MediaPipe Pose can predicts a full-body
|
Optionally, MediaPipe Pose can predict a full-body
|
||||||
[segmentation mask](#segmentation_mask) represented as a two-class segmentation
|
[segmentation mask](#segmentation_mask) represented as a two-class segmentation
|
||||||
(human or background).
|
(human or background).
|
||||||
|
|
||||||
@@ -259,6 +268,7 @@ Supported configuration options:
|
|||||||
```python
|
```python
|
||||||
import cv2
|
import cv2
|
||||||
import mediapipe as mp
|
import mediapipe as mp
|
||||||
|
import numpy as np
|
||||||
mp_drawing = mp.solutions.drawing_utils
|
mp_drawing = mp.solutions.drawing_utils
|
||||||
mp_drawing_styles = mp.solutions.drawing_styles
|
mp_drawing_styles = mp.solutions.drawing_styles
|
||||||
mp_pose = mp.solutions.pose
|
mp_pose = mp.solutions.pose
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/pose_landmarker/
|
||||||
title: Pose Classification
|
title: Pose Classification
|
||||||
parent: Pose
|
parent: Pose
|
||||||
grand_parent: Solutions
|
grand_parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 1
|
nav_order: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -19,6 +20,14 @@ nav_order: 1
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of March 1, 2023, this solution is planned to be upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/vision/pose_landmarker/)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
One of the applications
|
One of the applications
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/vision/image_segmenter/
|
||||||
title: Selfie Segmentation
|
title: Selfie Segmentation
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 7
|
nav_order: 7
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 7
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
As of April 4, 2023, this solution was upgraded to a new MediaPipe
|
||||||
|
Solution. For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/vision/image_segmenter/)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
*Fig 1. Example of MediaPipe Selfie Segmentation.* |
|
*Fig 1. Example of MediaPipe Selfie Segmentation.* |
|
||||||
|
|||||||
@@ -1,18 +1,40 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: default
|
||||||
title: Solutions
|
title: MediaPipe Legacy Solutions
|
||||||
nav_order: 3
|
nav_order: 3
|
||||||
has_children: true
|
has_children: true
|
||||||
has_toc: false
|
has_toc: false
|
||||||
---
|
---
|
||||||
|
|
||||||
# Solutions
|
# MediaPipe Legacy Solutions
|
||||||
{: .no_toc }
|
{: .no_toc }
|
||||||
|
|
||||||
1. TOC
|
1. TOC
|
||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions. We have
|
||||||
|
ended support for
|
||||||
|
[these MediaPipe Legacy Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
as of March 1, 2023. All other
|
||||||
|
[MediaPipe Legacy Solutions will be upgraded](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
to a new MediaPipe Solution. The
|
||||||
|
[code repository](https://github.com/google/mediapipe/tree/master/mediapipe)
|
||||||
|
and prebuilt binaries for all MediaPipe Legacy Solutions will continue to
|
||||||
|
be provided on an as-is basis. We encourage you to check out the new MediaPipe
|
||||||
|
Solutions at:
|
||||||
|
[https://developers.google.com/mediapipe/solutions](https://developers.google.com/mediapipe/solutions)*
|
||||||
|
|
||||||
|
*This notice and web page will be removed on June 1, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
<br><br><br><br><br><br><br><br><br><br>
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
MediaPipe offers open source cross-platform, customizable ML solutions for live
|
MediaPipe offers open source cross-platform, customizable ML solutions for live
|
||||||
and streaming media.
|
and streaming media.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/solutions/guide#legacy
|
||||||
title: YouTube-8M Feature Extraction and Model Inference
|
title: YouTube-8M Feature Extraction and Model Inference
|
||||||
parent: Solutions
|
parent: MediaPipe Legacy Solutions
|
||||||
nav_order: 16
|
nav_order: 16
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -18,6 +19,14 @@ nav_order: 16
|
|||||||
</details>
|
</details>
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thank you for your interest in MediaPipe Solutions.
|
||||||
|
We have ended support for this MediaPipe Legacy Solution as of March 1, 2023.
|
||||||
|
For more information, see the
|
||||||
|
[MediaPipe Solutions](https://developers.google.com/mediapipe/solutions/guide#legacy)
|
||||||
|
site.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
MediaPipe is a useful and general framework for media processing that can assist
|
MediaPipe is a useful and general framework for media processing that can assist
|
||||||
with research, development, and deployment of ML models. This example focuses on
|
with research, development, and deployment of ML models. This example focuses on
|
||||||
model development by demonstrating how to prepare training data and do model
|
model development by demonstrating how to prepare training data and do model
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/
|
||||||
title: Performance Benchmarking
|
title: Performance Benchmarking
|
||||||
parent: Tools
|
parent: Tools
|
||||||
nav_order: 3
|
nav_order: 3
|
||||||
@@ -12,6 +13,12 @@ nav_order: 3
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
*Coming soon.*
|
*Coming soon.*
|
||||||
|
|
||||||
Future mediapipe releases will include tools for visualizing and analysing the
|
Future mediapipe releases will include tools for visualizing and analysing the
|
||||||
|
|||||||
+8
-1
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/
|
||||||
title: Tools
|
title: Tools
|
||||||
nav_order: 4
|
nav_order: 4
|
||||||
has_children: true
|
has_children: true
|
||||||
@@ -11,3 +12,9 @@ has_children: true
|
|||||||
1. TOC
|
1. TOC
|
||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/
|
||||||
title: Tracing and Profiling
|
title: Tracing and Profiling
|
||||||
parent: Tools
|
parent: Tools
|
||||||
nav_order: 2
|
nav_order: 2
|
||||||
@@ -12,6 +13,12 @@ nav_order: 2
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
The MediaPipe framework includes a built-in tracer and profiler. The tracer
|
The MediaPipe framework includes a built-in tracer and profiler. The tracer
|
||||||
records various timing events related to packet processing, including the start
|
records various timing events related to packet processing, including the start
|
||||||
and end time of each Calculator::Process call. The tracer writes trace log files
|
and end time of each Calculator::Process call. The tracer writes trace log files
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: default
|
layout: forward
|
||||||
|
target: https://developers.google.com/mediapipe/framework/tools/visualizer
|
||||||
title: Visualizer
|
title: Visualizer
|
||||||
parent: Tools
|
parent: Tools
|
||||||
nav_order: 1
|
nav_order: 1
|
||||||
@@ -12,6 +13,12 @@ nav_order: 1
|
|||||||
{:toc}
|
{:toc}
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Attention:** *Thanks for your interest in MediaPipe! We have moved to
|
||||||
|
[https://developers.google.com/mediapipe](https://developers.google.com/mediapipe)
|
||||||
|
as the primary developer documentation site for MediaPipe as of April 3, 2023.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
To help users understand the structure of their calculator graphs and to
|
To help users understand the structure of their calculator graphs and to
|
||||||
understand the overall behavior of their machine learning inference pipelines,
|
understand the overall behavior of their machine learning inference pipelines,
|
||||||
we have built the [MediaPipe Visualizer](https://viz.mediapipe.dev/)
|
we have built the [MediaPipe Visualizer](https://viz.mediapipe.dev/)
|
||||||
|
|||||||
@@ -26,10 +26,11 @@
|
|||||||
namespace mediapipe {
|
namespace mediapipe {
|
||||||
namespace {
|
namespace {
|
||||||
static bool SafeMultiply(int x, int y, int* result) {
|
static bool SafeMultiply(int x, int y, int* result) {
|
||||||
static_assert(sizeof(int64) >= 2 * sizeof(int),
|
static_assert(sizeof(int64_t) >= 2 * sizeof(int),
|
||||||
"Unable to detect overflow after multiplication");
|
"Unable to detect overflow after multiplication");
|
||||||
const int64 big = static_cast<int64>(x) * static_cast<int64>(y);
|
const int64_t big = static_cast<int64_t>(x) * static_cast<int64_t>(y);
|
||||||
if (big > static_cast<int64>(INT_MIN) && big < static_cast<int64>(INT_MAX)) {
|
if (big > static_cast<int64_t>(INT_MIN) &&
|
||||||
|
big < static_cast<int64_t>(INT_MAX)) {
|
||||||
if (result != nullptr) *result = static_cast<int>(big);
|
if (result != nullptr) *result = static_cast<int>(big);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -182,12 +182,12 @@ class SpectrogramCalculator : public CalculatorBase {
|
|||||||
int frame_duration_samples_;
|
int frame_duration_samples_;
|
||||||
int frame_overlap_samples_;
|
int frame_overlap_samples_;
|
||||||
// How many samples we've been passed, used for checking input time stamps.
|
// How many samples we've been passed, used for checking input time stamps.
|
||||||
int64 cumulative_input_samples_;
|
int64_t cumulative_input_samples_;
|
||||||
// How many frames we've emitted, used for calculating output time stamps.
|
// How many frames we've emitted, used for calculating output time stamps.
|
||||||
int64 cumulative_completed_frames_;
|
int64_t cumulative_completed_frames_;
|
||||||
// How many frames were emitted last, used for estimating the timestamp on
|
// How many frames were emitted last, used for estimating the timestamp on
|
||||||
// Close when use_local_timestamp_ is true;
|
// Close when use_local_timestamp_ is true;
|
||||||
int64 last_completed_frames_;
|
int64_t last_completed_frames_;
|
||||||
Timestamp initial_input_timestamp_;
|
Timestamp initial_input_timestamp_;
|
||||||
int num_input_channels_;
|
int num_input_channels_;
|
||||||
// How many frequency bins we emit (=N_FFT/2 + 1).
|
// How many frequency bins we emit (=N_FFT/2 + 1).
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ class SpectrogramCalculatorTest
|
|||||||
.cos()
|
.cos()
|
||||||
.transpose();
|
.transpose();
|
||||||
}
|
}
|
||||||
int64 input_timestamp = round(packet_start_time_seconds *
|
int64_t input_timestamp = round(packet_start_time_seconds *
|
||||||
Timestamp::kTimestampUnitsPerSecond);
|
Timestamp::kTimestampUnitsPerSecond);
|
||||||
AppendInputPacket(packet_data, input_timestamp);
|
AppendInputPacket(packet_data, input_timestamp);
|
||||||
total_num_input_samples += packet_size_samples;
|
total_num_input_samples += packet_size_samples;
|
||||||
}
|
}
|
||||||
@@ -116,8 +116,8 @@ class SpectrogramCalculatorTest
|
|||||||
double packet_start_time_seconds =
|
double packet_start_time_seconds =
|
||||||
kInitialTimestampOffsetMicroseconds * 1e-6 +
|
kInitialTimestampOffsetMicroseconds * 1e-6 +
|
||||||
total_num_input_samples / input_sample_rate_;
|
total_num_input_samples / input_sample_rate_;
|
||||||
int64 input_timestamp = round(packet_start_time_seconds *
|
int64_t input_timestamp = round(packet_start_time_seconds *
|
||||||
Timestamp::kTimestampUnitsPerSecond);
|
Timestamp::kTimestampUnitsPerSecond);
|
||||||
std::unique_ptr<Matrix> impulse(
|
std::unique_ptr<Matrix> impulse(
|
||||||
new Matrix(Matrix::Zero(1, packet_sizes_samples[i])));
|
new Matrix(Matrix::Zero(1, packet_sizes_samples[i])));
|
||||||
(*impulse)(0, impulse_offsets_samples[i]) = 1.0;
|
(*impulse)(0, impulse_offsets_samples[i]) = 1.0;
|
||||||
@@ -157,8 +157,8 @@ class SpectrogramCalculatorTest
|
|||||||
.cos()
|
.cos()
|
||||||
.transpose();
|
.transpose();
|
||||||
}
|
}
|
||||||
int64 input_timestamp = round(packet_start_time_seconds *
|
int64_t input_timestamp = round(packet_start_time_seconds *
|
||||||
Timestamp::kTimestampUnitsPerSecond);
|
Timestamp::kTimestampUnitsPerSecond);
|
||||||
AppendInputPacket(packet_data, input_timestamp);
|
AppendInputPacket(packet_data, input_timestamp);
|
||||||
total_num_input_samples += packet_size_samples;
|
total_num_input_samples += packet_size_samples;
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ class SpectrogramCalculatorTest
|
|||||||
const double expected_timestamp_seconds =
|
const double expected_timestamp_seconds =
|
||||||
packet_timestamp_offset_seconds +
|
packet_timestamp_offset_seconds +
|
||||||
cumulative_output_frames * frame_step_seconds;
|
cumulative_output_frames * frame_step_seconds;
|
||||||
const int64 expected_timestamp_ticks =
|
const int64_t expected_timestamp_ticks =
|
||||||
expected_timestamp_seconds * Timestamp::kTimestampUnitsPerSecond;
|
expected_timestamp_seconds * Timestamp::kTimestampUnitsPerSecond;
|
||||||
EXPECT_EQ(expected_timestamp_ticks, packet.Timestamp().Value());
|
EXPECT_EQ(expected_timestamp_ticks, packet.Timestamp().Value());
|
||||||
// Accept the timestamp of the first packet as the baseline for checking
|
// Accept the timestamp of the first packet as the baseline for checking
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ TEST_F(StabilizedLogCalculatorTest, BasicOperation) {
|
|||||||
|
|
||||||
std::vector<Matrix> input_data_matrices;
|
std::vector<Matrix> input_data_matrices;
|
||||||
for (int input_packet = 0; input_packet < kNumPackets; ++input_packet) {
|
for (int input_packet = 0; input_packet < kNumPackets; ++input_packet) {
|
||||||
const int64 timestamp = input_packet * Timestamp::kTimestampUnitsPerSecond;
|
const int64_t timestamp =
|
||||||
|
input_packet * Timestamp::kTimestampUnitsPerSecond;
|
||||||
Matrix input_data_matrix =
|
Matrix input_data_matrix =
|
||||||
Matrix::Random(kNumChannels, kNumSamples).array().abs();
|
Matrix::Random(kNumChannels, kNumSamples).array().abs();
|
||||||
input_data_matrices.push_back(input_data_matrix);
|
input_data_matrices.push_back(input_data_matrix);
|
||||||
@@ -80,7 +81,8 @@ TEST_F(StabilizedLogCalculatorTest, OutputScaleWorks) {
|
|||||||
|
|
||||||
std::vector<Matrix> input_data_matrices;
|
std::vector<Matrix> input_data_matrices;
|
||||||
for (int input_packet = 0; input_packet < kNumPackets; ++input_packet) {
|
for (int input_packet = 0; input_packet < kNumPackets; ++input_packet) {
|
||||||
const int64 timestamp = input_packet * Timestamp::kTimestampUnitsPerSecond;
|
const int64_t timestamp =
|
||||||
|
input_packet * Timestamp::kTimestampUnitsPerSecond;
|
||||||
Matrix input_data_matrix =
|
Matrix input_data_matrix =
|
||||||
Matrix::Random(kNumChannels, kNumSamples).array().abs();
|
Matrix::Random(kNumChannels, kNumSamples).array().abs();
|
||||||
input_data_matrices.push_back(input_data_matrix);
|
input_data_matrices.push_back(input_data_matrix);
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class TimeSeriesFramerCalculator : public CalculatorBase {
|
|||||||
// Returns the timestamp of a sample on a base, which is usually the time
|
// Returns the timestamp of a sample on a base, which is usually the time
|
||||||
// stamp of a packet.
|
// stamp of a packet.
|
||||||
Timestamp CurrentSampleTimestamp(const Timestamp& timestamp_base,
|
Timestamp CurrentSampleTimestamp(const Timestamp& timestamp_base,
|
||||||
int64 number_of_samples) {
|
int64_t number_of_samples) {
|
||||||
return timestamp_base + round(number_of_samples / sample_rate_ *
|
return timestamp_base + round(number_of_samples / sample_rate_ *
|
||||||
Timestamp::kTimestampUnitsPerSecond);
|
Timestamp::kTimestampUnitsPerSecond);
|
||||||
}
|
}
|
||||||
@@ -118,10 +118,10 @@ class TimeSeriesFramerCalculator : public CalculatorBase {
|
|||||||
// emitted.
|
// emitted.
|
||||||
int next_frame_step_samples() const {
|
int next_frame_step_samples() const {
|
||||||
// All numbers are in input samples.
|
// All numbers are in input samples.
|
||||||
const int64 current_output_frame_start = static_cast<int64>(
|
const int64_t current_output_frame_start = static_cast<int64_t>(
|
||||||
round(cumulative_output_frames_ * average_frame_step_samples_));
|
round(cumulative_output_frames_ * average_frame_step_samples_));
|
||||||
CHECK_EQ(current_output_frame_start, cumulative_completed_samples_);
|
CHECK_EQ(current_output_frame_start, cumulative_completed_samples_);
|
||||||
const int64 next_output_frame_start = static_cast<int64>(
|
const int64_t next_output_frame_start = static_cast<int64_t>(
|
||||||
round((cumulative_output_frames_ + 1) * average_frame_step_samples_));
|
round((cumulative_output_frames_ + 1) * average_frame_step_samples_));
|
||||||
return next_output_frame_start - current_output_frame_start;
|
return next_output_frame_start - current_output_frame_start;
|
||||||
}
|
}
|
||||||
@@ -134,11 +134,11 @@ class TimeSeriesFramerCalculator : public CalculatorBase {
|
|||||||
// emulate_fractional_frame_overlap is true.
|
// emulate_fractional_frame_overlap is true.
|
||||||
double average_frame_step_samples_;
|
double average_frame_step_samples_;
|
||||||
int samples_still_to_drop_;
|
int samples_still_to_drop_;
|
||||||
int64 cumulative_output_frames_;
|
int64_t cumulative_output_frames_;
|
||||||
// "Completed" samples are samples that are no longer needed because
|
// "Completed" samples are samples that are no longer needed because
|
||||||
// the framer has completely stepped past them (taking into account
|
// the framer has completely stepped past them (taking into account
|
||||||
// any overlap).
|
// any overlap).
|
||||||
int64 cumulative_completed_samples_;
|
int64_t cumulative_completed_samples_;
|
||||||
Timestamp initial_input_timestamp_;
|
Timestamp initial_input_timestamp_;
|
||||||
// The current timestamp is updated along with the incoming packets.
|
// The current timestamp is updated along with the incoming packets.
|
||||||
Timestamp current_timestamp_;
|
Timestamp current_timestamp_;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class TimeSeriesFramerCalculatorTest
|
|||||||
|
|
||||||
// Returns a float value with the channel and timestamp separated by
|
// Returns a float value with the channel and timestamp separated by
|
||||||
// an order of magnitude, for easy parsing by humans.
|
// an order of magnitude, for easy parsing by humans.
|
||||||
float TestValue(int64 timestamp_in_microseconds, int channel) {
|
float TestValue(int64_t timestamp_in_microseconds, int channel) {
|
||||||
return timestamp_in_microseconds + channel / 10.0;
|
return timestamp_in_microseconds + channel / 10.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ class TimeSeriesFramerCalculatorTest
|
|||||||
auto matrix = new Matrix(num_channels, num_samples);
|
auto matrix = new Matrix(num_channels, num_samples);
|
||||||
for (int c = 0; c < num_channels; ++c) {
|
for (int c = 0; c < num_channels; ++c) {
|
||||||
for (int i = 0; i < num_samples; ++i) {
|
for (int i = 0; i < num_samples; ++i) {
|
||||||
int64 timestamp = time_series_util::SecondsToSamples(
|
int64_t timestamp = time_series_util::SecondsToSamples(
|
||||||
starting_timestamp_seconds + i / input_sample_rate_,
|
starting_timestamp_seconds + i / input_sample_rate_,
|
||||||
Timestamp::kTimestampUnitsPerSecond);
|
Timestamp::kTimestampUnitsPerSecond);
|
||||||
(*matrix)(c, i) = TestValue(timestamp, c);
|
(*matrix)(c, i) = TestValue(timestamp, c);
|
||||||
@@ -429,7 +429,7 @@ class TimeSeriesFramerCalculatorTimestampingTest
|
|||||||
num_full_packets -= 1;
|
num_full_packets -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 num_samples = 0;
|
int64_t num_samples = 0;
|
||||||
for (int packet_num = 0; packet_num < num_full_packets; ++packet_num) {
|
for (int packet_num = 0; packet_num < num_full_packets; ++packet_num) {
|
||||||
const Packet& packet = output().packets[packet_num];
|
const Packet& packet = output().packets[packet_num];
|
||||||
num_samples += FrameDurationSamples();
|
num_samples += FrameDurationSamples();
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ mediapipe_proto_library(
|
|||||||
"//mediapipe/framework:calculator_proto",
|
"//mediapipe/framework:calculator_proto",
|
||||||
"//mediapipe/framework/formats:classification_proto",
|
"//mediapipe/framework/formats:classification_proto",
|
||||||
"//mediapipe/framework/formats:landmark_proto",
|
"//mediapipe/framework/formats:landmark_proto",
|
||||||
|
"//mediapipe/framework/formats:time_series_header_proto",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -197,6 +198,7 @@ cc_library(
|
|||||||
"//mediapipe/framework/formats:landmark_cc_proto",
|
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||||
"//mediapipe/framework/formats:matrix",
|
"//mediapipe/framework/formats:matrix",
|
||||||
"//mediapipe/framework/formats:rect_cc_proto",
|
"//mediapipe/framework/formats:rect_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:tensor",
|
||||||
"//mediapipe/framework/port:integral_types",
|
"//mediapipe/framework/port:integral_types",
|
||||||
"//mediapipe/framework/port:ret_check",
|
"//mediapipe/framework/port:ret_check",
|
||||||
"//mediapipe/framework/port:status",
|
"//mediapipe/framework/port:status",
|
||||||
@@ -216,9 +218,11 @@ cc_library(
|
|||||||
"//mediapipe/framework:collection_item_id",
|
"//mediapipe/framework:collection_item_id",
|
||||||
"//mediapipe/framework/formats:classification_cc_proto",
|
"//mediapipe/framework/formats:classification_cc_proto",
|
||||||
"//mediapipe/framework/formats:detection_cc_proto",
|
"//mediapipe/framework/formats:detection_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:image",
|
||||||
"//mediapipe/framework/formats:landmark_cc_proto",
|
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||||
"//mediapipe/framework/formats:matrix",
|
"//mediapipe/framework/formats:matrix",
|
||||||
"//mediapipe/framework/formats:rect_cc_proto",
|
"//mediapipe/framework/formats:rect_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:tensor",
|
||||||
"//mediapipe/framework/port:integral_types",
|
"//mediapipe/framework/port:integral_types",
|
||||||
"//mediapipe/framework/port:ret_check",
|
"//mediapipe/framework/port:ret_check",
|
||||||
"//mediapipe/framework/port:status",
|
"//mediapipe/framework/port:status",
|
||||||
@@ -235,10 +239,12 @@ cc_test(
|
|||||||
":begin_loop_calculator",
|
":begin_loop_calculator",
|
||||||
":end_loop_calculator",
|
":end_loop_calculator",
|
||||||
":gate_calculator",
|
":gate_calculator",
|
||||||
|
":pass_through_calculator",
|
||||||
"//mediapipe/framework:calculator_context",
|
"//mediapipe/framework:calculator_context",
|
||||||
"//mediapipe/framework:calculator_contract",
|
"//mediapipe/framework:calculator_contract",
|
||||||
"//mediapipe/framework:calculator_framework",
|
"//mediapipe/framework:calculator_framework",
|
||||||
"//mediapipe/framework:packet",
|
"//mediapipe/framework:packet",
|
||||||
|
"//mediapipe/framework/formats:tensor",
|
||||||
"//mediapipe/framework/port:gtest_main",
|
"//mediapipe/framework/port:gtest_main",
|
||||||
"//mediapipe/framework/port:integral_types",
|
"//mediapipe/framework/port:integral_types",
|
||||||
"//mediapipe/framework/port:parse_text_proto",
|
"//mediapipe/framework/port:parse_text_proto",
|
||||||
@@ -277,6 +283,7 @@ cc_library(
|
|||||||
}),
|
}),
|
||||||
deps = [
|
deps = [
|
||||||
":concatenate_vector_calculator_cc_proto",
|
":concatenate_vector_calculator_cc_proto",
|
||||||
|
"//mediapipe/framework:calculator_framework",
|
||||||
"//mediapipe/framework/api2:node",
|
"//mediapipe/framework/api2:node",
|
||||||
"//mediapipe/framework/api2:port",
|
"//mediapipe/framework/api2:port",
|
||||||
"//mediapipe/framework/formats:classification_cc_proto",
|
"//mediapipe/framework/formats:classification_cc_proto",
|
||||||
@@ -285,7 +292,6 @@ cc_library(
|
|||||||
"//mediapipe/framework/port:integral_types",
|
"//mediapipe/framework/port:integral_types",
|
||||||
"//mediapipe/framework/port:ret_check",
|
"//mediapipe/framework/port:ret_check",
|
||||||
"//mediapipe/framework/port:status",
|
"//mediapipe/framework/port:status",
|
||||||
"//mediapipe/framework:calculator_framework",
|
|
||||||
"//mediapipe/util:render_data_cc_proto",
|
"//mediapipe/util:render_data_cc_proto",
|
||||||
"@org_tensorflow//tensorflow/lite:framework",
|
"@org_tensorflow//tensorflow/lite:framework",
|
||||||
] + select({
|
] + select({
|
||||||
@@ -895,12 +901,12 @@ cc_library(
|
|||||||
}),
|
}),
|
||||||
deps = [
|
deps = [
|
||||||
":split_vector_calculator_cc_proto",
|
":split_vector_calculator_cc_proto",
|
||||||
"//mediapipe/framework/formats:detection_cc_proto",
|
|
||||||
"//mediapipe/framework/formats:classification_cc_proto",
|
|
||||||
"//mediapipe/framework/formats:landmark_cc_proto",
|
|
||||||
"//mediapipe/framework/formats:rect_cc_proto",
|
|
||||||
"//mediapipe/framework:calculator_framework",
|
"//mediapipe/framework:calculator_framework",
|
||||||
|
"//mediapipe/framework/formats:classification_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:detection_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||||
"//mediapipe/framework/formats:matrix",
|
"//mediapipe/framework/formats:matrix",
|
||||||
|
"//mediapipe/framework/formats:rect_cc_proto",
|
||||||
"//mediapipe/framework/formats:tensor",
|
"//mediapipe/framework/formats:tensor",
|
||||||
"//mediapipe/framework/port:ret_check",
|
"//mediapipe/framework/port:ret_check",
|
||||||
"//mediapipe/framework/port:status",
|
"//mediapipe/framework/port:status",
|
||||||
@@ -1158,6 +1164,7 @@ cc_library(
|
|||||||
"//mediapipe/framework:collection_item_id",
|
"//mediapipe/framework:collection_item_id",
|
||||||
"//mediapipe/framework/formats:classification_cc_proto",
|
"//mediapipe/framework/formats:classification_cc_proto",
|
||||||
"//mediapipe/framework/formats:landmark_cc_proto",
|
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:time_series_header_cc_proto",
|
||||||
"//mediapipe/framework/port:integral_types",
|
"//mediapipe/framework/port:integral_types",
|
||||||
"//mediapipe/framework/port:ret_check",
|
"//mediapipe/framework/port:ret_check",
|
||||||
"//mediapipe/framework/port:status",
|
"//mediapipe/framework/port:status",
|
||||||
@@ -1329,6 +1336,7 @@ cc_library(
|
|||||||
hdrs = ["merge_to_vector_calculator.h"],
|
hdrs = ["merge_to_vector_calculator.h"],
|
||||||
deps = [
|
deps = [
|
||||||
"//mediapipe/framework:calculator_framework",
|
"//mediapipe/framework:calculator_framework",
|
||||||
|
"//mediapipe/framework:packet",
|
||||||
"//mediapipe/framework/api2:node",
|
"//mediapipe/framework/api2:node",
|
||||||
"//mediapipe/framework/api2:port",
|
"//mediapipe/framework/api2:port",
|
||||||
"//mediapipe/framework/formats:detection_cc_proto",
|
"//mediapipe/framework/formats:detection_cc_proto",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "mediapipe/calculators/core/end_loop_calculator.h"
|
#include "mediapipe/calculators/core/end_loop_calculator.h"
|
||||||
#include "mediapipe/framework/calculator_contract.h"
|
#include "mediapipe/framework/calculator_contract.h"
|
||||||
#include "mediapipe/framework/calculator_framework.h"
|
#include "mediapipe/framework/calculator_framework.h"
|
||||||
|
#include "mediapipe/framework/formats/tensor.h"
|
||||||
#include "mediapipe/framework/packet.h"
|
#include "mediapipe/framework/packet.h"
|
||||||
#include "mediapipe/framework/port/gmock.h"
|
#include "mediapipe/framework/port/gmock.h"
|
||||||
#include "mediapipe/framework/port/gtest.h"
|
#include "mediapipe/framework/port/gtest.h"
|
||||||
@@ -444,5 +445,67 @@ TEST_F(BeginEndLoopCalculatorGraphWithClonedInputsTest, MultipleVectors) {
|
|||||||
PacketOfIntsEq(input_timestamp2, std::vector<int>{6, 9})));
|
PacketOfIntsEq(input_timestamp2, std::vector<int>{6, 9})));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::Status InitBeginEndTensorLoopTestGraph(
|
||||||
|
CalculatorGraph& graph, std::vector<Packet>& output_packets) {
|
||||||
|
auto graph_config = ParseTextProtoOrDie<CalculatorGraphConfig>(
|
||||||
|
R"pb(
|
||||||
|
num_threads: 4
|
||||||
|
input_stream: "tensors"
|
||||||
|
node {
|
||||||
|
calculator: "BeginLoopTensorCalculator"
|
||||||
|
input_stream: "ITERABLE:tensors"
|
||||||
|
output_stream: "ITEM:tensor"
|
||||||
|
output_stream: "BATCH_END:timestamp"
|
||||||
|
}
|
||||||
|
node {
|
||||||
|
calculator: "PassThroughCalculator"
|
||||||
|
input_stream: "tensor"
|
||||||
|
output_stream: "passed_tensor"
|
||||||
|
}
|
||||||
|
node {
|
||||||
|
calculator: "EndLoopTensorCalculator"
|
||||||
|
input_stream: "ITEM:passed_tensor"
|
||||||
|
input_stream: "BATCH_END:timestamp"
|
||||||
|
output_stream: "ITERABLE:output_tensors"
|
||||||
|
}
|
||||||
|
)pb");
|
||||||
|
tool::AddVectorSink("output_tensors", &graph_config, &output_packets);
|
||||||
|
MP_RETURN_IF_ERROR(graph.Initialize(graph_config));
|
||||||
|
return graph.StartRun({});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BeginEndTensorLoopCalculatorGraphTest, SingleNonEmptyVector) {
|
||||||
|
// Initialize the graph.
|
||||||
|
CalculatorGraph graph;
|
||||||
|
std::vector<Packet> output_packets;
|
||||||
|
MP_ASSERT_OK(InitBeginEndTensorLoopTestGraph(graph, output_packets));
|
||||||
|
|
||||||
|
// Prepare the inputs and run.
|
||||||
|
Timestamp input_timestamp = Timestamp(0);
|
||||||
|
std::vector<mediapipe::Tensor> tensors;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
tensors.emplace_back(Tensor::ElementType::kFloat32,
|
||||||
|
Tensor::Shape{4, 3, 2, 1});
|
||||||
|
}
|
||||||
|
Packet vector_packet =
|
||||||
|
MakePacket<std::vector<mediapipe::Tensor>>(std::move(tensors));
|
||||||
|
MP_ASSERT_OK(graph.AddPacketToInputStream(
|
||||||
|
"tensors", std::move(vector_packet).At(input_timestamp)));
|
||||||
|
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||||
|
|
||||||
|
// Verify the output packet.
|
||||||
|
EXPECT_EQ(output_packets.size(), 1);
|
||||||
|
const std::vector<Tensor>& output_tensors =
|
||||||
|
output_packets[0].Get<std::vector<Tensor>>();
|
||||||
|
EXPECT_EQ(output_tensors.size(), 4);
|
||||||
|
for (int i = 0; i < output_tensors.size(); i++) {
|
||||||
|
EXPECT_THAT(output_tensors[i].shape().dims,
|
||||||
|
testing::ElementsAre(4, 3, 2, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
MP_ASSERT_OK(graph.CloseAllPacketSources());
|
||||||
|
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace mediapipe
|
} // namespace mediapipe
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "mediapipe/framework/formats/landmark.pb.h"
|
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||||
#include "mediapipe/framework/formats/matrix.h"
|
#include "mediapipe/framework/formats/matrix.h"
|
||||||
#include "mediapipe/framework/formats/rect.pb.h"
|
#include "mediapipe/framework/formats/rect.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/tensor.h"
|
||||||
|
|
||||||
namespace mediapipe {
|
namespace mediapipe {
|
||||||
|
|
||||||
@@ -55,4 +56,8 @@ REGISTER_CALCULATOR(BeginLoopMatrixVectorCalculator);
|
|||||||
typedef BeginLoopCalculator<std::vector<uint64_t>> BeginLoopUint64tCalculator;
|
typedef BeginLoopCalculator<std::vector<uint64_t>> BeginLoopUint64tCalculator;
|
||||||
REGISTER_CALCULATOR(BeginLoopUint64tCalculator);
|
REGISTER_CALCULATOR(BeginLoopUint64tCalculator);
|
||||||
|
|
||||||
|
// A calculator to process std::vector<mediapipe::Tensor>.
|
||||||
|
typedef BeginLoopCalculator<std::vector<Tensor>> BeginLoopTensorCalculator;
|
||||||
|
REGISTER_CALCULATOR(BeginLoopTensorCalculator);
|
||||||
|
|
||||||
} // namespace mediapipe
|
} // namespace mediapipe
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#ifndef MEDIAPIPE_CALCULATORS_CORE_BEGIN_LOOP_CALCULATOR_H_
|
#ifndef MEDIAPIPE_CALCULATORS_CORE_BEGIN_LOOP_CALCULATOR_H_
|
||||||
#define MEDIAPIPE_CALCULATORS_CORE_BEGIN_LOOP_CALCULATOR_H_
|
#define MEDIAPIPE_CALCULATORS_CORE_BEGIN_LOOP_CALCULATOR_H_
|
||||||
|
|
||||||
#include "absl/memory/memory.h"
|
|
||||||
#include "mediapipe/framework/calculator_context.h"
|
#include "mediapipe/framework/calculator_context.h"
|
||||||
#include "mediapipe/framework/calculator_contract.h"
|
#include "mediapipe/framework/calculator_contract.h"
|
||||||
#include "mediapipe/framework/calculator_framework.h"
|
#include "mediapipe/framework/calculator_framework.h"
|
||||||
@@ -24,6 +23,7 @@
|
|||||||
#include "mediapipe/framework/port/integral_types.h"
|
#include "mediapipe/framework/port/integral_types.h"
|
||||||
#include "mediapipe/framework/port/ret_check.h"
|
#include "mediapipe/framework/port/ret_check.h"
|
||||||
#include "mediapipe/framework/port/status.h"
|
#include "mediapipe/framework/port/status.h"
|
||||||
|
#include "mediapipe/framework/port/status_macros.h"
|
||||||
|
|
||||||
namespace mediapipe {
|
namespace mediapipe {
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ namespace mediapipe {
|
|||||||
// calculator: "EndLoopWithOutputCalculator"
|
// calculator: "EndLoopWithOutputCalculator"
|
||||||
// input_stream: "ITEM:output_of_loop_body" # ItemU @loop_internal_ts
|
// input_stream: "ITEM:output_of_loop_body" # ItemU @loop_internal_ts
|
||||||
// input_stream: "BATCH_END:ext_ts" # Timestamp @loop_internal_ts
|
// input_stream: "BATCH_END:ext_ts" # Timestamp @loop_internal_ts
|
||||||
// output_stream: "OUTPUT:aggregated_result" # IterableU @ext_ts
|
// output_stream: "ITERABLE:aggregated_result" # IterableU @ext_ts
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Input streams tagged with "CLONE" are cloned to the corresponding output
|
// Input streams tagged with "CLONE" are cloned to the corresponding output
|
||||||
@@ -112,13 +112,38 @@ class BeginLoopCalculator : public CalculatorBase {
|
|||||||
absl::Status Process(CalculatorContext* cc) final {
|
absl::Status Process(CalculatorContext* cc) final {
|
||||||
Timestamp last_timestamp = loop_internal_timestamp_;
|
Timestamp last_timestamp = loop_internal_timestamp_;
|
||||||
if (!cc->Inputs().Tag("ITERABLE").IsEmpty()) {
|
if (!cc->Inputs().Tag("ITERABLE").IsEmpty()) {
|
||||||
const IterableT& collection =
|
// Try to consume the ITERABLE packet if possible to obtain the ownership
|
||||||
cc->Inputs().Tag("ITERABLE").template Get<IterableT>();
|
// and emit the item packets by moving them.
|
||||||
for (const auto& item : collection) {
|
// If the ITERABLE packet is not consumable, then try to copy each item
|
||||||
cc->Outputs().Tag("ITEM").AddPacket(
|
// instead. If the ITEM type is not copy constructible, an error will be
|
||||||
MakePacket<ItemT>(item).At(loop_internal_timestamp_));
|
// returned.
|
||||||
ForwardClonePackets(cc, loop_internal_timestamp_);
|
auto iterable_ptr_or =
|
||||||
++loop_internal_timestamp_;
|
cc->Inputs().Tag("ITERABLE").Value().Consume<IterableT>();
|
||||||
|
if (iterable_ptr_or.ok()) {
|
||||||
|
for (auto& item : *iterable_ptr_or.value()) {
|
||||||
|
Packet item_packet = MakePacket<ItemT>(std::move(item));
|
||||||
|
cc->Outputs().Tag("ITEM").AddPacket(
|
||||||
|
item_packet.At(loop_internal_timestamp_));
|
||||||
|
ForwardClonePackets(cc, loop_internal_timestamp_);
|
||||||
|
++loop_internal_timestamp_;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if constexpr (std::is_copy_constructible<ItemT>()) {
|
||||||
|
const IterableT& collection =
|
||||||
|
cc->Inputs().Tag("ITERABLE").template Get<IterableT>();
|
||||||
|
for (const auto& item : collection) {
|
||||||
|
cc->Outputs().Tag("ITEM").AddPacket(
|
||||||
|
MakePacket<ItemT>(item).At(loop_internal_timestamp_));
|
||||||
|
ForwardClonePackets(cc, loop_internal_timestamp_);
|
||||||
|
++loop_internal_timestamp_;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return absl::InternalError(
|
||||||
|
"The element type is not copiable. Consider making the "
|
||||||
|
"BeginLoopCalculator the sole owner of the input packet so that "
|
||||||
|
"the "
|
||||||
|
"items can be consumed and moved.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +163,6 @@ class BeginLoopCalculator : public CalculatorBase {
|
|||||||
.Tag("BATCH_END")
|
.Tag("BATCH_END")
|
||||||
.AddPacket(MakePacket<Timestamp>(cc->InputTimestamp())
|
.AddPacket(MakePacket<Timestamp>(cc->InputTimestamp())
|
||||||
.At(Timestamp(loop_internal_timestamp_ - 1)));
|
.At(Timestamp(loop_internal_timestamp_ - 1)));
|
||||||
|
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace mediapipe {
|
|||||||
typedef ClipVectorSizeCalculator<int> TestClipIntVectorSizeCalculator;
|
typedef ClipVectorSizeCalculator<int> TestClipIntVectorSizeCalculator;
|
||||||
REGISTER_CALCULATOR(TestClipIntVectorSizeCalculator);
|
REGISTER_CALCULATOR(TestClipIntVectorSizeCalculator);
|
||||||
|
|
||||||
void AddInputVector(const std::vector<int>& input, int64 timestamp,
|
void AddInputVector(const std::vector<int>& input, int64_t timestamp,
|
||||||
CalculatorRunner* runner) {
|
CalculatorRunner* runner) {
|
||||||
runner->MutableInputs()->Index(0).packets.push_back(
|
runner->MutableInputs()->Index(0).packets.push_back(
|
||||||
MakePacket<std::vector<int>>(input).At(Timestamp(timestamp)));
|
MakePacket<std::vector<int>>(input).At(Timestamp(timestamp)));
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void ValidateCombinedLandmarks(
|
|||||||
|
|
||||||
void AddInputLandmarkLists(
|
void AddInputLandmarkLists(
|
||||||
const std::vector<NormalizedLandmarkList>& input_landmarks_vec,
|
const std::vector<NormalizedLandmarkList>& input_landmarks_vec,
|
||||||
int64 timestamp, CalculatorRunner* runner) {
|
int64_t timestamp, CalculatorRunner* runner) {
|
||||||
for (int i = 0; i < input_landmarks_vec.size(); ++i) {
|
for (int i = 0; i < input_landmarks_vec.size(); ++i) {
|
||||||
runner->MutableInputs()->Index(i).packets.push_back(
|
runner->MutableInputs()->Index(i).packets.push_back(
|
||||||
MakePacket<NormalizedLandmarkList>(input_landmarks_vec[i])
|
MakePacket<NormalizedLandmarkList>(input_landmarks_vec[i])
|
||||||
@@ -73,7 +73,7 @@ void AddInputLandmarkLists(
|
|||||||
|
|
||||||
void AddInputClassificationLists(
|
void AddInputClassificationLists(
|
||||||
const std::vector<ClassificationList>& input_classifications_vec,
|
const std::vector<ClassificationList>& input_classifications_vec,
|
||||||
int64 timestamp, CalculatorRunner* runner) {
|
int64_t timestamp, CalculatorRunner* runner) {
|
||||||
for (int i = 0; i < input_classifications_vec.size(); ++i) {
|
for (int i = 0; i < input_classifications_vec.size(); ++i) {
|
||||||
runner->MutableInputs()->Index(i).packets.push_back(
|
runner->MutableInputs()->Index(i).packets.push_back(
|
||||||
MakePacket<ClassificationList>(input_classifications_vec[i])
|
MakePacket<ClassificationList>(input_classifications_vec[i])
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ MEDIAPIPE_REGISTER_NODE(ConcatenateFloatVectorCalculator);
|
|||||||
// input_stream: "int32_vector_2"
|
// input_stream: "int32_vector_2"
|
||||||
// output_stream: "concatenated_int32_vector"
|
// output_stream: "concatenated_int32_vector"
|
||||||
// }
|
// }
|
||||||
typedef ConcatenateVectorCalculator<int32> ConcatenateInt32VectorCalculator;
|
typedef ConcatenateVectorCalculator<int32_t> ConcatenateInt32VectorCalculator;
|
||||||
MEDIAPIPE_REGISTER_NODE(ConcatenateInt32VectorCalculator);
|
MEDIAPIPE_REGISTER_NODE(ConcatenateInt32VectorCalculator);
|
||||||
|
|
||||||
typedef ConcatenateVectorCalculator<uint64> ConcatenateUInt64VectorCalculator;
|
typedef ConcatenateVectorCalculator<uint64_t> ConcatenateUInt64VectorCalculator;
|
||||||
MEDIAPIPE_REGISTER_NODE(ConcatenateUInt64VectorCalculator);
|
MEDIAPIPE_REGISTER_NODE(ConcatenateUInt64VectorCalculator);
|
||||||
|
|
||||||
typedef ConcatenateVectorCalculator<bool> ConcatenateBoolVectorCalculator;
|
typedef ConcatenateVectorCalculator<bool> ConcatenateBoolVectorCalculator;
|
||||||
|
|||||||
@@ -30,26 +30,26 @@ namespace mediapipe {
|
|||||||
typedef ConcatenateVectorCalculator<int> TestConcatenateIntVectorCalculator;
|
typedef ConcatenateVectorCalculator<int> TestConcatenateIntVectorCalculator;
|
||||||
MEDIAPIPE_REGISTER_NODE(TestConcatenateIntVectorCalculator);
|
MEDIAPIPE_REGISTER_NODE(TestConcatenateIntVectorCalculator);
|
||||||
|
|
||||||
void AddInputVector(int index, const std::vector<int>& input, int64 timestamp,
|
void AddInputVector(int index, const std::vector<int>& input, int64_t timestamp,
|
||||||
CalculatorRunner* runner) {
|
CalculatorRunner* runner) {
|
||||||
runner->MutableInputs()->Index(index).packets.push_back(
|
runner->MutableInputs()->Index(index).packets.push_back(
|
||||||
MakePacket<std::vector<int>>(input).At(Timestamp(timestamp)));
|
MakePacket<std::vector<int>>(input).At(Timestamp(timestamp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddInputVectors(const std::vector<std::vector<int>>& inputs,
|
void AddInputVectors(const std::vector<std::vector<int>>& inputs,
|
||||||
int64 timestamp, CalculatorRunner* runner) {
|
int64_t timestamp, CalculatorRunner* runner) {
|
||||||
for (int i = 0; i < inputs.size(); ++i) {
|
for (int i = 0; i < inputs.size(); ++i) {
|
||||||
AddInputVector(i, inputs[i], timestamp, runner);
|
AddInputVector(i, inputs[i], timestamp, runner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddInputItem(int index, int input, int64 timestamp,
|
void AddInputItem(int index, int input, int64_t timestamp,
|
||||||
CalculatorRunner* runner) {
|
CalculatorRunner* runner) {
|
||||||
runner->MutableInputs()->Index(index).packets.push_back(
|
runner->MutableInputs()->Index(index).packets.push_back(
|
||||||
MakePacket<int>(input).At(Timestamp(timestamp)));
|
MakePacket<int>(input).At(Timestamp(timestamp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddInputItems(const std::vector<int>& inputs, int64 timestamp,
|
void AddInputItems(const std::vector<int>& inputs, int64_t timestamp,
|
||||||
CalculatorRunner* runner) {
|
CalculatorRunner* runner) {
|
||||||
for (int i = 0; i < inputs.size(); ++i) {
|
for (int i = 0; i < inputs.size(); ++i) {
|
||||||
AddInputItem(i, inputs[i], timestamp, runner);
|
AddInputItem(i, inputs[i], timestamp, runner);
|
||||||
@@ -279,7 +279,7 @@ TEST(TestConcatenateIntVectorCalculatorTest, MixedVectorsAndItemsAnother) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddInputVectors(const std::vector<std::vector<float>>& inputs,
|
void AddInputVectors(const std::vector<std::vector<float>>& inputs,
|
||||||
int64 timestamp, CalculatorRunner* runner) {
|
int64_t timestamp, CalculatorRunner* runner) {
|
||||||
for (int i = 0; i < inputs.size(); ++i) {
|
for (int i = 0; i < inputs.size(); ++i) {
|
||||||
runner->MutableInputs()->Index(i).packets.push_back(
|
runner->MutableInputs()->Index(i).packets.push_back(
|
||||||
MakePacket<std::vector<float>>(inputs[i]).At(Timestamp(timestamp)));
|
MakePacket<std::vector<float>>(inputs[i]).At(Timestamp(timestamp)));
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "mediapipe/framework/collection_item_id.h"
|
#include "mediapipe/framework/collection_item_id.h"
|
||||||
#include "mediapipe/framework/formats/classification.pb.h"
|
#include "mediapipe/framework/formats/classification.pb.h"
|
||||||
#include "mediapipe/framework/formats/landmark.pb.h"
|
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/time_series_header.pb.h"
|
||||||
#include "mediapipe/framework/port/canonical_errors.h"
|
#include "mediapipe/framework/port/canonical_errors.h"
|
||||||
#include "mediapipe/framework/port/integral_types.h"
|
#include "mediapipe/framework/port/integral_types.h"
|
||||||
#include "mediapipe/framework/port/ret_check.h"
|
#include "mediapipe/framework/port/ret_check.h"
|
||||||
@@ -84,6 +85,8 @@ class ConstantSidePacketCalculator : public CalculatorBase {
|
|||||||
packet.Set<LandmarkList>();
|
packet.Set<LandmarkList>();
|
||||||
} else if (packet_options.has_double_value()) {
|
} else if (packet_options.has_double_value()) {
|
||||||
packet.Set<double>();
|
packet.Set<double>();
|
||||||
|
} else if (packet_options.has_time_series_header_value()) {
|
||||||
|
packet.Set<TimeSeriesHeader>();
|
||||||
} else {
|
} else {
|
||||||
return absl::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
"None of supported values were specified in options.");
|
"None of supported values were specified in options.");
|
||||||
@@ -118,6 +121,9 @@ class ConstantSidePacketCalculator : public CalculatorBase {
|
|||||||
MakePacket<LandmarkList>(packet_options.landmark_list_value()));
|
MakePacket<LandmarkList>(packet_options.landmark_list_value()));
|
||||||
} else if (packet_options.has_double_value()) {
|
} else if (packet_options.has_double_value()) {
|
||||||
packet.Set(MakePacket<double>(packet_options.double_value()));
|
packet.Set(MakePacket<double>(packet_options.double_value()));
|
||||||
|
} else if (packet_options.has_time_series_header_value()) {
|
||||||
|
packet.Set(MakePacket<TimeSeriesHeader>(
|
||||||
|
packet_options.time_series_header_value()));
|
||||||
} else {
|
} else {
|
||||||
return absl::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
"None of supported values were specified in options.");
|
"None of supported values were specified in options.");
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package mediapipe;
|
|||||||
import "mediapipe/framework/calculator.proto";
|
import "mediapipe/framework/calculator.proto";
|
||||||
import "mediapipe/framework/formats/classification.proto";
|
import "mediapipe/framework/formats/classification.proto";
|
||||||
import "mediapipe/framework/formats/landmark.proto";
|
import "mediapipe/framework/formats/landmark.proto";
|
||||||
|
import "mediapipe/framework/formats/time_series_header.proto";
|
||||||
|
|
||||||
message ConstantSidePacketCalculatorOptions {
|
message ConstantSidePacketCalculatorOptions {
|
||||||
extend CalculatorOptions {
|
extend CalculatorOptions {
|
||||||
@@ -35,6 +36,7 @@ message ConstantSidePacketCalculatorOptions {
|
|||||||
ClassificationList classification_list_value = 6;
|
ClassificationList classification_list_value = 6;
|
||||||
LandmarkList landmark_list_value = 7;
|
LandmarkList landmark_list_value = 7;
|
||||||
double double_value = 9;
|
double double_value = 9;
|
||||||
|
TimeSeriesHeader time_series_header_value = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,11 @@
|
|||||||
|
|
||||||
#include "mediapipe/framework/formats/classification.pb.h"
|
#include "mediapipe/framework/formats/classification.pb.h"
|
||||||
#include "mediapipe/framework/formats/detection.pb.h"
|
#include "mediapipe/framework/formats/detection.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/image.h"
|
||||||
#include "mediapipe/framework/formats/landmark.pb.h"
|
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||||
#include "mediapipe/framework/formats/matrix.h"
|
#include "mediapipe/framework/formats/matrix.h"
|
||||||
#include "mediapipe/framework/formats/rect.pb.h"
|
#include "mediapipe/framework/formats/rect.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/tensor.h"
|
||||||
#include "mediapipe/util/render_data.pb.h"
|
#include "mediapipe/util/render_data.pb.h"
|
||||||
#include "tensorflow/lite/interpreter.h"
|
#include "tensorflow/lite/interpreter.h"
|
||||||
|
|
||||||
@@ -52,8 +54,9 @@ typedef EndLoopCalculator<std::vector<::mediapipe::ClassificationList>>
|
|||||||
EndLoopClassificationListCalculator;
|
EndLoopClassificationListCalculator;
|
||||||
REGISTER_CALCULATOR(EndLoopClassificationListCalculator);
|
REGISTER_CALCULATOR(EndLoopClassificationListCalculator);
|
||||||
|
|
||||||
typedef EndLoopCalculator<std::vector<TfLiteTensor>> EndLoopTensorCalculator;
|
typedef EndLoopCalculator<std::vector<TfLiteTensor>>
|
||||||
REGISTER_CALCULATOR(EndLoopTensorCalculator);
|
EndLoopTfLiteTensorCalculator;
|
||||||
|
REGISTER_CALCULATOR(EndLoopTfLiteTensorCalculator);
|
||||||
|
|
||||||
typedef EndLoopCalculator<std::vector<::mediapipe::Detection>>
|
typedef EndLoopCalculator<std::vector<::mediapipe::Detection>>
|
||||||
EndLoopDetectionCalculator;
|
EndLoopDetectionCalculator;
|
||||||
@@ -62,4 +65,11 @@ REGISTER_CALCULATOR(EndLoopDetectionCalculator);
|
|||||||
typedef EndLoopCalculator<std::vector<Matrix>> EndLoopMatrixCalculator;
|
typedef EndLoopCalculator<std::vector<Matrix>> EndLoopMatrixCalculator;
|
||||||
REGISTER_CALCULATOR(EndLoopMatrixCalculator);
|
REGISTER_CALCULATOR(EndLoopMatrixCalculator);
|
||||||
|
|
||||||
|
typedef EndLoopCalculator<std::vector<Tensor>> EndLoopTensorCalculator;
|
||||||
|
REGISTER_CALCULATOR(EndLoopTensorCalculator);
|
||||||
|
|
||||||
|
typedef EndLoopCalculator<std::vector<::mediapipe::Image>>
|
||||||
|
EndLoopImageCalculator;
|
||||||
|
REGISTER_CALCULATOR(EndLoopImageCalculator);
|
||||||
|
|
||||||
} // namespace mediapipe
|
} // namespace mediapipe
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#ifndef MEDIAPIPE_CALCULATORS_CORE_END_LOOP_CALCULATOR_H_
|
#ifndef MEDIAPIPE_CALCULATORS_CORE_END_LOOP_CALCULATOR_H_
|
||||||
#define MEDIAPIPE_CALCULATORS_CORE_END_LOOP_CALCULATOR_H_
|
#define MEDIAPIPE_CALCULATORS_CORE_END_LOOP_CALCULATOR_H_
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "mediapipe/framework/calculator_context.h"
|
#include "mediapipe/framework/calculator_context.h"
|
||||||
#include "mediapipe/framework/calculator_contract.h"
|
#include "mediapipe/framework/calculator_contract.h"
|
||||||
#include "mediapipe/framework/calculator_framework.h"
|
#include "mediapipe/framework/calculator_framework.h"
|
||||||
@@ -75,8 +77,23 @@ class EndLoopCalculator : public CalculatorBase {
|
|||||||
if (!input_stream_collection_) {
|
if (!input_stream_collection_) {
|
||||||
input_stream_collection_.reset(new IterableT);
|
input_stream_collection_.reset(new IterableT);
|
||||||
}
|
}
|
||||||
input_stream_collection_->push_back(
|
// Try to consume the item and move it into the collection. If the items
|
||||||
cc->Inputs().Tag("ITEM").template Get<ItemT>());
|
// are not consumable, then try to copy them instead. If the items are
|
||||||
|
// not copiable, then an error will be returned.
|
||||||
|
auto item_ptr_or = cc->Inputs().Tag("ITEM").Value().Consume<ItemT>();
|
||||||
|
if (item_ptr_or.ok()) {
|
||||||
|
input_stream_collection_->push_back(std::move(*item_ptr_or.value()));
|
||||||
|
} else {
|
||||||
|
if constexpr (std::is_copy_constructible_v<ItemT>) {
|
||||||
|
input_stream_collection_->push_back(
|
||||||
|
cc->Inputs().Tag("ITEM").template Get<ItemT>());
|
||||||
|
} else {
|
||||||
|
return absl::InternalError(
|
||||||
|
"The item type is not copiable. Consider making the "
|
||||||
|
"EndLoopCalculator the sole owner of the input packets so that "
|
||||||
|
"it can be moved instead of copying.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cc->Inputs().Tag("BATCH_END").Value().IsEmpty()) { // flush signal
|
if (!cc->Inputs().Tag("BATCH_END").Value().IsEmpty()) { // flush signal
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ message FlowLimiterCalculatorOptions {
|
|||||||
optional int32 max_in_queue = 2 [default = 0];
|
optional int32 max_in_queue = 2 [default = 0];
|
||||||
|
|
||||||
// The maximum time in microseconds to wait for a frame to finish processing.
|
// The maximum time in microseconds to wait for a frame to finish processing.
|
||||||
// The default value stops waiting after 1 sec.
|
// The default value 0 specifies no timeout.
|
||||||
// The value 0 specifies no timeout.
|
optional int64 in_flight_timeout = 3 [default = 0];
|
||||||
optional int64 in_flight_timeout = 3 [default = 1000000];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ class AtomicSemaphore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Returns the timestamp values for a vector of Packets.
|
// Returns the timestamp values for a vector of Packets.
|
||||||
std::vector<int64> TimestampValues(const std::vector<Packet>& packets) {
|
std::vector<int64_t> TimestampValues(const std::vector<Packet>& packets) {
|
||||||
std::vector<int64> result;
|
std::vector<int64_t> result;
|
||||||
for (const Packet& packet : packets) {
|
for (const Packet& packet : packets) {
|
||||||
result.push_back(packet.Timestamp().Value());
|
result.push_back(packet.Timestamp().Value());
|
||||||
}
|
}
|
||||||
@@ -180,9 +180,9 @@ TEST_F(FlowLimiterCalculatorSemaphoreTest, FramesDropped) {
|
|||||||
InitializeGraph(1);
|
InitializeGraph(1);
|
||||||
MP_ASSERT_OK(graph_.StartRun({}));
|
MP_ASSERT_OK(graph_.StartRun({}));
|
||||||
|
|
||||||
auto send_packet = [this](const std::string& input_name, int64 n) {
|
auto send_packet = [this](const std::string& input_name, int64_t n) {
|
||||||
MP_EXPECT_OK(graph_.AddPacketToInputStream(
|
MP_EXPECT_OK(graph_.AddPacketToInputStream(
|
||||||
input_name, MakePacket<int64>(n).At(Timestamp(n))));
|
input_name, MakePacket<int64_t>(n).At(Timestamp(n))));
|
||||||
};
|
};
|
||||||
|
|
||||||
Packet allow_packet;
|
Packet allow_packet;
|
||||||
@@ -207,12 +207,12 @@ TEST_F(FlowLimiterCalculatorSemaphoreTest, FramesDropped) {
|
|||||||
EXPECT_EQ(10, out_1_packets_.size());
|
EXPECT_EQ(10, out_1_packets_.size());
|
||||||
|
|
||||||
// Timestamps have not been altered.
|
// Timestamps have not been altered.
|
||||||
EXPECT_EQ(PacketValues<int64>(out_1_packets_),
|
EXPECT_EQ(PacketValues<int64_t>(out_1_packets_),
|
||||||
TimestampValues(out_1_packets_));
|
TimestampValues(out_1_packets_));
|
||||||
|
|
||||||
// Extra inputs on in_1 have been dropped.
|
// Extra inputs on in_1 have been dropped.
|
||||||
EXPECT_EQ(TimestampValues(out_1_packets_),
|
EXPECT_EQ(TimestampValues(out_1_packets_),
|
||||||
(std::vector<int64>{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}));
|
(std::vector<int64_t>{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// A calculator that sleeps during Process.
|
// A calculator that sleeps during Process.
|
||||||
@@ -221,8 +221,8 @@ class SleepCalculator : public CalculatorBase {
|
|||||||
static absl::Status GetContract(CalculatorContract* cc) {
|
static absl::Status GetContract(CalculatorContract* cc) {
|
||||||
cc->Inputs().Tag(kPacketTag).SetAny();
|
cc->Inputs().Tag(kPacketTag).SetAny();
|
||||||
cc->Outputs().Tag(kPacketTag).SetSameAs(&cc->Inputs().Tag(kPacketTag));
|
cc->Outputs().Tag(kPacketTag).SetSameAs(&cc->Inputs().Tag(kPacketTag));
|
||||||
cc->InputSidePackets().Tag(kSleepTimeTag).Set<int64>();
|
cc->InputSidePackets().Tag(kSleepTimeTag).Set<int64_t>();
|
||||||
cc->InputSidePackets().Tag(kWarmupTimeTag).Set<int64>();
|
cc->InputSidePackets().Tag(kWarmupTimeTag).Set<int64_t>();
|
||||||
cc->InputSidePackets().Tag(kClockTag).Set<mediapipe::Clock*>();
|
cc->InputSidePackets().Tag(kClockTag).Set<mediapipe::Clock*>();
|
||||||
cc->SetTimestampOffset(0);
|
cc->SetTimestampOffset(0);
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
@@ -237,8 +237,8 @@ class SleepCalculator : public CalculatorBase {
|
|||||||
++packet_count;
|
++packet_count;
|
||||||
absl::Duration sleep_time = absl::Microseconds(
|
absl::Duration sleep_time = absl::Microseconds(
|
||||||
packet_count == 1
|
packet_count == 1
|
||||||
? cc->InputSidePackets().Tag(kWarmupTimeTag).Get<int64>()
|
? cc->InputSidePackets().Tag(kWarmupTimeTag).Get<int64_t>()
|
||||||
: cc->InputSidePackets().Tag(kSleepTimeTag).Get<int64>());
|
: cc->InputSidePackets().Tag(kSleepTimeTag).Get<int64_t>());
|
||||||
clock_->Sleep(sleep_time);
|
clock_->Sleep(sleep_time);
|
||||||
cc->Outputs()
|
cc->Outputs()
|
||||||
.Tag(kPacketTag)
|
.Tag(kPacketTag)
|
||||||
@@ -375,8 +375,8 @@ TEST_F(FlowLimiterCalculatorTest, FinishedTimestamps) {
|
|||||||
std::map<std::string, Packet> side_packets = {
|
std::map<std::string, Packet> side_packets = {
|
||||||
{"limiter_options",
|
{"limiter_options",
|
||||||
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
||||||
{"warmup_time", MakePacket<int64>(22000)},
|
{"warmup_time", MakePacket<int64_t>(22000)},
|
||||||
{"sleep_time", MakePacket<int64>(22000)},
|
{"sleep_time", MakePacket<int64_t>(22000)},
|
||||||
{"drop_timesamps", MakePacket<bool>(false)},
|
{"drop_timesamps", MakePacket<bool>(false)},
|
||||||
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
||||||
};
|
};
|
||||||
@@ -447,8 +447,8 @@ TEST_F(FlowLimiterCalculatorTest, FinishedLost) {
|
|||||||
std::map<std::string, Packet> side_packets = {
|
std::map<std::string, Packet> side_packets = {
|
||||||
{"limiter_options",
|
{"limiter_options",
|
||||||
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
||||||
{"warmup_time", MakePacket<int64>(22000)},
|
{"warmup_time", MakePacket<int64_t>(22000)},
|
||||||
{"sleep_time", MakePacket<int64>(22000)},
|
{"sleep_time", MakePacket<int64_t>(22000)},
|
||||||
{"drop_timesamps", MakePacket<bool>(true)},
|
{"drop_timesamps", MakePacket<bool>(true)},
|
||||||
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
||||||
};
|
};
|
||||||
@@ -511,8 +511,8 @@ TEST_F(FlowLimiterCalculatorTest, FinishedDelayed) {
|
|||||||
std::map<std::string, Packet> side_packets = {
|
std::map<std::string, Packet> side_packets = {
|
||||||
{"limiter_options",
|
{"limiter_options",
|
||||||
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
||||||
{"warmup_time", MakePacket<int64>(500000)},
|
{"warmup_time", MakePacket<int64_t>(500000)},
|
||||||
{"sleep_time", MakePacket<int64>(22000)},
|
{"sleep_time", MakePacket<int64_t>(22000)},
|
||||||
{"drop_timesamps", MakePacket<bool>(false)},
|
{"drop_timesamps", MakePacket<bool>(false)},
|
||||||
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
||||||
};
|
};
|
||||||
@@ -606,8 +606,8 @@ TEST_F(FlowLimiterCalculatorTest, TwoInputStreams) {
|
|||||||
std::map<std::string, Packet> side_packets = {
|
std::map<std::string, Packet> side_packets = {
|
||||||
{"limiter_options",
|
{"limiter_options",
|
||||||
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
||||||
{"warmup_time", MakePacket<int64>(22000)},
|
{"warmup_time", MakePacket<int64_t>(22000)},
|
||||||
{"sleep_time", MakePacket<int64>(22000)},
|
{"sleep_time", MakePacket<int64_t>(22000)},
|
||||||
{"drop_timesamps", MakePacket<bool>(true)},
|
{"drop_timesamps", MakePacket<bool>(true)},
|
||||||
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
||||||
};
|
};
|
||||||
@@ -715,8 +715,8 @@ TEST_F(FlowLimiterCalculatorTest, ZeroQueue) {
|
|||||||
std::map<std::string, Packet> side_packets = {
|
std::map<std::string, Packet> side_packets = {
|
||||||
{"limiter_options",
|
{"limiter_options",
|
||||||
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
MakePacket<FlowLimiterCalculatorOptions>(limiter_options)},
|
||||||
{"warmup_time", MakePacket<int64>(12000)},
|
{"warmup_time", MakePacket<int64_t>(12000)},
|
||||||
{"sleep_time", MakePacket<int64>(12000)},
|
{"sleep_time", MakePacket<int64_t>(12000)},
|
||||||
{"drop_timesamps", MakePacket<bool>(true)},
|
{"drop_timesamps", MakePacket<bool>(true)},
|
||||||
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
||||||
};
|
};
|
||||||
@@ -862,9 +862,9 @@ TEST_F(FlowLimiterCalculatorTest, AuxiliaryInputs) {
|
|||||||
|
|
||||||
std::map<std::string, Packet> side_packets = {
|
std::map<std::string, Packet> side_packets = {
|
||||||
// Fake processing lazy initialization time in microseconds.
|
// Fake processing lazy initialization time in microseconds.
|
||||||
{"warmup_time", MakePacket<int64>(22000)},
|
{"warmup_time", MakePacket<int64_t>(22000)},
|
||||||
// Fake processing duration in microseconds.
|
// Fake processing duration in microseconds.
|
||||||
{"sleep_time", MakePacket<int64>(22000)},
|
{"sleep_time", MakePacket<int64_t>(22000)},
|
||||||
// The SimulationClock to count virtual elapsed time.
|
// The SimulationClock to count virtual elapsed time.
|
||||||
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
{"clock", MakePacket<mediapipe::Clock*>(clock_)},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ class GateCalculator : public CalculatorBase {
|
|||||||
RET_CHECK_OK(CheckAndInitAllowDisallowInputs(cc));
|
RET_CHECK_OK(CheckAndInitAllowDisallowInputs(cc));
|
||||||
|
|
||||||
const int num_data_streams = cc->Inputs().NumEntries("");
|
const int num_data_streams = cc->Inputs().NumEntries("");
|
||||||
RET_CHECK_GE(num_data_streams, 1);
|
|
||||||
RET_CHECK_EQ(cc->Outputs().NumEntries(""), num_data_streams)
|
RET_CHECK_EQ(cc->Outputs().NumEntries(""), num_data_streams)
|
||||||
<< "Number of data output streams must match with data input streams.";
|
<< "Number of data output streams must match with data input streams.";
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ class GateCalculatorTest : public ::testing::Test {
|
|||||||
MP_ASSERT_OK(runner_->Run()) << "Calculator execution failed.";
|
MP_ASSERT_OK(runner_->Run()) << "Calculator execution failed.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RunTimeStepWithoutDataStream(int64_t timestamp,
|
||||||
|
const std::string& control_tag,
|
||||||
|
bool control) {
|
||||||
|
runner_->MutableInputs()
|
||||||
|
->Tag(control_tag)
|
||||||
|
.packets.push_back(MakePacket<bool>(control).At(Timestamp(timestamp)));
|
||||||
|
MP_ASSERT_OK(runner_->Run()) << "Calculator execution failed.";
|
||||||
|
}
|
||||||
|
|
||||||
void SetRunner(const std::string& proto) {
|
void SetRunner(const std::string& proto) {
|
||||||
runner_ = absl::make_unique<CalculatorRunner>(
|
runner_ = absl::make_unique<CalculatorRunner>(
|
||||||
ParseTextProtoOrDie<CalculatorGraphConfig::Node>(proto));
|
ParseTextProtoOrDie<CalculatorGraphConfig::Node>(proto));
|
||||||
@@ -332,6 +341,35 @@ TEST_F(GateCalculatorTest, AllowWithStateChange) {
|
|||||||
EXPECT_EQ(false, output[1].Get<bool>()); // Disallow.
|
EXPECT_EQ(false, output[1].Get<bool>()); // Disallow.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(GateCalculatorTest, AllowWithStateChangeNoDataStreams) {
|
||||||
|
SetRunner(R"(
|
||||||
|
calculator: "GateCalculator"
|
||||||
|
input_stream: "ALLOW:gating_stream"
|
||||||
|
output_stream: "STATE_CHANGE:state_changed"
|
||||||
|
)");
|
||||||
|
|
||||||
|
constexpr int64_t kTimestampValue0 = 42;
|
||||||
|
RunTimeStepWithoutDataStream(kTimestampValue0, "ALLOW", false);
|
||||||
|
constexpr int64_t kTimestampValue1 = 43;
|
||||||
|
RunTimeStepWithoutDataStream(kTimestampValue1, "ALLOW", true);
|
||||||
|
constexpr int64_t kTimestampValue2 = 44;
|
||||||
|
RunTimeStepWithoutDataStream(kTimestampValue2, "ALLOW", true);
|
||||||
|
constexpr int64_t kTimestampValue3 = 45;
|
||||||
|
RunTimeStepWithoutDataStream(kTimestampValue3, "ALLOW", false);
|
||||||
|
LOG(INFO) << "a";
|
||||||
|
const std::vector<Packet>& output =
|
||||||
|
runner()->Outputs().Get("STATE_CHANGE", 0).packets;
|
||||||
|
LOG(INFO) << "s";
|
||||||
|
ASSERT_EQ(2, output.size());
|
||||||
|
LOG(INFO) << "d";
|
||||||
|
EXPECT_EQ(kTimestampValue1, output[0].Timestamp().Value());
|
||||||
|
EXPECT_EQ(kTimestampValue3, output[1].Timestamp().Value());
|
||||||
|
LOG(INFO) << "f";
|
||||||
|
EXPECT_EQ(true, output[0].Get<bool>()); // Allow.
|
||||||
|
EXPECT_EQ(false, output[1].Get<bool>()); // Disallow.
|
||||||
|
LOG(INFO) << "g";
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(GateCalculatorTest, DisallowWithStateChange) {
|
TEST_F(GateCalculatorTest, DisallowWithStateChange) {
|
||||||
SetRunner(R"(
|
SetRunner(R"(
|
||||||
calculator: "GateCalculator"
|
calculator: "GateCalculator"
|
||||||
@@ -359,6 +397,31 @@ TEST_F(GateCalculatorTest, DisallowWithStateChange) {
|
|||||||
EXPECT_EQ(false, output[1].Get<bool>()); // Disallow.
|
EXPECT_EQ(false, output[1].Get<bool>()); // Disallow.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(GateCalculatorTest, DisallowWithStateChangeNoDataStreams) {
|
||||||
|
SetRunner(R"(
|
||||||
|
calculator: "GateCalculator"
|
||||||
|
input_stream: "DISALLOW:gating_stream"
|
||||||
|
output_stream: "STATE_CHANGE:state_changed"
|
||||||
|
)");
|
||||||
|
|
||||||
|
constexpr int64_t kTimestampValue0 = 42;
|
||||||
|
RunTimeStepWithoutDataStream(kTimestampValue0, "DISALLOW", true);
|
||||||
|
constexpr int64_t kTimestampValue1 = 43;
|
||||||
|
RunTimeStepWithoutDataStream(kTimestampValue1, "DISALLOW", false);
|
||||||
|
constexpr int64_t kTimestampValue2 = 44;
|
||||||
|
RunTimeStepWithoutDataStream(kTimestampValue2, "DISALLOW", false);
|
||||||
|
constexpr int64_t kTimestampValue3 = 45;
|
||||||
|
RunTimeStepWithoutDataStream(kTimestampValue3, "DISALLOW", true);
|
||||||
|
|
||||||
|
const std::vector<Packet>& output =
|
||||||
|
runner()->Outputs().Get("STATE_CHANGE", 0).packets;
|
||||||
|
ASSERT_EQ(2, output.size());
|
||||||
|
EXPECT_EQ(kTimestampValue1, output[0].Timestamp().Value());
|
||||||
|
EXPECT_EQ(kTimestampValue3, output[1].Timestamp().Value());
|
||||||
|
EXPECT_EQ(true, output[0].Get<bool>()); // Allow.
|
||||||
|
EXPECT_EQ(false, output[1].Get<bool>()); // Disallow.
|
||||||
|
}
|
||||||
|
|
||||||
// Must not detect disallow value for first timestamp as a state change.
|
// Must not detect disallow value for first timestamp as a state change.
|
||||||
TEST_F(GateCalculatorTest, DisallowInitialNoStateTransition) {
|
TEST_F(GateCalculatorTest, DisallowInitialNoStateTransition) {
|
||||||
SetRunner(R"(
|
SetRunner(R"(
|
||||||
|
|||||||
@@ -94,17 +94,17 @@ class GraphProfileCalculatorTest : public ::testing::Test {
|
|||||||
&graph_config_));
|
&graph_config_));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Packet PacketAt(int64 ts) {
|
static Packet PacketAt(int64_t ts) {
|
||||||
return Adopt(new int64(999)).At(Timestamp(ts));
|
return Adopt(new int64_t(999)).At(Timestamp(ts));
|
||||||
}
|
}
|
||||||
static Packet None() { return Packet().At(Timestamp::OneOverPostStream()); }
|
static Packet None() { return Packet().At(Timestamp::OneOverPostStream()); }
|
||||||
static bool IsNone(const Packet& packet) {
|
static bool IsNone(const Packet& packet) {
|
||||||
return packet.Timestamp() == Timestamp::OneOverPostStream();
|
return packet.Timestamp() == Timestamp::OneOverPostStream();
|
||||||
}
|
}
|
||||||
// Return the values of the timestamps of a vector of Packets.
|
// Return the values of the timestamps of a vector of Packets.
|
||||||
static std::vector<int64> TimestampValues(
|
static std::vector<int64_t> TimestampValues(
|
||||||
const std::vector<Packet>& packets) {
|
const std::vector<Packet>& packets) {
|
||||||
std::vector<int64> result;
|
std::vector<int64_t> result;
|
||||||
for (const Packet& p : packets) {
|
for (const Packet& p : packets) {
|
||||||
result.push_back(p.Timestamp().Value());
|
result.push_back(p.Timestamp().Value());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,17 +191,17 @@ class ImmediateMuxCalculatorTest : public ::testing::Test {
|
|||||||
&graph_config_));
|
&graph_config_));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Packet PacketAt(int64 ts) {
|
static Packet PacketAt(int64_t ts) {
|
||||||
return Adopt(new int64(999)).At(Timestamp(ts));
|
return Adopt(new int64_t(999)).At(Timestamp(ts));
|
||||||
}
|
}
|
||||||
static Packet None() { return Packet().At(Timestamp::OneOverPostStream()); }
|
static Packet None() { return Packet().At(Timestamp::OneOverPostStream()); }
|
||||||
static bool IsNone(const Packet& packet) {
|
static bool IsNone(const Packet& packet) {
|
||||||
return packet.Timestamp() == Timestamp::OneOverPostStream();
|
return packet.Timestamp() == Timestamp::OneOverPostStream();
|
||||||
}
|
}
|
||||||
// Return the values of the timestamps of a vector of Packets.
|
// Return the values of the timestamps of a vector of Packets.
|
||||||
static std::vector<int64> TimestampValues(
|
static std::vector<int64_t> TimestampValues(
|
||||||
const std::vector<Packet>& packets) {
|
const std::vector<Packet>& packets) {
|
||||||
std::vector<int64> result;
|
std::vector<int64_t> result;
|
||||||
for (const Packet& p : packets) {
|
for (const Packet& p : packets) {
|
||||||
result.push_back(p.Timestamp().Value());
|
result.push_back(p.Timestamp().Value());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ class MergeToVectorCalculator : public Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Process(CalculatorContext* cc) {
|
absl::Status Process(CalculatorContext* cc) {
|
||||||
const int input_num = kIn(cc).Count();
|
|
||||||
std::vector<T> output_vector;
|
std::vector<T> output_vector;
|
||||||
for (auto it = kIn(cc).begin(); it != kIn(cc).end(); it++) {
|
for (auto it = kIn(cc).begin(); it != kIn(cc).end(); it++) {
|
||||||
const auto& elem = *it;
|
const auto& elem = *it;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user