Project import generated by Copybara.
GitOrigin-RevId: b2062656e5b3d33264e28ed0cbca31c4b93fe1bf
This commit is contained in:
@@ -1 +1 @@
|
||||
This directory contains MediaPipe example applications for Android. Please see [Solutions](https://solutions.mediapipe.dev)for details.
|
||||
This directory contains MediaPipe example applications for Android. Please see [Solutions](https://solutions.mediapipe.dev) for details.
|
||||
|
||||
+7
-3
@@ -43,19 +43,23 @@ public class MainActivity extends com.google.mediapipe.apps.basic.MainActivity {
|
||||
inputSidePackets.put(INPUT_NUM_FACES_SIDE_PACKET_NAME, packetCreator.createInt32(NUM_FACES));
|
||||
processor.setInputSidePackets(inputSidePackets);
|
||||
|
||||
processor.addPacketCallback(
|
||||
// To show verbose logging, run:
|
||||
// adb shell setprop log.tag.MainActivity VERBOSE
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
processor.addPacketCallback(
|
||||
OUTPUT_LANDMARKS_STREAM_NAME,
|
||||
(packet) -> {
|
||||
Log.d(TAG, "Received multi face landmarks packet.");
|
||||
Log.v(TAG, "Received multi face landmarks packet.");
|
||||
List<NormalizedLandmarkList> multiFaceLandmarks =
|
||||
PacketGetter.getProtoVector(packet, NormalizedLandmarkList.parser());
|
||||
Log.d(
|
||||
Log.v(
|
||||
TAG,
|
||||
"[TS:"
|
||||
+ packet.getTimestamp()
|
||||
+ "] "
|
||||
+ getMultiFaceLandmarksDebugString(multiFaceLandmarks));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static String getMultiFaceLandmarksDebugString(
|
||||
|
||||
+8
-4
@@ -43,29 +43,33 @@ public class MainActivity extends com.google.mediapipe.apps.basic.MainActivity {
|
||||
}
|
||||
});
|
||||
|
||||
processor.addPacketCallback(
|
||||
// To show verbose logging, run:
|
||||
// adb shell setprop log.tag.MainActivity VERBOSE
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
processor.addPacketCallback(
|
||||
OUTPUT_LANDMARKS_STREAM_NAME,
|
||||
(packet) -> {
|
||||
byte[] landmarksRaw = PacketGetter.getProtoBytes(packet);
|
||||
try {
|
||||
NormalizedLandmarkList landmarks = NormalizedLandmarkList.parseFrom(landmarksRaw);
|
||||
if (landmarks == null) {
|
||||
Log.d(TAG, "[TS:" + packet.getTimestamp() + "] No hand landmarks.");
|
||||
Log.v(TAG, "[TS:" + packet.getTimestamp() + "] No hand landmarks.");
|
||||
return;
|
||||
}
|
||||
// Note: If hand_presence is false, these landmarks are useless.
|
||||
Log.d(
|
||||
Log.v(
|
||||
TAG,
|
||||
"[TS:"
|
||||
+ packet.getTimestamp()
|
||||
+ "] #Landmarks for hand: "
|
||||
+ landmarks.getLandmarkCount());
|
||||
Log.d(TAG, getLandmarksDebugString(landmarks));
|
||||
Log.v(TAG, getLandmarksDebugString(landmarks));
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
Log.e(TAG, "Couldn't Exception received - " + e);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLandmarksDebugString(NormalizedLandmarkList landmarks) {
|
||||
|
||||
+7
-3
@@ -31,19 +31,23 @@ public class MainActivity extends com.google.mediapipe.apps.basic.MainActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
processor.addPacketCallback(
|
||||
// To show verbose logging, run:
|
||||
// adb shell setprop log.tag.MainActivity VERBOSE
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
processor.addPacketCallback(
|
||||
OUTPUT_LANDMARKS_STREAM_NAME,
|
||||
(packet) -> {
|
||||
Log.d(TAG, "Received multi-hand landmarks packet.");
|
||||
Log.v(TAG, "Received multi-hand landmarks packet.");
|
||||
List<NormalizedLandmarkList> multiHandLandmarks =
|
||||
PacketGetter.getProtoVector(packet, NormalizedLandmarkList.parser());
|
||||
Log.d(
|
||||
Log.v(
|
||||
TAG,
|
||||
"[TS:"
|
||||
+ packet.getTimestamp()
|
||||
+ "] "
|
||||
+ getMultiHandLandmarksDebugString(multiHandLandmarks));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private String getMultiHandLandmarksDebugString(List<NormalizedLandmarkList> multiHandLandmarks) {
|
||||
|
||||
@@ -324,6 +324,19 @@ void MakeStaticFeatures(const int top_border, const int bottom_border,
|
||||
int path_offset_y;
|
||||
MP_RETURN_IF_ERROR(path_solver_offset_->GetState(&path_offset_y));
|
||||
|
||||
// Prevent box from extending beyond the image after camera smoothing.
|
||||
if (path_offset_y - ceil(path_height / 2.0) < 0) {
|
||||
path_offset_y = ceil(path_height / 2.0);
|
||||
} else if (path_offset_y + ceil(path_height / 2.0) > frame_height_) {
|
||||
path_offset_y = frame_height_ - ceil(path_height / 2.0);
|
||||
}
|
||||
int path_width = path_height * target_aspect_;
|
||||
if (path_offset_x - ceil(path_width / 2.0) < 0) {
|
||||
path_offset_x = ceil(path_width / 2.0);
|
||||
} else if (path_offset_x + ceil(path_width / 2.0) > frame_width_) {
|
||||
path_offset_x = frame_width_ - ceil(path_width / 2.0);
|
||||
}
|
||||
|
||||
// Convert to top/bottom borders to remove.
|
||||
int path_top = path_offset_y - path_height / 2;
|
||||
int path_bottom = frame_height_ - (path_offset_y + path_height / 2);
|
||||
|
||||
@@ -344,6 +344,28 @@ TEST(ContentZoomingCalculatorTest, ZoomTestPairSize) {
|
||||
CheckBorder(static_features, 1000, 1000, 495, 395);
|
||||
}
|
||||
|
||||
TEST(ContentZoomingCalculatorTest, ZoomTestNearOutsideBorder) {
|
||||
auto runner = ::absl::make_unique<CalculatorRunner>(
|
||||
ParseTextProtoOrDie<CalculatorGraphConfig::Node>(kConfigD));
|
||||
AddDetection(cv::Rect_<float>(.95, .95, .05, .05), 0, runner.get());
|
||||
AddDetection(cv::Rect_<float>(.9, .9, .1, .1), 1000000, runner.get());
|
||||
MP_ASSERT_OK(runner->Run());
|
||||
CheckCropRect(972, 972, 55, 55, 0,
|
||||
runner->Outputs().Tag("CROP_RECT").packets);
|
||||
CheckCropRect(958, 958, 83, 83, 1,
|
||||
runner->Outputs().Tag("CROP_RECT").packets);
|
||||
}
|
||||
|
||||
TEST(ContentZoomingCalculatorTest, ZoomTestNearInsideBorder) {
|
||||
auto runner = ::absl::make_unique<CalculatorRunner>(
|
||||
ParseTextProtoOrDie<CalculatorGraphConfig::Node>(kConfigD));
|
||||
AddDetection(cv::Rect_<float>(0, 0, .05, .05), 0, runner.get());
|
||||
AddDetection(cv::Rect_<float>(0, 0, .1, .1), 1000000, runner.get());
|
||||
MP_ASSERT_OK(runner->Run());
|
||||
CheckCropRect(28, 28, 55, 55, 0, runner->Outputs().Tag("CROP_RECT").packets);
|
||||
CheckCropRect(42, 42, 83, 83, 1, runner->Outputs().Tag("CROP_RECT").packets);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace autoflip
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@ namespace autoflip {
|
||||
current_time_ = time_us;
|
||||
initialized_ = true;
|
||||
current_velocity_deg_per_s_ = 0;
|
||||
RET_CHECK_GT(pixels_per_degree_, 0)
|
||||
<< "pixels_per_degree must be larger than 0.";
|
||||
RET_CHECK_GE(options_.min_motion_to_reframe(), options_.reframe_window())
|
||||
<< "Reframe window cannot exceed min_motion_to_reframe.";
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
@@ -22,6 +26,14 @@ namespace autoflip {
|
||||
if (abs(delta_degs) < options_.min_motion_to_reframe()) {
|
||||
position = current_position_px_;
|
||||
delta_degs = 0;
|
||||
} else if (delta_degs > 0) {
|
||||
// Apply new position, less the reframe window size.
|
||||
position = position - pixels_per_degree_ * options_.reframe_window();
|
||||
delta_degs = (position - current_position_px_) / pixels_per_degree_;
|
||||
} else {
|
||||
// Apply new position, plus the reframe window size.
|
||||
position = position + pixels_per_degree_ * options_.reframe_window();
|
||||
delta_degs = (position - current_position_px_) / pixels_per_degree_;
|
||||
}
|
||||
|
||||
// Time and position updates.
|
||||
|
||||
@@ -10,4 +10,9 @@ message KinematicOptions {
|
||||
optional double max_velocity = 2 [default = 18];
|
||||
// Min motion (in degrees) to react in pixels.
|
||||
optional float min_motion_to_reframe = 3 [default = 1.8];
|
||||
// When motion exceeds min_motion_to_reframe, move within this distance of the
|
||||
// camera from the starting direction. Setting this value non-zero reduces
|
||||
// total reframe distance on average. Value cannot exceed
|
||||
// min_motion_to_reframe value.
|
||||
optional float reframe_window = 4 [default = 0];
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ namespace mediapipe {
|
||||
namespace autoflip {
|
||||
namespace {
|
||||
|
||||
TEST(KinematicPathSolverTest, FailZeroPixelsPerDegree) {
|
||||
KinematicOptions options;
|
||||
KinematicPathSolver solver(options, 0, 1000, 0);
|
||||
EXPECT_FALSE(solver.AddObservation(500, kMicroSecInSec * 0).ok());
|
||||
}
|
||||
|
||||
TEST(KinematicPathSolverTest, FailNotInitializedState) {
|
||||
KinematicOptions options;
|
||||
KinematicPathSolver solver(options, 0, 1000, 1000.0 / kWidthFieldOfView);
|
||||
@@ -109,6 +115,38 @@ TEST(KinematicPathSolverTest, PassEnoughMotionSmallImg) {
|
||||
EXPECT_EQ(state, 410);
|
||||
}
|
||||
|
||||
TEST(KinematicPathSolverTest, FailReframeWindowSetting) {
|
||||
KinematicOptions options;
|
||||
// Set min motion to 1deg
|
||||
options.set_min_motion_to_reframe(1.0);
|
||||
options.set_update_rate(1);
|
||||
options.set_max_velocity(1000);
|
||||
// Set reframe window size to .75 for test.
|
||||
options.set_reframe_window(1.1);
|
||||
// Set degrees / pixel to 16.6
|
||||
KinematicPathSolver solver(options, 0, 1000, 1000.0 / kWidthFieldOfView);
|
||||
ASSERT_FALSE(solver.AddObservation(500, kMicroSecInSec * 0).ok());
|
||||
}
|
||||
|
||||
TEST(KinematicPathSolverTest, PassReframeWindow) {
|
||||
KinematicOptions options;
|
||||
// Set min motion to 1deg
|
||||
options.set_min_motion_to_reframe(1.0);
|
||||
options.set_update_rate(1);
|
||||
options.set_max_velocity(1000);
|
||||
// Set reframe window size to .75 for test.
|
||||
options.set_reframe_window(0.75);
|
||||
// Set degrees / pixel to 16.6
|
||||
KinematicPathSolver solver(options, 0, 1000, 1000.0 / kWidthFieldOfView);
|
||||
int state;
|
||||
MP_ASSERT_OK(solver.AddObservation(500, kMicroSecInSec * 0));
|
||||
// Move target by 20px / 16.6 = 1.2deg
|
||||
MP_ASSERT_OK(solver.AddObservation(520, kMicroSecInSec * 1));
|
||||
MP_ASSERT_OK(solver.GetState(&state));
|
||||
// Expect cam to move 1.2-.75 deg, * 16.6 = 7.47px + 500 =
|
||||
EXPECT_EQ(state, 507);
|
||||
}
|
||||
|
||||
TEST(KinematicPathSolverTest, PassUpdateRate) {
|
||||
KinematicOptions options;
|
||||
options.set_min_motion_to_reframe(1.0);
|
||||
|
||||
@@ -30,7 +30,7 @@ SECONDS_TO_MICROSECONDS = 1000000
|
||||
|
||||
|
||||
def bytes23(string):
|
||||
"""Creates a bytes string in either Python 2 or 3."""
|
||||
"""Creates a bytes string in either Python 2 or 3."""
|
||||
if sys.version_info >= (3, 0):
|
||||
return bytes(string, 'utf8')
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright 2020 The MediaPipe Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Configuration helper for iOS app bundle ids and provisioning profiles.
|
||||
"""
|
||||
|
||||
BUNDLE_ID_PREFIX = "*SEE_IOS_INSTRUCTIONS*.mediapipe.examples"
|
||||
|
||||
# Look for a provisioning profile in the example's directory first,
|
||||
# otherwise look for a common one.
|
||||
def example_provisioning():
|
||||
local_profile = native.glob(["provisioning_profile.mobileprovision"])
|
||||
if local_profile:
|
||||
return local_profile[0]
|
||||
return "//mediapipe/examples/ios:provisioning_profile"
|
||||
@@ -12,14 +12,19 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
alias(
|
||||
name = "edgedetectiongpu",
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "EdgeDetectionGpuApp",
|
||||
bundle_id = "com.google.mediapipe.EdgeDetectionGpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".EdgeDetectionGpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [":EdgeDetectionGpuAppLibrary"],
|
||||
)
|
||||
|
||||
|
||||
@@ -12,14 +12,19 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
alias(
|
||||
name = "facedetectioncpu",
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "FaceDetectionCpuApp",
|
||||
bundle_id = "com.google.mediapipe.FaceDetectionCpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".FaceDetectionCpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [
|
||||
":FaceDetectionCpuAppLibrary",
|
||||
"@ios_opencv//:OpencvFramework",
|
||||
|
||||
@@ -12,14 +12,19 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
alias(
|
||||
name = "facedetectiongpu",
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "FaceDetectionGpuApp",
|
||||
bundle_id = "com.google.mediapipe.FaceDetectionGpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".FaceDetectionGpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [
|
||||
":FaceDetectionGpuAppLibrary",
|
||||
"@ios_opencv//:OpencvFramework",
|
||||
|
||||
@@ -16,6 +16,11 @@ load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "FaceMeshGpuApp",
|
||||
bundle_id = "com.google.mediapipe.FaceMeshGpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".FaceMeshGpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [
|
||||
":FaceMeshGpuAppLibrary",
|
||||
"@ios_opencv//:OpencvFramework",
|
||||
|
||||
@@ -12,14 +12,19 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
alias(
|
||||
name = "handdetectiongpu",
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "HandDetectionGpuApp",
|
||||
bundle_id = "com.google.mediapipe.HandDetectionGpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".HandDetectionGpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [
|
||||
":HandDetectionGpuAppLibrary",
|
||||
"@ios_opencv//:OpencvFramework",
|
||||
|
||||
@@ -16,6 +16,11 @@ load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "HandTrackingGpuApp",
|
||||
bundle_id = "com.google.mediapipe.HandTrackingGpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".HandTrackingGpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [
|
||||
":HandTrackingGpuAppLibrary",
|
||||
"@ios_opencv//:OpencvFramework",
|
||||
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2020 The MediaPipe Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Lint as: python3
|
||||
"""This script is used to set up automatic provisioning for iOS examples.
|
||||
|
||||
It scans the provisioning profiles used by Xcode, looking for one matching the
|
||||
application identifier for each example app. If found, it symlinks the profile
|
||||
in the appropriate location for Bazel to find it.
|
||||
|
||||
It also checks whether the bundle_id.bzl file has a placeholder bundle ID, and
|
||||
replaces it with a unique ID if so.
|
||||
"""
|
||||
|
||||
import os
|
||||
import plistlib
|
||||
import re
|
||||
import subprocess
|
||||
import uuid
|
||||
|
||||
# This script is meant to be located in the MediaPipe iOS examples directory
|
||||
# root. The logic below will have to be changed if the directory structure is
|
||||
# reorganized.
|
||||
examples_ios = os.path.dirname(os.path.realpath(__file__))
|
||||
example_names = {
|
||||
f for f in os.listdir(examples_ios)
|
||||
if os.path.isdir(os.path.join(examples_ios, f))
|
||||
}
|
||||
|
||||
|
||||
def configure_bundle_id_prefix(
|
||||
bundle_id_bzl=os.path.join(examples_ios, "bundle_id.bzl")) -> str:
|
||||
"""Configures the bundle id prefix to use.
|
||||
|
||||
Gets the bundle id prefix in use from bundle_id.bzl; sets up a unique
|
||||
prefix if not already set.
|
||||
|
||||
Args:
|
||||
bundle_id_bzl: Path to the bzl file where the bundle id is stored.
|
||||
|
||||
Returns:
|
||||
The bundle id prefix to use.
|
||||
|
||||
Raises:
|
||||
Exception: If parsing of bundle_id.bzl fails.
|
||||
"""
|
||||
bundle_id_re = re.compile(
|
||||
r'^BUNDLE_ID_PREFIX\s*=\s*"(.*)"', flags=re.MULTILINE)
|
||||
|
||||
with open(bundle_id_bzl, "r") as f:
|
||||
contents = f.read()
|
||||
match = bundle_id_re.search(contents)
|
||||
if not match:
|
||||
raise Exception("could not find BUNDLE_ID_PREFIX")
|
||||
|
||||
bundle_id_prefix = match.group(1)
|
||||
# The default value contains a *, which is an invalid character in bundle IDs.
|
||||
if "*" in bundle_id_prefix:
|
||||
bundle_id_prefix = str(uuid.uuid4()) + ".mediapipe.examples"
|
||||
contents = contents[:match.start(1)] + bundle_id_prefix + contents[match
|
||||
.end(1):]
|
||||
with open(bundle_id_bzl, "w") as f:
|
||||
f.write(contents)
|
||||
print("Set up a unique bundle ID prefix: " + bundle_id_prefix)
|
||||
|
||||
return bundle_id_prefix
|
||||
|
||||
|
||||
def get_app_id(profile_path) -> str:
|
||||
try:
|
||||
plist = subprocess.check_output(
|
||||
["security", "cms", "-D", "-i", profile_path])
|
||||
profile = plistlib.loads(plist)
|
||||
return profile["Entitlements"]["application-identifier"]
|
||||
except Exception: # pylint: disable=broad-except
|
||||
return None
|
||||
|
||||
|
||||
def update_symlink(target_path, link_path):
|
||||
if os.path.islink(link_path):
|
||||
print(f" Removing existing symlink at {link_path}")
|
||||
os.remove(link_path)
|
||||
elif os.path.exists(link_path):
|
||||
print(f" Unexpected existing file at {link_path}; skipping")
|
||||
return
|
||||
os.symlink(target_path, link_path)
|
||||
print(f" Created symlink to {target_path} at {link_path}")
|
||||
|
||||
|
||||
def process_profile(profile_path, our_app_id_re):
|
||||
"""Processes one mobileprovision file.
|
||||
|
||||
Checks if its app ID matches one of our example apps, and symlinks it in the
|
||||
appropriate location if so.
|
||||
|
||||
Args:
|
||||
profile_path: Path to the mobileprovision file.
|
||||
our_app_id_re: Regular expression to extract the example name from one of
|
||||
out app ids.
|
||||
"""
|
||||
app_id = get_app_id(profile_path)
|
||||
if not app_id:
|
||||
print(f"Could not parse '{profile_path}', skipping")
|
||||
return
|
||||
match = our_app_id_re.match(app_id)
|
||||
if not match:
|
||||
return
|
||||
app_name = match.group(1)
|
||||
app_dir_name = app_name.lower()
|
||||
if app_dir_name not in example_names:
|
||||
print(f"The app id '{app_id}' has our prefix, but does not seem to match" +
|
||||
"any of our examples. Skipping.")
|
||||
return
|
||||
|
||||
print(f"Found profile for {app_name}")
|
||||
|
||||
link_path = os.path.join(examples_ios, app_dir_name,
|
||||
"provisioning_profile.mobileprovision")
|
||||
update_symlink(profile_path, link_path)
|
||||
|
||||
|
||||
def main():
|
||||
bundle_id_prefix = configure_bundle_id_prefix()
|
||||
our_app_id_re = re.compile(r"[0-9A-Z]+\." + re.escape(bundle_id_prefix) +
|
||||
r"\.(.*)")
|
||||
|
||||
profile_dir = os.path.expanduser(
|
||||
"~/Library/MobileDevice/Provisioning Profiles")
|
||||
if not os.path.isdir(profile_dir):
|
||||
print(f"Could not find provisioning profiles directory at {profile_dir}")
|
||||
return 2
|
||||
|
||||
print(
|
||||
f"Looking for profiles for app ids with prefix '{bundle_id_prefix}' in '{profile_dir}'"
|
||||
)
|
||||
|
||||
for name in os.listdir(profile_dir):
|
||||
if not name.endswith(".mobileprovision"):
|
||||
continue
|
||||
profile_path = os.path.join(profile_dir, name)
|
||||
process_profile(profile_path, our_app_id_re)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -16,6 +16,11 @@ load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "MultiHandTrackingGpuApp",
|
||||
bundle_id = "com.google.mediapipe.MultiHandTrackingGpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".MultiHandTrackingGpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [
|
||||
":MultiHandTrackingGpuAppLibrary",
|
||||
"@ios_opencv//:OpencvFramework",
|
||||
|
||||
@@ -12,14 +12,19 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
alias(
|
||||
name = "objectdetectioncpu",
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "ObjectDetectionCpuApp",
|
||||
bundle_id = "com.google.mediapipe.ObjectDetectionCpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".ObjectDetectionCpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [
|
||||
":ObjectDetectionCpuAppLibrary",
|
||||
"@ios_opencv//:OpencvFramework",
|
||||
|
||||
@@ -12,14 +12,19 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
load(
|
||||
"@build_bazel_rules_apple//apple:ios.bzl",
|
||||
"ios_application",
|
||||
)
|
||||
load(
|
||||
"//mediapipe/examples/ios:bundle_id.bzl",
|
||||
"BUNDLE_ID_PREFIX",
|
||||
"example_provisioning",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
MIN_IOS_VERSION = "10.0"
|
||||
|
||||
alias(
|
||||
name = "objectdetectiongpu",
|
||||
@@ -28,14 +33,14 @@ alias(
|
||||
|
||||
ios_application(
|
||||
name = "ObjectDetectionGpuApp",
|
||||
bundle_id = "com.google.mediapipe.ObjectDetectionGpu",
|
||||
bundle_id = BUNDLE_ID_PREFIX + ".ObjectDetectionGpu",
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = ["Info.plist"],
|
||||
minimum_os_version = MIN_IOS_VERSION,
|
||||
provisioning_profile = "//mediapipe/examples/ios:provisioning_profile",
|
||||
provisioning_profile = example_provisioning(),
|
||||
deps = [
|
||||
":ObjectDetectionGpuAppLibrary",
|
||||
"@ios_opencv//:OpencvFramework",
|
||||
|
||||
Reference in New Issue
Block a user