├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── drawable │ │ │ │ ├── lets.png │ │ │ │ ├── service.png │ │ │ │ ├── start_game.png │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_background.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── test_value.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── layout │ │ │ │ ├── activity_standalone.xml │ │ │ │ ├── fragment_password.xml │ │ │ │ ├── fragment_status.xml │ │ │ │ └── fragment_test_cv_.xml │ │ │ ├── xml │ │ │ │ └── device_filter.xml │ │ │ └── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ ├── cpp │ │ │ ├── util.h │ │ │ ├── pi_cv.h │ │ │ ├── pi2_cv.h │ │ │ ├── pi2_plot.h │ │ │ ├── HistType.h │ │ │ ├── pi_load.cpp │ │ │ ├── pi2_plot.cpp │ │ │ ├── pi2_cv.cpp │ │ │ └── pi_cv.cpp │ │ ├── java │ │ │ └── sermk │ │ │ │ └── pipi │ │ │ │ └── pilauncher │ │ │ │ ├── LogOptions.java │ │ │ │ ├── GUIFragment │ │ │ │ ├── SeekText.java │ │ │ │ ├── PasswordFragment.java │ │ │ │ ├── StatusFragment.java │ │ │ │ ├── CVMaskResolver.java │ │ │ │ ├── CVMaskView.java │ │ │ │ └── TestCV_Fragment.java │ │ │ │ ├── BehaviorSettings.java │ │ │ │ ├── PInterface_Impl.java │ │ │ │ ├── externalcooperation │ │ │ │ ├── RequestReciever.java │ │ │ │ ├── ProblemReceiver.java │ │ │ │ ├── SettingsReciever.java │ │ │ │ └── PiSettings.java │ │ │ │ ├── CVResolver.java │ │ │ │ ├── PiHandler.java │ │ │ │ ├── GlobalController.java │ │ │ │ ├── deprecated │ │ │ │ └── NotifyService.java │ │ │ │ ├── LauncherAct.java │ │ │ │ ├── PIService.java │ │ │ │ └── UVCReciver.java │ │ └── AndroidManifest.xml │ └── androidTest │ │ └── java │ │ └── sermk │ │ └── pipi │ │ └── pilauncher │ │ └── externalcooperation │ │ └── ProblemReceiverTest.java ├── proguard-rules.pro ├── CMakeLists.txt └── build.gradle ├── settingsCPP.jar ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitmodules ├── .editorconfig ├── settings.gradle ├── .gitignore ├── README.md ├── local.properties ├── gradle.properties ├── LICENSE ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settingsCPP.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/settingsCPP.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/lets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/drawable/lets.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/drawable/service.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/start_game.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/drawable/start_game.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/drawable/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ser-mk/pilauncher/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | PiLauncher 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "UVC"] 2 | path = UVC 3 | url = https://github.com/ARM-MK/UVC_library.git 4 | [submodule "EXT/PiLib"] 5 | path = EXT/PiLib 6 | url = https://github.com/ser-mk/pilib.git 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 640px 4 | 480px 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=false 5 | indent_style=space 6 | indent_size=4 7 | 8 | [*.json] 9 | indent_style=space 10 | indent_size=2 11 | 12 | [{*.yml,*.yaml}] 13 | indent_style=space 14 | indent_size=2 15 | 16 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':libuvccamera', ':openCVLibrary330', ':PiLib' 2 | project(':libuvccamera').projectDir = new File('UVC/libuvccamera') 3 | project(':openCVLibrary330').projectDir = new File('UVC/openCVLibrary330') 4 | project(':PiLib').projectDir = new File('EXT/PiLib') -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Oct 29 18:25:45 MSK 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-4.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/ 6 | /.idea/* 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | 12 | 13 | ############################ 14 | # Local configuration file (sdk path, etc) 15 | # local.properties 16 | *.properties 17 | # built application files 18 | *.apk 19 | *.ap_ 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pilauncher 2 | 3 | The control service for the Pinect hand-free game console. More info in the article: 4 | 5 | https://ser-mk.github.io/pinect/android1nput/ 6 | 7 | ## How Build 8 | To build you can use this repo https://github.com/ser-mk/pibuild 9 | 10 | ## Demo 11 | 12 | [demo1.webm](https://user-images.githubusercontent.com/6123791/214125630-00c7aa8a-a2a2-41dd-aabb-7709f062f4cc.webm) 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/test_value.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 111 4 | 44 5 | 70 6 | 16 7 | 70 8 | 16 9 | 1000 10 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file is automatically generated by Android Studio. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | # 7 | # Location of the SDK. This is only used by Gradle. 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | #Tue Feb 06 18:19:55 MSK 2018 11 | 12 | ndk.dir=/opt/android-ndk 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_standalone.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/cpp/util.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTIL__H__ 2 | #define __UTIL__H__ 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define LOG_TAG "PIPI-JNI#" 10 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 11 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 12 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) 13 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN ,LOG_TAG,__VA_ARGS__) 14 | #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE ,LOG_TAG,__VA_ARGS__) 15 | 16 | 17 | #define CLEAR(x) memset(&(x), 0, sizeof(x)) 18 | 19 | #define ERROR_LOCAL -1 20 | #define SUCCESS_LOCAL 0 21 | */ 22 | #endif // __UTIL__H__ 23 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/cpp/pi_cv.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by echormonov on 05.11.17. 3 | // 4 | 5 | #ifndef GAME_PIPI_CV_H 6 | #define GAME_PIPI_CV_H 7 | #include 8 | 9 | 10 | class pi_cv { 11 | 12 | static bool learn;// = false; 13 | static void resetLearnHist(); 14 | static void setupLearnHist(); 15 | public: 16 | static int setRectMask(jint xsRoi, jint ysRoi, ID_TYPE refMat); 17 | static int calcPipiChart(ID_TYPE refMatPreview, ID_TYPE refMatChart); 18 | static void setLearnEnable(bool enable){ 19 | const bool reset = (!learn) && enable; 20 | if(reset){ 21 | resetLearnHist(); 22 | } 23 | const bool setup = learn && (!enable); 24 | if(setup){ 25 | setupLearnHist(); 26 | } 27 | learn = enable; 28 | } 29 | static bool getLearnEnable(){ return learn; } 30 | }; 31 | 32 | 33 | #endif //GAME_PIPI_CV_H 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_password.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 16 | 17 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_status.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 16 | 17 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/LogOptions.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher; 2 | 3 | import com.orhanobut.logger.AndroidLogAdapter; 4 | import com.orhanobut.logger.FormatStrategy; 5 | import com.orhanobut.logger.Logger; 6 | import com.orhanobut.logger.PrettyFormatStrategy; 7 | 8 | /** 9 | * Created by ser on 31.10.17. 10 | */ 11 | 12 | abstract class LogOptions { 13 | 14 | static void SetupLog(){ 15 | FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder() 16 | .showThreadInfo(false) // (Optional) Whether to show thread info or not. Default true 17 | .methodCount(2) // (Optional) How many method line to show. Default 2 18 | .methodOffset(7) // (Optional) Hides internal method calls up to offset. Default 5 19 | //.logStrategy(customLog) // (Optional) Changes the log strategy to print out. Default LogCat 20 | .tag("@") // (Optional) Global tag for every log. Default PRETTY_LOGGER 21 | .build(); 22 | Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Evgeny Chormonov 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 | -------------------------------------------------------------------------------- /app/src/main/res/xml/device_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/GUIFragment/SeekText.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.GUIFragment; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.SeekBar; 6 | import android.widget.TextView; 7 | 8 | /** 9 | * Created by echormonov on 02.11.17. 10 | */ 11 | 12 | final public class SeekText extends SeekBar { 13 | 14 | private TextView tv; 15 | 16 | public void setTv(TextView tv) { 17 | this.tv = tv; 18 | } 19 | 20 | public SeekText(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | this.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { 23 | @Override 24 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 25 | if(tv == null) return; 26 | tv.setText(String.valueOf(progress)); 27 | } 28 | 29 | @Override 30 | public void onStartTrackingTouch(SeekBar seekBar) { 31 | 32 | } 33 | 34 | @Override 35 | public void onStopTrackingTouch(SeekBar seekBar) { 36 | if(tv == null) return; 37 | tv.setText(String.valueOf(seekBar.getProgress())); 38 | } 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/BehaviorSettings.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher; 2 | 3 | /** 4 | * Created by echormonov on 13.01.18. 5 | */ 6 | 7 | public class BehaviorSettings { 8 | 9 | final public int TIMES_PASS_START_GAME = 5; 10 | final public int TIMES_TRY_RESTART_UVC = 30; 11 | 12 | final public long TIMEOUT_BETWEEN_TRY_UVC_CONNECTION = 1000; 13 | final public int TRY_MAX_UVC_CONNECTION = 2; 14 | 15 | final public long WARMING_UP_TIME = 1000; 16 | final public long TRANNING_TIME = 1000; 17 | final public int COUNT_TRANNING_FRAMES = 10; 18 | 19 | final public long CAPTURE_WAIT_TIME = 300; 20 | final public long CAPTURE_FRAME_INTERVAL_PREV = 1000*60*60*12; 21 | public long CAPTURE_FRAME_INTERVAL = 1000*60*60*12; 22 | 23 | final public long VIBRATE_TIME_MS = 2*1000; 24 | 25 | public int MAX_PULSE_WIDTH = 200; //from width screen, default 640! 26 | public int MIN_PULSE_WIDTH = 2; // from width screen, default 640! 27 | final public int GAP_DECREASE_MASK = 50; // 1%20 from 1000 //set gap between learn and curr capture for bound 28 | 29 | final public long TIMEOUT_MS_FAIL_CONNECTION = 1000*60*10; 30 | final public long FINE_MS_FAIL_CONNECTION = 1000; 31 | 32 | final public String NAME_GAME_PACKAGE = "ser.pipi.piball"; 33 | final public String NAME_GAME_ACTIVITY = "ser.pipi.piball.AndroidLauncher"; 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/PInterface_Impl.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher; 2 | 3 | 4 | import android.os.RemoteException; 5 | import android.util.Log; 6 | 7 | import sermk.pipi.pilib.PiBind; 8 | import sermk.pipi.pilib.Pinterface; 9 | 10 | /** 11 | * Created by echormonov on 24.11.17. 12 | */ 13 | 14 | public class PInterface_Impl extends Pinterface.Stub implements CVResolver.ICallbackPosition 15 | { 16 | 17 | final String TAG = "PInterface_Impl"; 18 | @Override 19 | public int getPosition() throws RemoteException { 20 | //Log.v(TAG,"getPosition " + position); 21 | if (PIService.getStatusAttachedUSB() == PIService.ATTACHMENT_USB_INFO.DETACHED) 22 | return PiBind.CLOSE_GAME; 23 | return position; 24 | } 25 | 26 | private int position = PiBind.POSITION_UNDEFINED; 27 | 28 | @Override 29 | public boolean callbackPosition(int pos, final int width, CVResolver cvr) { 30 | //Log.v(TAG, "set position " + String.valueOf(pos)); 31 | if(pos < PiBind.POSITION_MIN){ 32 | position = PiBind.POSITION_UNDEFINED; 33 | } else { 34 | position = pos; 35 | } 36 | return true; 37 | } 38 | 39 | public void clearPosition(){ 40 | Log.i(TAG, "clearPosition!"); 41 | position = PiBind.POSITION_UNDEFINED; 42 | } 43 | 44 | public void sendingCloseCode(){ 45 | Log.i(TAG, "CLOSE GAME!"); 46 | position = PiBind.CLOSE_GAME; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/cpp/pi2_cv.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by echormonov on 12.11.17. 3 | // 4 | 5 | #ifndef GAME_PI2_CV_H 6 | #define GAME_PI2_CV_H 7 | #include 8 | #include 9 | #include "pi2_plot.h" 10 | 11 | class pi2_cv { 12 | 13 | enum MODE { 14 | CAPTURE = 0, 15 | LEARN, 16 | }; 17 | 18 | enum FRAME_CAPTURE_COMMAND { 19 | START_TO = 0, 20 | RETURN_RESULT, 21 | }; 22 | 23 | static int mode; 24 | 25 | static void cvProccessing(JNIEnv *env, uvc_frame_t *frame); 26 | static jobject objectCV; 27 | static jmethodID midCV; 28 | static cv::Rect maskRect; 29 | static bool enableSingleCaptureFrame; 30 | static cv::Mat captureFrame; 31 | static uint8_t arrayFromMask[pi2_plot::sizePreview]; 32 | static uint8_t arrayMask[pi2_plot::sizePreview]; 33 | static void calcUVC_FrameOfMask(uvc_frame_t *frame, const cv::Rect & maskRect); 34 | static int normilizePosition(const int position); 35 | 36 | static size_t MAX_PULSE_WIDTH; 37 | static size_t MIN_PULSE_WIDTH; 38 | static size_t GAP_DECREASE_MASK; 39 | 40 | public: 41 | 42 | static bool startCV(JNIEnv *env, jobject thiz); 43 | static void setRectOfMask(JNIEnv *env, jobject thiz, 44 | jint xsRoi, jint ysRoi, ID_TYPE refMat); 45 | 46 | static void setMode(JNIEnv *env, jobject thiz, jint mode); 47 | static jlong getFrame(JNIEnv *env, jobject thiz, jint mode); 48 | static void setOptions(JNIEnv *env, jobject thiz, jint MAX_PULSE_WIDTH, 49 | jint MIN_PULSE_WIDTH, jint GAP_DECREASE_MASK); 50 | }; 51 | 52 | #endif //GAME_PI2_CV_H 53 | -------------------------------------------------------------------------------- /app/src/main/cpp/pi2_plot.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by ser on 13.11.17. 3 | // 4 | 5 | #ifndef PIPI_STADALONE_PI2_PLOT_H 6 | #define PIPI_STADALONE_PI2_PLOT_H 7 | #include 8 | #include 9 | #include "HistType.h" 10 | 11 | struct pi2_plot{ 12 | 13 | static void setPlotOption(JNIEnv *env, jobject thiz, ID_TYPE refMat){ 14 | chart = *reinterpret_cast(refMat); 15 | setDisablePlot(0,0,false); 16 | } 17 | 18 | static cv::Mat chart; 19 | static cv::Mat grayCapture; 20 | static const size_t widthPreview = 640; 21 | static const size_t heightPreview = 480; 22 | static const size_t sizePreview = widthPreview * heightPreview; 23 | static size_t getSizePreview() { 24 | return sizePreview; 25 | } 26 | static const cv::Rect rect; 27 | 28 | static cv::Mat getSubPreviewMat(){ 29 | return cv::Mat(pi2_plot::chart( pi2_plot::rect)); 30 | } 31 | static cv::Mat getSubPlotMatAfterPreview(cv::Rect rectPlot){ 32 | rectPlot.y += heightPreview; 33 | return cv::Mat(pi2_plot::chart(rectPlot)); 34 | } 35 | 36 | static void clearAll(){ 37 | chart.setTo(0); 38 | } 39 | 40 | static void plotSubGrayArray(uint8_t * grayArray, cv::Rect rectPlot); 41 | static void plotPreviewFrameFast(uvc_frame_t *frame); 42 | static void plotPreviewFrame(uvc_frame_t *frame); 43 | 44 | static void plotHist(HistType &vh, const HistType &lh, HistType &ph); 45 | 46 | static bool disablePlot; 47 | 48 | static bool isEnablePlot() { 49 | return !disablePlot; 50 | } 51 | 52 | static void setDisablePlot(JNIEnv *env, jobject thiz, jboolean disable){ 53 | disablePlot = disable; // == 1 ? true : false; 54 | } 55 | }; 56 | 57 | 58 | #endif //PIPI_STADALONE_PI2_PLOT_H 59 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/externalcooperation/RequestReciever.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.externalcooperation; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.util.Log; 7 | 8 | import sermk.pipi.pilauncher.UVCReciver; 9 | import sermk.pipi.pilib.CommandCollection; 10 | import sermk.pipi.pilib.ErrorCollector; 11 | import sermk.pipi.pilib.MClient; 12 | import sermk.pipi.pilib.UniversalReciver; 13 | 14 | public class RequestReciever extends BroadcastReceiver { 15 | 16 | private String TAG = this.getClass().getName(); 17 | 18 | private final ErrorCollector EC = new ErrorCollector(); 19 | 20 | @Override 21 | public void onReceive(Context context, Intent intent) { 22 | EC.clear(); 23 | 24 | final UniversalReciver.ReciverVarible rv 25 | = UniversalReciver.parseIntent(intent, TAG); 26 | 27 | String error = ErrorCollector.NO_ERROR; 28 | 29 | try { 30 | error = doAction(context, rv.action); 31 | } catch (Exception e){ 32 | e.printStackTrace(); 33 | error = e.toString(); 34 | } 35 | 36 | if(ErrorCollector.NO_ERROR.equals(error)) return; 37 | 38 | EC.addError(error); 39 | 40 | Log.v(TAG, EC.error); 41 | 42 | MClient.sendMessage(context, EC.subjError(TAG, rv.action), EC.error); 43 | } 44 | 45 | private String doAction(Context context, final String action) { 46 | if (CommandCollection.ACTION_RECIVER_FOR_ALL_QUERY_SETTINGS.equals(action)) { 47 | PiSettings.getInstance().confirmSettings(context); 48 | } else if(CommandCollection.ACTION_RECIVER_CLEAR_CAPTURE_FRAME_INTERVAL.equals(action)){ 49 | UVCReciver.clear_CAPTURE_FRAME_INTERVAL_PREV(); 50 | } else { 51 | return "Undefined action!"; 52 | } 53 | 54 | return ErrorCollector.NO_ERROR; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/CVResolver.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher; 2 | 3 | import android.support.annotation.Nullable; 4 | import android.util.Log; 5 | 6 | /** 7 | * Created by echormonov on 31.10.17. 8 | */ 9 | 10 | public final class CVResolver { 11 | 12 | public interface ICallbackPosition { 13 | boolean callbackPosition(final int pos, final int width, final CVResolver cvr); 14 | } 15 | 16 | private final String TAG = "CVResolver"; 17 | 18 | public final int MODE_CAPTURE = 0; 19 | public final int MODE_LEARN = 1; 20 | 21 | public final int CAPTURE_ONE_FRAME_START_TO = 0; 22 | public final int CAPTURE_ONE_FRAME_RETURN_RESULT = 1; 23 | 24 | private ICallbackPosition mICallbackPosition = null; 25 | 26 | public CVResolver(@Nullable final ICallbackPosition callback) { 27 | setCallback(callback); 28 | setMode(MODE_CAPTURE); 29 | startCV(); 30 | } 31 | 32 | public void setCallback(@Nullable final ICallbackPosition callback) { 33 | this.mICallbackPosition = callback; 34 | } 35 | 36 | private void plottCV(final int position, final int width){ 37 | //Log.i(TAG,"width " + width); 38 | if(this.mICallbackPosition == null){ 39 | return; 40 | } 41 | this.mICallbackPosition.callbackPosition(position, width, this); 42 | } 43 | 44 | public native boolean startCV(); 45 | 46 | public static native int setRectOfMask(final int xsRoi, final int ysRoi, final long refMat); 47 | public static native void setMode(final int mode); 48 | public static native long getFrame(final int mode); 49 | public void stop(){} 50 | 51 | public static native void setDisablePlot(boolean disable); 52 | public static native void setPlotOption(final long previewMat); 53 | public static native void setOptions(final int MAX_PULSE_WIDTH, 54 | final int MIN_PULSE_WIDTH, 55 | final int GAP_DECREASE_MASK); 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/externalcooperation/ProblemReceiver.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.externalcooperation; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.util.Log; 7 | 8 | import java.util.HashSet; 9 | 10 | import sermk.pipi.pilauncher.GlobalController; 11 | import sermk.pipi.pilib.ErrorCollector; 12 | import sermk.pipi.pilib.ProblemStatusAPI; 13 | 14 | public class ProblemReceiver extends BroadcastReceiver { 15 | 16 | private final String TAG = this.getClass().getName(); 17 | 18 | private final ErrorCollector EC = new ErrorCollector(); 19 | 20 | @Override 21 | public void onReceive(Context context, Intent intent) { 22 | // TODO: This method is called when the BroadcastReceiver is receiving 23 | // an Intent broadcast. 24 | EC.clear(); 25 | Log.v(TAG, "intent: " + intent.toString()); 26 | String action; 27 | try{ 28 | action = intent.getAction().trim(); 29 | } catch (Exception e){ 30 | action = "wrong action!"; 31 | EC.addError(action); 32 | Log.w(TAG, "action is not exist!"); 33 | } 34 | Log.v(TAG, action); 35 | 36 | String content; 37 | try{ 38 | content = intent.getStringExtra(Intent.EXTRA_TEXT).trim(); 39 | } catch (Exception e){ 40 | content = "wrong content!"; 41 | EC.addError(content); 42 | Log.w(TAG, "content is not exist!"); 43 | } 44 | Log.v(TAG, content); 45 | 46 | if(EC.hasError()) return; 47 | 48 | condsiderProblem(context, content); 49 | } 50 | 51 | private void condsiderProblem(Context context, final String problem){ 52 | if(problem.isEmpty()) 53 | return; 54 | 55 | GlobalController gb = (GlobalController)context.getApplicationContext(); 56 | 57 | HashSet problems = gb.problem.problemSet(); 58 | 59 | final String deleted = ProblemStatusAPI.deletedStatus(problem); 60 | if(deleted.isEmpty()){ 61 | problems.add(problem); 62 | } else { 63 | problems.remove(deleted); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/PiHandler.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher; 2 | 3 | import android.os.Handler; 4 | import android.os.Message; 5 | import android.os.Messenger; 6 | import android.os.RemoteException; 7 | import android.util.Log; 8 | 9 | import com.orhanobut.logger.Logger; 10 | 11 | /** 12 | * Created by echormonov on 24.11.17. 13 | */ 14 | 15 | public final class PiHandler extends Handler implements CVResolver.ICallbackPosition { 16 | 17 | /** Command to the service to display a message */ 18 | static final int MSG_SAY_HELLO = 1; 19 | final String TAG = "PiHandler"; 20 | 21 | /** 22 | * Target we publish for clients to send messages to IncomingHandler. 23 | */ 24 | final Messenger mMessenger;// = new Messenger(new IncomingHandler()); 25 | int position = 0; 26 | 27 | 28 | public PiHandler() { 29 | super(); 30 | mMessenger = new Messenger(this); 31 | } 32 | 33 | public Messenger getMessenger() { 34 | return mMessenger; 35 | } 36 | 37 | @Override 38 | public void handleMessage(Message msg) { 39 | Log.v(TAG,"msg.what" + String.valueOf(msg.what)); 40 | 41 | //Setup the reply message 42 | Message message = Message.obtain(null, 2, position, 0); 43 | try 44 | { 45 | //make the RPC invocation 46 | replyTo = msg.replyTo; 47 | replyTo.send(message); 48 | } 49 | catch(RemoteException rme) 50 | { 51 | //Show an Error Message 52 | //Toast.makeText(RemoteService.this, "Invocation Failed!!", Toast.LENGTH_LONG).show(); 53 | Logger.e("Invocation Failed!!"); 54 | } 55 | } 56 | 57 | 58 | private Messenger replyTo = null; 59 | @Override 60 | public boolean callbackPosition(int pos, final int width, CVResolver cvr){ 61 | position = pos; 62 | return true; 63 | } 64 | 65 | 66 | public boolean callbackPosition1(int pos, CVResolver cvr) 67 | { 68 | /**/ 69 | Message message = Message.obtain(null, 2, 0, 0); 70 | if(replyTo==null){ 71 | return false; 72 | } 73 | try 74 | { 75 | replyTo.send(message); 76 | } 77 | catch(RemoteException rme) 78 | { 79 | //Show an Error Message 80 | //Toast.makeText(RemoteService.this, "Invocation Failed!!", Toast.LENGTH_LONG).show(); 81 | Logger.e(rme,"replyTo.send Failed!!"); 82 | } 83 | 84 | return true; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/androidTest/java/sermk/pipi/pilauncher/externalcooperation/ProblemReceiverTest.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.externalcooperation; 2 | 3 | import android.os.SystemClock; 4 | import android.support.test.rule.ActivityTestRule; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import java.util.HashSet; 12 | 13 | import sermk.pipi.pilauncher.GlobalController; 14 | import sermk.pipi.pilauncher.LauncherAct; 15 | import sermk.pipi.pilauncher.R; 16 | import sermk.pipi.pilib.ProblemStatusAPI; 17 | 18 | import static junit.framework.Assert.assertEquals; 19 | import static junit.framework.Assert.assertFalse; 20 | import static junit.framework.Assert.assertTrue; 21 | 22 | import static android.support.test.espresso.Espresso.onView; 23 | import static android.support.test.espresso.action.ViewActions.click; 24 | import static android.support.test.espresso.assertion.ViewAssertions.matches; 25 | import static android.support.test.espresso.matcher.ViewMatchers.withId; 26 | import static android.support.test.espresso.matcher.ViewMatchers.withText; 27 | 28 | /** 29 | * Created by ser on 09.02.18. 30 | */ 31 | @RunWith(AndroidJUnit4.class) 32 | public class ProblemReceiverTest { 33 | @Rule 34 | public ActivityTestRule ar = new ActivityTestRule<>(LauncherAct.class); 35 | 36 | @Test 37 | public void condsiderProblem() throws Exception { 38 | final int TIMEOUT = 1555; 39 | final String val1 = "11"; 40 | final String val2 = "22"; 41 | ProblemStatusAPI.setStatus(ar.getActivity(),val2); 42 | ProblemStatusAPI.setStatus(ar.getActivity(),val1); 43 | SystemClock.sleep(TIMEOUT); 44 | GlobalController gb = (GlobalController) ar.getActivity().getApplicationContext(); 45 | HashSet hs = gb.problem.problemSet(); 46 | System.out.println(hs.toString()); 47 | assertEquals(2, hs.size()); 48 | assertTrue(hs.contains(val2)); 49 | assertTrue(hs.contains(val1)); 50 | 51 | ProblemStatusAPI.clearStatus(ar.getActivity(),val1); 52 | SystemClock.sleep(TIMEOUT); 53 | assertFalse(hs.contains(val1)); 54 | assertTrue(hs.contains(val2)); 55 | assertEquals(1, hs.size()); 56 | System.out.println(hs.toString()); 57 | 58 | LauncherAct la = (LauncherAct)ar.getActivity(); 59 | la.addFragment(LauncherAct.Screen.Status); 60 | SystemClock.sleep(TIMEOUT); 61 | onView(withId(R.id.status)).check(matches(withText(val2))); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/GlobalController.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher; 2 | 3 | import android.app.Application; 4 | import android.content.res.Configuration; 5 | 6 | import com.orhanobut.logger.Logger; 7 | 8 | import org.opencv.android.OpenCVLoader; 9 | 10 | import java.util.HashSet; 11 | 12 | import sermk.pipi.pilauncher.externalcooperation.PiSettings; 13 | 14 | 15 | /** 16 | * Created by echormonov on 30.10.17. 17 | */ 18 | 19 | public final class GlobalController extends Application { 20 | 21 | private static GlobalController app = null; 22 | 23 | private final String TAG = this.getClass().getName(); 24 | 25 | // Called when the application is starting, before any other application objects have been created. 26 | // Overriding this method is totally optional! 27 | @Override 28 | public void onCreate() { 29 | super.onCreate(); 30 | LogOptions.SetupLog(); 31 | PiSettings.getInstance().init(this); 32 | // Required initialization logic here! 33 | } 34 | 35 | public static GlobalController getInstance(final String sObject){ 36 | return app; 37 | } 38 | 39 | 40 | // Called by the system when the device configuration changes while your component is running. 41 | // Overriding this method is totally optional! 42 | @Override 43 | public void onConfigurationChanged(Configuration newConfig) { 44 | super.onConfigurationChanged(newConfig); 45 | } 46 | 47 | // This is called when the overall system is running low on memory, 48 | // and would like actively running processes to tighten their belts. 49 | // Overriding this method is totally optional! 50 | @Override 51 | public void onLowMemory() { 52 | super.onLowMemory(); 53 | } 54 | 55 | // Used to load the 'native-lib' library on application startup. 56 | static { 57 | System.loadLibrary("native-lib"); 58 | if(!(OpenCVLoader.initDebug())){ 59 | Logger.w("Fail opencv load!"); 60 | } else { 61 | Logger.v("succes opencv load library"); 62 | } 63 | } 64 | 65 | public static class Problem { 66 | private HashSet SetProblem = new HashSet(); 67 | 68 | public HashSet problemSet() { 69 | return SetProblem; 70 | } 71 | 72 | public String getAllStatus(){ 73 | String ret = new String(); 74 | for(String s: SetProblem){ 75 | ret += s; 76 | } 77 | return ret; 78 | } 79 | } 80 | 81 | public Problem problem = new Problem(); 82 | 83 | } 84 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/externalcooperation/SettingsReciever.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.externalcooperation; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.support.annotation.NonNull; 7 | import android.util.Log; 8 | 9 | import sermk.pipi.pilib.CommandCollection; 10 | import sermk.pipi.pilib.ErrorCollector; 11 | import sermk.pipi.pilib.MClient; 12 | import sermk.pipi.pilib.UniversalReciver; 13 | 14 | public class SettingsReciever extends BroadcastReceiver { 15 | 16 | private final String TAG = this.getClass().getName(); 17 | 18 | private final ErrorCollector EC = new ErrorCollector(); 19 | 20 | 21 | @Override 22 | public void onReceive(Context context, Intent intent) { 23 | 24 | EC.clear(); 25 | 26 | final UniversalReciver.ReciverVarible rv 27 | = UniversalReciver.parseIntent(intent, TAG); 28 | 29 | String error = ErrorCollector.NO_ERROR; 30 | 31 | try { 32 | error = doAction(context, rv.content, rv.array, rv.action); 33 | } catch (Exception e){ 34 | e.printStackTrace(); 35 | error = e.toString(); 36 | } 37 | 38 | if(ErrorCollector.NO_ERROR.equals(error)) return; 39 | 40 | EC.addError(error); 41 | 42 | Log.v(TAG, EC.error); 43 | 44 | MClient.sendMessage(context, EC.subjError(TAG, rv.action), EC.error); 45 | } 46 | 47 | private String doAction(Context context, final String content, final byte[] bytesArray, @NonNull final String action){ 48 | if(action.equals(CommandCollection.ACTION_RECIVER_PILAUNCHER_SET_SETTINGS)){ 49 | return setSettings(content, bytesArray); 50 | } else if (action.equals(CommandCollection.ACTION_RECIVER_PILAUNCHER_SAVE_SETTINGS)){ 51 | return saveSettings(context); 52 | } 53 | 54 | final String err = "undefined action!"; 55 | Log.w(TAG, err); 56 | EC.addError(err); 57 | 58 | return err; 59 | } 60 | 61 | private String setSettings(final String content, final byte[] bytesArray){ 62 | return PiSettings.getInstance().setCurrentSettings(content, bytesArray); 63 | } 64 | 65 | private String saveSettings(Context context){ 66 | return PiSettings.getInstance().saveCurrentSettings(context); 67 | } 68 | 69 | static void sendBroadCastData(Context context, final String action, 70 | final String content, final byte[] data){ 71 | Intent intent = new Intent(context, SettingsReciever.class); 72 | intent.setAction(action); 73 | 74 | intent.putExtra(Intent.EXTRA_TEXT, content); 75 | intent.putExtra(Intent.EXTRA_INITIAL_INTENTS,data); 76 | 77 | context.sendBroadcast(intent); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/cpp/HistType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by ser on 14.11.17. 3 | // 4 | 5 | #ifndef PIPI_STADALONE_HISTTYPE_H 6 | #define PIPI_STADALONE_HISTTYPE_H 7 | #include 8 | struct HistType{ 9 | static const size_t MAX_WIGTH_HIST = 640; 10 | uint64 hist[MAX_WIGTH_HIST] = {0}; 11 | size_t currSize = 0; 12 | 13 | void clearHist(uint64 val = 0) { 14 | memset(hist, val, MAX_WIGTH_HIST * sizeof(uint64)); 15 | } 16 | 17 | void newVerHistArrayYUYV(const uint8_t *array, const cv::Rect &maskRect); 18 | }; 19 | 20 | 21 | struct LearnHType: HistType { 22 | void setMinValue(const HistType & compHist){ 23 | for(size_t i = 0; i < compHist.currSize; i++){ 24 | uint64 val = compHist.hist[i]; 25 | if(this->hist[i] > val){ 26 | this->hist[i] = val; 27 | } 28 | } 29 | this->currSize = compHist.currSize; 30 | } 31 | void mullArray(const uint64 factor, const uint64 denominator){ 32 | for(size_t i=0; icurrSize; i++){ 33 | hist[i] -= (hist[i]*factor)/denominator; 34 | } 35 | } 36 | }; 37 | 38 | enum POSITION_STATE { 39 | UNDEFINED_POSITION = -1, 40 | UNCORRECT_BIG_PULSE = -2, 41 | UNCORRECT_LITLE_PULSE = -3, 42 | }; 43 | 44 | #define DIVIDER_WITDH 1000 45 | #define FACTOR_TRANSFER_POSITION 1000 46 | #define DIVIDER_GAP_MASK 1000 47 | 48 | struct PowerHType: HistType { 49 | void calcPower(const LearnHType & learn, const HistType & signal){ 50 | this->clearHist(); 51 | for(size_t i=1; i < signal.currSize; i++){ 52 | int dif = static_cast(learn.hist[i] - signal.hist[i]); 53 | if(dif > 0) { 54 | this->hist[i] = dif; 55 | this->hist[i] += this->hist[i - 1]; 56 | } 57 | } 58 | this->currSize = signal.currSize; 59 | } 60 | 61 | __inline int calcPosition(int & refWidth,const size_t MAX_WIDTH, const size_t MIN_WIDTH){ 62 | uint64 mv = 0; //max value 63 | int mw = 0; //width of max value 64 | int width = 0; 65 | int position = -1; 66 | for(int i=0; i < this->currSize; i++){ 67 | uint64 val = hist[i]; 68 | if(val > mv){ 69 | mv = val; 70 | position = i; 71 | mw = width; 72 | } 73 | 74 | if(val > 0){ 75 | width++; 76 | } else { 77 | width = 0; 78 | } 79 | } 80 | 81 | refWidth = mw; 82 | 83 | const size_t MAXW = (this->currSize*MAX_WIDTH)/DIVIDER_WITDH; 84 | 85 | if(mw > MAXW){ 86 | return UNCORRECT_BIG_PULSE; 87 | } 88 | 89 | const size_t MINW = (this->currSize*MIN_WIDTH)/DIVIDER_WITDH; 90 | 91 | if(mw < MINW){ 92 | return UNCORRECT_LITLE_PULSE; 93 | } 94 | 95 | return position; 96 | } 97 | }; 98 | #endif //PIPI_STADALONE_HISTTYPE_H 99 | -------------------------------------------------------------------------------- /app/src/main/cpp/pi_load.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "util.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "pi_cv.h" 8 | #include "pi2_cv.h" 9 | #include "pi2_plot.h" 10 | 11 | bool pi_cv::learn = false; 12 | #if 0 13 | static jint passFrameToCVPIPI(JNIEnv *env, jobject thiz, 14 | ID_TYPE refMatPreview, ID_TYPE refMatChart) { 15 | 16 | jint result = 0; 17 | //ENTER(); 18 | result = pi_cv::calcPipiChart(refMatPreview, refMatChart); 19 | //RETURN(result, jint); 20 | return result; 21 | } 22 | 23 | static jint passRoiRectToCVPIPI(JNIEnv *env, jobject thiz, 24 | jint xsRoi, jint ysRoi, ID_TYPE refMat) { 25 | 26 | jint result = 0; 27 | //ENTER(); 28 | result = pi_cv::setRectMask(xsRoi, ysRoi, refMat); 29 | //RETURN(result, jint); 30 | return result; 31 | } 32 | 33 | static void enableLearn(JNIEnv *env, jobject thiz, 34 | jboolean enable) { 35 | 36 | pi_cv::setLearnEnable(static_cast(enable)); 37 | //result = pi_cv::setRectMask(xsRoi, ysRoi, refMat); 38 | 39 | } 40 | #endif 41 | 42 | static JNINativeMethod methods[] = { 43 | #if 0 44 | { "passFrameToCVPIPI", "(JJ)I", (void *) passFrameToCVPIPI }, 45 | { "passRoiRectToCVPIPI", "(IIJ)I", (void *) passRoiRectToCVPIPI }, 46 | { "enableLearn", "(Z)V", (void *) enableLearn }, 47 | #endif 48 | { "startCV", "()Z", (void *) pi2_cv::startCV }, 49 | { "setRectOfMask", "(IIJ)I", (void *) pi2_cv::setRectOfMask }, 50 | { "setMode", "(I)V", (void *)pi2_cv::setMode }, 51 | { "setPlotOption", "(J)V", (void *)pi2_plot::setPlotOption }, 52 | { "setDisablePlot", "(Z)V", (void *)pi2_plot::setDisablePlot }, 53 | { "getFrame", "(I)J", (void *)pi2_cv::getFrame }, 54 | { "setOptions", "(III)V", (void *) pi2_cv::setOptions }, 55 | 56 | }; 57 | 58 | #define NUM_ARRAY_ELEMENTS(p) ((int) sizeof(p) / sizeof(p[0])) 59 | 60 | jint JNI_OnLoad(JavaVM* vm, void* reserved) { 61 | LOGI("register CV resolver:"); 62 | JNIEnv *env; 63 | if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { 64 | LOGE("it's not JNI_VERSION_1_6"); 65 | return JNI_ERR; 66 | } 67 | 68 | const char JAVA_CLASS[] = "sermk/pipi/pilauncher/CVResolver"; 69 | 70 | jclass cls = env->FindClass(JAVA_CLASS); 71 | if (cls == NULL) 72 | { 73 | LOGE("not find class : %s",JAVA_CLASS); 74 | return JNI_ERR; 75 | } 76 | LOGI("find class %s succes!", JAVA_CLASS); 77 | 78 | if (env->RegisterNatives( cls, 79 | methods, NUM_ARRAY_ELEMENTS(methods)) < 0) { 80 | LOGE("can not register method<"); 81 | return -1; 82 | } 83 | 84 | LOGI("register CV resolver succes!"); 85 | return JNI_VERSION_1_6; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/GUIFragment/PasswordFragment.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.GUIFragment; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.app.Fragment; 6 | import android.os.CountDownTimer; 7 | import android.util.Log; 8 | import android.view.KeyEvent; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.EditText; 13 | 14 | import sermk.pipi.pilauncher.R; 15 | 16 | /** 17 | * A simple {@link Fragment} subclass. 18 | */ 19 | public class PasswordFragment extends Fragment implements View.OnKeyListener { 20 | 21 | final String TAG = this.getClass().getName(); 22 | private final String etalon = "741236985"; 23 | 24 | 25 | public PasswordFragment() { 26 | // Required empty public constructor 27 | } 28 | 29 | 30 | @Override 31 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 32 | Bundle savedInstanceState) { 33 | // Inflate the layout for this fragment 34 | final View rootView = inflater.inflate(R.layout.fragment_password, container, false); 35 | 36 | ((EditText)rootView.findViewById(R.id.password)).setOnKeyListener(this); 37 | 38 | timer.start(); 39 | 40 | return rootView; 41 | } 42 | 43 | @Override 44 | public boolean onKey(View v, int keyCode, KeyEvent event) { 45 | if(event.getAction() != KeyEvent.ACTION_DOWN || 46 | (keyCode != KeyEvent.KEYCODE_ENTER)){ 47 | return false; 48 | } 49 | 50 | EditText editText = (EditText)v; 51 | // сохраняем текст, введенный до нажатия Enter в переменную 52 | String pass = editText.getText().toString(); 53 | Log.v(TAG, pass); 54 | 55 | if(!etalon.equals(pass)){ 56 | Log.v(TAG,"unknown pass!"); 57 | return false; 58 | } 59 | 60 | timer.cancel(); 61 | 62 | getFragmentManager().beginTransaction() 63 | .replace(R.id.container, new TestCV_Fragment(), TestCV_Fragment.class.getName()) 64 | .addToBackStack("") 65 | .commit(); 66 | 67 | return true; 68 | 69 | } 70 | 71 | @Override 72 | public void onDetach() { 73 | Log.v(TAG, "onDetach"); 74 | timer.cancel(); 75 | super.onDetach(); 76 | } 77 | 78 | private final int TIMEOUT = 20*1000; 79 | 80 | final CountDownTimer timer = new CountDownTimer(TIMEOUT, TIMEOUT){ 81 | @Override 82 | public void onTick(long millisUntilFinished) { 83 | Log.v(TAG, "onTick"); 84 | } 85 | 86 | @Override 87 | public void onFinish() { 88 | Log.v(TAG, "finish timer"); 89 | //todo: check current visible fragment! 90 | getFragmentManager().beginTransaction() 91 | .replace(R.id.container, new StatusFragment(), StatusFragment.class.getName()) 92 | .commit(); 93 | } 94 | }; 95 | 96 | } 97 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # OpenCV stuff 9 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../UVC/opencv_sdk/native/jni/include) 10 | add_library( lib_opencv SHARED IMPORTED ) 11 | set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../UVC/opencv_sdk/native/libs/${ANDROID_ABI}/libopencv_java3.so) 12 | 13 | add_library( libUVCCamera SHARED IMPORTED ) 14 | set_target_properties(libUVCCamera PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../UVC/libuvccamera/src/main/libs/${ANDROID_ABI}/libUVCCamera.so) 15 | 16 | 17 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../UVC/libuvccamera/src/main/jni/libuvc/include/) 18 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../UVC/libuvccamera/src/main/jni/libuvc/include/libuvc/) 19 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../UVC/libuvccamera/src/main/jni/libusb/) 20 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../UVC/libuvccamera/src/main/jni/libusb/libusb/) 21 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../UVC/libuvccamera/src/main/jni/) 22 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../UVC/libuvccamera/src/main/jni/UVCCamera/) 23 | 24 | # Creates and names a library, sets it as either STATIC 25 | # or SHARED, and provides the relative paths to its source code. 26 | # You can define multiple libraries, and CMake builds them for you. 27 | # Gradle automatically packages shared libraries with your APK. 28 | 29 | add_library( # Sets the name of the library. 30 | native-lib 31 | 32 | # Sets the library as a shared library. 33 | SHARED 34 | 35 | # Provides a relative path to your source file(s). 36 | src/main/cpp/pi_load.cpp 37 | #src/main/cpp/pi_cv.cpp 38 | src/main/cpp/pi2_cv.cpp 39 | src/main/cpp/pi2_plot.cpp) 40 | 41 | # Searches for a specified prebuilt library and stores the path as a 42 | # variable. Because CMake includes system libraries in the search path by 43 | # default, you only need to specify the name of the public NDK library 44 | # you want to add. CMake verifies that the library exists before 45 | # completing its build. 46 | 47 | find_library( # Sets the name of the path variable. 48 | log-lib 49 | 50 | # Specifies the name of the NDK library that 51 | # you want CMake to locate. 52 | log ) 53 | 54 | # Specifies libraries CMake should link to your target library. You 55 | # can link multiple libraries, such as libraries you define in this 56 | # build script, prebuilt third-party libraries, or system libraries. 57 | 58 | target_link_libraries( # Specifies the target library. 59 | native-lib 60 | 61 | libUVCCamera 62 | 63 | # OpenCV lib 64 | lib_opencv 65 | # Links the target library to the log library 66 | # included in the NDK. 67 | ${log-lib} ) -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 40 | 41 | 45 | 46 | 47 | 48 | 49 | 50 | 54 | 55 | 56 | 57 | 58 | 59 | 63 | 64 | 65 | 66 | 67 | 68 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | /* 3 | // Create a variable called keystorePropertiesFile, and initialize it to your 4 | // keystore.properties file, in the rootProject folder. 5 | def keystorePropertiesFile = rootProject.file("keystore.properties") 6 | 7 | // Initialize a new Properties() object called keystoreProperties. 8 | def keystoreProperties = new Properties() 9 | 10 | // Load your keystore.properties file into the keystoreProperties object. 11 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 12 | */ 13 | android { 14 | compileSdkVersion versionCompiler 15 | buildToolsVersion versionBuildTool 16 | 17 | defaultConfig { 18 | applicationId "sermk.pipi.pilauncher" 19 | minSdkVersion versionMinSdkTarget 20 | targetSdkVersion versionTarget 21 | versionCode 1 22 | versionName "1.0" 23 | 24 | externalNativeBuild { 25 | cmake { 26 | cppFlags "-fexceptions -std=c++11" 27 | abiFilters 'arm64-v8a' 28 | } 29 | } 30 | 31 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 32 | } 33 | /* 34 | signingConfigs { 35 | config { 36 | keyAlias keystoreProperties['keyAlias'] 37 | keyPassword keystoreProperties['keyPassword'] 38 | storeFile file(keystoreProperties['storeFile']) 39 | storePassword keystoreProperties['storePassword'] 40 | } 41 | } 42 | */ 43 | buildTypes { 44 | release { 45 | minifyEnabled false 46 | //signingConfig signingConfigs.config 47 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 48 | splits { 49 | abi { 50 | enable true 51 | reset() 52 | include 'arm64-v8a' 53 | universalApk false 54 | } 55 | } 56 | } 57 | 58 | debug { 59 | splits { 60 | abi { 61 | enable true 62 | reset() 63 | include 'arm64-v8a' 64 | universalApk false 65 | } 66 | } 67 | } 68 | } 69 | 70 | sourceSets { main { jni.srcDirs = ['src/main/cpp'] } } 71 | externalNativeBuild { 72 | cmake { 73 | path "CMakeLists.txt" 74 | } 75 | } 76 | 77 | } 78 | 79 | task run(type: Exec) { 80 | def path 81 | def localProperties = project.file("../local.properties") 82 | if (localProperties.exists()) { 83 | Properties properties = new Properties() 84 | localProperties.withInputStream { instr -> 85 | properties.load(instr) 86 | } 87 | def sdkDir = properties.getProperty('sdk.dir') 88 | if (sdkDir) { 89 | path = sdkDir 90 | } else { 91 | path = "$System.env.ANDROID_HOME" 92 | } 93 | } else { 94 | path = "$System.env.ANDROID_HOME" 95 | } 96 | 97 | def adb = path + "/platform-tools/adb" 98 | commandLine "$adb", 'shell', 'am', 'start', '-n', 'sermk.pipi.pilauncher/sermk.pipi.pilauncher.LauncherAct' 99 | } 100 | 101 | dependencies { 102 | implementation fileTree(include: ['*.jar'], dir: 'libs') 103 | implementation project(':libuvccamera') 104 | implementation project(':openCVLibrary330') 105 | implementation project(':PiLib') 106 | 107 | compile 'com.orhanobut:logger:2.1.1' 108 | compile 'com.google.code.gson:gson:2.8.2' 109 | compile 'org.greenrobot:eventbus:3.1.1' 110 | 111 | testImplementation 'junit:junit:4.12' 112 | androidTestCompile 'com.android.support:support-annotations:' + rootProject.supportLibVersion; 113 | androidTestCompile 'com.android.support.test:runner:' + rootProject.runnerVersion; 114 | androidTestCompile 'com.android.support.test:rules:' + rootProject.rulesVersion; 115 | androidTestCompile 'com.android.support.test.espresso:espresso-core:' + rootProject.espressoVersion; 116 | 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/deprecated/NotifyService.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.deprecated; 2 | 3 | 4 | import android.app.Notification; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.app.Service; 8 | import android.content.Intent; 9 | import android.os.Handler; 10 | import android.os.IBinder; 11 | import android.os.Message; 12 | import android.os.Messenger; 13 | import android.os.RemoteException; 14 | import android.util.Log; 15 | import android.widget.Toast; 16 | 17 | import com.orhanobut.logger.Logger; 18 | 19 | import sermk.pipi.pilauncher.R; 20 | import sermk.pipi.pilauncher.LauncherAct; 21 | 22 | /** 23 | * Created by echormonov on 18.11.17. 24 | */ 25 | 26 | final public class NotifyService extends Service { 27 | 28 | NotificationManager mNotificationManager; 29 | final String TAG = "NotifyService"; 30 | private static final int NOTIFICATION = R.string.app_name; 31 | 32 | @Override 33 | public void onCreate() { 34 | super.onCreate(); 35 | Logger.v("onCreate service"); 36 | mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 37 | showNotification("@@@@@@@@@@@@@@"); 38 | } 39 | 40 | @Override 41 | public int onStartCommand(Intent intent, int flags, int startId) { 42 | Logger.v("onStartCommand service"); 43 | return super.onStartCommand(intent, flags, startId); 44 | } 45 | 46 | private void showNotification(final CharSequence text) { 47 | Log.v(TAG, "showNotification:" + text); 48 | // Set the info for the views that show in the notification panel. 49 | final Notification notification = new Notification.Builder(this) 50 | .setSmallIcon(R.drawable.ic_launcher) // the status icon 51 | .setTicker(text) // the status text 52 | .setWhen(System.currentTimeMillis()) // the time stamp 53 | .setContentTitle(getText(R.string.app_name)) // the label of the entry 54 | .setContentText(text) // the contents of the entry 55 | .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, LauncherAct.class), 0)) // The intent to send when the entry is clicked 56 | .build(); 57 | 58 | startForeground(NOTIFICATION, notification); 59 | // Send the notification. 60 | mNotificationManager.notify(NOTIFICATION, notification); 61 | } 62 | 63 | public void onDestroy() { 64 | super.onDestroy(); 65 | Log.d(TAG, "onDestroy"); 66 | } 67 | 68 | /** Command to the service to display a message */ 69 | static final int MSG_SAY_HELLO = 1; 70 | 71 | /** 72 | * Handler of incoming messages from clients. 73 | */ 74 | class IncomingHandler extends Handler { 75 | @Override 76 | public void handleMessage(Message msg) { 77 | Logger.v("msg.what" + String.valueOf(msg.what)); 78 | 79 | //Setup the reply message 80 | Message message = Message.obtain(null, 2, 0, 0); 81 | try 82 | { 83 | //make the RPC invocation 84 | Messenger replyTo = msg.replyTo; 85 | replyTo.send(message); 86 | } 87 | catch(RemoteException rme) 88 | { 89 | //Show an Error Message 90 | //Toast.makeText(RemoteService.this, "Invocation Failed!!", Toast.LENGTH_LONG).show(); 91 | Logger.e("Invocation Failed!!"); 92 | } 93 | } 94 | } 95 | 96 | /** 97 | * Target we publish for clients to send messages to IncomingHandler. 98 | */ 99 | final Messenger mMessenger = new Messenger(new IncomingHandler()); 100 | 101 | /** 102 | * When binding to the service, we return an interface to our messenger 103 | * for sending messages to the service. 104 | */ 105 | @Override 106 | public IBinder onBind(Intent intent) { 107 | Logger.v("onBind service! " + intent.toString()); 108 | Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); 109 | return mMessenger.getBinder(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/cpp/pi2_plot.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by ser on 13.11.17. 3 | // 4 | 5 | #include "pi2_plot.h" 6 | 7 | 8 | using namespace cv; 9 | 10 | Mat pi2_plot::chart; 11 | const Rect pi2_plot::rect = Rect(0,0, pi2_plot::widthPreview, pi2_plot::heightPreview); 12 | Mat pi2_plot::grayCapture = Mat(pi2_plot::heightPreview,pi2_plot::widthPreview,CV_8UC1); 13 | bool pi2_plot::disablePlot = false; 14 | 15 | void pi2_plot::plotSubGrayArray(uint8_t *grayArray, cv::Rect rectPlot) { 16 | Mat subMat = Mat(pi2_plot::chart(rectPlot)); 17 | Mat matOfArray = Mat(rectPlot.height, rectPlot.width, CV_8UC1, grayArray); 18 | cvtColor(matOfArray, subMat, COLOR_GRAY2RGB); 19 | } 20 | 21 | void pi2_plot::plotPreviewFrameFast(uvc_frame_t *frame) { 22 | uint8_t * pMat = pi2_plot::chart.data; 23 | const uint8_t * pFrame = reinterpret_cast(frame->data); 24 | const size_t size_frame = (frame->data_bytes)/2; 25 | for(size_t i=0; i < size_frame; i++){ 26 | pMat[3*i + 1] = pFrame[2*i]; 27 | } 28 | } 29 | 30 | void pi2_plot::plotPreviewFrame(uvc_frame_t *frame) { 31 | Mat frameMat = Mat(frame->height, frame->width, CV_8UC2, frame->data); 32 | Rect rectFrame = Rect(0, 0, frame->width, frame->height); 33 | Mat subMatPreview = Mat(pi2_plot::chart(rectFrame)); 34 | cvtColor(frameMat, subMatPreview, COLOR_YUV2RGB_YUYV); 35 | } 36 | 37 | 38 | static uint64 getMaxValueOfHist(const HistType &vh){ 39 | uint64 maxValue = 0; 40 | for(int i= 0; i < vh.currSize; i++){ 41 | const uint64 val = vh.hist[i]; 42 | if( maxValue < val){ 43 | maxValue = val; 44 | } 45 | } 46 | return maxValue; 47 | } 48 | 49 | void normalizeHist(HistType &vh,const size_t maxHeight, const uint64 maxValue){ 50 | for(size_t i=0; i < vh.currSize; i++){ 51 | vh.hist[i] = (maxHeight * vh.hist[i])/maxValue; 52 | } 53 | } 54 | 55 | #define LINE_OPTIONS 2,8,0 56 | 57 | void pi2_plot::plotHist(HistType &vh, const HistType &lh, HistType &ph) { 58 | size_t heightChart = chart.rows - pi2_plot::heightPreview; 59 | heightChart -= heightChart/20; 60 | const uint64 maxVH = getMaxValueOfHist(vh); 61 | if(maxVH == 0){ 62 | return; 63 | } 64 | normalizeHist(vh, heightChart, maxVH); 65 | const Scalar redPoint(255,0,0); 66 | for( int i = 1; i < vh.currSize; i++ ){ 67 | cv::line(chart, 68 | Point(i-1, vh.hist[i-1] + pi2_plot::heightPreview), 69 | Point(i, vh.hist[i] + pi2_plot::heightPreview), 70 | redPoint, 71 | LINE_OPTIONS 72 | ); 73 | } 74 | 75 | HistType copyHist; 76 | for(size_t i=0; i< lh.currSize; i++){ 77 | copyHist.hist[i] = lh.hist[i]; 78 | } 79 | copyHist.currSize = lh.currSize; 80 | normalizeHist(copyHist, heightChart, maxVH); 81 | const Scalar greenPoints(0,255,0); 82 | for( int i = 1; i < copyHist.currSize; i++ ){ 83 | cv::line(chart, 84 | Point(i-1, copyHist.hist[i-1] + pi2_plot::heightPreview), 85 | Point(i, copyHist.hist[i] + pi2_plot::heightPreview), 86 | greenPoints, 87 | LINE_OPTIONS 88 | ); 89 | } 90 | 91 | const uint64 maxPH = getMaxValueOfHist(ph); 92 | if(maxPH == 0){ 93 | return; 94 | } 95 | normalizeHist(ph, heightChart, maxPH); 96 | const Scalar bluePoints(0,0,255); 97 | for( int i = 1; i < ph.currSize; i++ ){ 98 | cv::line(chart, 99 | Point(i-1, ph.hist[i-1] + pi2_plot::heightPreview), 100 | Point(i, ph.hist[i] + pi2_plot::heightPreview), 101 | bluePoints, 102 | LINE_OPTIONS 103 | ); 104 | } 105 | 106 | int levelPower = 0; 107 | Scalar levelColor; 108 | if(maxPH > maxVH){ 109 | levelPower = (maxVH * heightChart) / maxPH; 110 | levelColor = Scalar(255,0,255); 111 | } else { 112 | levelPower = (maxPH * heightChart) / maxVH; 113 | levelColor = Scalar(0,255,255); 114 | } 115 | 116 | cv::line(chart, 117 | Point(0, levelPower + pi2_plot::heightPreview), 118 | Point(ph.currSize-1, levelPower + pi2_plot::heightPreview), 119 | levelColor, 120 | LINE_OPTIONS 121 | ); 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/GUIFragment/StatusFragment.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.GUIFragment; 2 | 3 | import android.app.FragmentManager; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.app.Fragment; 7 | import android.util.Log; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.ImageView; 12 | import android.widget.TextView; 13 | import android.widget.Toast; 14 | 15 | import java.util.Timer; 16 | import java.util.TimerTask; 17 | 18 | import sermk.pipi.pilauncher.BehaviorSettings; 19 | import sermk.pipi.pilauncher.LauncherAct; 20 | import sermk.pipi.pilauncher.PIService; 21 | import sermk.pipi.pilauncher.R; 22 | import sermk.pipi.pilauncher.externalcooperation.PiSettings; 23 | import sermk.pipi.pilib.WatchConnectionMClient; 24 | 25 | 26 | public class StatusFragment extends Fragment implements View.OnClickListener { 27 | 28 | private static final int COUNT_MAX = 11; 29 | private final String TAG = this.getClass().getName(); 30 | private Timer mTimer; 31 | 32 | private final String CONNECTION_PROBLEM_TITLE 33 | = "Internet connection problem \r\ncheck Wifi net"; 34 | 35 | @Override 36 | public void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | } 39 | 40 | static int count = 0; 41 | 42 | TextView connectionStatus; 43 | WatchConnectionMClient watcher; 44 | ImageView imageView; 45 | 46 | private int passStartGame = 0; 47 | 48 | @Override 49 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 50 | Bundle savedInstanceState) { 51 | // Inflate the layout for this fragment 52 | final View rootView = inflater.inflate(R.layout.fragment_status, container, false); 53 | 54 | imageView = (ImageView)rootView.findViewById(R.id.image_welcome); //.setOnClickListener(this); 55 | count = 0; 56 | 57 | getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { 58 | @Override 59 | public void onBackStackChanged() { 60 | Log.v(TAG,"onBackStackChanged"); 61 | } 62 | }); 63 | 64 | connectionStatus = (TextView)rootView.findViewById(R.id.status); 65 | 66 | watcher = getWatcherMC(getActivity()); 67 | 68 | passStartGame = 0; 69 | 70 | return rootView; 71 | } 72 | 73 | public static WatchConnectionMClient getWatcherMC(Context context){ 74 | final BehaviorSettings options = PiSettings.getInstance().getCurrentSettings().behaviorSettings; 75 | return new WatchConnectionMClient(context,options.TIMEOUT_MS_FAIL_CONNECTION, 76 | options.FINE_MS_FAIL_CONNECTION); 77 | } 78 | 79 | @Override 80 | public void onStart() { 81 | super.onStart(); 82 | mTimer = new Timer("connection status updating"); 83 | mTimer.schedule(new UpdateStatusTask(), 1000L, 100L); 84 | } 85 | 86 | //todo: read connection status from Piservice and run try game after timeout 87 | private class UpdateStatusTask extends TimerTask { 88 | @Override 89 | public void run() { 90 | getActivity().runOnUiThread(new Runnable() { 91 | @Override 92 | public void run() { 93 | if(PIService.getStatusAttachedUSB() == PIService.ATTACHMENT_USB_INFO.ATTACHED) 94 | imageView.setImageResource(R.drawable.start_game); 95 | else { 96 | imageView.setImageResource(R.drawable.lets); 97 | passStartGame -= passStartGame > 0 ? 1 : 0; 98 | } 99 | 100 | if(watcher.checkTimeout()){ 101 | connectionStatus.setText(CONNECTION_PROBLEM_TITLE); 102 | } else { 103 | connectionStatus.setText(""); 104 | if(PIService.getStatusConnectedUSB() == PIService.CONNECTED_USB_INFO.CONNECTED 105 | && passStartGame == 0){ 106 | Log.i(TAG, "try start game!"); 107 | Toast.makeText(getActivity(), "Start Game...", Toast.LENGTH_LONG).show(); 108 | passStartGame = PiSettings.getInstance().getCurrentSettings().behaviorSettings.TIMES_PASS_START_GAME; 109 | LauncherAct.tryStartGame(); 110 | } 111 | } 112 | } 113 | }); 114 | } 115 | } 116 | 117 | @Override 118 | public void onStop() { 119 | try { 120 | mTimer.cancel(); 121 | mTimer.purge(); 122 | } catch (Exception e) { 123 | e.printStackTrace(); 124 | } 125 | super.onStop(); 126 | } 127 | 128 | @Override 129 | public void onClick(View v) { 130 | Log.v(TAG,"onClick"); 131 | /* 132 | count+=1; 133 | if(count < COUNT_MAX) return; 134 | 135 | Log.v(TAG,"replace"); 136 | getFragmentManager().beginTransaction() 137 | .replace(R.id.container, new PasswordFragment(), PasswordFragment.class.getName()) 138 | .addToBackStack("") 139 | .commit(); 140 | */ 141 | LauncherAct.tryStartGame(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/GUIFragment/CVMaskResolver.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.GUIFragment; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.support.annotation.Nullable; 6 | import android.util.AttributeSet; 7 | import android.widget.ImageView; 8 | 9 | import org.opencv.android.Utils; 10 | import org.opencv.core.CvType; 11 | import org.opencv.core.Mat; 12 | import org.opencv.core.MatOfPoint; 13 | import org.opencv.core.Rect; 14 | import org.opencv.core.Scalar; 15 | import org.opencv.imgproc.Imgproc; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | import sermk.pipi.pilauncher.CVResolver; 21 | 22 | 23 | /** 24 | * Created by ser on 02.11.17. 25 | */ 26 | 27 | public class CVMaskResolver extends ImageView { 28 | 29 | protected Rect rectMaskByte; 30 | protected Mat roiMask; 31 | 32 | public CVMaskResolver(Context context, @Nullable AttributeSet attrs) { 33 | super(context, attrs); 34 | clearMask(); 35 | } 36 | 37 | private Mat previewRGBMat; 38 | protected Bitmap previewBitmap; 39 | 40 | public Rect getRectMaskByte() { 41 | return rectMaskByte; 42 | } 43 | 44 | public static byte[] convertMat2BAGRAY(final long ref){ 45 | Mat capMat = new Mat(ref); 46 | Mat bw = new Mat(); 47 | Imgproc.cvtColor(capMat,bw,Imgproc.COLOR_YUV2GRAY_YUYV); 48 | byte[] return_buff = new byte[(int) (bw.total() * 49 | bw.channels())]; 50 | bw.get(0, 0, return_buff); 51 | return return_buff; 52 | } 53 | 54 | public static long createRefMat(Rect rect, final byte[] bytes){ 55 | Mat mat = new Mat(rect.height, rect.width, CvType.CV_8UC1); 56 | mat.put(0,0,bytes); 57 | return mat.getNativeObjAddr(); 58 | } 59 | 60 | public byte[] getByteArrayMask() { 61 | byte[] return_buff = new byte[(int) (roiMask.total() * 62 | roiMask.channels())]; 63 | roiMask.get(0, 0, return_buff); 64 | return return_buff; 65 | } 66 | 67 | public void setMask(Rect mask, byte[] bytes){ 68 | rectMaskByte = mask; 69 | if(roiMask != null) { 70 | roiMask.release(); 71 | } 72 | roiMask = new Mat(mask.height, mask.width, CvType.CV_8UC1); 73 | roiMask.put(0,0,bytes); 74 | } 75 | 76 | @Override 77 | public void onSizeChanged (int w, int h, int oldw, int oldh){ 78 | super.onSizeChanged(w, h, oldw, oldh); 79 | if(previewRGBMat != null) 80 | previewRGBMat.release(); 81 | previewRGBMat = new Mat(h, w, CvType.CV_8UC3); 82 | previewBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 83 | CVResolver.setPlotOption(previewRGBMat.getNativeObjAddr()); 84 | } 85 | 86 | protected void clearMask(){ 87 | rectMaskByte = new Rect(0,0,0,0); 88 | if(roiMask != null) { 89 | roiMask.release(); 90 | } 91 | roiMask = new Mat(0,0,0); 92 | } 93 | public void cvCallback(final int position, final CVResolver cvr){ 94 | cvr.setRectOfMask(rectMaskByte.x, rectMaskByte.y, roiMask.getNativeObjAddr()); 95 | } 96 | protected Bitmap getPreviewBitmap(){ 97 | Utils.matToBitmap(previewRGBMat, previewBitmap); 98 | return previewBitmap; 99 | } 100 | 101 | protected android.graphics.Rect findMaskCounter(final Bitmap inMask){ 102 | Mat color = new Mat(); 103 | Mat bw = new Mat(); 104 | Utils.bitmapToMat(inMask,color); 105 | Imgproc.cvtColor(color,bw,Imgproc.COLOR_RGB2GRAY,1); 106 | color.release(); 107 | 108 | //Logger.v("channels :" + String.valueOf(bw.channels())); 109 | List contours = new ArrayList(); 110 | Mat hierarchy = new Mat(); 111 | 112 | Imgproc.findContours(bw,contours,hierarchy, 113 | Imgproc.RETR_EXTERNAL,Imgproc.CHAIN_APPROX_SIMPLE); 114 | //Logger.v("qty contourse :" + String.valueOf(contours.size())); 115 | double maxVal = 0; 116 | int maxValIdx = 0; 117 | for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) 118 | { 119 | double contourArea = Imgproc.contourArea(contours.get(contourIdx)); 120 | if (maxVal < contourArea) 121 | { 122 | maxVal = contourArea; 123 | maxValIdx = contourIdx; 124 | } 125 | } 126 | 127 | hierarchy.release(); 128 | MatOfPoint maxContour = contours.get(maxValIdx); 129 | Rect rect = Imgproc.boundingRect(maxContour); 130 | 131 | rectMaskByte = rect; 132 | bw.setTo(Scalar.all(0)); 133 | Imgproc.drawContours(bw,contours,maxValIdx,Scalar.all(255), -1); 134 | Mat submatRect = bw.submat(rect); 135 | //may be danger 136 | roiMask = new Mat(submatRect.size(), CvType.CV_8UC1); 137 | submatRect.copyTo(roiMask); 138 | 139 | bw.release(); 140 | 141 | android.graphics.Rect rectOfMask = new android.graphics.Rect(); 142 | rectOfMask.set( 143 | rect.x, rect.y, 144 | rect.x + rect.width, rect.y + rect.height 145 | ); 146 | return rectOfMask; 147 | } 148 | 149 | protected android.graphics.Rect getViewMask(){ 150 | android.graphics.Rect rectOfMask = new android.graphics.Rect(); 151 | rectOfMask.set(rectMaskByte.x, rectMaskByte.y, 152 | rectMaskByte.x + rectMaskByte.width, 153 | rectMaskByte.y + rectMaskByte.height); 154 | return rectOfMask; 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/externalcooperation/PiSettings.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.externalcooperation; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.google.gson.Gson; 7 | import com.google.gson.GsonBuilder; 8 | 9 | import org.opencv.core.Rect; 10 | 11 | import java.io.FileInputStream; 12 | import java.io.FileNotFoundException; 13 | import java.io.FileOutputStream; 14 | import java.io.IOException; 15 | 16 | import sermk.pipi.pilauncher.BehaviorSettings; 17 | import sermk.pipi.pilauncher.UVCReciver; 18 | import sermk.pipi.pilib.CommandCollection; 19 | import sermk.pipi.pilib.ErrorCollector; 20 | import sermk.pipi.pilib.MClient; 21 | import sermk.pipi.pilib.PiUtils; 22 | 23 | /** 24 | * Created by ser on 02.11.17. 25 | */ 26 | 27 | public final class PiSettings { 28 | 29 | final private String TAG = this.getClass().getName(); 30 | 31 | public static class Settings { 32 | public Rect rectMask = new Rect(); 33 | public UVCReciver.Settings uvcSettings = new UVCReciver.Settings(); 34 | public BehaviorSettings behaviorSettings = new BehaviorSettings(); 35 | } 36 | 37 | private Settings currentSettings = new Settings(); 38 | private byte[] bytesMask = new byte[0]; 39 | 40 | private static final String NAME_FILE_MASK = "mask.byte"; 41 | 42 | private static final String subjConfirm = "confirm.settings"; 43 | 44 | public void init(final Context context){ 45 | loadSettings(context); 46 | } 47 | 48 | private static PiSettings instance = null; 49 | 50 | static public PiSettings getInstance(){ 51 | if (instance == null){ 52 | instance = new PiSettings(); 53 | } 54 | return instance; 55 | } 56 | 57 | public Settings getCurrentSettings(){ 58 | return currentSettings; 59 | } 60 | public byte[] getBytesMask(){ return bytesMask; } 61 | 62 | public String setCurrentSettings( String json, byte[] bytesMask) { 63 | GsonBuilder builder = new GsonBuilder(); 64 | Gson gson = builder.create(); 65 | if (bytesMask != null){ 66 | this.bytesMask = bytesMask; 67 | } else { 68 | final String err ="setted byte mask not exist!"; 69 | this.bytesMask = new byte[0]; 70 | Log.e(TAG, err); 71 | return err; 72 | } 73 | 74 | final Settings temp = new Gson().fromJson(json, Settings.class); 75 | if(!PiUtils.checkHasNullPublicField(temp, Settings.class)){ 76 | this.currentSettings = temp; 77 | } else { 78 | final String err = "setted Struct Settings has null object!"; 79 | Log.e(TAG, err); 80 | this.currentSettings = new Settings(); 81 | return err; 82 | } 83 | return ErrorCollector.NO_ERROR; 84 | } 85 | 86 | public void clear(final Context context){ 87 | Log.v(TAG,"clear all settings!"); 88 | PiUtils.clearJson(context); 89 | } 90 | 91 | private String loadSettings(final Context context){ 92 | final String json = PiUtils.getJsonFromShared(context); 93 | Log.i(TAG, "load settings : " + json ); 94 | byte[] bytes = new byte[0]; 95 | try(FileInputStream inputStream = context.openFileInput(NAME_FILE_MASK)){ 96 | bytes = new byte[inputStream.available()]; 97 | inputStream.read(bytes); 98 | } catch (FileNotFoundException e) { 99 | e.printStackTrace(); 100 | return ErrorCollector.getStackTraceString(e); 101 | } catch (IOException e) { 102 | e.printStackTrace(); 103 | return ErrorCollector.getStackTraceString(e); 104 | } 105 | return setCurrentSettings(json, bytes); 106 | } 107 | 108 | public String saveCurrentSettings(Context context){ 109 | 110 | PiUtils.saveJson(context,jsonCurrentSettings()); 111 | try(FileOutputStream outputStream 112 | = context.openFileOutput(NAME_FILE_MASK, Context.MODE_PRIVATE) ) { 113 | outputStream.write(bytesMask); 114 | } catch (Exception e) { 115 | e.printStackTrace(); 116 | return ErrorCollector.getStackTraceString(e); 117 | } 118 | Log.v(TAG, "save mask in " + NAME_FILE_MASK); 119 | return ErrorCollector.NO_ERROR; 120 | } 121 | 122 | private String jsonCurrentSettings(){ 123 | GsonBuilder builder = new GsonBuilder(); 124 | Gson gson = builder.create(); 125 | final String json = gson.toJson(currentSettings); 126 | return json; 127 | } 128 | 129 | 130 | public boolean saveMaskInReceiver(Context context, final byte[] byteMask, final Rect rm){ 131 | currentSettings.rectMask = rm; 132 | final String json = jsonCurrentSettings(); 133 | Log.v(TAG, "json = " + json); 134 | SettingsReciever.sendBroadCastData(context, CommandCollection.ACTION_RECIVER_PILAUNCHER_SET_SETTINGS, json, byteMask); 135 | SettingsReciever.sendBroadCastData(context, CommandCollection.ACTION_RECIVER_PILAUNCHER_SAVE_SETTINGS, null, null); 136 | return true; 137 | } 138 | 139 | public boolean confirmSettings(Context context){ 140 | final String json = jsonCurrentSettings(); 141 | return MClient.sendMessage(context, subjConfirm, 142 | json, bytesMask); 143 | } 144 | 145 | public boolean confirmSettings(Context context, final byte[] frame){ 146 | final String json = jsonCurrentSettings(); 147 | return MClient.sendMessage(context, subjConfirm, 148 | json, frame); 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /app/src/main/java/sermk/pipi/pilauncher/GUIFragment/CVMaskView.java: -------------------------------------------------------------------------------- 1 | package sermk.pipi.pilauncher.GUIFragment; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Rect; 9 | import android.support.annotation.Nullable; 10 | import android.util.AttributeSet; 11 | import android.view.MotionEvent; 12 | 13 | import com.orhanobut.logger.Logger; 14 | 15 | import sermk.pipi.pilauncher.CVResolver; 16 | import sermk.pipi.pilib.PiBind; 17 | 18 | /** 19 | * Created by echormonov on 01.11.17. 20 | */ 21 | 22 | public class CVMaskView extends CVMaskResolver { 23 | 24 | private final String TAG = "CVMaskView"; 25 | 26 | public CVMaskView(Context context, @Nullable AttributeSet attrs) { 27 | super(context, attrs); 28 | } 29 | 30 | private Bitmap mask = null; 31 | private Bitmap result = null; 32 | private Canvas canvasResult = null; 33 | private Canvas canvasMask = null; 34 | private Paint maskPaint = null; 35 | private Paint renderPaint = null; 36 | private float halfDiagonal = 33; 37 | private Rect rectOfMask = null; 38 | private Paint pRectMask; 39 | 40 | private boolean checkInit(){ 41 | if (mask == null) 42 | return false; 43 | return true; 44 | } 45 | 46 | private int position = -1; 47 | private Paint positionPaint = new Paint(); 48 | 49 | public void clearMask(){ 50 | super.clearMask(); 51 | if(mask == null) return; 52 | mask.eraseColor(Color.TRANSPARENT); 53 | rectOfMask = null; 54 | position = -1; 55 | } 56 | 57 | 58 | public void setHdiag(final String str){ 59 | try{ 60 | int num = Integer.parseInt(str); 61 | halfDiagonal = (float)num; 62 | } catch (NumberFormatException e) { 63 | Logger.w("it's not float param " + str); 64 | halfDiagonal = 0; 65 | } 66 | } 67 | 68 | private void drawRectFrCenter(float x, float y){ 69 | float top = y - halfDiagonal; 70 | float bottom = y + halfDiagonal; 71 | float left = x - halfDiagonal; 72 | float right = x + halfDiagonal; 73 | 74 | canvasMask.drawRect(left,top,right,bottom,maskPaint); 75 | } 76 | 77 | private void drawPosition(){ 78 | if(rectOfMask == null) 79 | return; 80 | final float top = 0; 81 | final float bottom = result.getHeight(); 82 | final int w = 20; 83 | final float left = rectOfMask.left + position - w; 84 | final float right = left + 2*w; 85 | positionPaint.setColor(Color.MAGENTA); 86 | positionPaint.setAlpha(44); 87 | canvasResult.drawRect(left,top,right,bottom,positionPaint); 88 | } 89 | 90 | public int relativePosition(final int position, final int maxValue){ 91 | if(position < 0) 92 | return 0; 93 | if(rectOfMask == null) 94 | return 0; 95 | 96 | final int width = PiBind.POSITION_MAX;//rectOfMask.width(); 97 | if(position > width) 98 | return maxValue; 99 | final int relativePos = (position * maxValue )/ width; 100 | return relativePos; 101 | } 102 | 103 | @Override 104 | protected void onDraw(Canvas canvasResult) { 105 | canvasResult.drawBitmap(super.getPreviewBitmap(),0,0,null); 106 | 107 | canvasResult.drawBitmap(mask,0,0,renderPaint); 108 | 109 | rectOfMask = getViewMask(); 110 | 111 | if(rectOfMask != null){ 112 | canvasResult.drawRect(rectOfMask,pRectMask); 113 | } 114 | 115 | if(position > 0){ 116 | drawPosition(); 117 | } 118 | 119 | super.onDraw(canvasResult); 120 | } 121 | 122 | @Override 123 | public void cvCallback(final int position, final CVResolver cvr){ 124 | super.cvCallback(position,cvr); 125 | this.position = position; 126 | this.postInvalidate(); 127 | } 128 | 129 | @Override 130 | public void onSizeChanged (int w, int h, int oldw, int oldh){ 131 | super.onSizeChanged(w, h, oldw, oldh); 132 | mask = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 133 | clearMask(); 134 | canvasMask = new Canvas(mask); 135 | maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 136 | maskPaint.setColor(Color.RED); 137 | 138 | result = Bitmap.createBitmap(mask); 139 | result.eraseColor(Color.TRANSPARENT); 140 | canvasResult = new Canvas(result); 141 | renderPaint = new Paint(); 142 | renderPaint.setAlpha(70); 143 | 144 | pRectMask = new Paint(); 145 | pRectMask.setColor(Color.GREEN); 146 | pRectMask.setStyle(Paint.Style.STROKE); 147 | } 148 | 149 | @Override 150 | public boolean onTouchEvent(MotionEvent e) { 151 | 152 | if(!checkInit()) 153 | return true; 154 | 155 | // MotionEvent reports input details from the touch screen 156 | // and other input controls. In this case, you are only 157 | // interested in events where the touch position changed. 158 | 159 | final float x = e.getX(); 160 | final float y = e.getY(); 161 | 162 | switch (e.getAction()) { 163 | case MotionEvent.ACTION_DOWN: 164 | //Log.v(TAG,"ACTION_DOWN " + String.valueOf(x) + " " + String.valueOf(y) + " " + String.valueOf(w) + " " + String.valueOf(h)); 165 | case MotionEvent.ACTION_MOVE: 166 | drawRectFrCenter(x,y); 167 | break; 168 | case MotionEvent.ACTION_UP: 169 | //Log.v(TAG,"ACTION_UP " + String.valueOf(x) + " " + String.valueOf(y) + " " + String.valueOf(w) + " " + String.valueOf(h)); 170 | rectOfMask = super.findMaskCounter(mask); 171 | break; 172 | } 173 | 174 | return true; 175 | } 176 | 177 | } -------------------------------------------------------------------------------- /app/src/main/cpp/pi2_cv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by echormonov on 12.11.17. 3 | // 4 | 5 | #include "pi2_cv.h" 6 | #include 7 | #include "pi2_plot.h" 8 | 9 | using namespace cv; 10 | 11 | jobject pi2_cv::objectCV = NULL; 12 | jmethodID pi2_cv::midCV = NULL; 13 | uint8_t pi2_cv::arrayFromMask[pi2_plot::sizePreview] = {0}; 14 | uint8_t pi2_cv::arrayMask[pi2_plot::sizePreview] = {0}; 15 | Rect pi2_cv::maskRect; 16 | int pi2_cv::mode = pi2_cv::CAPTURE; 17 | 18 | bool pi2_cv::enableSingleCaptureFrame = false; 19 | Mat pi2_cv::captureFrame = Mat(); 20 | 21 | size_t pi2_cv::MAX_PULSE_WIDTH = pi2_plot::widthPreview; 22 | size_t pi2_cv::MIN_PULSE_WIDTH = 0; 23 | size_t pi2_cv::GAP_DECREASE_MASK = 50; // 50%1000 24 | 25 | 26 | #define TAG "# native #>" 27 | 28 | void HistType::newVerHistArrayYUYV(const uint8_t *array, const Rect &maskRect){ 29 | const size_t sizeHist = static_cast(maskRect.width); 30 | const size_t rows = static_cast(maskRect.height); 31 | this->clearHist(); 32 | for(size_t y=0; yhist[x] += array[y*sizeHist + x]; 35 | } 36 | } 37 | this->currSize = sizeHist; 38 | } 39 | 40 | void pi2_cv::setRectOfMask(JNIEnv *env, jobject thiz, jint x, jint y, ID_TYPE refMat) { 41 | Mat m = *reinterpret_cast(refMat); 42 | maskRect = Rect(x, y, m.cols, m.rows); 43 | uint8_t * pData = m.data; 44 | memcpy(arrayMask, pData, m.total()*m.elemSize()); 45 | m.release(); //remember! 46 | } 47 | 48 | void pi2_cv::calcUVC_FrameOfMask(uvc_frame_t *frame, const cv::Rect & maskRect) { 49 | const size_t xEnd = maskRect.x + maskRect.width; 50 | const size_t yEnd = maskRect.y + maskRect.height; 51 | const size_t widhtFrameYU = frame->width * 2; 52 | const uint8_t * pFrame = reinterpret_cast(frame->data); 53 | size_t i = 0; 54 | for(size_t y= maskRect.y; y < yEnd; y++){ 55 | for(size_t x=maskRect.x; x < xEnd; x++){ 56 | arrayFromMask[i] = pFrame[y*widhtFrameYU + 2*x] & arrayMask[i]; 57 | i++; 58 | } 59 | } 60 | } 61 | 62 | __inline int pi2_cv::normilizePosition(const int position) { 63 | const int norm = (position * FACTOR_TRANSFER_POSITION)/maskRect.width; 64 | return norm; 65 | } 66 | 67 | struct HistType vertHist; 68 | struct LearnHType learnHist; 69 | struct PowerHType powerHist; 70 | 71 | void pi2_cv::cvProccessing(JNIEnv *env, uvc_frame_t *frame) { 72 | 73 | if (!LIKELY(frame)) { 74 | LOGW(TAG"bad frame !!!"); 75 | return; 76 | } 77 | 78 | int position = UNDEFINED_POSITION; 79 | int width = 0; 80 | 81 | if(!maskRect.empty()){ 82 | Rect testRect = Rect(maskRect); 83 | calcUVC_FrameOfMask(frame,maskRect); 84 | vertHist.newVerHistArrayYUYV(arrayFromMask,maskRect); 85 | if( mode == LEARN) { 86 | LOGI("learn---"); 87 | learnHist.setMinValue(vertHist); 88 | } else { 89 | powerHist.calcPower(learnHist, vertHist); 90 | position = powerHist.calcPosition(width,MAX_PULSE_WIDTH, MIN_PULSE_WIDTH); 91 | if(position >= 0) { 92 | position = normilizePosition(position); 93 | } 94 | } 95 | } else { 96 | LOGI("empty +++ "); 97 | } 98 | 99 | if(enableSingleCaptureFrame){ 100 | Mat tmp = Mat(frame->height, frame->width, CV_8UC2, frame->data); 101 | captureFrame = tmp.clone(); 102 | enableSingleCaptureFrame = false; 103 | } 104 | 105 | if(pi2_plot::isEnablePlot()) { 106 | pi2_plot::clearAll(); 107 | Rect testRect = Rect(maskRect); 108 | testRect.y = pi2_plot::heightPreview; 109 | testRect.x = 0; 110 | if(!maskRect.empty()) { 111 | pi2_plot::plotSubGrayArray(arrayFromMask, testRect); 112 | pi2_plot::plotHist(vertHist, learnHist, powerHist); 113 | } 114 | pi2_plot::plotPreviewFrame(frame); 115 | } 116 | 117 | env->CallVoidMethod(objectCV, midCV, position, width); 118 | 119 | } 120 | 121 | jlong pi2_cv::getFrame(JNIEnv *env, jobject thiz, jint mode) { 122 | if (mode == START_TO) { 123 | enableSingleCaptureFrame = true; 124 | return 0; 125 | } 126 | if (captureFrame.empty()) { 127 | return 0; 128 | } 129 | return ((long)&captureFrame); 130 | } 131 | 132 | 133 | void pi2_cv::setMode(JNIEnv *env, jobject thiz, jint modeWork) { 134 | if( modeWork==CAPTURE ){ 135 | if( mode != CAPTURE ){ 136 | LOGI("provisioning for capture"); 137 | learnHist.mullArray(GAP_DECREASE_MASK,DIVIDER_GAP_MASK); 138 | } 139 | } 140 | 141 | if( modeWork==LEARN ){ 142 | if( mode != LEARN ){ 143 | LOGI("reset learnHist"); 144 | learnHist.clearHist(UINT64_MAX); 145 | } 146 | } 147 | mode = modeWork; 148 | } 149 | 150 | bool pi2_cv::startCV(JNIEnv *env, jobject thiz) { 151 | LOGI(TAG"startCV"); 152 | UVCPreview::setPass2cv(pi2_cv::cvProccessing); 153 | jclass clazz = env->GetObjectClass(thiz); 154 | if (env->IsSameObject(objectCV, thiz)){ 155 | LOGV(TAG"Same CV jobject"); 156 | return false; 157 | } 158 | env->DeleteGlobalRef(objectCV); 159 | objectCV = env->NewGlobalRef(thiz); 160 | if (LIKELY(clazz)) { 161 | midCV = env->GetMethodID(clazz, "plottCV","(II)V"); 162 | } else { 163 | LOGW(TAG"failed to get object class"); 164 | } 165 | env->ExceptionClear(); 166 | if (!midCV) { 167 | LOGE(TAG"Can't find plottCV : %p %p", midCV, clazz); 168 | } 169 | LOGI(TAG"succes set startCV! midCV point %p ",midCV); 170 | 171 | return true; 172 | } 173 | void pi2_cv::setOptions(JNIEnv *env, 174 | jobject thiz, 175 | jint MAX_PULSE_WIDTH, 176 | jint MIN_PULSE_WIDTH, 177 | jint GAP_DECREASE_MASK) { 178 | LOGI(TAG"set options %d %d %d",MAX_PULSE_WIDTH, MIN_PULSE_WIDTH, GAP_DECREASE_MASK); 179 | pi2_cv::MAX_PULSE_WIDTH = MAX_PULSE_WIDTH; 180 | pi2_cv::MIN_PULSE_WIDTH = MIN_PULSE_WIDTH; 181 | pi2_cv::GAP_DECREASE_MASK = GAP_DECREASE_MASK; 182 | } 183 | 184 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/cpp/pi_cv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by echormonov on 05.11.17. 3 | // 4 | 5 | #include "pi_cv.h" 6 | #include 7 | 8 | using namespace cv; 9 | 10 | static struct { 11 | Mat Mask;// = new Mat(0, 0, CV_8UC1); 12 | Rect rect; 13 | } piMask; 14 | 15 | static const size_t MAX_WIGTH_HIST = 640; 16 | static const size_t NUM_CHANNEL = 2; 17 | 18 | struct HistStruct{ 19 | uint64 hist[MAX_WIGTH_HIST] = {0}; 20 | int normHist[MAX_WIGTH_HIST] = {0}; 21 | size_t size = 0; 22 | uint64 maxValue = 0; 23 | 24 | void clearHist(uint64 val = 0){ 25 | memset(hist,val,MAX_WIGTH_HIST* sizeof(uint64)); 26 | maxValue = 0; 27 | } 28 | 29 | size_t verHistForMat(const Mat &mat){ 30 | const int matRows = mat.rows; 31 | const int matCols = mat.cols; 32 | clearHist(); 33 | const uint8_t * pMat = mat.data; 34 | for(size_t row= 0; row < matRows; row++ ){ 35 | for(size_t col= 0; col < matCols; col++){ 36 | hist[col] += pMat[row * matCols + col]; 37 | } 38 | } 39 | size = static_cast(matCols); 40 | return size; 41 | } 42 | 43 | uint64 getMaxValue(){ 44 | maxValue = 0; 45 | for(int i= 0; i < size; i++){ 46 | const uint64 val = hist[i]; 47 | if( maxValue < val){ 48 | maxValue = val; 49 | } 50 | } 51 | return maxValue; 52 | } 53 | 54 | void normalize(const int chartRow, const uint64 maxValue){ 55 | for(size_t i=0; i < size; i++){ 56 | normHist[i] = static_cast((chartRow * hist[i])/maxValue); 57 | } 58 | } 59 | 60 | void plot2MatRGB(const Mat & mat, const Scalar & colorPoints){ 61 | const int matRows = mat.rows; 62 | const int matCols = mat.cols; 63 | for( int i = 1; i < this->size; i++ ){ 64 | cv:line(mat, 65 | Point(i-1, normHist[i-1]), 66 | Point(i, normHist[i]), 67 | colorPoints, 68 | 2,8,0); 69 | } 70 | } 71 | }; 72 | 73 | struct LearnStruct: public HistStruct { 74 | 75 | void compareHist(const HistStruct & compHist){ 76 | for(size_t i = 0; i < compHist.size; i++){ 77 | uint64 val = compHist.hist[i]; 78 | if(this->hist[i] > val){ 79 | this->hist[i] = val; 80 | } 81 | } 82 | this->size = compHist.size; 83 | } 84 | 85 | void decreaseBound(const uint64 factor, const uint64 denominator){ 86 | for(size_t i=0; iclearHist(); 96 | for(size_t i=1; i < signal.size; i++){ 97 | int dif = static_cast(learn.hist[i] - signal.hist[i]); 98 | if(dif > 0) { 99 | this->hist[i] = dif; 100 | this->hist[i] += this->hist[i - 1]; 101 | } 102 | } 103 | this->size = signal.size; 104 | } 105 | 106 | int calcPosition(){ 107 | uint64 mv = 0; 108 | int position = -1; 109 | for(int i=0; i < size; i++){ 110 | uint64 val = hist[i]; 111 | if(val > mv){ 112 | mv = val; 113 | position = i; 114 | } 115 | } 116 | return position; 117 | } 118 | }; 119 | 120 | struct HistStruct currHist; 121 | struct LearnStruct learnHist; 122 | struct PowerStruct powerHist; 123 | 124 | 125 | void clear3UMat(const Mat & mat){ 126 | const int matRows = mat.rows; 127 | const int matCols = mat.cols; 128 | uint8_t * pMat = mat.data; 129 | const size_t size = matRows*matCols*3; 130 | for(size_t i=0; i < size; i++ ){ 131 | pMat[i] = 0; 132 | } 133 | } 134 | 135 | 136 | static Mat channels[NUM_CHANNEL]; 137 | 138 | int pi_cv::calcPipiChart(ID_TYPE refMatPreview, ID_TYPE refMatChart) { 139 | const Mat & preview = *reinterpret_cast(refMatPreview); 140 | const Mat & chart = *reinterpret_cast(refMatChart); 141 | //return 0; 142 | Mat roiPreview = Mat(preview, piMask.rect); 143 | #if 0 144 | Mat rgbRoiPreview = Mat(roiPreview.rows, roiPreview.cols, CV_8UC3); 145 | cvtColor(roiPreview, rgbRoiPreview, COLOR_YUV2RGB_YUYV); 146 | Rect rect = Rect(0,0, piMask.rect.width, piMask.rect.height); 147 | 148 | //Mat subChart = Mat(chart( piMask.rect)); 149 | Mat subChart = Mat(chart( rect)); 150 | rgbRoiPreview.copyTo(subChart 151 | ,piMask.Mask 152 | ); 153 | #endif 154 | clear3UMat(chart); 155 | split(roiPreview,channels); 156 | const Mat & samplesMat = channels[0]; 157 | bitwise_and(samplesMat,piMask.Mask,samplesMat, noArray()); 158 | #if 1 159 | Mat rgbRoiPreview = Mat(roiPreview.rows, roiPreview.cols, CV_8UC3); 160 | cvtColor(samplesMat, rgbRoiPreview, COLOR_GRAY2RGB); 161 | Rect rect = Rect(0,0, piMask.rect.width, piMask.rect.height); 162 | Mat subChart = Mat(chart( rect)); 163 | rgbRoiPreview.copyTo(subChart, piMask.Mask); 164 | #endif 165 | 166 | currHist.verHistForMat(samplesMat); 167 | const int maxRow = chart.rows - chart.rows/10; 168 | currHist.normalize(maxRow, currHist.getMaxValue()); 169 | const Scalar redPoints(255,0,0); 170 | currHist.plot2MatRGB(chart,redPoints); 171 | 172 | if(pi_cv::getLearnEnable()){ 173 | learnHist.compareHist(currHist); 174 | } else { 175 | powerHist.calcPower(learnHist,currHist); 176 | } 177 | 178 | learnHist.normalize(maxRow,currHist.maxValue); 179 | const Scalar greenPoints(0,255,0); 180 | learnHist.plot2MatRGB(chart,greenPoints); 181 | 182 | 183 | powerHist.normalize(maxRow,powerHist.getMaxValue()); 184 | const Scalar bluePoints(0,0,255); 185 | powerHist.plot2MatRGB(chart,bluePoints); 186 | 187 | return powerHist.calcPosition(); 188 | } 189 | 190 | 191 | int pi_cv::setRectMask(jint xsRoi, jint ysRoi, ID_TYPE refMat) { 192 | const Mat & mask = *reinterpret_cast(refMat); 193 | piMask.Mask = mask.clone(); 194 | int rows = mask.rows; 195 | int cols = mask.cols; 196 | piMask.rect = Rect(xsRoi, ysRoi, cols, rows); 197 | return 0; 198 | } 199 | 200 | void pi_cv::resetLearnHist() { 201 | learnHist.clearHist(UINT64_MAX); 202 | } 203 | 204 | void pi_cv::setupLearnHist() { 205 | learnHist.decreaseBound(1, 20); 206 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_test_cv_.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 14 | 15 | 22 | 23 | 28 | 29 | 30 | 34 | 35 | 41 | 42 | 47 | 48 | 52 | 53 | 58 | 59 | 60 | 64 | 65 | 70 | 71 | 72 | 73 | 77 | 78 | 83 | 84 |