Repository: fritzlabs/fritz-examples Branch: master Commit: 3a74ba7fd269 Files: 701 Total size: 1.9 MB Directory structure: gitextract_je7ujmkl/ ├── .gitattributes ├── .gitignore ├── .swiftlint.yml ├── Android/ │ ├── .gitignore │ ├── AnimatedSkyApp/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── animatedSky/ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── OverlayView.java │ │ │ └── res/ │ │ │ ├── drawable/ │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── round_button.xml │ │ │ ├── drawable-v24/ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout/ │ │ │ │ ├── activity_main.xml │ │ │ │ └── sky_fragment.xml │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── dimen.xml │ │ │ ├── fritz.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── BackgroundReplacementApp/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── replaceBackground/ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── OverlayView.java │ │ │ └── res/ │ │ │ ├── drawable/ │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── round_button.xml │ │ │ ├── drawable-v24/ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout/ │ │ │ │ ├── activity_main.xml │ │ │ │ └── camera_connection_fragment_background_replace.xml │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── dimen.xml │ │ │ ├── fritz.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── CameraBoilerplateApp/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ ├── androidTest/ │ │ │ │ └── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── camera/ │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java/ │ │ │ │ │ └── ai/ │ │ │ │ │ └── fritz/ │ │ │ │ │ └── camera/ │ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ │ ├── LiveCameraActivity.java │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── OverlayView.java │ │ │ │ └── res/ │ │ │ │ ├── drawable/ │ │ │ │ │ ├── ic_close.xml │ │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ │ └── round_button.xml │ │ │ │ ├── drawable-v24/ │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── layout/ │ │ │ │ │ ├── activity_main.xml │ │ │ │ │ ├── camera_connection_fragment.xml │ │ │ │ │ └── camera_connection_fragment_stylize.xml │ │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ └── values/ │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── fritz.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── test/ │ │ │ └── java/ │ │ │ └── ai/ │ │ │ └── fritz/ │ │ │ └── camera/ │ │ │ └── ExampleUnitTest.java │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── FritzAIStudio/ │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── app/ │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets/ │ │ │ │ ├── coco_labels_list.txt │ │ │ │ └── imagenet_comp_graph_label_strings.txt │ │ │ ├── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── aistudio/ │ │ │ │ ├── Navigation.java │ │ │ │ ├── PredictorType.java │ │ │ │ ├── activities/ │ │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ │ ├── BaseLiveVideoActivity.java │ │ │ │ │ ├── BaseRecordingActivity.java │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ ├── SplashActivity.java │ │ │ │ │ ├── custommodel/ │ │ │ │ │ │ ├── CustomTFLiteActivity.java │ │ │ │ │ │ └── ml/ │ │ │ │ │ │ ├── Classifier.java │ │ │ │ │ │ └── MnistClassifier.java │ │ │ │ │ └── vision/ │ │ │ │ │ ├── ImageLabelingActivity.java │ │ │ │ │ ├── ImageSegmentationActivity.java │ │ │ │ │ ├── ObjectDetectionActivity.java │ │ │ │ │ ├── PoseEstimationActivity.java │ │ │ │ │ └── StyleTransferActivity.java │ │ │ │ ├── adapters/ │ │ │ │ │ ├── DemoAdapter.java │ │ │ │ │ └── DemoItem.java │ │ │ │ ├── fragments/ │ │ │ │ │ └── CameraConnectionFragment.java │ │ │ │ ├── ui/ │ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ │ ├── ChooseModelDialog.java │ │ │ │ │ ├── DrawModel.java │ │ │ │ │ ├── DrawRenderer.java │ │ │ │ │ ├── DrawView.java │ │ │ │ │ ├── OverlayView.java │ │ │ │ │ ├── RecognitionScoreView.java │ │ │ │ │ ├── ResultsView.java │ │ │ │ │ └── SeparatorDecoration.java │ │ │ │ └── utils/ │ │ │ │ └── VideoProcessingQueue.java │ │ │ └── res/ │ │ │ ├── drawable/ │ │ │ │ ├── circle.xml │ │ │ │ ├── circle_white.xml │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_heartbeat_logo.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ ├── round_button.xml │ │ │ │ └── splash_bg.xml │ │ │ ├── drawable-v24/ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── font/ │ │ │ │ ├── sf_display.xml │ │ │ │ ├── sf_ui_display_bold.otf │ │ │ │ ├── sf_ui_display_light.otf │ │ │ │ └── sf_ui_display_regular.otf │ │ │ ├── layout/ │ │ │ │ ├── activity_camera.xml │ │ │ │ ├── activity_fritz_vision.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── activity_mnist.xml │ │ │ │ ├── activity_tfmobile_camera.xml │ │ │ │ ├── app_bar.xml │ │ │ │ ├── camera_connection_fragment.xml │ │ │ │ ├── camera_connection_fragment_recording.xml │ │ │ │ ├── camera_connection_fragment_stylize.xml │ │ │ │ ├── camera_connection_fragment_tracking.xml │ │ │ │ ├── camera_connection_snapshot.xml │ │ │ │ ├── list_item_demo.xml │ │ │ │ └── list_text_item.xml │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── custom_models.xml │ │ │ ├── dimens.xml │ │ │ ├── fritz.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── FritzVisionVideoApp/ │ │ ├── .gitignore │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ ├── androidTest/ │ │ │ │ └── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── fritzvisionvideo/ │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java/ │ │ │ │ │ └── ai/ │ │ │ │ │ └── fritz/ │ │ │ │ │ └── fritzvisionvideo/ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ ├── VideoActivity.java │ │ │ │ │ ├── strategies/ │ │ │ │ │ │ ├── MaskCutStrategy.java │ │ │ │ │ │ ├── ObjectPoseStrategy.java │ │ │ │ │ │ ├── PoseDoubleMaskStrategy.java │ │ │ │ │ │ ├── StylizeBackgroundStrategy.java │ │ │ │ │ │ ├── StylizeHairStrategy.java │ │ │ │ │ │ ├── VideoFilterStrategy.java │ │ │ │ │ │ └── customfilters/ │ │ │ │ │ │ └── StylizeHairFilter.java │ │ │ │ │ └── ui/ │ │ │ │ │ ├── DemoAdapter.java │ │ │ │ │ ├── DemoItem.java │ │ │ │ │ └── SeparatorDecoration.java │ │ │ │ └── res/ │ │ │ │ ├── drawable/ │ │ │ │ │ └── ic_launcher_background.xml │ │ │ │ ├── drawable-v24/ │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── font/ │ │ │ │ │ ├── sf_display.xml │ │ │ │ │ ├── sf_ui_display_bold.otf │ │ │ │ │ ├── sf_ui_display_light.otf │ │ │ │ │ └── sf_ui_display_regular.otf │ │ │ │ ├── layout/ │ │ │ │ │ ├── activity_main.xml │ │ │ │ │ ├── activity_video.xml │ │ │ │ │ ├── app_bar.xml │ │ │ │ │ └── list_item_demo.xml │ │ │ │ ├── menu/ │ │ │ │ │ └── video_menu.xml │ │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ └── values/ │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── fritz.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── test/ │ │ │ └── java/ │ │ │ └── ai/ │ │ │ └── fritz/ │ │ │ └── fritzvisionvideo/ │ │ │ └── ExampleUnitTest.java │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── HairColoringApp/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ ├── androidTest/ │ │ │ │ └── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── haircoloring/ │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java/ │ │ │ │ │ └── ai/ │ │ │ │ │ └── fritz/ │ │ │ │ │ └── haircoloring/ │ │ │ │ │ ├── activities/ │ │ │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ │ │ ├── BaseLiveGPUActivity.java │ │ │ │ │ │ ├── LiveHairColorActivity.java │ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ │ └── VideoHairColorActivity.java │ │ │ │ │ ├── ui/ │ │ │ │ │ │ ├── DemoAdapter.java │ │ │ │ │ │ ├── DemoItem.java │ │ │ │ │ │ └── SeparatorDecoration.java │ │ │ │ │ └── views/ │ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ │ └── OverlayView.java │ │ │ │ └── res/ │ │ │ │ ├── drawable/ │ │ │ │ │ ├── ic_close.xml │ │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ │ └── round_button.xml │ │ │ │ ├── drawable-v24/ │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── font/ │ │ │ │ │ ├── sf_display.xml │ │ │ │ │ ├── sf_ui_display_bold.otf │ │ │ │ │ ├── sf_ui_display_light.otf │ │ │ │ │ └── sf_ui_display_regular.otf │ │ │ │ ├── layout/ │ │ │ │ │ ├── activity_camera.xml │ │ │ │ │ ├── activity_main.xml │ │ │ │ │ ├── activity_video.xml │ │ │ │ │ ├── camera_color_slider.xml │ │ │ │ │ ├── camera_connection_fragment.xml │ │ │ │ │ └── list_item_demo.xml │ │ │ │ ├── menu/ │ │ │ │ │ └── video_menu.xml │ │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ └── values/ │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── fritz.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── test/ │ │ │ └── java/ │ │ │ └── ai/ │ │ │ └── fritz/ │ │ │ └── haircoloring/ │ │ │ └── ExampleUnitTest.java │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── ImageLabelingApp/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets/ │ │ │ │ ├── image_labeling_quantized_model.tflite │ │ │ │ └── label_recording_model.json │ │ │ ├── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── camera/ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── OverlayView.java │ │ │ └── res/ │ │ │ ├── drawable/ │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── round_button.xml │ │ │ ├── drawable-v24/ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout/ │ │ │ │ ├── activity_main.xml │ │ │ │ ├── camera_connection_fragment.xml │ │ │ │ ├── main_camera.xml │ │ │ │ ├── snapshot_button.xml │ │ │ │ └── snapshot_overlay_frame.xml │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── fritz.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── ObjectDetectionApp/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets/ │ │ │ │ ├── detect.tflite │ │ │ │ └── object_recording_model.json │ │ │ ├── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── camera/ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── OverlayView.java │ │ │ └── res/ │ │ │ ├── drawable/ │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── round_button.xml │ │ │ ├── drawable-v24/ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout/ │ │ │ │ ├── activity_main.xml │ │ │ │ ├── camera_connection_fragment.xml │ │ │ │ ├── main_camera.xml │ │ │ │ ├── snapshot_button.xml │ │ │ │ └── snapshot_overlay_frame.xml │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── fritz.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── PetMonitoringApp/ │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── petdetector/ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── OverlayView.java │ │ │ └── res/ │ │ │ ├── drawable/ │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── ic_warning.xml │ │ │ ├── drawable-v24/ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout/ │ │ │ │ ├── activity_main.xml │ │ │ │ └── camera_connection_fragment_stylize.xml │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── fritz.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── PetStickerApp/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── petSticker/ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── OverlayView.java │ │ │ └── res/ │ │ │ ├── drawable/ │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── round_button.xml │ │ │ ├── drawable-v24/ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout/ │ │ │ │ ├── activity_main.xml │ │ │ │ └── camera_connection_fragment_pet_sticker.xml │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── dimen.xml │ │ │ ├── fritz.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── PoseEstimationApp/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets/ │ │ │ │ ├── PoseMobilenet353x25758Large1565627685.tflite │ │ │ │ └── pose_recording_model.json │ │ │ ├── java/ │ │ │ │ └── ai/ │ │ │ │ └── fritz/ │ │ │ │ └── camera/ │ │ │ │ ├── AutoFitTextureView.java │ │ │ │ ├── BaseCameraActivity.java │ │ │ │ ├── CameraConnectionFragment.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── OverlayView.java │ │ │ └── res/ │ │ │ ├── drawable/ │ │ │ │ ├── ic_close.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── round_button.xml │ │ │ ├── drawable-v24/ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout/ │ │ │ │ ├── activity_main.xml │ │ │ │ ├── camera_connection_fragment.xml │ │ │ │ ├── main_camera.xml │ │ │ │ ├── snapshot_button.xml │ │ │ │ └── snapshot_overlay_frame.xml │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── fritz.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ └── README.md ├── LICENSE ├── README.md ├── SnapLensStudio/ │ └── README.md └── iOS/ ├── .gitignore ├── FritzAIStudio/ │ ├── FritzAIStudio/ │ │ ├── Media/ │ │ │ ├── Assets.xcassets/ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ └── Contents.json │ │ │ │ ├── Contents.json │ │ │ │ ├── SettingsIcon.imageset/ │ │ │ │ │ └── Contents.json │ │ │ │ └── fritzLogo.imageset/ │ │ │ │ └── Contents.json │ │ │ └── Base.lproj/ │ │ │ └── LaunchScreen.storyboard │ │ ├── Source/ │ │ │ ├── Delegate/ │ │ │ │ └── AppDelegate.swift │ │ │ ├── FritzCamera/ │ │ │ │ ├── FritzCamera/ │ │ │ │ │ ├── Delegates/ │ │ │ │ │ │ ├── CameraAVCaptureVideoDelegate.swift │ │ │ │ │ │ └── CapturePhotoDelgate.swift │ │ │ │ │ ├── Extensions/ │ │ │ │ │ │ ├── AVPhotoExtension.swift │ │ │ │ │ │ ├── CameraResolutionExtension.swift │ │ │ │ │ │ ├── CameraSessionExtensions.swift │ │ │ │ │ │ ├── FritzCamera+CaptureDeviceExtensions.swift │ │ │ │ │ │ ├── FritzCamera+Focus.swift │ │ │ │ │ │ └── PhotoCaptureExtensions.swift │ │ │ │ │ └── FritzCamera.swift │ │ │ │ └── FritzCameraUI/ │ │ │ │ ├── CameraDelegateImplmentation.swift │ │ │ │ ├── Extensions/ │ │ │ │ │ ├── ButtonFunctionality.swift │ │ │ │ │ ├── CameraInterfaceHandler.swift │ │ │ │ │ ├── DebugImageExtensions.swift │ │ │ │ │ ├── FocusExtension.swift │ │ │ │ │ └── GestureReconizerDelegateExtension.swift │ │ │ │ ├── FritzCameraButton.swift │ │ │ │ ├── FritzCameraControllerDelegate.swift │ │ │ │ ├── FritzCameraViewController.swift │ │ │ │ ├── FritzTextPromptView.swift │ │ │ │ ├── Media.xcassets/ │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── cameraFocus.imageset/ │ │ │ │ │ │ └── Contents.json │ │ │ │ │ ├── cameraSwitch.imageset/ │ │ │ │ │ │ └── Contents.json │ │ │ │ │ ├── cameraTorchAuto.imageset/ │ │ │ │ │ │ └── Contents.json │ │ │ │ │ ├── cameraTorchOff.imageset/ │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── cameraTorchOn.imageset/ │ │ │ │ │ └── Contents.json │ │ │ │ └── Shaders/ │ │ │ │ ├── DepthToGrayscale.metal │ │ │ │ ├── Mixer.metal │ │ │ │ ├── PassThrough.metal │ │ │ │ └── RosyEffect.metal │ │ │ └── Modules/ │ │ │ ├── Common/ │ │ │ │ ├── AIStudioFeaturePredictors.swift │ │ │ │ ├── AIStudioImagePredictor.swift │ │ │ │ ├── FritzModelDetails.swift │ │ │ │ ├── ImagePredictorProtocol.swift │ │ │ │ ├── Logging/ │ │ │ │ │ ├── Locks.swift │ │ │ │ │ ├── LogHandler.swift │ │ │ │ │ └── Logging.swift │ │ │ │ ├── ModelGroupManager.swift │ │ │ │ ├── PredictorOptionTypes.swift │ │ │ │ └── Utils/ │ │ │ │ ├── FritzDeviceUtil.swift │ │ │ │ └── FritzLogger.swift │ │ │ ├── Demos/ │ │ │ │ ├── Cells/ │ │ │ │ │ ├── DemoTableViewCell.swift │ │ │ │ │ └── LinkTableViewCell.swift │ │ │ │ ├── Demos.storyboard │ │ │ │ ├── DemosViewController.swift │ │ │ │ └── NavigationController.swift │ │ │ ├── FeatureController/ │ │ │ │ ├── ChooseModelController.swift │ │ │ │ ├── ConfigureModelCells/ │ │ │ │ │ ├── ChooseColorCell.swift │ │ │ │ │ ├── ChooseColorCell.xib │ │ │ │ │ ├── ChooseModelCell.swift │ │ │ │ │ ├── ChooseModelCell.xib │ │ │ │ │ ├── RangeSliderCell.swift │ │ │ │ │ ├── RangeSliderCell.xib │ │ │ │ │ ├── SegmentSliderCell.swift │ │ │ │ │ └── SegmentSliderCell.xib │ │ │ │ ├── ConfigurePopover.swift │ │ │ │ ├── Extensions/ │ │ │ │ │ ├── NavigationBarCustomization.swift │ │ │ │ │ └── SettingsButtonInteractionExtension.swift │ │ │ │ ├── FeatureContainer.xib │ │ │ │ ├── FeatureOptions.swift │ │ │ │ ├── FeatureViewController.swift │ │ │ │ ├── ModelOptions.storyboard │ │ │ │ └── SettingsButton.swift │ │ │ ├── ImageSegmentation/ │ │ │ │ └── ImageSegFeature.swift │ │ │ ├── ModelExtensions/ │ │ │ │ ├── ImageSegmentationFeature.swift │ │ │ │ └── PoseEstimation+ImagePredictor.swift │ │ │ ├── PredictorControllers/ │ │ │ │ ├── DetectObjects/ │ │ │ │ │ ├── DetectObjectsStoryboard.storyboard │ │ │ │ │ └── DetectObjectsViewController.swift │ │ │ │ ├── HairColor+ColorSlider.swift │ │ │ │ ├── HairColorViewController.swift │ │ │ │ ├── ImageSegmentationViewController.swift │ │ │ │ ├── LabelImages/ │ │ │ │ │ ├── FritzVisionLabelViewController.swift │ │ │ │ │ └── LabelImages.storyboard │ │ │ │ ├── PoseEstimationViewController.swift │ │ │ │ └── StyleTransferViewController.swift │ │ │ └── Root/ │ │ │ ├── Root.storyboard │ │ │ └── RootViewController.swift │ │ └── Supporting Files/ │ │ └── Info.plist │ ├── FritzAIStudio.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FritzAIStudio.xcscheme │ ├── LICENSE │ ├── Podfile │ ├── README.md │ └── fastlane/ │ ├── Appfile │ ├── Deliverfile │ └── Fastfile ├── FritzARKitDemo/ │ ├── ARKIt+Utilities.swift │ ├── FritzARKitDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── ObjectDetectionViewController.swift │ │ ├── SCNVector+Extensions.swift │ │ ├── Utils.swift │ │ ├── ViewController.swift │ │ └── art.scnassets/ │ │ ├── box.scn │ │ └── ship.scn │ ├── FritzARKitDemo.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FritzARKitDemo.xcscheme │ ├── Podfile │ └── README.md ├── FritzHairColorDemo/ │ ├── FritzHairColorDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Controllers/ │ │ │ ├── HairPredictor.swift │ │ │ ├── LiveHairViewController.swift │ │ │ ├── NavigationController.swift │ │ │ ├── VideoHairViewController.swift │ │ │ └── ViewController.swift │ │ ├── Info.plist │ │ ├── Storyboards/ │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── LiveHairColorStoryboard.storyboard │ │ │ ├── Main.storyboard │ │ │ └── VideoHairViewStoryboard.storyboard │ │ └── UI/ │ │ ├── DemoTableViewCell.swift │ │ ├── LinkTableViewCell.swift │ │ └── VideoPicker.swift │ ├── FritzHairColorDemo.xcodeproj/ │ │ └── project.pbxproj │ ├── Podfile │ └── README.md ├── FritzHandPoseEstimationDemo/ │ ├── FritzHandPoseEstimationDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── CameraButton.swift │ │ ├── DraggableKeypoint.swift │ │ ├── HandPose.mlmodel │ │ ├── HandPoseModel.swift │ │ ├── Info.plist │ │ ├── UIImageView+Transformations.swift │ │ └── ViewController.swift │ ├── FritzHandPoseEstimationDemo.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FritzHandPoseEstimationDemo.xcscheme │ ├── Podfile │ └── README.md ├── FritzImageLabelingDemo/ │ ├── FritzImageLabelingDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── SceneDelegate.swift │ │ └── ViewController.swift │ ├── FritzImageLabelingDemo.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FritzImageLabelingDemo.xcscheme │ ├── Podfile │ └── README.md ├── FritzImageSegmentationDemo/ │ ├── FritzImageSegmentationDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── CustomBlurView.swift │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── FritzImageSegmentationDemo.xcodeproj/ │ │ └── project.pbxproj │ ├── Podfile │ └── README.md ├── FritzMaskRecognitionDemo/ │ ├── FritzMaskRecognitionDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── MaskRecognition.mlmodel │ │ ├── SceneDelegate.swift │ │ └── ViewController.swift │ ├── FritzMaskRecognitionDemo.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FritzMaskRecognitionDemo.xcscheme │ ├── Podfile │ └── README.md ├── FritzObjectDetectionDemo/ │ ├── FritzObjectDetectionDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── SceneDelegate.swift │ │ └── ViewController.swift │ ├── FritzObjectDetectionDemo.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FritzObjectDetectionDemo.xcscheme │ └── Podfile ├── FritzPetStickerDemo/ │ ├── FritzPetStickerDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── FritzPetStickerDemo.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── FritzPetStickerDemo.xcscheme │ ├── Podfile │ └── README.md ├── FritzPizzaDetectorDemo/ │ ├── Final/ │ │ ├── FritzPizzaDetectorDemo/ │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets/ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ └── Contents.json │ │ │ │ ├── Contents.json │ │ │ │ └── pizza.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ ├── Info.plist │ │ │ └── ViewController.swift │ │ ├── FritzPizzaDetectorDemo.xcodeproj/ │ │ │ └── project.pbxproj │ │ └── Podfile │ ├── README.md │ └── Starter/ │ ├── FritzPizzaDetectorDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ └── pizza.imageset/ │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── FritzPizzaDetectorDemo.xcodeproj/ │ │ └── project.pbxproj │ └── Podfile ├── FritzPoseEstimationDemo/ │ ├── FritzPoseEstimationDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── FritzPoseEstimationDemo.xcodeproj/ │ │ └── project.pbxproj │ ├── Podfile │ └── README.md ├── FritzSkyReplacementDemo/ │ ├── FritzSkyReplacementDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── FritzSkyReplacementDemo.xcodeproj/ │ │ └── project.pbxproj │ ├── Podfile │ └── README.md ├── FritzStyleTransferDemo/ │ ├── FritzStyleTransferDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── FritzStyleTransferDemo.xcodeproj/ │ │ └── project.pbxproj │ ├── Podfile │ └── README.md ├── FritzVisionVideoDemo/ │ ├── FritzVisionVideoDemo/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ └── ExportIcon.imageset/ │ │ │ └── Contents.json │ │ ├── Controllers/ │ │ │ ├── NavigationController.swift │ │ │ ├── SingleScreenViewController.swift │ │ │ ├── SplitScreenViewController.swift │ │ │ ├── Strategies/ │ │ │ │ ├── DoubleStyleStrategy.swift │ │ │ │ ├── FemmesStrategy.swift │ │ │ │ ├── ObjectPoseStrategy.swift │ │ │ │ ├── PoseDoubleMaskStrategy.swift │ │ │ │ ├── ScreamStrategy.swift │ │ │ │ ├── StyleOptionStrategy.swift │ │ │ │ ├── StylizeBackgroundStrategy.swift │ │ │ │ ├── StylizeHairStrategy.swift │ │ │ │ └── VideoOptionStrategy.swift │ │ │ └── ViewController.swift │ │ ├── Info.plist │ │ ├── SceneDelegate.swift │ │ ├── Storyboards/ │ │ │ ├── LaunchScreen.storyboard │ │ │ ├── Main.storyboard │ │ │ ├── SingleScreenStoryboard.storyboard │ │ │ └── SplitScreenStoryboard.storyboard │ │ └── Utils/ │ │ └── StylizeHairMaskFilter.swift │ ├── FritzVisionVideoDemo.xcodeproj/ │ │ └── project.pbxproj │ ├── Podfile │ └── README.md └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ *.zip filter=lfs diff=lfs merge=lfs -text ================================================ FILE: .gitignore ================================================ #### CocoaPods Pods/ *.generated.swift #### Fastlane fastlane/report.xml fastlane/README.md #### macOS .DS_Store #### Xcode xcuserdata/ *.xcworkspace iOS/*.zip *.ipa # For rswift build workaround rswift.workaround.file *.Framework/ [Ll]ibrary/ [Tt]emp/ [Oo]bj/ [Bb]uild/ [Bb]uilds/ Assets/AssetStoreTools* # Visual Studio cache directory .vs/ # Autogenerated VS/MD/Consulo solution and project files ExportedObj/ .consulo/ *.csproj *.unityproj *.sln *.suo *.tmp *.user *.userprefs *.pidb *.booproj *.svd *.pdb *.opendb # Unity3D generated meta files *.pidb.meta *.pdb.meta # Unity3D Generated File On Crash Reports sysinfo.txt # Builds *.apk *.unitypackage *.Framework/ *.framework.meta .DS_Store FritzConfig.asset FritzConfig.asset.meta # excluding local python version .python-version ================================================ FILE: .swiftlint.yml ================================================ included: - Heartbeat/Source excluded: - Pods - Supporting Files opt_in_rules: - attributes - closure_end_indentation - empty_count - explicit_top_level_acl - force_unwrapping disabled_rules: - explicit_top_level_acl - line_length ================================================ FILE: Android/.gitignore ================================================ # Built application files *.apk *.ap_ # Files for the ART/Dalvik VM *.dex # Java class files *.class # Generated files bin/ gen/ out/ # Gradle files .gradle/ build/ gradle/ # Local configuration file (sdk path, etc) local.properties # Proguard folder generated by Eclipse proguard/ # Log Files *.log # Android Studio Navigation editor temp files .navigation/ # Android Studio captures folder captures/ # Intellij *.iml .idea # Keystore files *.jks # External native build folder generated in Android Studio 2.2 and later .externalNativeBuild # Google Services (e.g. APIs or Firebase) google-services.json # Freeline freeline.py freeline/ freeline_project_description.json .DS_Store ================================================ FILE: Android/AnimatedSkyApp/.gitignore ================================================ # Built application files *.apk *.ap_ # Files for the ART/Dalvik VM *.dex # Java class files *.class # Generated files bin/ gen/ out/ # Gradle files .gradle/ build/ # Local configuration file (sdk path, etc) local.properties # Proguard folder generated by Eclipse proguard/ # Log Files *.log # Android Studio Navigation editor temp files .navigation/ # Android Studio captures folder captures/ # IntelliJ *.iml .idea # Keystore files # Uncomment the following line if you do not want to check your keystore files in. #*.jks # External native build folder generated in Android Studio 2.2 and later .externalNativeBuild # Google Services (e.g. APIs or Firebase) google-services.json # Freeline freeline.py freeline/ freeline_project_description.json # fastlane fastlane/report.xml fastlane/Preview.html fastlane/screenshots fastlane/test_output fastlane/readme.md ================================================ FILE: Android/AnimatedSkyApp/README.md ================================================ # Animations with Sky Segmentation [ ![Codeship Status for fritzlabs/fritz-sdk-android](https://app.codeship.com/projects/c74152e0-65d1-0136-2d69-32e87736c6c6/status?branch=master)](https://app.codeship.com/projects/297281) [![Twitter](https://img.shields.io/badge/twitter-@fritzlabs-blue.svg?style=flat)](http://twitter.com/fritzlabs) In this app, we create a simple photo app to replace the sky with an animation. ![](images/skyani.gif) This example app uses the on-device Image Segmentation API with the Sky Segmentation Model for Android. - [Overview](https://www.fritz.ai/features/image-segmentation.html?utm_source=github&utm_campaign=fritz-examples) - [Documentation](https://docs.fritz.ai/develop/vision/image-segmentation/android.html?utm_source=github&utm_campaign=fritz-examples) ## Fritz AI Fritz AI is the machine learning platform for iOS and Android developers. Teach your mobile apps to see, hear, sense, and think. Start with our ready-to-use feature APIs or connect and deploy your own custom models. ## Requirements - Android Studio 3.2 or above - Android device in developer model (USB debugging enabled) ## Getting Started **Step 1: Choose a Fritz AI Plan** [Sign up](https://www.fritz.ai/pricing/?utm_source=github&utm_campaign=fritz-examples) for a Fritz AI plan to get started. Register the Android app in your Fritz account with the package id "ai.fritz.animatedSky". During registration, you'll receive an API key for the app. Save this for later. To find it in the webapp, you can go to Project Settings > Apps > Your App > Show API Key. **Step 2: Clone / Fork the fritz-examples repository and open the AnimatedSkyApp app in Android Studio** ``` git clone https://github.com/fritzlabs/fritz-examples.git ``` In Android Studio, choose "Open an existing Android Studio project" and select `AnimatedSkyApp`. **Step 3: Edit the fritz.xml file with your API Key** In app/src/main/res/values/fritz.xml, change the fritz_api_key attribute with the one you received in step 1. **Step 4: Build the Android Studio Project** Select "Build > Make Project" from the top nav. Download any missing libraries if applicable. This should sync the gradle dependencies so give the build a second to complete. **Step 5: Install the app onto your device** With your Android device connected, select `Run > Run App` from the top nav. When running the app for the first time, you'll have to give permissions to access the camera. After the app is installed and running, take a picture outside and watch as we replace the sky with an animated image. ## Official Documentation [SDK Documentation](https://docs.fritz.ai/?utm_source=github&utm_campaign=fritz-examples) [Android API Docs](https://docs.fritz.ai/android/latest/index.html?utm_source=github&utm_campaign=fritz-examples) ## Join the community [Heartbeat](https://heartbeat.fritz.ai/?utm_source=github&utm_campaign=fritz-examples) is a community of developers interested in the intersection of mobile and machine learning. [Chat with us in Slack](https://www.fritz.ai/slack?utm_source=github&utm_campaign=fritz-examples) and stay up to date on the latest mobile ML news with our [Newsletter](https://www.fritz.ai/newsletter?utm_source=github&utm_campaign=fritz-examples). ## Help For any questions or issues, you can: - Submit an issue on this repo - Go to [Support](https://support.fritz.ai/?utm_source=github&utm_campaign=fritz-examples) - Message us directly in [Slack](https://www.fritz.ai/slack?utm_source=github&utm_campaign=fritz-examples) ================================================ FILE: Android/AnimatedSkyApp/app/.gitignore ================================================ /build ================================================ FILE: Android/AnimatedSkyApp/app/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { // MUST MATCH THE APPLICATION YOU CREATE IN FRITZ applicationId "ai.fritz.animatedSky" minSdkVersion 24 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { debug { debuggable true } release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } aaptOptions { noCompress "tflite" } lintOptions { abortOnError false } } dependencies { implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation "ai.fritz:vision:6.0.3" implementation "ai.fritz:vision-sky-segmentation-model-fast:3.0.0" testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } ================================================ FILE: Android/AnimatedSkyApp/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the # proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Uncomment this to preserve the line number information for # debugging stack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile ================================================ FILE: Android/AnimatedSkyApp/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: Android/AnimatedSkyApp/app/src/main/java/ai/fritz/animatedSky/AutoFitTextureView.java ================================================ package ai.fritz.animatedSky; import android.content.Context; import android.util.AttributeSet; import android.view.TextureView; /** * A {@link TextureView} that can be adjusted to a specified aspect ratio. */ public class AutoFitTextureView extends TextureView { private int mRatioWidth = 0; private int mRatioHeight = 0; public AutoFitTextureView(Context context) { this(context, null); } public AutoFitTextureView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio * calculated from the parameters. Note that the actual sizes of parameters don't matter, that * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. * * @param width Relative horizontal size * @param height Relative vertical size */ public void setAspectRatio(int width, int height) { if (width < 0 || height < 0) { throw new IllegalArgumentException("Size cannot be negative."); } mRatioWidth = width; mRatioHeight = height; requestLayout(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (0 == mRatioWidth || 0 == mRatioHeight) { setMeasuredDimension(width, height); return; } if (width < height * mRatioWidth / mRatioHeight) { setMeasuredDimension(width, width * mRatioHeight / mRatioWidth); return; } setMeasuredDimension(height * mRatioWidth / mRatioHeight, height); } } ================================================ FILE: Android/AnimatedSkyApp/app/src/main/java/ai/fritz/animatedSky/BaseCameraActivity.java ================================================ package ai.fritz.animatedSky; import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraManager; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.ImageReader.OnImageAvailableListener; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; import android.util.Log; import android.util.Size; import android.view.KeyEvent; import android.view.WindowManager; import android.widget.Toast; public abstract class BaseCameraActivity extends AppCompatActivity implements OnImageAvailableListener { private static final String TAG = BaseCameraActivity.class.getSimpleName(); private static int MAX_WIDTH = 500; private static final int PERMISSIONS_REQUEST = 1; private static final String PERMISSION_CAMERA = Manifest.permission.CAMERA; private static final String PERMISSION_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE; private boolean useCamera2API; private boolean debug = false; private Handler handler; private HandlerThread handlerThread; protected String cameraId; protected int cameraFacingDirection = CameraCharacteristics.LENS_FACING_BACK; @Override protected void onCreate(final Bundle savedInstanceState) { Log.d(TAG, "onCreate " + this); super.onCreate(null); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.activity_main); if (hasPermission()) { setFragment(); } else { requestPermission(); } } @Override public synchronized void onStart() { Log.d(TAG, "onStart " + this); super.onStart(); } @Override public synchronized void onResume() { Log.d(TAG, "onResume " + this); super.onResume(); handlerThread = new HandlerThread("inference"); handlerThread.start(); handler = new Handler(handlerThread.getLooper()); } @Override public synchronized void onPause() { Log.d(TAG, "onPause " + this); handlerThread.quitSafely(); try { handlerThread.join(); handlerThread = null; handler = null; } catch (final InterruptedException e) { Log.e(TAG, "Exception!" + e); } super.onPause(); } @Override public synchronized void onStop() { Log.d(TAG, "onStop " + this); super.onStop(); } @Override public synchronized void onDestroy() { Log.d(TAG, "onDestroy " + this); super.onDestroy(); } protected int getCameraFacingDirection() { return cameraFacingDirection; } protected synchronized void runInBackground(final Runnable r) { if (handler != null) { handler.post(r); } } @Override public void onRequestPermissionsResult( final int requestCode, final String[] permissions, final int[] grantResults) { switch (requestCode) { case PERMISSIONS_REQUEST: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { setFragment(); } else { requestPermission(); } } } } private boolean hasPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { boolean cameraPermission = checkSelfPermission(PERMISSION_CAMERA) == PackageManager.PERMISSION_GRANTED; return cameraPermission; } else { return true; } } private void requestPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (shouldShowRequestPermissionRationale(PERMISSION_CAMERA) || shouldShowRequestPermissionRationale(PERMISSION_STORAGE)) { Toast.makeText(BaseCameraActivity.this, "Camera AND storage permission are required for this demo", Toast.LENGTH_LONG).show(); } requestPermissions(new String[]{PERMISSION_CAMERA, PERMISSION_STORAGE}, PERMISSIONS_REQUEST); } } protected void setFragment() { cameraId = chooseCamera(); final CameraConnectionFragment fragment = CameraConnectionFragment.newInstance( new CameraConnectionFragment.ConnectionCallback() { @Override public void onPreviewSizeChosen(final Size previewSize, final Size cameraViewSize, final int rotation) { BaseCameraActivity.this.onPreviewSizeChosen(previewSize, cameraViewSize, rotation); } }, this, getLayoutId(), getDesiredPreviewFrameSize()); fragment.setCamera(cameraId); getFragmentManager() .beginTransaction() .replace(R.id.camera_container, fragment) .commit(); } protected void toggleCameraFacingDirection() { if (cameraFacingDirection == CameraCharacteristics.LENS_FACING_FRONT) { cameraFacingDirection = CameraCharacteristics.LENS_FACING_BACK; } else { cameraFacingDirection = CameraCharacteristics.LENS_FACING_FRONT; } setFragment(); } private String chooseCamera() { final CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { for (final String cameraId : manager.getCameraIdList()) { final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); // We don't use a front facing camera in this sample. final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); if (facing != null && facing != cameraFacingDirection) { continue; } final StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); if (map == null) { continue; } // Fallback to camera1 API for internal cameras that don't have full support. // This should help with legacy situations where using the camera2 API causes // distorted or otherwise broken previews. useCamera2API = (facing == CameraCharacteristics.LENS_FACING_EXTERNAL) || isHardwareLevelSupported(characteristics, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL); Log.i(TAG, "Camera API lv2?: " + useCamera2API); return cameraId; } } catch (CameraAccessException e) { Log.e(TAG, "Not allowed to access camera: " + e); } return null; } // Returns true if the device supports the required hardware level, or better. private boolean isHardwareLevelSupported( CameraCharacteristics characteristics, int requiredLevel) { int deviceLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) { return requiredLevel == deviceLevel; } // deviceLevel is not LEGACY, can use numerical sort return requiredLevel <= deviceLevel; } public boolean isDebug() { return debug; } public void requestRender() { final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay); if (overlay != null) { overlay.postInvalidate(); } } public void setCallback(final OverlayView.DrawCallback callback) { final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay); if (overlay != null) { overlay.setCallback(callback); } } public void onSetDebug(final boolean debug) { } @Override public boolean onKeyDown(final int keyCode, final KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { debug = !debug; requestRender(); onSetDebug(debug); return true; } return super.onKeyDown(keyCode, event); } protected abstract void onPreviewSizeChosen(final Size previewSize, final Size cameraViewSize, final int rotation); protected abstract int getLayoutId(); protected Size getDesiredPreviewFrameSize() { DisplayMetrics metrics = getResources().getDisplayMetrics(); float ratio = (float) metrics.heightPixels / metrics.widthPixels; return new Size(MAX_WIDTH, (int) ratio * MAX_WIDTH); } } ================================================ FILE: Android/AnimatedSkyApp/app/src/main/java/ai/fritz/animatedSky/CameraConnectionFragment.java ================================================ package ai.fritz.animatedSky; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.Fragment; import android.content.Context; import android.content.DialogInterface; import android.graphics.ImageFormat; import android.graphics.Matrix; import android.graphics.RectF; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.ImageReader; import android.media.ImageReader.OnImageAvailableListener; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.text.TextUtils; import android.util.Log; import android.util.Size; import android.view.LayoutInflater; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class CameraConnectionFragment extends Fragment { private static final String TAG = CameraConnectionFragment.class.getSimpleName(); public CameraConnectionFragment() { } /** * The camera preview size will be chosen to be the smallest frame by pixel size capable of * containing a DESIRED_SIZE x DESIRED_SIZE square. */ private static final int MINIMUM_PREVIEW_SIZE = 320; /** * Conversion from screen rotation to JPEG orientation. */ private static final String FRAGMENT_DIALOG = "dialog"; /** * {@link android.view.TextureView.SurfaceTextureListener} handles several lifecycle events on a * {@link TextureView}. */ private final TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable( final SurfaceTexture texture, final int width, final int height) { openCamera(width, height); } @Override public void onSurfaceTextureSizeChanged( final SurfaceTexture texture, final int width, final int height) { configureTransform(width, height); } @Override public boolean onSurfaceTextureDestroyed(final SurfaceTexture texture) { return true; } @Override public void onSurfaceTextureUpdated(final SurfaceTexture texture) { } }; /** * Callback for Activities to use to initialize their data once the * selected preview size is known. */ public interface ConnectionCallback { void onPreviewSizeChosen(Size size, Size cameraViewSize, int cameraRotation); } /** * ID of the current {@link CameraDevice}. */ private String cameraId; /** * An {@link AutoFitTextureView} for camera preview. */ private AutoFitTextureView textureView; /** * A {@link CameraCaptureSession } for camera preview. */ private CameraCaptureSession captureSession; /** * A reference to the opened {@link CameraDevice}. */ private CameraDevice cameraDevice; /** * The rotation in degrees of the camera sensor from the display. */ private Integer sensorOrientation; /** * The {@link android.util.Size} of camera preview. */ private Size previewSize; /** * {@link android.hardware.camera2.CameraDevice.StateCallback} * is called when {@link CameraDevice} changes its state. */ private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(final CameraDevice cd) { // This method is called when the camera is opened. We start camera preview here. cameraOpenCloseLock.release(); cameraDevice = cd; createCameraPreviewSession(); } @Override public void onDisconnected(final CameraDevice cd) { cameraOpenCloseLock.release(); cd.close(); cameraDevice = null; } @Override public void onError(final CameraDevice cd, final int error) { cameraOpenCloseLock.release(); cd.close(); cameraDevice = null; final Activity activity = getActivity(); if (null != activity) { activity.finish(); } } }; /** * An additional thread for running tasks that shouldn't block the UI. */ private HandlerThread backgroundThread; /** * A {@link Handler} for running tasks in the background. */ private Handler backgroundHandler; /** * An {@link ImageReader} that handles preview frame capture. */ private ImageReader previewReader; /** * {@link android.hardware.camera2.CaptureRequest.Builder} for the camera preview */ private CaptureRequest.Builder previewRequestBuilder; /** * {@link CaptureRequest} generated by {@link #previewRequestBuilder} */ private CaptureRequest previewRequest; /** * A {@link Semaphore} to prevent the app from exiting before closing the camera. */ private final Semaphore cameraOpenCloseLock = new Semaphore(1); /** * A {@link OnImageAvailableListener} to receive frames as they are available. */ private OnImageAvailableListener imageListener = null; /** * The input size in pixels desired by TensorFlow (width and height of a square bitmap). */ private Size inputSize = null; /** * The layout identifier to inflate for this Fragment. */ private int layout = -1; private ConnectionCallback cameraConnectionCallback = null; private CameraConnectionFragment( final ConnectionCallback connectionCallback, final OnImageAvailableListener imageListener, final int layout, final Size inputSize) { this.cameraConnectionCallback = connectionCallback; this.imageListener = imageListener; this.layout = layout; this.inputSize = inputSize; } /** * Shows a {@link Toast} on the UI thread. * * @param text The message to show */ private void showToast(final String text) { final Activity activity = getActivity(); if (activity != null) { activity.runOnUiThread( new Runnable() { @Override public void run() { Toast.makeText(activity, text, Toast.LENGTH_SHORT).show(); } }); } } /** * Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose * width and height are at least as large as the minimum of both, or an exact match if possible. * * @param choices The list of sizes that the camera supports for the intended output class * @param width The minimum desired width * @param height The minimum desired height * @return The optimal {@code Size}, or an arbitrary one if none were big enough */ protected static Size chooseOptimalSize(final Size[] choices, final int width, final int height) { final int minSize = Math.max(Math.min(width, height), MINIMUM_PREVIEW_SIZE); final Size desiredSize = new Size(width, height); // Collect the supported resolutions that are at least as big as the preview Surface boolean exactSizeFound = false; final List bigEnough = new ArrayList(); final List tooSmall = new ArrayList(); for (final Size option : choices) { if (option.equals(desiredSize)) { // Set the size but don't return yet so that remaining sizes will still be logged. exactSizeFound = true; } if (option.getHeight() >= minSize && option.getWidth() >= minSize) { bigEnough.add(option); } else { tooSmall.add(option); } } Log.d(TAG, "Desired size: " + desiredSize + ", min size: " + minSize + "x" + minSize); Log.d(TAG, "Valid preview sizes: [" + TextUtils.join(", ", bigEnough) + "]"); Log.d(TAG, "Rejected preview sizes: [" + TextUtils.join(", ", tooSmall) + "]"); if (exactSizeFound) { Log.d(TAG, "Exact size match found."); return desiredSize; } // Pick the smallest of those, assuming we found any if (bigEnough.size() > 0) { final Size chosenSize = Collections.min(bigEnough, new CompareSizesByArea()); Log.d(TAG, "Chosen size: " + chosenSize.getWidth() + "x" + chosenSize.getHeight()); return chosenSize; } else { Log.e(TAG, "Couldn't find any suitable preview size"); return choices[0]; } } public static CameraConnectionFragment newInstance( final ConnectionCallback callback, final OnImageAvailableListener imageListener, final int layout, final Size inputSize) { return new CameraConnectionFragment(callback, imageListener, layout, inputSize); } @Override public View onCreateView( final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { return inflater.inflate(layout, container, false); } @Override public void onViewCreated(final View view, final Bundle savedInstanceState) { textureView = (AutoFitTextureView) view.findViewById(R.id.texture); } @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Override public void onResume() { super.onResume(); startBackgroundThread(); // When the screen is turned off and turned back on, the SurfaceTexture is ai.fritz.heartbeat.ui.AutoFitTextureViewalready // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open // a camera and start preview from here (otherwise, we wait until the surface is ready in // the SurfaceTextureListener). if (textureView.isAvailable()) { openCamera(textureView.getWidth(), textureView.getHeight()); } else { textureView.setSurfaceTextureListener(surfaceTextureListener); } } @Override public void onPause() { closeCamera(); stopBackgroundThread(); super.onPause(); } public void setCamera(String cameraId) { this.cameraId = cameraId; } /** * Sets up member variables related to camera. */ private void setUpCameraOutputs() { final Activity activity = getActivity(); final CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); try { final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); final StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); // For still image captures, we use the largest available size. final Size largest = Collections.max( Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)), new CompareSizesByArea()); sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); // Danger, W.R.! Attempting to use too large a preview size could exceed the camera // bus' bandwidth limitation, resulting in gorgeous previews but the storage of // garbage capture data. previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), inputSize.getWidth(), inputSize.getHeight()); } catch (final CameraAccessException e) { Log.e(TAG, "Exception!" + e); } catch (final NullPointerException e) { // Currently an NPE is thrown when the Camera2API is used but not supported on the // device this code runs. // TODO(andrewharp): abstract ErrorDialog/RuntimeException handling out into new method and // reuse throughout app. ErrorDialog.newInstance(getString(R.string.camera_error)) .show(getChildFragmentManager(), FRAGMENT_DIALOG); throw new RuntimeException(getString(R.string.camera_error)); } Size textureViewSize = new Size(textureView.getWidth(), textureView.getHeight()); cameraConnectionCallback.onPreviewSizeChosen(previewSize, textureViewSize, sensorOrientation); } /** * Opens the camera specified by {@link CameraConnectionFragment#cameraId}. */ private void openCamera(final int width, final int height) { setUpCameraOutputs(); configureTransform(width, height); final Activity activity = getActivity(); final CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); try { if (!cameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { throw new RuntimeException("Time out waiting to lock camera opening."); } manager.openCamera(cameraId, stateCallback, backgroundHandler); } catch (final CameraAccessException | SecurityException e) { Log.e(TAG, "Exception!" + e); } catch (final InterruptedException e) { throw new RuntimeException("Interrupted while trying to lock camera opening.", e); } } /** * Closes the current {@link CameraDevice}. */ private void closeCamera() { try { cameraOpenCloseLock.acquire(); if (null != captureSession) { captureSession.close(); captureSession = null; } if (null != cameraDevice) { cameraDevice.close(); cameraDevice = null; } if (null != previewReader) { previewReader.close(); previewReader = null; } } catch (final InterruptedException e) { throw new RuntimeException("Interrupted while trying to lock camera closing.", e); } finally { cameraOpenCloseLock.release(); } } /** * Starts a background thread and its {@link Handler}. */ private void startBackgroundThread() { backgroundThread = new HandlerThread("ImageListener"); backgroundThread.start(); backgroundHandler = new Handler(backgroundThread.getLooper()); } /** * Stops the background thread and its {@link Handler}. */ private void stopBackgroundThread() { backgroundThread.quitSafely(); try { backgroundThread.join(); backgroundThread = null; backgroundHandler = null; } catch (final InterruptedException e) { Log.e(TAG, "Exception!" + e); } } private final CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureProgressed( final CameraCaptureSession session, final CaptureRequest request, final CaptureResult partialResult) { } @Override public void onCaptureCompleted( final CameraCaptureSession session, final CaptureRequest request, final TotalCaptureResult result) { } }; /** * Creates a new {@link CameraCaptureSession} for camera preview. */ private void createCameraPreviewSession() { try { final SurfaceTexture texture = textureView.getSurfaceTexture(); assert texture != null; // We configure the size of default buffer to be the size of camera preview we want. texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); // This is the output Surface we need to start preview. final Surface surface = new Surface(texture); // We set up a CaptureRequest.Builder with the output Surface. previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); previewRequestBuilder.addTarget(surface); Log.i(TAG, "Opening camera preview: " + previewSize.getWidth() + "x" + previewSize.getHeight()); // Create the reader for the preview frames. previewReader = ImageReader.newInstance( previewSize.getWidth(), previewSize.getHeight(), ImageFormat.YUV_420_888, 2); previewReader.setOnImageAvailableListener(imageListener, backgroundHandler); previewRequestBuilder.addTarget(previewReader.getSurface()); // Here, we create a CameraCaptureSession for camera preview. cameraDevice.createCaptureSession( Arrays.asList(surface, previewReader.getSurface()), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(final CameraCaptureSession cameraCaptureSession) { // The camera is already closed if (null == cameraDevice) { return; } // When the session is ready, we start displaying the preview. captureSession = cameraCaptureSession; try { // Auto focus should be continuous for camera preview. previewRequestBuilder.set( CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // Flash is automatically enabled when necessary. previewRequestBuilder.set( CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); // Finally, we start displaying the camera preview. previewRequest = previewRequestBuilder.build(); captureSession.setRepeatingRequest( previewRequest, captureCallback, backgroundHandler); } catch (final CameraAccessException e) { Log.e(TAG, "Exception!" + e); } } @Override public void onConfigureFailed(final CameraCaptureSession cameraCaptureSession) { showToast("Failed"); } }, null); } catch (final CameraAccessException e) { Log.e(TAG, "Exception!" + e); } } /** * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`. * This method should be called after the camera preview size is determined in * setUpCameraOutputs and also the size of `mTextureView` is fixed. * * @param viewWidth The width of `mTextureView` * @param viewHeight The height of `mTextureView` */ private void configureTransform(final int viewWidth, final int viewHeight) { final Activity activity = getActivity(); if (null == textureView || null == previewSize || null == activity) { return; } final int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); final Matrix matrix = new Matrix(); final RectF viewRect = new RectF(0, 0, viewWidth, viewHeight); final RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth()); final float centerX = viewRect.centerX(); final float centerY = viewRect.centerY(); if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) { bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY()); matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL); final float scale = Math.max( (float) viewHeight / previewSize.getHeight(), (float) viewWidth / previewSize.getWidth()); matrix.postScale(scale, scale, centerX, centerY); matrix.postRotate(90 * (rotation - 2), centerX, centerY); } else if (Surface.ROTATION_180 == rotation) { matrix.postRotate(180, centerX, centerY); } textureView.setTransform(matrix); } /** * Compares two {@code Size}s based on their areas. */ static class CompareSizesByArea implements Comparator { @Override public int compare(final Size lhs, final Size rhs) { // We cast here to ensure the multiplications won't overflow return Long.signum( (long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight()); } } /** * Shows an error message dialog. */ public static class ErrorDialog extends DialogFragment { private static final String ARG_MESSAGE = "message"; public static ErrorDialog newInstance(final String message) { final ErrorDialog dialog = new ErrorDialog(); final Bundle args = new Bundle(); args.putString(ARG_MESSAGE, message); dialog.setArguments(args); return dialog; } @Override public Dialog onCreateDialog(final Bundle savedInstanceState) { final Activity activity = getActivity(); return new AlertDialog.Builder(activity) .setMessage(getArguments().getString(ARG_MESSAGE)) .setPositiveButton( android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialogInterface, final int i) { activity.finish(); } }) .create(); } } } ================================================ FILE: Android/AnimatedSkyApp/app/src/main/java/ai/fritz/animatedSky/MainActivity.java ================================================ package ai.fritz.animatedSky; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.media.Image; import android.media.ImageReader; import android.os.Bundle; import android.util.Size; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.atomic.AtomicBoolean; import ai.fritz.core.Fritz; import ai.fritz.vision.FritzVision; import ai.fritz.vision.FritzVisionImage; import ai.fritz.vision.FritzVisionModels; import ai.fritz.vision.FritzVisionOrientation; import ai.fritz.vision.ImageOrientation; import ai.fritz.vision.ImageRotation; import ai.fritz.vision.ModelVariant; import ai.fritz.vision.imagesegmentation.FritzVisionSegmentationPredictor; import ai.fritz.vision.imagesegmentation.FritzVisionSegmentationPredictorOptions; import ai.fritz.vision.imagesegmentation.FritzVisionSegmentationResult; import ai.fritz.vision.imagesegmentation.MaskClass; import ai.fritz.vision.imagesegmentation.SegmentationOnDeviceModel; public class MainActivity extends BaseCameraActivity implements ImageReader.OnImageAvailableListener { private static final String TAG = MainActivity.class.getSimpleName(); private AtomicBoolean shouldSample = new AtomicBoolean(true); private FritzVisionSegmentationPredictor predictor; private ImageOrientation orientation; private static final int DURATION = 5000; private ValueAnimator mCurrentAnimator; private Matrix mMatrix = new Matrix(); private ImageView mImageView; private float mScaleFactor; private RectF mDisplayRect = new RectF(); private FritzVisionSegmentationResult segmentResult; private FritzVisionImage visionImage; Button snapshotButton; RelativeLayout previewLayout; RelativeLayout snapshotLayout; OverlayView snapshotOverlay; ProgressBar snapshotProcessingSpinner; Button closeButton; FritzVisionSegmentationPredictorOptions options; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); Fritz.configure(getApplicationContext()); SegmentationOnDeviceModel onDeviceModel = FritzVisionModels.getSkySegmentationOnDeviceModel(ModelVariant.FAST); options = new FritzVisionSegmentationPredictorOptions(); options.confidenceThreshold = .6f; predictor = FritzVision.ImageSegmentation.getPredictor(onDeviceModel, options); } @Override protected int getLayoutId() { return R.layout.sky_fragment; } @Override public void onPreviewSizeChosen(final Size size, final Size cameraSize, final int rotation) { orientation = FritzVisionOrientation.getImageOrientationFromCamera(this, cameraId); snapshotButton = findViewById(R.id.take_picture_btn); previewLayout = findViewById(R.id.preview_frame); snapshotLayout = findViewById(R.id.snapshot_frame); snapshotOverlay = findViewById(R.id.snapshot_view); closeButton = findViewById(R.id.close_btn); snapshotProcessingSpinner = findViewById(R.id.snapshotProcessingSpinner); mImageView = findViewById(R.id.backgroundImgView); snapshotOverlay.setCallback(new OverlayView.DrawCallback() { @Override public void drawCallback(final Canvas canvas) { // If there's no result, just return if (segmentResult == null) { return; } // Create a bitmap for undetected items. Scale it up for the camera. Bitmap notSkyMask = segmentResult.buildSingleClassMask(MaskClass.NONE); Bitmap notSkyBitmap = visionImage.mask(notSkyMask); // Scale the non-sky bitmap (scale up from preview size (size of the original image) // to fill the view (cameraSize)). float scaleWidth = ((float) cameraSize.getWidth()) / notSkyBitmap.getWidth(); float scaleHeight = ((float) cameraSize.getHeight()) / notSkyBitmap.getHeight(); final Matrix matrix = new Matrix(); float scale = Math.min(scaleWidth, scaleHeight); matrix.postScale(scale, scale); Bitmap scaledNonSkyBitmap = Bitmap.createBitmap(notSkyBitmap, 0, 0, notSkyBitmap.getWidth(), notSkyBitmap.getHeight(), matrix, false); // Start the animation mImageView.post(new Runnable() { @Override public void run() { mScaleFactor = (float) mImageView.getHeight() / (float) mImageView.getDrawable().getIntrinsicHeight(); mMatrix.postScale(mScaleFactor, mScaleFactor); mImageView.setImageMatrix(mMatrix); startAnimation(); } }); // Draw the non-sky bitmap on the bottom center. canvas.drawBitmap(scaledNonSkyBitmap, (cameraSize.getWidth() - scaledNonSkyBitmap.getWidth()) / 2, cameraSize.getHeight() - scaledNonSkyBitmap.getHeight(), new Paint()); } }); snapshotButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!shouldSample.compareAndSet(true, false)) { return; } snapshotOverlay.postInvalidate(); runInBackground( new Runnable() { @Override public void run() { showSpinner(); segmentResult = predictor.predict(visionImage); showSnapshotLayout(); hideSpinner(); snapshotOverlay.postInvalidate(); } }); } }); closeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showPreviewLayout(); shouldSample.set(true); mCurrentAnimator.end(); mMatrix = new Matrix(); mImageView.setImageMatrix(mMatrix); mDisplayRect = new RectF(); } }); } // For more information on how this animation works: // http://old.flavienlaurent.com/blog/2013/08/05/make-your-background-moving-like-on-play-music-app/ // In short, use displayRect to maintain the real size and position of the bg. // Animate the background by applying a translation. private void startAnimation() { int width = mImageView.getDrawable().getIntrinsicWidth(); int height = mImageView.getDrawable().getIntrinsicHeight(); mDisplayRect.set(0, 0, width, height); mMatrix.mapRect(mDisplayRect); animate(mDisplayRect.left, mDisplayRect.left - (mDisplayRect.right - mImageView.getWidth())); } private void animate(float from, float to) { mCurrentAnimator = ValueAnimator.ofFloat(from, to); mCurrentAnimator.setRepeatCount(ValueAnimator.INFINITE); mCurrentAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (Float) animation.getAnimatedValue(); mMatrix.reset(); mMatrix.postScale(mScaleFactor, mScaleFactor); mMatrix.postTranslate(value, 0); mImageView.setImageMatrix(mMatrix); } }); mCurrentAnimator.setDuration(DURATION); mCurrentAnimator.start(); } private void showSpinner() { runOnUiThread(new Runnable() { @Override public void run() { snapshotProcessingSpinner.setVisibility(View.VISIBLE); } }); } private void hideSpinner() { runOnUiThread(new Runnable() { @Override public void run() { snapshotProcessingSpinner.setVisibility(View.GONE); } }); } private void showSnapshotLayout() { runOnUiThread(new Runnable() { @Override public void run() { previewLayout.setVisibility(View.GONE); snapshotLayout.setVisibility(View.VISIBLE); } }); } private void showPreviewLayout() { previewLayout.setVisibility(View.VISIBLE); snapshotLayout.setVisibility(View.GONE); } @Override public void onImageAvailable(final ImageReader reader) { Image image = reader.acquireLatestImage(); if (image == null) { return; } if (!shouldSample.get()) { image.close(); return; } // Feel free to uncomment if you'd like to try it out with a static image // Bitmap testImage = getBitmapForAsset(this, "climbing.png"); // visionImage = FritzVisionImage.fromBitmap(testImage, ImageRotation.ROTATE_0); // Using the image from the camera visionImage = FritzVisionImage.fromMediaImage(image, orientation); image.close(); } public static Bitmap getBitmapForAsset(Context context, String path) { AssetManager assetManager = context.getAssets(); InputStream inputStream; Bitmap bitmap = null; try { inputStream = assetManager.open(path); bitmap = BitmapFactory.decodeStream(inputStream); } catch (IOException e) { throw new RuntimeException(e); } return bitmap; } } ================================================ FILE: Android/AnimatedSkyApp/app/src/main/java/ai/fritz/animatedSky/OverlayView.java ================================================ package ai.fritz.animatedSky; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.View; /** * A simple View providing a render callback to other classes. */ public class OverlayView extends View { private DrawCallback callback; public OverlayView(final Context context, final AttributeSet attrs) { super(context, attrs); } /** * Interface defining the callback for client classes. */ public interface DrawCallback { public void drawCallback(final Canvas canvas); } public void setCallback(final DrawCallback callback) { this.callback = callback; } @Override public synchronized void draw(final Canvas canvas) { super.draw(canvas); if(callback != null) { callback.drawCallback(canvas); } } } ================================================ FILE: Android/AnimatedSkyApp/app/src/main/res/drawable/ic_close.xml ================================================ ================================================ FILE: Android/AnimatedSkyApp/app/src/main/res/drawable/ic_launcher_background.xml ================================================ ================================================ FILE: Android/AnimatedSkyApp/app/src/main/res/drawable/round_button.xml ================================================ ================================================ FILE: Android/AnimatedSkyApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml ================================================ ================================================ FILE: Android/AnimatedSkyApp/app/src/main/res/layout/activity_main.xml ================================================ ================================================ FILE: Android/AnimatedSkyApp/app/src/main/res/layout/sky_fragment.xml ================================================