├── LICENSE ├── native_opencv ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── CMakeLists.txt │ ├── build.gradle │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── kotlin │ │ └── com │ │ └── valyouw │ │ └── native_opencv │ │ └── NativeOpencvPlugin.kt ├── example │ ├── .gitignore │ ├── .metadata │ ├── README.md │ ├── analysis_options.yaml │ ├── android │ │ ├── .gitignore │ │ ├── app │ │ │ ├── build.gradle │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ ├── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── com │ │ │ │ │ │ └── valyouw │ │ │ │ │ │ └── native_opencv_example │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── res │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── values-night │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values │ │ │ │ │ └── styles.xml │ │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ └── gradle-wrapper.properties │ │ └── settings.gradle │ ├── ios │ │ ├── .gitignore │ │ ├── Flutter │ │ │ ├── AppFrameworkInfo.plist │ │ │ ├── Debug.xcconfig │ │ │ └── Release.xcconfig │ │ ├── Runner.xcodeproj │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ ├── Runner.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── Runner │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── LaunchImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ └── README.md │ │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ │ ├── Info.plist │ │ │ └── Runner-Bridging-Header.h │ ├── lib │ │ └── main.dart │ ├── pubspec.lock │ ├── pubspec.yaml │ └── test │ │ └── widget_test.dart ├── ios │ ├── .gitignore │ ├── Assets │ │ └── .gitkeep │ ├── Classes │ │ ├── ArucoDetector │ │ │ ├── ArucoDetector.cpp │ │ │ └── ArucoDetector.h │ │ ├── NativeOpencvPlugin.h │ │ ├── NativeOpencvPlugin.m │ │ ├── SwiftNativeOpencvPlugin.swift │ │ └── native_opencv.cpp │ ├── native_opencv.modulemap │ └── native_opencv.podspec ├── lib │ └── native_opencv.dart ├── pubspec.yaml └── test │ └── native_opencv_test.dart ├── opencv_app ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── vyw │ │ │ │ │ └── opencv_app │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── assets │ └── drawable │ │ └── marker.png ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── detection │ │ ├── detection_page.dart │ │ └── detections_layer.dart │ ├── detector │ │ ├── aruco_detector.dart │ │ └── aruco_detector_async.dart │ └── main.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── widget_test.dart ├── readme.md └── tutorial.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 ValYouW 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /native_opencv/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 25 | /pubspec.lock 26 | **/doc/api/ 27 | .dart_tool/ 28 | .packages 29 | build/ 30 | -------------------------------------------------------------------------------- /native_opencv/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b 8 | channel: stable 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /native_opencv/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.1 2 | 3 | * TODO: Describe initial release. 4 | -------------------------------------------------------------------------------- /native_opencv/LICENSE: -------------------------------------------------------------------------------- 1 | TODO: Add your license here. 2 | -------------------------------------------------------------------------------- /native_opencv/README.md: -------------------------------------------------------------------------------- 1 | # native_opencv 2 | 3 | A new flutter plugin project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter 8 | [plug-in package](https://flutter.dev/developing-packages/), 9 | a specialized package that includes platform-specific implementation code for 10 | Android and/or iOS. 11 | 12 | For help getting started with Flutter, view our 13 | [online documentation](https://flutter.dev/docs), which offers tutorials, 14 | samples, guidance on mobile development, and a full API reference. 15 | 16 | -------------------------------------------------------------------------------- /native_opencv/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /native_opencv/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .cxx/ 10 | -------------------------------------------------------------------------------- /native_opencv/android/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10.2) 2 | 3 | # opencv 4 | set(OpenCV_STATIC ON) 5 | set(OpenCV_DIR $ENV{OPENCV_ANDROID}/sdk/native/jni) 6 | find_package (OpenCV REQUIRED) 7 | 8 | add_library( # Sets the name of the library. 9 | native_opencv 10 | SHARED 11 | # Provides a relative path to your source file(s). 12 | ../ios/Classes/ArucoDetector/ArucoDetector.cpp 13 | ../ios/Classes/native_opencv.cpp 14 | ) 15 | 16 | target_include_directories( 17 | native_opencv PRIVATE 18 | ../ios/Classes/ArucoDetector 19 | ) 20 | 21 | find_library(log-lib log) 22 | 23 | target_link_libraries( # Specifies the target library. 24 | native_opencv 25 | ${OpenCV_LIBS} 26 | ${log-lib} 27 | ) 28 | -------------------------------------------------------------------------------- /native_opencv/android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.valyouw.native_opencv' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.3.50' 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:4.1.0' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | } 15 | } 16 | 17 | rootProject.allprojects { 18 | repositories { 19 | google() 20 | mavenCentral() 21 | } 22 | } 23 | 24 | apply plugin: 'com.android.library' 25 | apply plugin: 'kotlin-android' 26 | 27 | android { 28 | compileSdkVersion 30 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | defaultConfig { 44 | minSdkVersion 24 45 | } 46 | 47 | externalNativeBuild { 48 | cmake { 49 | path "CMakeLists.txt" 50 | version "3.10.2" 51 | } 52 | } 53 | } 54 | 55 | dependencies { 56 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 57 | } 58 | -------------------------------------------------------------------------------- /native_opencv/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'native_opencv' 2 | -------------------------------------------------------------------------------- /native_opencv/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /native_opencv/android/src/main/kotlin/com/valyouw/native_opencv/NativeOpencvPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.valyouw.native_opencv 2 | 3 | import androidx.annotation.NonNull 4 | 5 | import io.flutter.embedding.engine.plugins.FlutterPlugin 6 | import io.flutter.plugin.common.MethodCall 7 | import io.flutter.plugin.common.MethodChannel 8 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler 9 | import io.flutter.plugin.common.MethodChannel.Result 10 | 11 | /** NativeOpencvPlugin */ 12 | class NativeOpencvPlugin: FlutterPlugin, MethodCallHandler { 13 | /// The MethodChannel that will the communication between Flutter and native Android 14 | /// 15 | /// This local reference serves to register the plugin with the Flutter Engine and unregister it 16 | /// when the Flutter Engine is detached from the Activity 17 | private lateinit var channel : MethodChannel 18 | 19 | override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { 20 | channel = MethodChannel(flutterPluginBinding.binaryMessenger, "native_opencv") 21 | channel.setMethodCallHandler(this) 22 | } 23 | 24 | override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { 25 | if (call.method == "getPlatformVersion") { 26 | result.success("Android ${android.os.Build.VERSION.RELEASE}") 27 | } else { 28 | result.notImplemented() 29 | } 30 | } 31 | 32 | override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { 33 | channel.setMethodCallHandler(null) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /native_opencv/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /native_opencv/example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /native_opencv/example/README.md: -------------------------------------------------------------------------------- 1 | # native_opencv_example 2 | 3 | Demonstrates how to use the native_opencv plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /native_opencv/example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /native_opencv/example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 31 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.valyouw.native_opencv_example" 47 | minSdkVersion 24 48 | targetSdkVersion 31 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/kotlin/com/valyouw/native_opencv_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.valyouw.native_opencv_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /native_opencv/example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /native_opencv/example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /native_opencv/example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /native_opencv/example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /native_opencv/example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /native_opencv/example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 97 | ); 98 | path = Runner; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 97C146ED1CF9000F007C117D /* Runner */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 107 | buildPhases = ( 108 | 9740EEB61CF901F6004384FC /* Run Script */, 109 | 97C146EA1CF9000F007C117D /* Sources */, 110 | 97C146EB1CF9000F007C117D /* Frameworks */, 111 | 97C146EC1CF9000F007C117D /* Resources */, 112 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = Runner; 120 | productName = Runner; 121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | 97C146E61CF9000F007C117D /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastUpgradeCheck = 1300; 131 | ORGANIZATIONNAME = ""; 132 | TargetAttributes = { 133 | 97C146ED1CF9000F007C117D = { 134 | CreatedOnToolsVersion = 7.3.1; 135 | LastSwiftMigration = 1100; 136 | }; 137 | }; 138 | }; 139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 140 | compatibilityVersion = "Xcode 9.3"; 141 | developmentRegion = en; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | Base, 146 | ); 147 | mainGroup = 97C146E51CF9000F007C117D; 148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 149 | projectDirPath = ""; 150 | projectRoot = ""; 151 | targets = ( 152 | 97C146ED1CF9000F007C117D /* Runner */, 153 | ); 154 | }; 155 | /* End PBXProject section */ 156 | 157 | /* Begin PBXResourcesBuildPhase section */ 158 | 97C146EC1CF9000F007C117D /* Resources */ = { 159 | isa = PBXResourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXResourcesBuildPhase section */ 170 | 171 | /* Begin PBXShellScriptBuildPhase section */ 172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 173 | isa = PBXShellScriptBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | inputPaths = ( 178 | ); 179 | name = "Thin Binary"; 180 | outputPaths = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 185 | }; 186 | 9740EEB61CF901F6004384FC /* Run Script */ = { 187 | isa = PBXShellScriptBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | ); 191 | inputPaths = ( 192 | ); 193 | name = "Run Script"; 194 | outputPaths = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | shellPath = /bin/sh; 198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 199 | }; 200 | /* End PBXShellScriptBuildPhase section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 97C146EA1CF9000F007C117D /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXSourcesBuildPhase section */ 213 | 214 | /* Begin PBXVariantGroup section */ 215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 216 | isa = PBXVariantGroup; 217 | children = ( 218 | 97C146FB1CF9000F007C117D /* Base */, 219 | ); 220 | name = Main.storyboard; 221 | sourceTree = ""; 222 | }; 223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C147001CF9000F007C117D /* Base */, 227 | ); 228 | name = LaunchScreen.storyboard; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXVariantGroup section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_COMMA = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 276 | MTL_ENABLE_DEBUG_INFO = NO; 277 | SDKROOT = iphoneos; 278 | SUPPORTED_PLATFORMS = iphoneos; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Profile; 283 | }; 284 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 285 | isa = XCBuildConfiguration; 286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | CLANG_ENABLE_MODULES = YES; 290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 291 | ENABLE_BITCODE = NO; 292 | INFOPLIST_FILE = Runner/Info.plist; 293 | LD_RUNPATH_SEARCH_PATHS = ( 294 | "$(inherited)", 295 | "@executable_path/Frameworks", 296 | ); 297 | PRODUCT_BUNDLE_IDENTIFIER = com.valyouw.nativeOpencvExample; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 300 | SWIFT_VERSION = 5.0; 301 | VERSIONING_SYSTEM = "apple-generic"; 302 | }; 303 | name = Profile; 304 | }; 305 | 97C147031CF9000F007C117D /* Debug */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | CLANG_ANALYZER_NONNULL = YES; 310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 311 | CLANG_CXX_LIBRARY = "libc++"; 312 | CLANG_ENABLE_MODULES = YES; 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 315 | CLANG_WARN_BOOL_CONVERSION = YES; 316 | CLANG_WARN_COMMA = YES; 317 | CLANG_WARN_CONSTANT_CONVERSION = YES; 318 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 319 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 320 | CLANG_WARN_EMPTY_BODY = YES; 321 | CLANG_WARN_ENUM_CONVERSION = YES; 322 | CLANG_WARN_INFINITE_RECURSION = YES; 323 | CLANG_WARN_INT_CONVERSION = YES; 324 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 325 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 326 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 328 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 329 | CLANG_WARN_STRICT_PROTOTYPES = YES; 330 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 331 | CLANG_WARN_UNREACHABLE_CODE = YES; 332 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 333 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 334 | COPY_PHASE_STRIP = NO; 335 | DEBUG_INFORMATION_FORMAT = dwarf; 336 | ENABLE_STRICT_OBJC_MSGSEND = YES; 337 | ENABLE_TESTABILITY = YES; 338 | GCC_C_LANGUAGE_STANDARD = gnu99; 339 | GCC_DYNAMIC_NO_PIC = NO; 340 | GCC_NO_COMMON_BLOCKS = YES; 341 | GCC_OPTIMIZATION_LEVEL = 0; 342 | GCC_PREPROCESSOR_DEFINITIONS = ( 343 | "DEBUG=1", 344 | "$(inherited)", 345 | ); 346 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 347 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 348 | GCC_WARN_UNDECLARED_SELECTOR = YES; 349 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 350 | GCC_WARN_UNUSED_FUNCTION = YES; 351 | GCC_WARN_UNUSED_VARIABLE = YES; 352 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 353 | MTL_ENABLE_DEBUG_INFO = YES; 354 | ONLY_ACTIVE_ARCH = YES; 355 | SDKROOT = iphoneos; 356 | TARGETED_DEVICE_FAMILY = "1,2"; 357 | }; 358 | name = Debug; 359 | }; 360 | 97C147041CF9000F007C117D /* Release */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ALWAYS_SEARCH_USER_PATHS = NO; 364 | CLANG_ANALYZER_NONNULL = YES; 365 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 366 | CLANG_CXX_LIBRARY = "libc++"; 367 | CLANG_ENABLE_MODULES = YES; 368 | CLANG_ENABLE_OBJC_ARC = YES; 369 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 370 | CLANG_WARN_BOOL_CONVERSION = YES; 371 | CLANG_WARN_COMMA = YES; 372 | CLANG_WARN_CONSTANT_CONVERSION = YES; 373 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 374 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 375 | CLANG_WARN_EMPTY_BODY = YES; 376 | CLANG_WARN_ENUM_CONVERSION = YES; 377 | CLANG_WARN_INFINITE_RECURSION = YES; 378 | CLANG_WARN_INT_CONVERSION = YES; 379 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 380 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 381 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 382 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 383 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 384 | CLANG_WARN_STRICT_PROTOTYPES = YES; 385 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 386 | CLANG_WARN_UNREACHABLE_CODE = YES; 387 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 388 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 389 | COPY_PHASE_STRIP = NO; 390 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 391 | ENABLE_NS_ASSERTIONS = NO; 392 | ENABLE_STRICT_OBJC_MSGSEND = YES; 393 | GCC_C_LANGUAGE_STANDARD = gnu99; 394 | GCC_NO_COMMON_BLOCKS = YES; 395 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 396 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 397 | GCC_WARN_UNDECLARED_SELECTOR = YES; 398 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 399 | GCC_WARN_UNUSED_FUNCTION = YES; 400 | GCC_WARN_UNUSED_VARIABLE = YES; 401 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 402 | MTL_ENABLE_DEBUG_INFO = NO; 403 | SDKROOT = iphoneos; 404 | SUPPORTED_PLATFORMS = iphoneos; 405 | SWIFT_COMPILATION_MODE = wholemodule; 406 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 407 | TARGETED_DEVICE_FAMILY = "1,2"; 408 | VALIDATE_PRODUCT = YES; 409 | }; 410 | name = Release; 411 | }; 412 | 97C147061CF9000F007C117D /* Debug */ = { 413 | isa = XCBuildConfiguration; 414 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 415 | buildSettings = { 416 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 417 | CLANG_ENABLE_MODULES = YES; 418 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 419 | ENABLE_BITCODE = NO; 420 | INFOPLIST_FILE = Runner/Info.plist; 421 | LD_RUNPATH_SEARCH_PATHS = ( 422 | "$(inherited)", 423 | "@executable_path/Frameworks", 424 | ); 425 | PRODUCT_BUNDLE_IDENTIFIER = com.valyouw.nativeOpencvExample; 426 | PRODUCT_NAME = "$(TARGET_NAME)"; 427 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 428 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 429 | SWIFT_VERSION = 5.0; 430 | VERSIONING_SYSTEM = "apple-generic"; 431 | }; 432 | name = Debug; 433 | }; 434 | 97C147071CF9000F007C117D /* Release */ = { 435 | isa = XCBuildConfiguration; 436 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 437 | buildSettings = { 438 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 439 | CLANG_ENABLE_MODULES = YES; 440 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 441 | ENABLE_BITCODE = NO; 442 | INFOPLIST_FILE = Runner/Info.plist; 443 | LD_RUNPATH_SEARCH_PATHS = ( 444 | "$(inherited)", 445 | "@executable_path/Frameworks", 446 | ); 447 | PRODUCT_BUNDLE_IDENTIFIER = com.valyouw.nativeOpencvExample; 448 | PRODUCT_NAME = "$(TARGET_NAME)"; 449 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 450 | SWIFT_VERSION = 5.0; 451 | VERSIONING_SYSTEM = "apple-generic"; 452 | }; 453 | name = Release; 454 | }; 455 | /* End XCBuildConfiguration section */ 456 | 457 | /* Begin XCConfigurationList section */ 458 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 459 | isa = XCConfigurationList; 460 | buildConfigurations = ( 461 | 97C147031CF9000F007C117D /* Debug */, 462 | 97C147041CF9000F007C117D /* Release */, 463 | 249021D3217E4FDB00AE95B9 /* Profile */, 464 | ); 465 | defaultConfigurationIsVisible = 0; 466 | defaultConfigurationName = Release; 467 | }; 468 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 469 | isa = XCConfigurationList; 470 | buildConfigurations = ( 471 | 97C147061CF9000F007C117D /* Debug */, 472 | 97C147071CF9000F007C117D /* Release */, 473 | 249021D4217E4FDB00AE95B9 /* Profile */, 474 | ); 475 | defaultConfigurationIsVisible = 0; 476 | defaultConfigurationName = Release; 477 | }; 478 | /* End XCConfigurationList section */ 479 | }; 480 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 481 | } 482 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Native Opencv 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | native_opencv_example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /native_opencv/example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /native_opencv/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'dart:async'; 3 | 4 | import 'package:flutter/services.dart'; 5 | import 'package:native_opencv/native_opencv.dart'; 6 | 7 | void main() { 8 | runApp(const MyApp()); 9 | } 10 | 11 | class MyApp extends StatefulWidget { 12 | const MyApp({Key? key}) : super(key: key); 13 | 14 | @override 15 | State createState() => _MyAppState(); 16 | } 17 | 18 | class _MyAppState extends State { 19 | String _platformVersion = 'Unknown'; 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | initPlatformState(); 25 | } 26 | 27 | // Platform messages are asynchronous, so we initialize in an async method. 28 | Future initPlatformState() async { 29 | String platformVersion; 30 | // Platform messages may fail, so we use a try/catch PlatformException. 31 | // We also handle the message potentially returning null. 32 | try { 33 | platformVersion = 34 | await NativeOpencv.platformVersion ?? 'Unknown platform version'; 35 | } on PlatformException { 36 | platformVersion = 'Failed to get platform version.'; 37 | } 38 | 39 | // If the widget was removed from the tree while the asynchronous platform 40 | // message was in flight, we want to discard the reply rather than calling 41 | // setState to update our non-existent appearance. 42 | if (!mounted) return; 43 | 44 | setState(() { 45 | _platformVersion = platformVersion; 46 | }); 47 | } 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return MaterialApp( 52 | home: Scaffold( 53 | appBar: AppBar( 54 | title: const Text('Plugin example app'), 55 | ), 56 | body: Center( 57 | child: Text('Running on: $_platformVersion\n'), 58 | ), 59 | ), 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /native_opencv/example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.2" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.2.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | cupertino_icons: 47 | dependency: "direct main" 48 | description: 49 | name: cupertino_icons 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.0.4" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.2.0" 60 | ffi: 61 | dependency: transitive 62 | description: 63 | name: ffi 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.1.2" 67 | flutter: 68 | dependency: "direct main" 69 | description: flutter 70 | source: sdk 71 | version: "0.0.0" 72 | flutter_lints: 73 | dependency: "direct dev" 74 | description: 75 | name: flutter_lints 76 | url: "https://pub.dartlang.org" 77 | source: hosted 78 | version: "1.0.4" 79 | flutter_test: 80 | dependency: "direct dev" 81 | description: flutter 82 | source: sdk 83 | version: "0.0.0" 84 | lints: 85 | dependency: transitive 86 | description: 87 | name: lints 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "1.0.1" 91 | matcher: 92 | dependency: transitive 93 | description: 94 | name: matcher 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "0.12.11" 98 | meta: 99 | dependency: transitive 100 | description: 101 | name: meta 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "1.7.0" 105 | native_opencv: 106 | dependency: "direct main" 107 | description: 108 | path: ".." 109 | relative: true 110 | source: path 111 | version: "0.0.1" 112 | path: 113 | dependency: transitive 114 | description: 115 | name: path 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "1.8.0" 119 | sky_engine: 120 | dependency: transitive 121 | description: flutter 122 | source: sdk 123 | version: "0.0.99" 124 | source_span: 125 | dependency: transitive 126 | description: 127 | name: source_span 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.8.1" 131 | stack_trace: 132 | dependency: transitive 133 | description: 134 | name: stack_trace 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.10.0" 138 | stream_channel: 139 | dependency: transitive 140 | description: 141 | name: stream_channel 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "2.1.0" 145 | string_scanner: 146 | dependency: transitive 147 | description: 148 | name: string_scanner 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.1.0" 152 | term_glyph: 153 | dependency: transitive 154 | description: 155 | name: term_glyph 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.2.0" 159 | test_api: 160 | dependency: transitive 161 | description: 162 | name: test_api 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "0.4.3" 166 | typed_data: 167 | dependency: transitive 168 | description: 169 | name: typed_data 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.3.0" 173 | vector_math: 174 | dependency: transitive 175 | description: 176 | name: vector_math 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "2.1.1" 180 | sdks: 181 | dart: ">=2.15.1 <3.0.0" 182 | flutter: ">=2.5.0" 183 | -------------------------------------------------------------------------------- /native_opencv/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: native_opencv_example 2 | description: Demonstrates how to use the native_opencv plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | environment: 9 | sdk: ">=2.15.1 <3.0.0" 10 | 11 | # Dependencies specify other packages that your package needs in order to work. 12 | # To automatically upgrade your package dependencies to the latest versions 13 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 14 | # dependencies can be manually updated by changing the version numbers below to 15 | # the latest version available on pub.dev. To see which dependencies have newer 16 | # versions available, run `flutter pub outdated`. 17 | dependencies: 18 | flutter: 19 | sdk: flutter 20 | 21 | native_opencv: 22 | # When depending on this package from a real application you should use: 23 | # native_opencv: ^x.y.z 24 | # See https://dart.dev/tools/pub/dependencies#version-constraints 25 | # The example app is bundled with the plugin so we use a path dependency on 26 | # the parent directory to use the current plugin's version. 27 | path: ../ 28 | 29 | # The following adds the Cupertino Icons font to your application. 30 | # Use with the CupertinoIcons class for iOS style icons. 31 | cupertino_icons: ^1.0.2 32 | 33 | dev_dependencies: 34 | flutter_test: 35 | sdk: flutter 36 | 37 | # The "flutter_lints" package below contains a set of recommended lints to 38 | # encourage good coding practices. The lint set provided by the package is 39 | # activated in the `analysis_options.yaml` file located at the root of your 40 | # package. See that file for information about deactivating specific lint 41 | # rules and activating additional ones. 42 | flutter_lints: ^1.0.0 43 | 44 | # For information on the generic Dart part of this file, see the 45 | # following page: https://dart.dev/tools/pub/pubspec 46 | 47 | # The following section is specific to Flutter. 48 | flutter: 49 | 50 | # The following line ensures that the Material Icons font is 51 | # included with your application, so that you can use the icons in 52 | # the material Icons class. 53 | uses-material-design: true 54 | 55 | # To add assets to your application, add an assets section, like this: 56 | # assets: 57 | # - images/a_dot_burr.jpeg 58 | # - images/a_dot_ham.jpeg 59 | 60 | # An image asset can refer to one or more resolution-specific "variants", see 61 | # https://flutter.dev/assets-and-images/#resolution-aware. 62 | 63 | # For details regarding adding assets from package dependencies, see 64 | # https://flutter.dev/assets-and-images/#from-packages 65 | 66 | # To add custom fonts to your application, add a fonts section here, 67 | # in this "flutter" section. Each entry in this list should have a 68 | # "family" key with the font family name, and a "fonts" key with a 69 | # list giving the asset and other descriptors for the font. For 70 | # example: 71 | # fonts: 72 | # - family: Schyler 73 | # fonts: 74 | # - asset: fonts/Schyler-Regular.ttf 75 | # - asset: fonts/Schyler-Italic.ttf 76 | # style: italic 77 | # - family: Trajan Pro 78 | # fonts: 79 | # - asset: fonts/TrajanPro.ttf 80 | # - asset: fonts/TrajanPro_Bold.ttf 81 | # weight: 700 82 | # 83 | # For details regarding fonts from package dependencies, 84 | # see https://flutter.dev/custom-fonts/#from-packages 85 | -------------------------------------------------------------------------------- /native_opencv/example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:native_opencv_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => widget is Text && 22 | widget.data!.startsWith('Running on:'), 23 | ), 24 | findsOneWidget, 25 | ); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /native_opencv/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/ephemeral/ 38 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /native_opencv/ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/native_opencv/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /native_opencv/ios/Classes/ArucoDetector/ArucoDetector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ArucoDetector.h" 3 | 4 | using namespace std; 5 | using namespace cv; 6 | 7 | ArucoDetector::ArucoDetector(Mat marker, int bits) { 8 | m_dict = loadMarkerDictionary(marker, bits); 9 | } 10 | 11 | vector ArucoDetector::getContoursBits(Mat image, vector cnt, int bits) { 12 | assert(bits > 0 && round(sqrt(bits)) == sqrt(bits)); 13 | int pixelLen = sqrt(bits); 14 | 15 | // NOTE: we assume contour points are clockwise starting from top-left 16 | vector corners = { Point2f(0, 0), Point2f(bits, 0), Point2f(bits, bits), Point2f(0, bits) }; 17 | Mat M = getPerspectiveTransform(cnt, corners); 18 | Mat warpped; 19 | warpPerspective(image, warpped, M, Size(bits, bits)); 20 | 21 | Mat binary; 22 | threshold(warpped, binary, 0, 255, THRESH_BINARY | THRESH_OTSU); 23 | 24 | Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); 25 | erode(binary, binary, element); 26 | 27 | vector res; 28 | for (int r = 0; r < pixelLen; ++r) { 29 | for (int c = 0; c < pixelLen; ++c) { 30 | int y = r * pixelLen + (pixelLen / 2); 31 | int x = c * pixelLen + (pixelLen / 2); 32 | if (binary.at(y, x) >= 128) 33 | { 34 | res.push_back(1); 35 | } 36 | else 37 | { 38 | res.push_back(0); 39 | } 40 | } 41 | } 42 | 43 | return res; 44 | } 45 | 46 | bool ArucoDetector::equalSig(vector& sig1, vector& sig2, int allowedMisses) 47 | { 48 | int misses = 0; 49 | for (int i = 0; i < sig1.size(); ++i) { 50 | if (sig1[i] != sig2[i]) 51 | ++misses; 52 | } 53 | 54 | return misses <= allowedMisses; 55 | } 56 | 57 | void ArucoDetector::orderContour(vector& cnt) 58 | { 59 | float cx = (cnt[0].x + cnt[1].x + cnt[2].x + cnt[3].x) / 4.0f; 60 | float cy = (cnt[0].y + cnt[1].y + cnt[2].y + cnt[3].y) / 4.0f; 61 | 62 | // IMPORTANT! We assume the contour points are counter-clockwise (as we use EXTERNAL contours in findContours) 63 | if (cnt[0].x <= cx && cnt[0].y <= cy) 64 | { 65 | swap(cnt[1], cnt[3]); 66 | } 67 | else 68 | { 69 | swap(cnt[0], cnt[1]); 70 | swap(cnt[2], cnt[3]); 71 | } 72 | } 73 | 74 | vector> ArucoDetector::findSquares(Mat img) { 75 | vector> cand; 76 | 77 | Mat thresh; 78 | adaptiveThreshold(img, thresh, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 11, 5); 79 | 80 | thresh = ~thresh; 81 | vector> cnts; 82 | findContours(thresh, cnts, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); 83 | 84 | vector cnt; 85 | for (int i = 0; i < cnts.size(); ++i) 86 | { 87 | approxPolyDP(cnts[i], cnt, 0.05 * arcLength(cnts[i], true), true); 88 | if (cnt.size() != 4 || contourArea(cnt) < 200 || !isContourConvex(cnt)) { 89 | continue; 90 | } 91 | 92 | cornerSubPix(img, cnt, Size(5, 5), Size(-1, -1), TERM_CRIT); 93 | 94 | orderContour(cnt); 95 | cand.push_back(cnt); 96 | } 97 | 98 | return cand; 99 | } 100 | 101 | vector ArucoDetector::detectArucos(Mat frame, int misses) { 102 | vector res; 103 | vector> cands = findSquares(frame); 104 | 105 | for (int i = 0; i < cands.size() && res.size() < 3; ++i) { 106 | vector cnt = cands[i]; 107 | vector sig = getContoursBits(frame, cnt, 36); 108 | for (int j = 0; j < m_dict.sigs.size(); ++j) { 109 | if (equalSig(sig, m_dict.sigs[j], misses)) { 110 | ArucoResult ar; 111 | ar.corners = cnt; 112 | ar.index = j; 113 | res.push_back(ar); 114 | break; 115 | } 116 | } 117 | } 118 | 119 | return res; 120 | } 121 | 122 | ArucoDict ArucoDetector::loadMarkerDictionary(Mat marker, int bits) { 123 | ArucoDict res; 124 | int w = marker.cols; 125 | int h = marker.rows; 126 | 127 | cvtColor(marker, marker, COLOR_BGRA2GRAY); 128 | 129 | vector cnt = { Point2f(0, 0), Point2f(w, 0) , Point2f(w, h) , Point2f(0, h) }; 130 | vector world = { Point3f(0, 0, 0), Point3f(25, 0, 0), Point3f(25, 25, 0), Point3f(0, 25, 0) }; 131 | 132 | for (int i = 0; i < 4; ++i) { 133 | vector sig = getContoursBits(marker, cnt, bits); 134 | res.sigs.push_back(sig); 135 | 136 | vector w(world); 137 | res.worldLoc.push_back(w); 138 | 139 | rotate(marker, marker, ROTATE_90_CLOCKWISE); 140 | 141 | world.insert(world.begin(), world[3]); 142 | world.pop_back(); 143 | } 144 | 145 | return res; 146 | } 147 | -------------------------------------------------------------------------------- /native_opencv/ios/Classes/ArucoDetector/ArucoDetector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | using namespace std; 5 | using namespace cv; 6 | 7 | struct ArucoResult { 8 | vector corners; 9 | int index = -1; 10 | }; 11 | 12 | struct ArucoDict { 13 | vector> sigs; 14 | vector> worldLoc; 15 | }; 16 | 17 | class ArucoDetector { 18 | public: 19 | ArucoDetector(Mat marker, int bits); 20 | vector detectArucos(Mat frame, int misses = 0); 21 | ArucoDict m_dict; 22 | 23 | private: 24 | vector getContoursBits(Mat image, vector cnt, int bits); 25 | bool equalSig(vector& sig1, vector& sig2, int allowedMisses = 0); 26 | void orderContour(vector& cnt); 27 | vector> findSquares(Mat img); 28 | ArucoDict loadMarkerDictionary(Mat marker, int bits); 29 | TermCriteria TERM_CRIT = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001); 30 | }; 31 | -------------------------------------------------------------------------------- /native_opencv/ios/Classes/NativeOpencvPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NativeOpencvPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /native_opencv/ios/Classes/NativeOpencvPlugin.m: -------------------------------------------------------------------------------- 1 | #import "NativeOpencvPlugin.h" 2 | #if __has_include() 3 | #import 4 | #else 5 | // Support project import fallback if the generated compatibility header 6 | // is not copied when this plugin is created as a library. 7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 8 | #import "native_opencv-Swift.h" 9 | #endif 10 | 11 | @implementation NativeOpencvPlugin 12 | + (void)registerWithRegistrar:(NSObject*)registrar { 13 | [SwiftNativeOpencvPlugin registerWithRegistrar:registrar]; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /native_opencv/ios/Classes/SwiftNativeOpencvPlugin.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | public class SwiftNativeOpencvPlugin: NSObject, FlutterPlugin { 5 | public static func register(with registrar: FlutterPluginRegistrar) { 6 | let channel = FlutterMethodChannel(name: "native_opencv", binaryMessenger: registrar.messenger()) 7 | let instance = SwiftNativeOpencvPlugin() 8 | registrar.addMethodCallDelegate(instance, channel: channel) 9 | } 10 | 11 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 12 | result("iOS " + UIDevice.current.systemVersion) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /native_opencv/ios/Classes/native_opencv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ArucoDetector.h" 5 | #include 6 | 7 | using namespace std; 8 | using namespace cv; 9 | 10 | static ArucoDetector* detector = nullptr; 11 | 12 | void rotateMat(Mat &matImage, int rotation) 13 | { 14 | if (rotation == 90) { 15 | transpose(matImage, matImage); 16 | flip(matImage, matImage, 1); //transpose+flip(1)=CW 17 | } else if (rotation == 270) { 18 | transpose(matImage, matImage); 19 | flip(matImage, matImage, 0); //transpose+flip(0)=CCW 20 | } else if (rotation == 180) { 21 | flip(matImage, matImage, -1); //flip(-1)=180 22 | } 23 | } 24 | 25 | extern "C" { 26 | // Attributes to prevent 'unused' function from being removed and to make it visible 27 | __attribute__((visibility("default"))) __attribute__((used)) 28 | const char* version() { 29 | return CV_VERSION; 30 | } 31 | 32 | __attribute__((visibility("default"))) __attribute__((used)) 33 | void initDetector(uint8_t* markerPngBytes, int inBytesCount, int bits) { 34 | if (detector != nullptr) { 35 | delete detector; 36 | detector = nullptr; 37 | } 38 | 39 | vector buffer(markerPngBytes, markerPngBytes + inBytesCount); 40 | Mat marker = imdecode(buffer, IMREAD_COLOR); 41 | 42 | detector = new ArucoDetector(marker, bits); 43 | } 44 | 45 | __attribute__((visibility("default"))) __attribute__((used)) 46 | void destroyDetector() { 47 | if (detector != nullptr) { 48 | delete detector; 49 | detector = nullptr; 50 | } 51 | } 52 | 53 | __attribute__((visibility("default"))) __attribute__((used)) 54 | const float* detect(int width, int height, int rotation, uint8_t* bytes, bool isYUV, int32_t* outCount) { 55 | if (detector == nullptr) { 56 | float* jres = new float[1]; 57 | jres[0] = 0; 58 | return jres; 59 | } 60 | 61 | Mat frame; 62 | if (isYUV) { 63 | Mat myyuv(height + height / 2, width, CV_8UC1, bytes); 64 | cvtColor(myyuv, frame, COLOR_YUV2BGRA_NV21); 65 | } else { 66 | frame = Mat(height, width, CV_8UC4, bytes); 67 | } 68 | 69 | rotateMat(frame, rotation); 70 | cvtColor(frame, frame, COLOR_BGRA2GRAY); 71 | vector res = detector->detectArucos(frame, 0); 72 | 73 | vector output; 74 | 75 | for (int i = 0; i < res.size(); ++i) { 76 | ArucoResult ar = res[i]; 77 | // each aruco has 4 corners 78 | output.push_back(ar.corners[0].x); 79 | output.push_back(ar.corners[0].y); 80 | output.push_back(ar.corners[1].x); 81 | output.push_back(ar.corners[1].y); 82 | output.push_back(ar.corners[2].x); 83 | output.push_back(ar.corners[2].y); 84 | output.push_back(ar.corners[3].x); 85 | output.push_back(ar.corners[3].y); 86 | } 87 | 88 | // Copy result bytes as output vec will get freed 89 | unsigned int total = sizeof(float) * output.size(); 90 | float* jres = (float*)malloc(total); 91 | memcpy(jres, output.data(), total); 92 | 93 | *outCount = output.size(); 94 | return jres; 95 | } 96 | } -------------------------------------------------------------------------------- /native_opencv/ios/native_opencv.modulemap: -------------------------------------------------------------------------------- 1 | framework module native_opencv {} 2 | -------------------------------------------------------------------------------- /native_opencv/ios/native_opencv.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint native_opencv.podspec` to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'native_opencv' 7 | s.version = '0.0.1' 8 | s.summary = 'A new flutter plugin project.' 9 | s.description = <<-DESC 10 | A new flutter plugin project. 11 | DESC 12 | s.homepage = 'http://example.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | 18 | # Set as a static lib 19 | s.static_framework = true 20 | s.dependency 'Flutter' 21 | 22 | # Add OpenCV dep from cocoapods and update min ios ver to 11 23 | s.dependency 'OpenCV', '4.3.0' 24 | s.platform = :ios, '11.0' 25 | 26 | # module_map is needed so this module can be used as a framework 27 | s.module_map = 'native_opencv.modulemap' 28 | 29 | # Flutter.framework does not contain a i386 slice. 30 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } 31 | s.swift_version = '5.0' 32 | end 33 | -------------------------------------------------------------------------------- /native_opencv/lib/native_opencv.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'dart:async'; 4 | import 'dart:ffi'; 5 | import 'dart:io'; 6 | import 'dart:typed_data'; 7 | import 'package:ffi/ffi.dart'; 8 | import 'package:flutter/services.dart'; 9 | 10 | // Load our C lib 11 | final DynamicLibrary nativeLib = 12 | Platform.isAndroid ? DynamicLibrary.open("libnative_opencv.so") : DynamicLibrary.process(); 13 | 14 | // C Functions signatures 15 | typedef _c_version = Pointer Function(); 16 | typedef _c_initDetector = Void Function(Pointer markerPngBytes, Int32 inSize, Int32 bits); 17 | typedef _c_destroyDetector = Void Function(); 18 | typedef _c_detect = Pointer Function( 19 | Int32 width, Int32 height, Int32 rotation, Pointer bytes, Bool isYUV, Pointer outCount); 20 | 21 | // Dart functions signatures 22 | typedef _dart_version = Pointer Function(); 23 | typedef _dart_initDetector = void Function(Pointer markerPngBytes, int inSize, int bits); 24 | typedef _dart_destroyDetector = void Function(); 25 | typedef _dart_detect = Pointer Function( 26 | int width, int height, int rotation, Pointer bytes, bool isYUV, Pointer outCount); 27 | 28 | // Create dart functions that invoke the C funcion 29 | final _version = nativeLib.lookupFunction<_c_version, _dart_version>('version'); 30 | final _initDetector = nativeLib.lookupFunction<_c_initDetector, _dart_initDetector>('initDetector'); 31 | final _destroyDetector = nativeLib.lookupFunction<_c_destroyDetector, _dart_destroyDetector>('destroyDetector'); 32 | final _detect = nativeLib.lookupFunction<_c_detect, _dart_detect>('detect'); 33 | 34 | class NativeOpencv { 35 | Pointer? _imageBuffer; 36 | 37 | static const MethodChannel _channel = MethodChannel('native_opencv'); 38 | static Future get platformVersion async { 39 | final String? version = await _channel.invokeMethod('getPlatformVersion'); 40 | return version; 41 | } 42 | 43 | String cvVersion() { 44 | return _version().toDartString(); 45 | } 46 | 47 | void initDetector(Uint8List markerPngBytes, int bits) { 48 | var totalSize = markerPngBytes.lengthInBytes; 49 | var imgBuffer = malloc.allocate(totalSize); 50 | Uint8List bytes = imgBuffer.asTypedList(totalSize); 51 | bytes.setAll(0, markerPngBytes); 52 | 53 | _initDetector(imgBuffer, totalSize, bits); 54 | 55 | malloc.free(imgBuffer); 56 | } 57 | 58 | void destroy() { 59 | _destroyDetector(); 60 | if (_imageBuffer != null) { 61 | malloc.free(_imageBuffer!); 62 | } 63 | } 64 | 65 | Float32List detect(int width, int height, int rotation, Uint8List yBuffer, Uint8List? uBuffer, Uint8List? vBuffer) { 66 | var ySize = yBuffer.lengthInBytes; 67 | var uSize = uBuffer?.lengthInBytes ?? 0; 68 | var vSize = vBuffer?.lengthInBytes ?? 0; 69 | var totalSize = ySize + uSize + vSize; 70 | 71 | _imageBuffer ??= malloc.allocate(totalSize); 72 | 73 | // We always have at least 1 plane, on Android it si the yPlane on iOS its the rgba plane 74 | Uint8List _bytes = _imageBuffer!.asTypedList(totalSize); 75 | _bytes.setAll(0, yBuffer); 76 | 77 | if (Platform.isAndroid) { 78 | // Swap u&v buffer for opencv 79 | _bytes.setAll(ySize, vBuffer!); 80 | _bytes.setAll(ySize + vSize, uBuffer!); 81 | } 82 | 83 | Pointer outCount = malloc.allocate(1); 84 | var res = _detect(width, height, rotation, _imageBuffer!, Platform.isAndroid ? true : false, outCount); 85 | final count = outCount.value; 86 | 87 | malloc.free(outCount); 88 | return res.asTypedList(count); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /native_opencv/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: native_opencv 2 | description: A new flutter plugin project. 3 | version: 0.0.1 4 | homepage: 5 | 6 | environment: 7 | sdk: ">=2.15.1 <3.0.0" 8 | flutter: ">=2.5.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | ffi: ^1.1.2 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | flutter_lints: ^1.0.0 19 | 20 | # For information on the generic Dart part of this file, see the 21 | # following page: https://dart.dev/tools/pub/pubspec 22 | 23 | # The following section is specific to Flutter. 24 | flutter: 25 | # This section identifies this Flutter project as a plugin project. 26 | # The 'pluginClass' and Android 'package' identifiers should not ordinarily 27 | # be modified. They are used by the tooling to maintain consistency when 28 | # adding or updating assets for this project. 29 | plugin: 30 | platforms: 31 | android: 32 | package: com.valyouw.native_opencv 33 | pluginClass: NativeOpencvPlugin 34 | ios: 35 | pluginClass: NativeOpencvPlugin 36 | 37 | # To add assets to your plugin package, add an assets section, like this: 38 | # assets: 39 | # - images/a_dot_burr.jpeg 40 | # - images/a_dot_ham.jpeg 41 | # 42 | # For details regarding assets in packages, see 43 | # https://flutter.dev/assets-and-images/#from-packages 44 | # 45 | # An image asset can refer to one or more resolution-specific "variants", see 46 | # https://flutter.dev/assets-and-images/#resolution-aware. 47 | 48 | # To add custom fonts to your plugin package, add a fonts section here, 49 | # in this "flutter" section. Each entry in this list should have a 50 | # "family" key with the font family name, and a "fonts" key with a 51 | # list giving the asset and other descriptors for the font. For 52 | # example: 53 | # fonts: 54 | # - family: Schyler 55 | # fonts: 56 | # - asset: fonts/Schyler-Regular.ttf 57 | # - asset: fonts/Schyler-Italic.ttf 58 | # style: italic 59 | # - family: Trajan Pro 60 | # fonts: 61 | # - asset: fonts/TrajanPro.ttf 62 | # - asset: fonts/TrajanPro_Bold.ttf 63 | # weight: 700 64 | # 65 | # For details regarding fonts in packages, see 66 | # https://flutter.dev/custom-fonts/#from-packages 67 | -------------------------------------------------------------------------------- /native_opencv/test/native_opencv_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:native_opencv/native_opencv.dart'; 4 | 5 | void main() { 6 | const MethodChannel channel = MethodChannel('native_opencv'); 7 | 8 | TestWidgetsFlutterBinding.ensureInitialized(); 9 | 10 | setUp(() { 11 | channel.setMockMethodCallHandler((MethodCall methodCall) async { 12 | return '42'; 13 | }); 14 | }); 15 | 16 | tearDown(() { 17 | channel.setMockMethodCallHandler(null); 18 | }); 19 | 20 | test('getPlatformVersion', () async { 21 | expect(await NativeOpencv.platformVersion, '42'); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /opencv_app/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /opencv_app/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /opencv_app/README.md: -------------------------------------------------------------------------------- 1 | # opencv_app 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /opencv_app/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /opencv_app/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /opencv_app/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 31 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.vyw.opencv_app" 47 | minSdkVersion 24 48 | targetSdkVersion 31 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /opencv_app/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/kotlin/com/vyw/opencv_app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.vyw.opencv_app 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /opencv_app/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /opencv_app/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /opencv_app/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /opencv_app/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /opencv_app/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /opencv_app/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /opencv_app/assets/drawable/marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/assets/drawable/marker.png -------------------------------------------------------------------------------- /opencv_app/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /opencv_app/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /opencv_app/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /opencv_app/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /opencv_app/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '11.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /opencv_app/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - camera (0.0.1): 3 | - Flutter 4 | - Flutter (1.0.0) 5 | - native_opencv (0.0.1): 6 | - Flutter 7 | - OpenCV (= 4.3.0) 8 | - OpenCV (4.3.0) 9 | 10 | DEPENDENCIES: 11 | - camera (from `.symlinks/plugins/camera/ios`) 12 | - Flutter (from `Flutter`) 13 | - native_opencv (from `.symlinks/plugins/native_opencv/ios`) 14 | 15 | SPEC REPOS: 16 | trunk: 17 | - OpenCV 18 | 19 | EXTERNAL SOURCES: 20 | camera: 21 | :path: ".symlinks/plugins/camera/ios" 22 | Flutter: 23 | :path: Flutter 24 | native_opencv: 25 | :path: ".symlinks/plugins/native_opencv/ios" 26 | 27 | SPEC CHECKSUMS: 28 | camera: fe33292aff715a981eb34d7ce7b35b54337ff34c 29 | Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a 30 | native_opencv: ab8b4bcfa5ca37eaa2634098698b3ea494e3b1fb 31 | OpenCV: 681e0451c1e54c5930a8922277f817ed5d5ab459 32 | 33 | PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d 34 | 35 | COCOAPODS: 1.11.2 36 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValYouW/flutter-opencv-stream-processing/e2b503dbad9ce2b01a6a7ddd2e62cde1f3a32288/opencv_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSCameraUsageDescription 6 | Need camera permission 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleDisplayName 10 | Opencv App 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | opencv_app 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | $(FLUTTER_BUILD_NAME) 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | $(FLUTTER_BUILD_NUMBER) 27 | LSRequiresIPhoneOS 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | UIViewControllerBasedStatusBarAppearance 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /opencv_app/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /opencv_app/lib/detection/detection_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | import 'dart:io'; 3 | import 'package:camera/camera.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:opencv_app/detection/detections_layer.dart'; 6 | import 'package:opencv_app/detector/aruco_detector_async.dart'; 7 | 8 | class DetectionPage extends StatefulWidget { 9 | const DetectionPage({Key? key}) : super(key: key); 10 | 11 | @override 12 | _DetectionPageState createState() => _DetectionPageState(); 13 | } 14 | 15 | class _DetectionPageState extends State with WidgetsBindingObserver { 16 | CameraController? _camController; 17 | late ArucoDetectorAsync _arucoDetector; 18 | int _camFrameRotation = 0; 19 | double _camFrameToScreenScale = 0; 20 | int _lastRun = 0; 21 | bool _detectionInProgress = false; 22 | List _arucos = List.empty(); 23 | 24 | @override 25 | void initState() { 26 | super.initState(); 27 | WidgetsBinding.instance?.addObserver(this); 28 | _arucoDetector = ArucoDetectorAsync(); 29 | initCamera(); 30 | } 31 | 32 | @override 33 | void didChangeAppLifecycleState(AppLifecycleState state) { 34 | final CameraController? cameraController = _camController; 35 | 36 | // App state changed before we got the chance to initialize. 37 | if (cameraController == null || !cameraController.value.isInitialized) { 38 | return; 39 | } 40 | 41 | if (state == AppLifecycleState.inactive) { 42 | cameraController.dispose(); 43 | } else if (state == AppLifecycleState.resumed) { 44 | initCamera(); 45 | } 46 | } 47 | 48 | @override 49 | void dispose() { 50 | WidgetsBinding.instance?.removeObserver(this); 51 | _arucoDetector.destroy(); 52 | _camController?.dispose(); 53 | super.dispose(); 54 | } 55 | 56 | Future initCamera() async { 57 | final cameras = await availableCameras(); 58 | var idx = cameras.indexWhere((c) => c.lensDirection == CameraLensDirection.back); 59 | if (idx < 0) { 60 | log("No Back camera found - weird"); 61 | return; 62 | } 63 | 64 | var desc = cameras[idx]; 65 | _camFrameRotation = Platform.isAndroid ? desc.sensorOrientation : 0; 66 | _camController = CameraController( 67 | desc, 68 | ResolutionPreset.high, // 720p 69 | enableAudio: false, 70 | imageFormatGroup: Platform.isAndroid ? ImageFormatGroup.yuv420 : ImageFormatGroup.bgra8888, 71 | ); 72 | 73 | try { 74 | await _camController!.initialize(); 75 | await _camController!.startImageStream((image) => _processCameraImage(image)); 76 | } catch (e) { 77 | log("Error initializing camera, error: ${e.toString()}"); 78 | } 79 | 80 | if (mounted) { 81 | setState(() {}); 82 | } 83 | } 84 | 85 | void _processCameraImage(CameraImage image) async { 86 | if (_detectionInProgress || !mounted || DateTime.now().millisecondsSinceEpoch - _lastRun < 30) { 87 | return; 88 | } 89 | 90 | // calc the scale factor to convert from camera frame coords to screen coords. 91 | // NOTE!!!! We assume camera frame takes the entire screen width, if that's not the case 92 | // (like if camera is landscape or the camera frame is limited to some area) then you will 93 | // have to find the correct scale factor somehow else 94 | if (_camFrameToScreenScale == 0) { 95 | var w = (_camFrameRotation == 0 || _camFrameRotation == 180) ? image.width : image.height; 96 | _camFrameToScreenScale = MediaQuery.of(context).size.width / w; 97 | } 98 | 99 | // Call the detector 100 | _detectionInProgress = true; 101 | var res = await _arucoDetector.detect(image, _camFrameRotation); 102 | _detectionInProgress = false; 103 | _lastRun = DateTime.now().millisecondsSinceEpoch; 104 | 105 | // Make sure we are still mounted, the background thread can return a response after we navigate away from this 106 | // screen but before bg thread is killed 107 | if (!mounted || res == null || res.isEmpty) { 108 | return; 109 | } 110 | 111 | // Check that the number of coords we got divides by 8 exactly, each aruco has 8 coords (4 corners x/y) 112 | if ((res.length / 8) != (res.length ~/ 8)) { 113 | log('Got invalid response from ArucoDetector, number of coords is ${res.length} and does not represent complete arucos with 4 corners'); 114 | return; 115 | } 116 | 117 | // convert arucos from camera frame coords to screen coords 118 | final arucos = res.map((x) => x * _camFrameToScreenScale).toList(growable: false); 119 | setState(() { 120 | _arucos = arucos; 121 | }); 122 | } 123 | 124 | @override 125 | Widget build(BuildContext context) { 126 | if (_camController == null) { 127 | return const Center( 128 | child: Text('Loading...'), 129 | ); 130 | } 131 | 132 | return Stack( 133 | children: [ 134 | CameraPreview(_camController!), 135 | DetectionsLayer( 136 | arucos: _arucos, 137 | ), 138 | ], 139 | ); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /opencv_app/lib/detection/detections_layer.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class DetectionsLayer extends StatelessWidget { 4 | const DetectionsLayer({ 5 | Key? key, 6 | required this.arucos, 7 | }) : super(key: key); 8 | 9 | final List arucos; 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return CustomPaint( 14 | painter: ArucosPainter(arucos: arucos), 15 | ); 16 | } 17 | } 18 | 19 | class ArucosPainter extends CustomPainter { 20 | ArucosPainter({required this.arucos}); 21 | 22 | // list of aruco coordinates, each aruco has 4 corners with x/y, total of 8 numbers per aruco 23 | final List arucos; 24 | 25 | // paint we will use to draw to arucos 26 | final _paint = Paint() 27 | ..strokeWidth = 2.0 28 | ..color = Colors.red 29 | ..style = PaintingStyle.stroke; 30 | 31 | @override 32 | void paint(Canvas canvas, Size size) { 33 | if (arucos.isEmpty) { 34 | return; 35 | } 36 | 37 | // Each aruco is 8 numbers (4 corners * x,y) and corners are starting from 38 | // top-left going clockwise 39 | final count = arucos.length ~/ 8; 40 | for (int i = 0; i < count; ++i) { 41 | // where current aruco coords starts 42 | int arucoIdx = i * 8; 43 | 44 | // Draw the 4 lines of the aruco 45 | for (int j = 0; j < 4; ++j) { 46 | // each corner has x and y so we jump in 2 47 | final corner1Idx = arucoIdx + j * 2; 48 | 49 | // since the corners are clockwise we can take the next corner by adding 1 to j 50 | // making sure not to overflow to the next aruco, hence the modulo 8, so when 51 | // j=3 corner1 will be the bottom-left corner, and corner2 will be the top-left (like j=0) 52 | final corner2Idx = arucoIdx + ((j + 1) * 2) % 8; 53 | 54 | // Draw the line between the 2 corners 55 | final from = Offset(arucos[corner1Idx], arucos[corner1Idx + 1]); 56 | final to = Offset(arucos[corner2Idx], arucos[corner2Idx + 1]); 57 | canvas.drawLine(from, to, _paint); 58 | } 59 | } 60 | } 61 | 62 | @override 63 | bool shouldRepaint(ArucosPainter oldDelegate) { 64 | // We check if the arucos array was changed, if so we should re-paint 65 | if (arucos.length != oldDelegate.arucos.length) { 66 | return true; 67 | } 68 | 69 | for (int i = 0; i < arucos.length; ++i) { 70 | if (arucos[i] != oldDelegate.arucos[i]) { 71 | return true; 72 | } 73 | } 74 | 75 | return false; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /opencv_app/lib/detector/aruco_detector.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | import 'dart:io'; 3 | import 'dart:isolate'; 4 | import 'dart:typed_data'; 5 | import 'package:camera/camera.dart'; 6 | import 'package:native_opencv/native_opencv.dart'; 7 | 8 | // This class will be used as argument to the init method, since we cant access the bundled assets 9 | // from an Isolate we must get the marker png from the main thread 10 | class InitRequest { 11 | SendPort toMainThread; 12 | ByteData markerPng; 13 | InitRequest({required this.toMainThread, required this.markerPng}); 14 | } 15 | 16 | // this is the class that the main thread will send here asking to invoke a function on ArucoDetector 17 | class Request { 18 | // a correlation id so the main thread will be able to match response with request 19 | int reqId; 20 | String method; 21 | dynamic params; 22 | Request({required this.reqId, required this.method, this.params}); 23 | } 24 | 25 | // this is the class that will be sent as a response to the main thread 26 | class Response { 27 | int reqId; 28 | dynamic data; 29 | Response({required this.reqId, this.data}); 30 | } 31 | 32 | // This is the port that will be used to send data to main thread 33 | late SendPort _toMainThread; 34 | late _ArucoDetector _detector; 35 | 36 | void init(InitRequest initReq) { 37 | // Create ArucoDetector 38 | _detector = _ArucoDetector(initReq.markerPng); 39 | 40 | // Save the port on which we will send messages to the main thread 41 | _toMainThread = initReq.toMainThread; 42 | 43 | // Create a port on which the main thread can send us messages and listen to it 44 | ReceivePort fromMainThread = ReceivePort(); 45 | fromMainThread.listen(_handleMessage); 46 | 47 | // Send the main thread the port on which it can send us messages 48 | _toMainThread.send(fromMainThread.sendPort); 49 | } 50 | 51 | void _handleMessage(data) { 52 | if (data is Request) { 53 | dynamic res; 54 | switch (data.method) { 55 | case 'detect': 56 | var image = data.params['image'] as CameraImage; 57 | var rotation = data.params['rotation']; 58 | res = _detector.detect(image, rotation); 59 | break; 60 | case 'destroy': 61 | _detector.destroy(); 62 | break; 63 | default: 64 | log('Unknown method: ${data.method}'); 65 | } 66 | 67 | _toMainThread.send(Response(reqId: data.reqId, data: res)); 68 | } 69 | } 70 | 71 | class _ArucoDetector { 72 | NativeOpencv? _nativeOpencv; 73 | 74 | _ArucoDetector(ByteData markerPng) { 75 | init(markerPng); 76 | } 77 | 78 | init(ByteData markerPng) async { 79 | // Note our c++ init detector code expects marker to be in png format 80 | final pngBytes = markerPng.buffer.asUint8List(); 81 | 82 | // init the detector 83 | _nativeOpencv = NativeOpencv(); 84 | _nativeOpencv!.initDetector(pngBytes, 36); 85 | } 86 | 87 | Float32List? detect(CameraImage image, int rotation) { 88 | // make sure we have a detector 89 | if (_nativeOpencv == null) { 90 | return null; 91 | } 92 | 93 | // On Android the image format is YUV and we get a buffer per channel, 94 | // in iOS the format is BGRA and we get a single buffer for all channels. 95 | // So the yBuffer variable on Android will be just the Y channel but on iOS it will be 96 | // the entire image 97 | var planes = image.planes; 98 | var yBuffer = planes[0].bytes; 99 | 100 | Uint8List? uBuffer; 101 | Uint8List? vBuffer; 102 | 103 | if (Platform.isAndroid) { 104 | uBuffer = planes[1].bytes; 105 | vBuffer = planes[2].bytes; 106 | } 107 | 108 | var res = _nativeOpencv!.detect(image.width, image.height, rotation, yBuffer, uBuffer, vBuffer); 109 | return res; 110 | } 111 | 112 | destroy() { 113 | if (_nativeOpencv != null) { 114 | _nativeOpencv!.destroy(); 115 | _nativeOpencv = null; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /opencv_app/lib/detector/aruco_detector_async.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:developer'; 3 | import 'dart:isolate'; 4 | import 'dart:typed_data'; 5 | import 'package:camera/camera.dart'; 6 | import 'package:flutter/services.dart'; 7 | import 'package:opencv_app/detector/aruco_detector.dart' as aruco_detector; 8 | 9 | class ArucoDetectorAsync { 10 | bool arThreadReady = false; 11 | late Isolate _detectorThread; 12 | late SendPort _toDetectorThread; 13 | int _reqId = 0; 14 | final Map _cbs = {}; 15 | 16 | ArucoDetectorAsync() { 17 | _initDetectionThread(); 18 | } 19 | 20 | void _initDetectionThread() async { 21 | // Create the port on which the detector thread will send us messages and listen to it. 22 | ReceivePort fromDetectorThread = ReceivePort(); 23 | fromDetectorThread.listen(_handleMessage, onDone: () { 24 | arThreadReady = false; 25 | }); 26 | 27 | // Spawn a new Isolate using the ArucoDetector.init method as entry point and 28 | // the port on which it can send us messages as parameter 29 | final bytes = await rootBundle.load('assets/drawable/marker.png'); 30 | final initReq = aruco_detector.InitRequest(toMainThread: fromDetectorThread.sendPort, markerPng: bytes); 31 | _detectorThread = await Isolate.spawn(aruco_detector.init, initReq); 32 | } 33 | 34 | Future detect(CameraImage image, int rotation) { 35 | if (!arThreadReady) { 36 | return Future.value(null); 37 | } 38 | 39 | var reqId = ++_reqId; 40 | var res = Completer(); 41 | _cbs[reqId] = res; 42 | var msg = aruco_detector.Request( 43 | reqId: reqId, 44 | method: 'detect', 45 | params: {'image': image, 'rotation': rotation}, 46 | ); 47 | 48 | _toDetectorThread.send(msg); 49 | return res.future; 50 | } 51 | 52 | void destroy() async { 53 | if (!arThreadReady) { 54 | return; 55 | } 56 | 57 | arThreadReady = false; 58 | 59 | // We send a Destroy request and wait for a response before killing the thread 60 | var reqId = ++_reqId; 61 | var res = Completer(); 62 | _cbs[reqId] = res; 63 | var msg = aruco_detector.Request(reqId: reqId, method: 'destroy'); 64 | _toDetectorThread.send(msg); 65 | 66 | // Wait for the detector to acknoledge the destory and kill the thread 67 | await res.future; 68 | _detectorThread.kill(); 69 | } 70 | 71 | void _handleMessage(data) { 72 | // The detector thread send us its SendPort on init, if we got it this meand the detector is ready 73 | if (data is SendPort) { 74 | _toDetectorThread = data; 75 | arThreadReady = true; 76 | return; 77 | } 78 | 79 | // Make sure we got a Response object 80 | if (data is aruco_detector.Response) { 81 | // Find the Completer associated with this request and resolve it 82 | var reqId = data.reqId; 83 | _cbs[reqId]?.complete(data.data); 84 | _cbs.remove(reqId); 85 | return; 86 | } 87 | 88 | log('Unknown message from ArucoDetector, got: $data'); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /opencv_app/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:native_opencv/native_opencv.dart'; 6 | import 'package:opencv_app/detection/detection_page.dart'; 7 | 8 | void main() async { 9 | WidgetsFlutterBinding.ensureInitialized(); 10 | await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); 11 | 12 | runApp(const OpenCVApp()); 13 | } 14 | 15 | class OpenCVApp extends StatelessWidget { 16 | const OpenCVApp({Key? key}) : super(key: key); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return const MaterialApp( 21 | title: 'Flutter Demo', 22 | home: HomePage(), 23 | ); 24 | } 25 | } 26 | 27 | class HomePage extends StatelessWidget { 28 | const HomePage({Key? key}) : super(key: key); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return Container( 33 | color: Colors.white, 34 | child: Center( 35 | child: ElevatedButton( 36 | child: const Text('Camera'), 37 | onPressed: () { 38 | Navigator.of(context).push(MaterialPageRoute(builder: (ctx) { 39 | return const DetectionPage(); 40 | })); 41 | }, 42 | ), 43 | ), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /opencv_app/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.2" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | camera: 19 | dependency: "direct main" 20 | description: 21 | name: camera 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "0.9.4+5" 25 | camera_platform_interface: 26 | dependency: transitive 27 | description: 28 | name: camera_platform_interface 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.1.4" 32 | camera_web: 33 | dependency: transitive 34 | description: 35 | name: camera_web 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "0.2.1+1" 39 | characters: 40 | dependency: transitive 41 | description: 42 | name: characters 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.2.0" 46 | charcode: 47 | dependency: transitive 48 | description: 49 | name: charcode 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.3.1" 53 | clock: 54 | dependency: transitive 55 | description: 56 | name: clock 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.1.0" 60 | collection: 61 | dependency: transitive 62 | description: 63 | name: collection 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.15.0" 67 | cross_file: 68 | dependency: transitive 69 | description: 70 | name: cross_file 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "0.3.2" 74 | fake_async: 75 | dependency: transitive 76 | description: 77 | name: fake_async 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "1.2.0" 81 | ffi: 82 | dependency: transitive 83 | description: 84 | name: ffi 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "1.1.2" 88 | flutter: 89 | dependency: "direct main" 90 | description: flutter 91 | source: sdk 92 | version: "0.0.0" 93 | flutter_lints: 94 | dependency: "direct dev" 95 | description: 96 | name: flutter_lints 97 | url: "https://pub.dartlang.org" 98 | source: hosted 99 | version: "1.0.4" 100 | flutter_plugin_android_lifecycle: 101 | dependency: transitive 102 | description: 103 | name: flutter_plugin_android_lifecycle 104 | url: "https://pub.dartlang.org" 105 | source: hosted 106 | version: "2.0.5" 107 | flutter_test: 108 | dependency: "direct dev" 109 | description: flutter 110 | source: sdk 111 | version: "0.0.0" 112 | flutter_web_plugins: 113 | dependency: transitive 114 | description: flutter 115 | source: sdk 116 | version: "0.0.0" 117 | js: 118 | dependency: transitive 119 | description: 120 | name: js 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "0.6.3" 124 | lints: 125 | dependency: transitive 126 | description: 127 | name: lints 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.0.1" 131 | matcher: 132 | dependency: transitive 133 | description: 134 | name: matcher 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "0.12.11" 138 | meta: 139 | dependency: transitive 140 | description: 141 | name: meta 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.7.0" 145 | native_opencv: 146 | dependency: "direct main" 147 | description: 148 | path: "../native_opencv" 149 | relative: true 150 | source: path 151 | version: "0.0.1" 152 | path: 153 | dependency: transitive 154 | description: 155 | name: path 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.8.0" 159 | pedantic: 160 | dependency: transitive 161 | description: 162 | name: pedantic 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.11.1" 166 | plugin_platform_interface: 167 | dependency: transitive 168 | description: 169 | name: plugin_platform_interface 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "2.1.2" 173 | quiver: 174 | dependency: transitive 175 | description: 176 | name: quiver 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "3.0.1+1" 180 | sky_engine: 181 | dependency: transitive 182 | description: flutter 183 | source: sdk 184 | version: "0.0.99" 185 | source_span: 186 | dependency: transitive 187 | description: 188 | name: source_span 189 | url: "https://pub.dartlang.org" 190 | source: hosted 191 | version: "1.8.1" 192 | stack_trace: 193 | dependency: transitive 194 | description: 195 | name: stack_trace 196 | url: "https://pub.dartlang.org" 197 | source: hosted 198 | version: "1.10.0" 199 | stream_channel: 200 | dependency: transitive 201 | description: 202 | name: stream_channel 203 | url: "https://pub.dartlang.org" 204 | source: hosted 205 | version: "2.1.0" 206 | stream_transform: 207 | dependency: transitive 208 | description: 209 | name: stream_transform 210 | url: "https://pub.dartlang.org" 211 | source: hosted 212 | version: "2.0.0" 213 | string_scanner: 214 | dependency: transitive 215 | description: 216 | name: string_scanner 217 | url: "https://pub.dartlang.org" 218 | source: hosted 219 | version: "1.1.0" 220 | term_glyph: 221 | dependency: transitive 222 | description: 223 | name: term_glyph 224 | url: "https://pub.dartlang.org" 225 | source: hosted 226 | version: "1.2.0" 227 | test_api: 228 | dependency: transitive 229 | description: 230 | name: test_api 231 | url: "https://pub.dartlang.org" 232 | source: hosted 233 | version: "0.4.3" 234 | typed_data: 235 | dependency: transitive 236 | description: 237 | name: typed_data 238 | url: "https://pub.dartlang.org" 239 | source: hosted 240 | version: "1.3.0" 241 | vector_math: 242 | dependency: transitive 243 | description: 244 | name: vector_math 245 | url: "https://pub.dartlang.org" 246 | source: hosted 247 | version: "2.1.1" 248 | sdks: 249 | dart: ">=2.15.1 <3.0.0" 250 | flutter: ">=2.5.0" 251 | -------------------------------------------------------------------------------- /opencv_app/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: opencv_app 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.15.1 <3.0.0" 22 | 23 | # Dependencies specify other packages that your package needs in order to work. 24 | # To automatically upgrade your package dependencies to the latest versions 25 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 26 | # dependencies can be manually updated by changing the version numbers below to 27 | # the latest version available on pub.dev. To see which dependencies have newer 28 | # versions available, run `flutter pub outdated`. 29 | dependencies: 30 | flutter: 31 | sdk: flutter 32 | camera: ^0.9.4+5 33 | native_opencv: 34 | path: ../native_opencv 35 | 36 | dev_dependencies: 37 | flutter_test: 38 | sdk: flutter 39 | 40 | # The "flutter_lints" package below contains a set of recommended lints to 41 | # encourage good coding practices. The lint set provided by the package is 42 | # activated in the `analysis_options.yaml` file located at the root of your 43 | # package. See that file for information about deactivating specific lint 44 | # rules and activating additional ones. 45 | flutter_lints: ^1.0.0 46 | 47 | # For information on the generic Dart part of this file, see the 48 | # following page: https://dart.dev/tools/pub/pubspec 49 | 50 | # The following section is specific to Flutter. 51 | flutter: 52 | 53 | # The following line ensures that the Material Icons font is 54 | # included with your application, so that you can use the icons in 55 | # the material Icons class. 56 | uses-material-design: true 57 | 58 | # To add assets to your application, add an assets section, like this: 59 | assets: 60 | - assets/drawable/ 61 | 62 | # An image asset can refer to one or more resolution-specific "variants", see 63 | # https://flutter.dev/assets-and-images/#resolution-aware. 64 | 65 | # For details regarding adding assets from package dependencies, see 66 | # https://flutter.dev/assets-and-images/#from-packages 67 | 68 | # To add custom fonts to your application, add a fonts section here, 69 | # in this "flutter" section. Each entry in this list should have a 70 | # "family" key with the font family name, and a "fonts" key with a 71 | # list giving the asset and other descriptors for the font. For 72 | # example: 73 | # fonts: 74 | # - family: Schyler 75 | # fonts: 76 | # - asset: fonts/Schyler-Regular.ttf 77 | # - asset: fonts/Schyler-Italic.ttf 78 | # style: italic 79 | # - family: Trajan Pro 80 | # fonts: 81 | # - asset: fonts/TrajanPro.ttf 82 | # - asset: fonts/TrajanPro_Bold.ttf 83 | # weight: 700 84 | # 85 | # For details regarding fonts from package dependencies, 86 | # see https://flutter.dev/custom-fonts/#from-packages 87 | -------------------------------------------------------------------------------- /opencv_app/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:opencv_app/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # flutter-opencv-stream-processing 2 | Sample project of running OpenCV C++ code in a flutter app processing real-time camera frames. 3 | 4 | # YouTube tutorial 5 | [OpenCV C++ in Flutter using Isolate for background processing](https://www.youtube.com/watch?v=wGH_KWpaAVM) 6 | 7 | # Step by Step tutorial 8 | Can be found [here](./tutorial.md) 9 | 10 | 11 | -------------------------------------------------------------------------------- /tutorial.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | In this tutorial we will go over on how to use OpenCV with flutter to process real-time camera frames in C++. 3 | 4 | The Aruco detector we will use can be found [here](https://github.com/ValYouW/ArucoDetector), there is also a [YouTube video](https://www.youtube.com/watch?v=aXB04DleOiE). 5 | 6 | Using C/C++ in Flutter is available via [Dart FFI](https://docs.flutter.dev/development/platform-integration/c-interop). 7 | 8 | # Get the starter project 9 | This tutorial is built upon a starter app, you can get the starter app by cloning this repo and checking out to tag `tutorial-start-here`. 10 | 11 | ## The widgets in the starter app 12 | 1. `detection_page.dart` - This is the Aruco detector class, it has a single `detect` method that currently does nothing. 13 | 1. `detection_page.dart` - This is where we open the camera and display a live feed, main functions: 14 | 1. `initCamera` - Here we open the back camera and register to the camera stream `_camController!.startImageStream((image) => _processCameraImage(image))` 15 | 1. `_processCameraImage` - Here we just call to the aruco detector with the current camera frame. 16 | 1. `detections_layer.dart` - This will be the widget that will render the arucos we would find, it will use a `CustomPaint` to do the job. 17 | 18 | # Create the native_opencv plugin 19 | 20 | `flutter create --platforms=android,ios --template=plugin native_opencv --org com.valyouw` 21 | 22 | # Android Studio 23 | 24 | Open Android Studio: `native_opencv/example/android` 25 | 26 | 1. Copy the ArucoDetector to ios/Classes 27 | 1. Create native_opencv.cpp in ios/Classes 28 | 1. Create a `CMakeLists.txt` under Android/ 29 | 30 | ## CMakeLists: 31 | ``` 32 | cmake_minimum_required(VERSION 3.10.2) 33 | 34 | # opencv 35 | set(OpenCV_STATIC ON) 36 | set(OpenCV_DIR $ENV{OPENCV_ANDROID}/sdk/native/jni) 37 | find_package (OpenCV REQUIRED) 38 | 39 | add_library( # Sets the name of the library. 40 | native_opencv 41 | SHARED 42 | # Provides a relative path to your source file(s). 43 | ../ios/Classes/ArucoDetector/ArucoDetector.cpp 44 | ../ios/Classes/native_opencv.cpp 45 | ) 46 | 47 | target_include_directories( 48 | native_opencv PRIVATE 49 | ../ios/Classes/ArucoDetector 50 | ) 51 | 52 | find_library(log-lib log) 53 | 54 | target_link_libraries( # Specifies the target library. 55 | native_opencv 56 | ${OpenCV_LIBS} 57 | ${log-lib} 58 | ) 59 | ``` 60 | 61 | ## Build setup 62 | 63 | Open `build.gradle` of native_opencv and add this inside the "android {" section 64 | ``` 65 | externalNativeBuild { 66 | cmake { 67 | path "CMakeLists.txt" 68 | version "3.10.2" 69 | } 70 | } 71 | ``` 72 | 73 | 1. Run sync - it will fail, in the build log look for **"Minimum required by OpenCV API level is android-21"** 74 | 1. Change `minSdkVersion` to 24 in **build.gradle** of native_opencv AND of the **android:app**, there also change `targetSdkVersion` and `compileSdkVersion` to 31 75 | 1. Run sync again 76 | 1. Check that the "cpp" folder was populated 77 | 78 | ## native_opencv.cpp 79 | Add this initial code 80 | ``` 81 | #include 82 | #include "ArucoDetector.h" 83 | 84 | using namespace std; 85 | using namespace cv; 86 | 87 | static ArucoDetector* detector = nullptr; 88 | 89 | void rotateMat(Mat &matImage, int rotation) 90 | { 91 | if (rotation == 90) { 92 | transpose(matImage, matImage); 93 | flip(matImage, matImage, 1); //transpose+flip(1)=CW 94 | } else if (rotation == 270) { 95 | transpose(matImage, matImage); 96 | flip(matImage, matImage, 0); //transpose+flip(0)=CCW 97 | } else if (rotation == 180) { 98 | flip(matImage, matImage, -1); //flip(-1)=180 99 | } 100 | } 101 | 102 | extern "C" { 103 | // Attributes to prevent 'unused' function from being removed and to make it visible 104 | __attribute__((visibility("default"))) __attribute__((used)) 105 | const char* version() { 106 | return CV_VERSION; 107 | } 108 | } 109 | ``` 110 | 111 | Build the project and show how it compiles the ArucoDetector.cpp 112 | 113 | # VSCode 114 | 1. Open `native_opencv` 115 | 1. Add `ffi: ^1.1.2` to `pubspec.yaml` under `dependencies` 116 | 1. Add this to `native_opencv.dart` 117 | ``` 118 | // Load our C lib 119 | final DynamicLibrary nativeLib = 120 | Platform.isAndroid ? DynamicLibrary.open("libnative_opencv.so") : DynamicLibrary.process(); 121 | 122 | // C Functions signatures 123 | typedef _c_version = Pointer Function(); 124 | 125 | // Dart functions signatures 126 | typedef _dart_version = Pointer Function(); 127 | 128 | // Create dart functions that invoke the C function 129 | final _version = nativeLib.lookupFunction<_c_version, _dart_version>('version'); 130 | 131 | class NativeOpencv { 132 | static const MethodChannel _channel = MethodChannel('native_opencv'); 133 | 134 | static Future get platformVersion async { 135 | final String? version = await _channel.invokeMethod('getPlatformVersion'); 136 | return version; 137 | } 138 | 139 | String cvVersion() { 140 | return _version().toDartString(); 141 | } 142 | } 143 | ``` 144 | 145 | ## Use native_opencv in opencv_app 146 | 1. Add native_opencv as dep 147 | ``` 148 | native_opencv: 149 | path: ../native_opencv 150 | ``` 151 | 1. Add to `main.dart` `main()` method 152 | ``` 153 | final nativeOpencv = NativeOpencv(); 154 | log('--> OpenCV version: ${nativeOpencv.cvVersion()}'); 155 | ``` 156 | 1. Run the app and watch the console for output 157 | 158 | # Expose ArucoDetector functions 159 | Back in AndroidStudio open `native_opencv.cpp` 160 | ```cpp 161 | __attribute__((visibility("default"))) __attribute__((used)) 162 | void initDetector(uint8_t* markerPngBytes, int inBytesCount, int bits) { 163 | if (detector != nullptr) { 164 | delete detector; 165 | detector = nullptr; 166 | } 167 | 168 | vector buffer(markerPngBytes, markerPngBytes + inBytesCount); 169 | Mat marker = imdecode(buffer, IMREAD_COLOR); 170 | 171 | detector = new ArucoDetector(marker, bits); 172 | } 173 | 174 | __attribute__((visibility("default"))) __attribute__((used)) 175 | void destroyDetector() { 176 | if (detector != nullptr) { 177 | delete detector; 178 | detector = nullptr; 179 | } 180 | } 181 | 182 | __attribute__((visibility("default"))) __attribute__((used)) 183 | const float* detect(int width, int height, int rotation, uint8_t* bytes, bool isYUV, int32_t* outCount) { 184 | if (detector == nullptr) { 185 | float* jres = new float[1]; 186 | jres[0] = 0; 187 | return jres; 188 | } 189 | 190 | Mat frame; 191 | if (isYUV) { 192 | Mat myyuv(height + height / 2, width, CV_8UC1, bytes); 193 | cvtColor(myyuv, frame, COLOR_YUV2BGRA_NV21); 194 | } else { 195 | frame = Mat(height, width, CV_8UC4, bytes); 196 | } 197 | 198 | rotateMat(frame, rotation); 199 | cvtColor(frame, frame, COLOR_BGRA2GRAY); 200 | vector res = detector->detectArucos(frame, 0); 201 | 202 | vector output; 203 | 204 | for (int i = 0; i < res.size(); ++i) { 205 | ArucoResult ar = res[i]; 206 | // each aruco has 4 corners 207 | output.push_back(ar.corners[0].x); 208 | output.push_back(ar.corners[0].y); 209 | output.push_back(ar.corners[1].x); 210 | output.push_back(ar.corners[1].y); 211 | output.push_back(ar.corners[2].x); 212 | output.push_back(ar.corners[2].y); 213 | output.push_back(ar.corners[3].x); 214 | output.push_back(ar.corners[3].y); 215 | } 216 | 217 | // Copy result bytes as output vec will get freed 218 | unsigned int total = sizeof(float) * output.size(); 219 | float* jres = (float*)malloc(total); 220 | memcpy(jres, output.data(), total); 221 | 222 | *outCount = output.size(); 223 | return jres; 224 | } 225 | ``` 226 | And now in `native_opencv.dart` in VSCode define the C Functions 227 | ```dart 228 | typedef _c_initDetector = Void Function(Pointer markerPngBytes, Int32 inSize, Int32 bits); 229 | typedef _c_destroyDetector = Void Function(); 230 | typedef _c_detect = Pointer Function( 231 | Int32 width, Int32 height, Int32 rotation, Pointer bytes, Bool isYUV, Pointer outCount); 232 | ``` 233 | And the Dart Functions 234 | ```dart 235 | typedef _dart_version = Pointer Function(); 236 | typedef _dart_initDetector = void Function(Pointer markerPngBytes, int inSize, int bits); 237 | typedef _dart_destroyDetector = void Function(); 238 | typedef _dart_detect = Pointer Function( 239 | int width, int height, int rotation, Pointer bytes, bool isYUV, Pointer outCount); 240 | ``` 241 | And finally associate the functions 242 | ```dart 243 | final _initDetector = nativeLib.lookupFunction<_c_initDetector, _dart_initDetector>('initDetector'); 244 | final _destroyDetector = nativeLib.lookupFunction<_c_destroyDetector, _dart_destroyDetector>('destroyDetector'); 245 | final _detect = nativeLib.lookupFunction<_c_detect, _dart_detect>('detect'); 246 | ``` 247 | 248 | And inside `class NativeOpencv` define the methods that will be exposed to our app: 249 | ```dart 250 | // Reuse this aloocated buffer when running detection so we won't re-allocate on every call to "detect" 251 | Pointer? _imageBuffer; 252 | 253 | void initDetector(Uint8List markerPngBytes, int bits) { 254 | var totalSize = markerPngBytes.lengthInBytes; 255 | var imgBuffer = malloc.allocate(totalSize); 256 | Uint8List bytes = imgBuffer.asTypedList(totalSize); 257 | bytes.setAll(0, markerPngBytes); 258 | 259 | _initDetector(imgBuffer, totalSize, bits); 260 | 261 | //// todo: Should delete imgBuffer ?? 262 | } 263 | 264 | void destroy() { 265 | _destroyDetector(); 266 | } 267 | 268 | Float32List detect(int width, int height, int rotation, Uint8List yBuffer, Uint8List? uBuffer, Uint8List? vBuffer) { 269 | var ySize = yBuffer.lengthInBytes; 270 | var uSize = uBuffer?.lengthInBytes ?? 0; 271 | var vSize = vBuffer?.lengthInBytes ?? 0; 272 | var totalSize = ySize + uSize + vSize; 273 | 274 | _imageBuffer ??= malloc.allocate(totalSize); 275 | 276 | // We always have at least 1 plane, on Android it si the yPlane on iOS its the rgba plane 277 | Uint8List _bytes = _imageBuffer!.asTypedList(totalSize); 278 | _bytes.setAll(0, yBuffer); 279 | 280 | if (Platform.isAndroid) { 281 | // Swap u&v buffer for opencv 282 | _bytes.setAll(ySize, vBuffer!); 283 | _bytes.setAll(ySize + vSize, uBuffer!); 284 | } 285 | 286 | Pointer outCount = malloc.allocate(1); 287 | var res = _detect(width, height, rotation, _imageBuffer!, Platform.isAndroid ? true : false, outCount); 288 | final count = outCount.value; 289 | 290 | //// todo: Should delete outCount ?? 291 | return res.asTypedList(count); 292 | } 293 | ``` 294 | 295 | # Use native_opencv plugin in flutter app 296 | 297 | ## ArucoDetector class 298 | In `aruco_detector.dart` this is the implementation: 299 | ```dart 300 | class ArucoDetector { 301 | NativeOpencv? _nativeOpencv; 302 | 303 | ArucoDetector() { 304 | init(); 305 | } 306 | 307 | init() async { 308 | // Read the marker template from the assets folder, note it is read in png format which is what 309 | // our c++ init detector code expects 310 | final bytes = await rootBundle.load('assets/drawable/marker.png'); 311 | final pngBytes = bytes.buffer.asUint8List(); 312 | 313 | // init the detector 314 | _nativeOpencv = NativeOpencv(); 315 | _nativeOpencv!.initDetector(pngBytes, 36); 316 | } 317 | 318 | Float32List? detect(CameraImage image, int rotation) { 319 | // make sure we have a detector 320 | if (_nativeOpencv == null) { 321 | return null; 322 | } 323 | 324 | // On Android the image format is YUV and we get a buffer per channel, 325 | // in iOS the format is BGRA and we get a single buffer for all channels. 326 | // So the yBuffer variable on Android will be just the Y channel but on iOS it will be 327 | // the entire image 328 | var planes = image.planes; 329 | var yBuffer = planes[0].bytes; 330 | 331 | Uint8List? uBuffer; 332 | Uint8List? vBuffer; 333 | 334 | if (Platform.isAndroid) { 335 | uBuffer = planes[1].bytes; 336 | vBuffer = planes[2].bytes; 337 | } 338 | 339 | var res = _nativeOpencv!.detect(image.width, image.height, rotation, yBuffer, uBuffer, vBuffer); 340 | return res; 341 | } 342 | 343 | destroy() { 344 | if (_nativeOpencv != null) { 345 | _nativeOpencv!.destroy(); 346 | _nativeOpencv = null; 347 | } 348 | } 349 | } 350 | ``` 351 | 352 | ## Call detection on each camera frame 353 | In `detection_page.dart` add these 2 members to `_DetectionPageState`: 354 | ```dart 355 | double _camFrameToScreenScale = 0; 356 | List _arucos = List.empty(); 357 | ``` 358 | Then this is the updated `_processCameraImage` method: 359 | ```dart 360 | void _processCameraImage(CameraImage image) async { 361 | if (!mounted || DateTime.now().millisecondsSinceEpoch - _lastRun < 30) { 362 | return; 363 | } 364 | 365 | // calc the scale factor to convert from camera frame coords to screen coords. 366 | // NOTE!!!! We assume camera frame takes the entire screen width, if that's not the case 367 | // (like if camera is landscape or the camera frame is limited to some area) then you will 368 | // have to find the correct scale factor somehow else 369 | if (_camFrameToScreenScale == 0) { 370 | var w = (_camFrameRotation == 0 || _camFrameRotation == 180) ? image.width : image.height; 371 | _camFrameToScreenScale = MediaQuery.of(context).size.width / w; 372 | } 373 | 374 | // Call the detector 375 | var res = _arucoDetector.detect(image, _camFrameRotation); 376 | _lastRun = DateTime.now().millisecondsSinceEpoch; 377 | 378 | if (res == null || res.isEmpty) { 379 | return; 380 | } 381 | 382 | // Check that the number of coords we got divides by 8 exactly, each aruco has 8 coords (4 corners x/y) 383 | if ((res.length / 8) != (res.length ~/ 8)) { 384 | log('Got invalid response from ArucoDetector, number of coords is ${res.length} and does not represent complete arucos with 4 corners'); 385 | return; 386 | } 387 | 388 | // convert arucos from camera frame coords to screen coords 389 | final arucos = res.map((x) => x * _camFrameToScreenScale).toList(growable: false); 390 | setState(() { 391 | _arucos = arucos; 392 | }); 393 | } 394 | ``` 395 | 396 | ## Drawing the Aruco results on DetectionsLayer 397 | Take a look at `detections_layer.dart` it is already implemented to draw the arucos onto a canvas using a custom painter. 398 | 399 | Run the app and point it to some Arucos, see if it works... 400 | 401 | # Running detection on background thread 402 | Currently our detection runs on the main (ui) thread and we should avoid running intensive work on the ui thread, so lets run our detector on a separate thread, or as it is called in Dart - Isolate. 403 | 404 | ## Changes to `aruco_detector.dart` 405 | We will convert this file to be the entry point of our new Isolate. 406 | 407 | 1. Convert the `ArucoDetector` class to be private by renaming it to `_ArucoDetector`. This class will only be used locally int his file. 408 | 1. Add the Request/Response classes that will be sent between the 409 | ```dart 410 | // This class will be used as argument to the init method, since we cant access the bundled assets 411 | // from an Isolate we must get the marker png from the main thread 412 | class InitRequest { 413 | SendPort toMainThread; 414 | ByteData markerPng; 415 | InitRequest({required this.toMainThread, required this.markerPng}); 416 | } 417 | 418 | // this is the class that the main thread will send here asking to invoke a function on ArucoDetector 419 | class Request { 420 | // a correlation id so the main thread will be able to match response with request 421 | int reqId; 422 | String method; 423 | dynamic params; 424 | Request({required this.reqId, required this.method, this.params}); 425 | } 426 | 427 | // this is the class that will be sent as a response to the main thread 428 | class Response { 429 | int reqId; 430 | dynamic data; 431 | Response({required this.reqId, this.data}); 432 | } 433 | 434 | // This is the port that will be used to send data to main thread 435 | late SendPort _toMainThread; 436 | late _ArucoDetector _detector; 437 | ``` 438 | 439 | Next lets write the function that will be the entry point when the main thread will invoke a new Isolate: 440 | ```dart 441 | void init(InitRequest initReq) { 442 | // Create ArucoDetector 443 | _detector = _ArucoDetector(initReq.markerPng); 444 | 445 | // Save the port on which we will send messages to the main thread 446 | _toMainThread = initReq.toMainThread; 447 | 448 | // Create a port on which the main thread can send us messages and listen to it 449 | ReceivePort fromMainThread = ReceivePort(); 450 | fromMainThread.listen(_handleMessage); 451 | 452 | // Send the main thread the port on which it can send us messages 453 | _toMainThread.send(fromMainThread.sendPort); 454 | } 455 | ``` 456 | This is the `_handleMessage` function where we handle incoming requests from the main thread: 457 | ```dart 458 | void _handleMessage(data) { 459 | if (data is Request) { 460 | dynamic res; 461 | switch (data.method) { 462 | case 'detect': 463 | var image = data.params['image'] as CameraImage; 464 | var rotation = data.params['rotation']; 465 | res = _detector.detect(image, rotation); 466 | break; 467 | case 'destroy': 468 | _detector.destroy(); 469 | break; 470 | default: 471 | log('Unknown method: ${data.method}'); 472 | } 473 | 474 | _toMainThread.send(Response(reqId: data.reqId, data: res)); 475 | } 476 | } 477 | ``` 478 | 479 | And change `_ArucoDetector` to receive the marker png in its constructor and pass it on to its `init` method: 480 | ```dart 481 | _ArucoDetector(ByteData markerPng) { 482 | init(markerPng); 483 | } 484 | 485 | init(ByteData markerPng) async { 486 | // Note our c++ init detector code expects marker to be in png format 487 | final pngBytes = markerPng.buffer.asUint8List(); 488 | ... 489 | } 490 | ``` 491 | 492 | ## ArucoDetector wrapper 493 | In order to prevent the detection page of handling the background thread lets create a wrapper around ArucoDetector that will do that. We call it `ArucoDetectorAsync` 494 | 495 | Create a file `aruco_detector_async.dart` 496 | ```dart 497 | import 'dart:async'; 498 | import 'dart:developer'; 499 | import 'dart:isolate'; 500 | import 'dart:typed_data'; 501 | import 'package:camera/camera.dart'; 502 | import 'package:opencv_app/detector/aruco_detector.dart' as aruco_detector; 503 | 504 | class ArucoDetectorAsync { 505 | bool arThreadReady = false; 506 | late Isolate _detectorThread; 507 | late SendPort _toDetectorThread; 508 | int _reqId = 0; 509 | final Map _cbs = {}; 510 | 511 | ArucoDetectorAsync() { 512 | _initDetectionThread(); 513 | } 514 | 515 | void _initDetectionThread() async { 516 | // Create the port on which the detector thread will send us messages and listen to it. 517 | ReceivePort fromDetectorThread = ReceivePort(); 518 | fromDetectorThread.listen(_handleMessage, onDone: () { 519 | arThreadReady = false; 520 | }); 521 | 522 | // Spawn a new Isolate using the ArucoDetector.init method as entry point and 523 | // the port on which it can send us messages as parameter 524 | final bytes = await rootBundle.load('assets/drawable/marker.png'); 525 | final initReq = aruco_detector.InitRequest(toMainThread: fromDetectorThread.sendPort, markerPng: bytes); 526 | _detectorThread = await Isolate.spawn(aruco_detector.init, initReq); 527 | } 528 | 529 | Future detect(CameraImage image, int rotation) { 530 | if (!arThreadReady) { 531 | return Future.value(null); 532 | } 533 | 534 | var reqId = ++_reqId; 535 | var res = Completer(); 536 | _cbs[reqId] = res; 537 | var msg = aruco_detector.Request( 538 | reqId: reqId, 539 | method: 'detect', 540 | params: {'image': image, 'rotation': rotation}, 541 | ); 542 | 543 | _toDetectorThread.send(msg); 544 | return res.future; 545 | } 546 | 547 | void destroy() async { 548 | if (!arThreadReady) { 549 | return; 550 | } 551 | 552 | arThreadReady = false; 553 | 554 | // We send a Destroy request and wait for a response before killing the thread 555 | var reqId = ++_reqId; 556 | var res = Completer(); 557 | _cbs[reqId] = res; 558 | var msg = aruco_detector.Request(reqId: reqId, method: 'destroy'); 559 | _toDetectorThread.send(msg); 560 | 561 | // Wait for the detector to acknoledge the destory and kill the thread 562 | await res.future; 563 | _detectorThread.kill(); 564 | } 565 | 566 | void _handleMessage(data) { 567 | // The detector thread send us its SendPort on init, if we got it this means the detector is ready 568 | if (data is SendPort) { 569 | _toDetectorThread = data; 570 | arThreadReady = true; 571 | return; 572 | } 573 | 574 | // Make sure we got a Response object 575 | if (data is aruco_detector.Response) { 576 | // Find the Completer associated with this request and resolve it 577 | var reqId = data.reqId; 578 | _cbs[reqId]?.complete(data.data); 579 | _cbs.remove(reqId); 580 | return; 581 | } 582 | 583 | log('Unknown message from ArucoDetector, got: $data'); 584 | } 585 | } 586 | ``` 587 | 588 | ## Use ArucoDetectorAsync 589 | In `detection_page.dart` use `ArucoDetectorAsync` instead of `ArucoDetector` 590 | 1. Replace the definition and initialization of `_arucoDetecor` with `ArucoDetectorAsync` 591 | 1. Introduce a new class variable `bool _detectionInProgress = false;` - because detection is async now we need to make sure not to call it while it is already running 592 | 1. In `_processCameraImage`: 593 | 1. use `_detectionInProgress` in the first `if` so it becomes: `if (_detectionInProgress || !mounted || ...` 594 | 1. use `await` when calling to `detect` and set `_detectionInProgress` to true/false before/after calling detect, and make sure we are still mounted before handling the result: 595 | ```dart 596 | // Call the detector 597 | _detectionInProgress = true; 598 | var res = await _arucoDetector.detect(image, _camFrameRotation); 599 | _detectionInProgress = false; 600 | _lastRun = DateTime.now().millisecondsSinceEpoch; 601 | 602 | // Make sure we are still mounted, the background thread can return a response after we navigate away from this 603 | // screen but before bg thread is killed 604 | if (!mounted || res == null || res.isEmpty) { 605 | return; 606 | } 607 | ``` 608 | 609 | # iOS Support 610 | Time to handle ios, the items we have to do are: 611 | 1. Add OpenCV as a dependency to `native_opencv` plugin 612 | 1. Add the detector c++ files to `opencv_app` 613 | 1. Add camera permissions to `Info.plist` 614 | 615 | ## Add OpenCV 616 | Open `native_opencv/ios/native_opencv.podspec`, it should become 617 | ``` 618 | # 619 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 620 | # Run `pod lib lint native_opencv.podspec` to validate before publishing. 621 | # 622 | Pod::Spec.new do |s| 623 | s.name = 'native_opencv' 624 | s.version = '0.0.1' 625 | s.summary = 'A new flutter plugin project.' 626 | s.description = <<-DESC 627 | A new flutter plugin project. 628 | DESC 629 | s.homepage = 'http://example.com' 630 | s.license = { :file => '../LICENSE' } 631 | s.author = { 'Your Company' => 'email@example.com' } 632 | s.source = { :path => '.' } 633 | s.source_files = 'Classes/**/*' 634 | 635 | # Set as a static lib 636 | s.static_framework = true 637 | s.dependency 'Flutter' 638 | 639 | # Add OpenCV dep from cocoapods and update min ios ver to 11 640 | s.dependency 'OpenCV', '4.3.0' 641 | s.platform = :ios, '11.0' 642 | 643 | # module_map is needed so this module can be used as a framework 644 | s.module_map = 'native_opencv.modulemap' 645 | 646 | # Flutter.framework does not contain a i386 slice. 647 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } 648 | s.swift_version = '5.0' 649 | end 650 | ``` 651 | 652 | Next create `native_opencv/ios/native_opencv.modulemap` file with content: 653 | ``` 654 | framework module native_opencv {} 655 | ``` 656 | 657 | ## Update opencv_app ios build 658 | 1. Go to `opencv_app` and run `flutter pub get`, this will create a Podfile. 659 | 1. Edit `opencv_app/ios/Podfile` and add `platform :ios, '11.0'` to the first line, it is already there just uncomment it and change the ios version 660 | 1. Go to `opencv_app/ios` and run `pod install` 661 | 1. Open in xcode `opencv_app/ios/Runner.xcworkspace` 662 | 1. Edit `Runner/Info.plist` and add key `Privacy - Camera Usage Description` with some description 663 | 1. Right-click on `Runner` group and choose `Add files to Runner...` 664 | 1. Add the file `native_opencv/io/Classes/native_opencv.cpp` 665 | 1. Add the 2 files under `native_opencv/io/Classes/ArucoDetector` 666 | 1. Run the project 667 | 668 | # THE END 669 | --------------------------------------------------------------------------------