├── 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 |
89 |
90 |
95 |
96 |
104 |
105 |
112 |
113 |
121 |
122 |
130 |
131 |
136 |
137 |
142 |
143 |
148 |
149 |
154 |
155 |
160 |
161 |
166 |
167 |
174 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/app/src/main/java/sermk/pipi/pilauncher/LauncherAct.java:
--------------------------------------------------------------------------------
1 | package sermk.pipi.pilauncher;
2 |
3 | import android.app.Activity;
4 | import android.app.Fragment;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.pm.ActivityInfo;
8 | import android.os.Bundle;
9 | import android.os.PowerManager;
10 | import android.util.Log;
11 | import android.view.View;
12 | import android.view.WindowManager;
13 | import android.widget.Toast;
14 |
15 | import org.greenrobot.eventbus.EventBus;
16 | import org.greenrobot.eventbus.Subscribe;
17 | import org.greenrobot.eventbus.ThreadMode;
18 |
19 |
20 | import sermk.pipi.pilauncher.GUIFragment.PasswordFragment;
21 | import sermk.pipi.pilauncher.GUIFragment.TestCV_Fragment;
22 | import sermk.pipi.pilauncher.GUIFragment.StatusFragment;
23 | import sermk.pipi.pilauncher.externalcooperation.PiSettings;
24 | import sermk.pipi.pilib.AppRunner;
25 | import sermk.pipi.pilib.ErrorCollector;
26 | import sermk.pipi.pilib.MClient;
27 | import sermk.pipi.pilib.WatchConnectionMClient;
28 |
29 |
30 | public class LauncherAct extends Activity implements Thread.UncaughtExceptionHandler {
31 |
32 | private final String TAG = this.getClass().getName();
33 |
34 | private final String TEST_INTENT_FIELD = "test";
35 |
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) { //todo buildconfig.DEBUG
38 | super.onCreate(savedInstanceState);
39 | setContentView(R.layout.activity_standalone);
40 |
41 | /** Problem on T310
42 | * this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
43 | */
44 | this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
45 |
46 | View decorView = getWindow().getDecorView();
47 | // Hide the status bar.
48 | int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
49 | decorView.setSystemUiVisibility(uiOptions);
50 |
51 | final boolean test = true; //this.getIntent().getBooleanExtra(TEST_INTENT_FIELD, false);
52 |
53 | if (test) {
54 | // do something for a debug build
55 | getFragmentManager().beginTransaction()
56 | .add(R.id.container, new TestCV_Fragment()).commit();
57 | } else {
58 | getFragmentManager().beginTransaction()
59 | .add(R.id.container, new StatusFragment()).commit();
60 | }
61 | PIService.runTry(this);
62 |
63 | Thread.setDefaultUncaughtExceptionHandler(this);
64 | }
65 |
66 | public enum Screen { TestCV, Password, Status};
67 |
68 | public void addFragment(final Screen screen){
69 | switch (screen){
70 | case Status: getFragmentManager().beginTransaction()
71 | .add(R.id.container, new StatusFragment()).commit();
72 | case Password:
73 | getFragmentManager().beginTransaction()
74 | .add(R.id.container, new PasswordFragment()).commit();
75 | case TestCV: getFragmentManager().beginTransaction()
76 | .add(R.id.container, new TestCV_Fragment()).commit();
77 | }
78 | }
79 |
80 | @Override
81 | protected void onStart() {
82 | //standTo();
83 | EventBus.getDefault().register(this);
84 | super.onStart();
85 | }
86 |
87 | @Override
88 | protected void onResume() {
89 | standTo();
90 | rest();
91 | super.onResume();
92 | }
93 |
94 | @Override
95 | protected void onStop() {
96 | EventBus.getDefault().unregister(this);
97 | super.onStop();
98 | }
99 |
100 | static public void lightOn(){
101 | EventBus.getDefault().post(State.STAND_TO);
102 | }
103 |
104 | static public void lightOff(){
105 | EventBus.getDefault().post(State.REST);
106 | }
107 |
108 | private enum State {STAND_TO, REST};
109 |
110 | @Subscribe(threadMode = ThreadMode.MAIN)
111 | public void onWakeUpEvent(State state) {
112 | Log.v(TAG, "status " + state);
113 | if(state.equals(State.STAND_TO)){
114 | Log.v(TAG, "Wake Up!!!" );
115 | Toast.makeText(this, "player came", Toast.LENGTH_LONG).show();
116 | standTo();
117 | } else {
118 | Log.v(TAG, "REST!!!" );
119 | Toast.makeText(this, "player left", Toast.LENGTH_LONG).show();
120 | rest();
121 | }
122 | }
123 |
124 | private void standTo(){
125 | PowerManager powerManager = ((PowerManager) getSystemService(Context.POWER_SERVICE));
126 | PowerManager.WakeLock wake = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
127 |
128 | wake.acquire();
129 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
130 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
131 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
132 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
133 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
134 | }
135 |
136 | private void rest(){
137 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
138 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
139 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
140 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
141 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
142 | }
143 |
144 | @Override
145 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
146 | AppRunner.onGameResult(requestCode,resultCode,data);
147 | }
148 |
149 |
150 | public static void tryStartGame(){
151 | EventBus.getDefault().post(RUN_APP.START);
152 | }
153 |
154 | private enum RUN_APP {START};
155 |
156 | @Subscribe
157 | public void tryRunGame(RUN_APP start){
158 | if (StatusFragment.getWatcherMC(this).checkTimeout()){
159 | Toast.makeText(this, "WIFI connection problem", Toast.LENGTH_LONG).show();
160 | return;
161 | }
162 |
163 | Fragment currFragment = getFragmentManager().findFragmentById(R.id.container);
164 | if(currFragment instanceof StatusFragment){
165 | runGame();
166 | return;
167 | }
168 |
169 | Log.i(TAG, "unvalible start game!");
170 | }
171 |
172 | public boolean runGame() {
173 | final String NAME_GAME_PACKAGE = PiSettings.getInstance().
174 | getCurrentSettings().behaviorSettings.NAME_GAME_PACKAGE;
175 | final String NAME_GAME_ACTIVITY = PiSettings.getInstance().
176 | getCurrentSettings().behaviorSettings.NAME_GAME_ACTIVITY;
177 | if (!AppRunner.run(this,NAME_GAME_PACKAGE,NAME_GAME_ACTIVITY)){
178 | Toast.makeText(this, "not found game", Toast.LENGTH_LONG).show();
179 | return false;
180 | }
181 | return true;
182 | }
183 |
184 | public static void restartThisApp(){
185 | EventBus.getDefault().post(RESTART_THIS_APP.RESTART);
186 | }
187 |
188 | private enum RESTART_THIS_APP { RESTART }
189 |
190 | @Subscribe
191 | public void tryRunGame(RESTART_THIS_APP restart){
192 | Toast.makeText(this, "Loading ...", Toast.LENGTH_LONG).show();
193 | this.finish();
194 | System.exit(3);
195 | }
196 |
197 |
198 | @Override
199 | public void uncaughtException(Thread t, Throwable e) {
200 | Log.e(TAG,"uncaughtException");
201 |
202 | MClient.sendMessage(this,
203 | ErrorCollector.subjError(TAG,"uncaughtException"),
204 | ErrorCollector.getStackTraceString(e));
205 | /*
206 | Intent intent = new Intent(this, LauncherAct.class);
207 | intent.putExtra("crash", true);
208 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
209 | | Intent.FLAG_ACTIVITY_CLEAR_TASK
210 | | Intent.FLAG_ACTIVITY_NEW_TASK);
211 | PendingIntent pendingIntent = PendingIntent.getActivity(getApplication().getBaseContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
212 | AlarmManager mgr = (AlarmManager) getApplication().getBaseContext().getSystemService(Context.ALARM_SERVICE);
213 | mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
214 | */
215 | this.finish();
216 | System.exit(2);
217 | }
218 |
219 | @Override
220 | public void onBackPressed() {
221 | Log.v(TAG,"onBackPressed");
222 | Fragment currFragment = getFragmentManager().findFragmentById(R.id.container);
223 | if(currFragment instanceof StatusFragment){
224 | getFragmentManager().beginTransaction()
225 | .replace(R.id.container, new PasswordFragment())
226 | .addToBackStack("")
227 | .commit();
228 | return;
229 | }
230 | super.onBackPressed();
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/app/src/main/java/sermk/pipi/pilauncher/PIService.java:
--------------------------------------------------------------------------------
1 | package sermk.pipi.pilauncher;
2 |
3 | import android.app.ActivityManager;
4 | import android.app.Notification;
5 | import android.app.NotificationManager;
6 | import android.app.PendingIntent;
7 | import android.app.Service;
8 | import android.content.Context;
9 | import android.content.Intent;
10 | import android.hardware.usb.UsbDevice;
11 | import android.os.IBinder;
12 | import android.os.Vibrator;
13 | import android.util.Log;
14 |
15 | import com.orhanobut.logger.Logger;
16 | import com.serenegiant.usb.USBMonitor;
17 |
18 | import org.greenrobot.eventbus.EventBus;
19 | import org.greenrobot.eventbus.Subscribe;
20 | import org.greenrobot.eventbus.ThreadMode;
21 |
22 | import sermk.pipi.pilauncher.GUIFragment.CVMaskResolver;
23 | import sermk.pipi.pilauncher.externalcooperation.PiSettings;
24 |
25 | /**
26 | * Created by echormonov on 20.11.17.
27 | */
28 |
29 | public final class PIService extends Service {
30 | private static final String TAG = "PIService";
31 |
32 | private static final int NOTIFICATION = R.string.app_name;
33 |
34 | private USBMonitor mUSBMonitor;
35 | private UVCReciver mUVCReciver;
36 | private NotificationManager mNotificationManager;
37 |
38 | @Override
39 | public void onCreate() {
40 | super.onCreate();
41 | Log.d(TAG, "onCreate:");
42 | mUSBMonitor = new USBMonitor(this, mOnDeviceConnectListener);
43 | mUSBMonitor.register();
44 | mUVCReciver = new UVCReciver(mUSBMonitor);
45 |
46 | mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
47 | showNotification("PIService start!");
48 | EventBus.getDefault().register(this);
49 | }
50 |
51 | @Override
52 | public boolean stopService(Intent name) {
53 | EventBus.getDefault().unregister(this);
54 | return super.stopService(name);
55 | }
56 |
57 | @Override
58 | public void onDestroy() {
59 | Log.d(TAG, "onDestroy:");
60 | stopForeground(true/*removeNotification*/);
61 | if (mNotificationManager != null) {
62 | mNotificationManager.cancel(NOTIFICATION);
63 | mNotificationManager = null;
64 | }
65 | super.onDestroy();
66 | }
67 |
68 | private void setPositionHandler(){
69 | final boolean res = mUVCReciver.setCallBackPositionInRun(mBinder);
70 | Logger.i("set pos callback " + res);
71 | }
72 |
73 | private void releasePositionHandler(){//todo may be not use?
74 | final boolean res = mUVCReciver.setCallBackPositionInRun(null);
75 | Logger.i("unset pos callback " + res);
76 | }
77 |
78 | private final PInterface_Impl mBinder = new PInterface_Impl();
79 |
80 |
81 | @Override
82 | public IBinder onBind(final Intent intent) {
83 | Log.i(TAG, "----onBind:" + intent);
84 |
85 | setPositionHandler();
86 |
87 | return mBinder;
88 | }
89 |
90 | @Override
91 | public void onRebind(final Intent intent) {
92 | Log.i(TAG, "onRebind:" + intent);
93 | setPositionHandler(); //todo may be not use?
94 | }
95 |
96 | @Override
97 | public boolean onUnbind(final Intent intent) {
98 | Log.i(TAG, "onUnbind:" + intent);
99 | releasePositionHandler();
100 | Log.i(TAG, "onUnbind:finished");
101 | return true;
102 | }
103 |
104 | private void showNotification(final CharSequence text) {
105 | Log.v(TAG, "showNotification:" + text);
106 | // Set the info for the views that show in the notification panel.
107 | final Notification notification = new Notification.Builder(this)
108 | .setSmallIcon(R.drawable.ic_launcher) // the status icon
109 | .setTicker(text) // the status text
110 | .setWhen(System.currentTimeMillis()) // the time stamp
111 | .setContentTitle(getText(R.string.app_name)) // the label of the entry
112 | .setContentText(text) // the contents of the entry
113 | .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, LauncherAct.class), 0)) // The intent to send when the entry is clicked
114 | .build();
115 |
116 | startForeground(NOTIFICATION, notification);
117 | // Send the notification.
118 | mNotificationManager.notify(NOTIFICATION, notification);
119 | }
120 |
121 | public static void startUVCwithCallbackPosition(CVResolver.ICallbackPosition callback){
122 | EventBus.getDefault().post(callback);
123 | }
124 |
125 | private enum RESTART_UVC { WAIT_RESTART }
126 |
127 | @Subscribe(threadMode = ThreadMode.BACKGROUND)
128 | public void restartUVC(RESTART_UVC restart){
129 | int try_restart = PiSettings.getInstance().getCurrentSettings()
130 | .behaviorSettings.TIMES_TRY_RESTART_UVC;
131 | while (mUVCReciver.isAlive() && try_restart != 0){
132 | mUVCReciver.exitRun();
133 | try_restart--;
134 | Log.w(TAG, "try exit UVC Thread!");
135 | try {
136 | Thread.sleep(100L);
137 | } catch (InterruptedException e) {
138 | e.printStackTrace();
139 | }
140 | }
141 | if(try_restart == 0)
142 | LauncherAct.restartThisApp();
143 | }
144 |
145 | @Subscribe(threadMode = ThreadMode.BACKGROUND)
146 | public void startUVC(CVResolver.ICallbackPosition callback){
147 | mBinder.clearPosition();
148 | if(mUVCReciver != null)
149 | if(!mUVCReciver.isAlive()) {
150 | mUVCReciver.startCapture(callback);
151 | } else { //todo forse release if run!
152 | Log.w(TAG, "thread UVC run!");
153 | EventBus.getDefault().post(RESTART_UVC.WAIT_RESTART);
154 | }
155 |
156 | }
157 |
158 | private enum SIGNAL_VIBRATION {SIGNAL}
159 |
160 | public static void external_trySignalVibration(){
161 | EventBus.getDefault().post(SIGNAL_VIBRATION.SIGNAL);
162 | }
163 |
164 | @Subscribe
165 | public void trySignalVibration(SIGNAL_VIBRATION signal){
166 | Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
167 | final long time = PiSettings.getInstance().getCurrentSettings().behaviorSettings.VIBRATE_TIME_MS;
168 | if(v.hasVibrator()) {
169 | Log.v(TAG, "hasVibrator");
170 | v.vibrate(time);
171 | }
172 | }
173 |
174 | private enum STOP_UVC_TYPE {STOP}
175 |
176 | public static void external_completeUVC(){
177 | EventBus.getDefault().post(STOP_UVC_TYPE.STOP);
178 | }
179 |
180 | @Subscribe(threadMode = ThreadMode.BACKGROUND)
181 | public void completeUVC(STOP_UVC_TYPE stop) {
182 | mUVCReciver.exitRun();
183 | mBinder.sendingCloseCode();
184 | }
185 |
186 | public enum ATTACHMENT_USB_INFO {ATTACHED, DETACHED}
187 |
188 | public enum CONNECTED_USB_INFO {CONNECTED, DISCONNECTED}
189 |
190 | private static ATTACHMENT_USB_INFO statusAttachedUSB = ATTACHMENT_USB_INFO.DETACHED;
191 |
192 | private static CONNECTED_USB_INFO statusConnectedUSB = CONNECTED_USB_INFO.DISCONNECTED;
193 |
194 | public static ATTACHMENT_USB_INFO getStatusAttachedUSB(){return statusAttachedUSB;}
195 |
196 | public static CONNECTED_USB_INFO getStatusConnectedUSB(){return statusConnectedUSB;}
197 |
198 | private final USBMonitor.OnDeviceConnectListener mOnDeviceConnectListener = new USBMonitor.OnDeviceConnectListener() {
199 | @Override
200 | public void onAttach(final UsbDevice device) {
201 | Logger.i("onAttach");
202 | startUVC(mBinder);
203 | LauncherAct.lightOn();
204 | statusAttachedUSB = ATTACHMENT_USB_INFO.ATTACHED;
205 | EventBus.getDefault().post(statusAttachedUSB);
206 | }
207 |
208 | //todo: remove run game, set state connected
209 | @Override
210 | public void onConnect(final UsbDevice device, final USBMonitor.UsbControlBlock ctrlBlock, final boolean createNew) {
211 | Logger.i("onConnect");
212 | //LauncherAct.tryStartGame();
213 | statusConnectedUSB = CONNECTED_USB_INFO.CONNECTED;
214 | }
215 |
216 | @Override
217 | public void onDisconnect(final UsbDevice device, final USBMonitor.UsbControlBlock ctrlBlock) {
218 | Logger.i("onDisconnect");
219 |
220 | statusConnectedUSB = CONNECTED_USB_INFO.DISCONNECTED;
221 |
222 | final long refFrame = mUVCReciver.getRefCaptureFrameMat();
223 | if(refFrame == 0)
224 | return;
225 | final byte[] capture = CVMaskResolver.convertMat2BAGRAY(refFrame);
226 | if(PiSettings.getInstance().confirmSettings(
227 | PIService.this,capture)){
228 | mUVCReciver.markingSuccessCaptureFrameMat();
229 | }
230 | }
231 | @Override
232 | public void onDettach(final UsbDevice device) {
233 | Logger.i("onDettach");
234 | LauncherAct.lightOff();
235 | external_completeUVC();
236 | statusAttachedUSB = ATTACHMENT_USB_INFO.DETACHED;
237 | EventBus.getDefault().post(statusAttachedUSB);
238 | }
239 |
240 | @Override
241 | public void onCancel(final UsbDevice device) {
242 | Logger.v("onCancel");
243 | }
244 |
245 | };
246 |
247 | public static void runTry(Context context){
248 | final String TAG_CONTEXT = context.getClass().getName();
249 | ActivityManager manager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
250 | for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)){
251 | if(PIService.class.getName().equals(service.service.getClassName())) {
252 | Log.v(TAG_CONTEXT, "service run");
253 | return;
254 | }
255 | }
256 | Log.v(TAG_CONTEXT, "start services!");
257 | context.startService(new Intent(context, PIService.class));
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/app/src/main/java/sermk/pipi/pilauncher/UVCReciver.java:
--------------------------------------------------------------------------------
1 | package sermk.pipi.pilauncher;
2 |
3 | import android.hardware.usb.UsbDevice;
4 | import android.support.annotation.Nullable;
5 | import android.util.Log;
6 | import android.view.Surface;
7 |
8 | import com.orhanobut.logger.Logger;
9 | import com.serenegiant.usb.IStatusCallback;
10 | import com.serenegiant.usb.USBMonitor;
11 | import com.serenegiant.usb.USBMonitor.UsbControlBlock;
12 | import com.serenegiant.usb.UVCCamera;
13 |
14 | import org.opencv.core.Rect;
15 |
16 | import java.lang.ref.WeakReference;
17 | import java.nio.ByteBuffer;
18 | import java.util.Date;
19 | import java.util.List;
20 |
21 | import sermk.pipi.pilauncher.GUIFragment.CVMaskResolver;
22 | import sermk.pipi.pilauncher.externalcooperation.PiSettings;
23 |
24 | /**
25 | * Created by ser on 31.10.17.
26 | */
27 |
28 | public class UVCReciver extends Thread implements CVResolver.ICallbackPosition {
29 | private final String TAG = this.getName();
30 |
31 | private final Object mSyncExit = new Object();
32 |
33 | private enum State { USB_MONITOR_ERROR,
34 | USB_LIST_EMPTY,
35 | CAMERA_OPEN_ERROR,
36 | TRANING_ERROR,
37 | RELEASE };
38 |
39 |
40 | static public class Settings {
41 | public int width = UVCCamera.DEFAULT_PREVIEW_WIDTH;
42 | public int height = UVCCamera.DEFAULT_PREVIEW_HEIGHT;
43 | public int minFps = 25;
44 | public int maxFps = 30;
45 | public int frameformat = UVCCamera.FRAME_FORMAT_YUYV;
46 | public float bandwightFactor = 1.0f;
47 | }
48 |
49 | Settings uvcSettings;
50 |
51 | private WeakReference inThreadResolver;
52 |
53 | /**
54 | * for accessing USB
55 | */
56 | private USBMonitor mUSBMonitor;
57 |
58 | public UVCReciver(final USBMonitor usbMonitor) {
59 | super("UVCReciver");
60 | Logger.v(TAG);
61 | this.mUSBMonitor = usbMonitor;
62 | }
63 |
64 | public void startCapture(@Nullable final CVResolver.ICallbackPosition callback){
65 | mCallBackPosition = callback;
66 | this.start();
67 | Logger.v("start UVC thread");
68 | }
69 |
70 | public boolean setCallBackPositionInRun(CVResolver.ICallbackPosition callBackPosition) {
71 | if(inThreadResolver == null){
72 | Logger.w("UVC not RAN!");
73 | return false;
74 | }
75 | final CVResolver cvr = inThreadResolver.get();
76 | if(cvr==null){
77 | Logger.w("cvresolver not exist!");
78 | return false;
79 | }
80 |
81 | if(callBackPosition != null){
82 | mCallBackPosition = callBackPosition;
83 | } else {
84 | mCallBackPosition = this;
85 | }
86 |
87 | cvr.setCallback(mCallBackPosition);
88 | return true;
89 | }
90 |
91 | void exitRun(){
92 | synchronized(mSyncExit) {
93 | mSyncExit.notifyAll();
94 | }
95 | mCallBackPosition = this;
96 | }
97 |
98 | @Override
99 | public void run() {
100 | final long TIMEOUT = getBS().TIMEOUT_BETWEEN_TRY_UVC_CONNECTION;
101 | final int TRY_MAX = getBS().TRY_MAX_UVC_CONNECTION;
102 | int try_start = TRY_MAX;
103 | while (try_start > 0) {
104 | final State state = openUVC();
105 | switch (state){
106 | case CAMERA_OPEN_ERROR:
107 | case TRANING_ERROR:
108 | try {sleep(TIMEOUT);} catch (InterruptedException e) {
109 | e.printStackTrace();
110 | }
111 | try_start--;
112 | continue;
113 | }
114 | break;
115 | }
116 | if(try_start == 0){
117 | PIService.external_trySignalVibration();
118 | }
119 | Logger.v("exit run");
120 | }
121 |
122 | private State openUVC(){
123 | if (!mUSBMonitor.isRegistered())
124 | return State.USB_MONITOR_ERROR;
125 | final List list = mUSBMonitor.getDeviceList();
126 | Logger.v("list size: " + String.valueOf(list.size()));
127 | if (list.size() == 0) {
128 | return State.USB_LIST_EMPTY;
129 | }
130 | UsbDevice device = list.get(0);
131 |
132 | Logger.v("getDeviceClass :" +
133 | String.valueOf(device.getDeviceClass()) +" did: "
134 | + String.valueOf(device.getDeviceId()) + " PId: "
135 | + String.valueOf(device.getProductId()) + " Vid"
136 | + String.valueOf(device.getVendorId() ) + " name: "
137 | + device.getDeviceName()
138 | );
139 |
140 | mUSBMonitor.requestPermission(device);
141 |
142 | final UsbControlBlock ublock = mUSBMonitor.openDevice(device);
143 | final UVCCamera camera = new UVCCamera();
144 |
145 | State state = State.RELEASE;
146 |
147 | //todo: try - catch - no!
148 | camera.open(ublock);
149 | if(!initCamera(camera)){
150 | state = State.CAMERA_OPEN_ERROR;
151 | } else {
152 | final CVResolver cvr = new CVResolver(mCallBackPosition);
153 | cvr.setDisablePlot(true);
154 | inThreadResolver = new WeakReference(cvr);
155 |
156 | camera.startPreview();
157 |
158 | if (!tranning(cvr)) {
159 | state = State.TRANING_ERROR;
160 | } else {
161 | waitExit(INF_WAIT);
162 | } //tranning - success
163 | cvr.stop();
164 | } //initCamera - success
165 |
166 | releaseCamera(camera);
167 |
168 | return state;
169 | }
170 |
171 | private static final long INF_WAIT = 0;
172 |
173 | private boolean waitExit(final long millis){
174 | synchronized (mSyncExit) {
175 | try {
176 | if(millis > 0)
177 | mSyncExit.wait(millis);
178 | else
179 | mSyncExit.wait();
180 | } catch (final InterruptedException e) {
181 | Logger.e(e, "wait failed");
182 | return false;
183 | }
184 | } //mSyncExit
185 | return true;
186 | }
187 |
188 | private void releaseCamera(final UVCCamera camera){
189 | if (camera != null) {
190 | camera.stopPreview();
191 | camera.setStatusCallback(null);
192 | camera.setButtonCallback(null);
193 | camera.close();
194 | camera.destroy();
195 | }
196 | }
197 |
198 | boolean initCamera(final UVCCamera camera){
199 | camera.setStatusCallback(new IStatusCallback() {
200 | @Override
201 | public void onStatus(final int statusClass, final int event, final int selector,
202 | final int statusAttribute, final ByteBuffer data) {
203 | final String status = "onStatus( statusClass= " + statusClass + "; event= " + event
204 | + "; selector= " + selector + "; statusAttribute= " + statusAttribute;
205 | Log.v(TAG, status); }
206 | });
207 |
208 | final Settings settings = PiSettings.getInstance().getCurrentSettings().uvcSettings;
209 |
210 | try {
211 | camera.setPreviewDisplay((Surface)null);
212 | camera.setPreviewSize(settings.width,settings.height, settings.minFps,
213 | settings.maxFps, settings.frameformat, settings.bandwightFactor);
214 | } catch (final IllegalArgumentException e1) {
215 | camera.destroy();
216 | Logger.e(e1, "camera IllegalArgumentException!");
217 | return false;
218 | } catch (Exception e) {
219 | Logger.e(e,"camera common exaption!");
220 | camera.destroy();
221 | return false;
222 | }
223 | return true;
224 | }
225 |
226 | static private BehaviorSettings getBS() {
227 | return PiSettings.getInstance().getCurrentSettings().behaviorSettings;
228 | }
229 |
230 |
231 | private boolean tranning(final CVResolver cvr){
232 | countTraningFrame = 0;
233 | final long WARMING_UP_TIME = getBS().WARMING_UP_TIME;
234 | final long TRANNING_TIME = getBS().TRANNING_TIME;
235 | final int COUNT_MIN = getBS().COUNT_TRANNING_FRAMES;
236 |
237 | setUpMask(cvr);
238 | cvr.setOptions(getBS().MAX_PULSE_WIDTH,
239 | getBS().MIN_PULSE_WIDTH,
240 | getBS().GAP_DECREASE_MASK);
241 |
242 | cvr.setCallback(this);
243 |
244 | Logger.v( "warming-up start time " + String.valueOf(WARMING_UP_TIME));
245 | if(!waitExit(WARMING_UP_TIME))
246 | return false;
247 | Log.v(TAG, "warming-up stop");
248 |
249 | Logger.v( "Start tranning!");
250 | cvr.setMode(cvr.MODE_LEARN);
251 | if(!waitExit(TRANNING_TIME))
252 | return false;
253 |
254 | Logger.v( "Stop tranning, Start capturing!");
255 | cvr.setMode(cvr.MODE_CAPTURE);
256 |
257 | if(countTraningFrame < COUNT_MIN){
258 | Log.w(TAG,"callback don't call!");
259 | return false;
260 | }
261 |
262 | if(!captureFrameAndSave(cvr))
263 | return false;
264 |
265 | cvr.setCallback(mCallBackPosition);
266 | return true;
267 | }
268 |
269 | private void setUpMask(CVResolver cvr){
270 | Rect rect = PiSettings.getInstance().getCurrentSettings().rectMask;
271 | final byte[] bytes = PiSettings.getInstance().getBytesMask();
272 | final long refMat = CVMaskResolver.createRefMat(rect, bytes);
273 | cvr.setRectOfMask(rect.x, rect.y, refMat);
274 | }
275 |
276 | private static long lastCaptureDate = 0;
277 | private long refFrame = 0;
278 | public static final long MIN_CAPTURE_FRAME_INTERVAL = 0;
279 |
280 | public static void clear_CAPTURE_FRAME_INTERVAL_PREV(){
281 | getBS().CAPTURE_FRAME_INTERVAL = MIN_CAPTURE_FRAME_INTERVAL;
282 | }
283 |
284 | public long getRefCaptureFrameMat(){ return refFrame; }
285 | public void markingSuccessCaptureFrameMat(){
286 | lastCaptureDate = new Date().getTime();
287 | refFrame=0;
288 | if (getBS().CAPTURE_FRAME_INTERVAL == MIN_CAPTURE_FRAME_INTERVAL){
289 | getBS().CAPTURE_FRAME_INTERVAL = getBS().CAPTURE_FRAME_INTERVAL_PREV;
290 | }
291 | }
292 |
293 | private boolean captureFrameAndSave(final CVResolver cvr){
294 | final long CAPTURE_WAIT_TIME = getBS().CAPTURE_WAIT_TIME;
295 | final long CAPTURE_FRAME_INTERVAL = getBS().CAPTURE_FRAME_INTERVAL;
296 |
297 | final long lastCaptureAgo = new Date().getTime() - lastCaptureDate;
298 | if(lastCaptureAgo < CAPTURE_FRAME_INTERVAL)
299 | return true;
300 |
301 | Logger.v("start capture Frame");
302 | final int firstCount = countTraningFrame;
303 | cvr.getFrame(cvr.CAPTURE_ONE_FRAME_START_TO);
304 | if(!waitExit(CAPTURE_WAIT_TIME))
305 | return false;
306 | if( countTraningFrame == firstCount )
307 | return true;
308 |
309 | Logger.v("capture Frame");
310 |
311 | refFrame = cvr.getFrame(cvr.CAPTURE_ONE_FRAME_RETURN_RESULT);
312 | if(refFrame == 0){
313 | return true;
314 | }
315 |
316 | Log.v(TAG, "date : " + new Date() );
317 | return true;
318 | }
319 |
320 | int countTraningFrame = 0;
321 |
322 | @Override
323 | public boolean callbackPosition(int pos, final int width, CVResolver cvr) {
324 | countTraningFrame++;
325 | //Log.v(TAG,"!");
326 | return true;
327 | }
328 |
329 | private CVResolver.ICallbackPosition mCallBackPosition = this;
330 |
331 | }
332 |
--------------------------------------------------------------------------------
/app/src/main/java/sermk/pipi/pilauncher/GUIFragment/TestCV_Fragment.java:
--------------------------------------------------------------------------------
1 | package sermk.pipi.pilauncher.GUIFragment;
2 |
3 | import android.app.Fragment;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.Color;
7 | import android.os.Bundle;
8 | import android.util.Log;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.view.WindowManager;
13 | import android.widget.Button;
14 | import android.widget.CompoundButton;
15 | import android.widget.EditText;
16 | import android.widget.TextView;
17 | import android.widget.Toast;
18 | import android.widget.ToggleButton;
19 |
20 | import com.serenegiant.utils.CpuMonitor;
21 | import com.serenegiant.utils.FpsCounter;
22 |
23 | import org.greenrobot.eventbus.EventBus;
24 | import org.greenrobot.eventbus.Subscribe;
25 | import org.greenrobot.eventbus.ThreadMode;
26 |
27 | import java.util.Locale;
28 | import java.util.Timer;
29 | import java.util.TimerTask;
30 |
31 | import sermk.pipi.pilauncher.CVResolver;
32 | import sermk.pipi.pilauncher.PIService;
33 | import sermk.pipi.pilauncher.R;
34 | import sermk.pipi.pilauncher.LauncherAct;
35 | import sermk.pipi.pilauncher.externalcooperation.PiSettings;
36 | import sermk.pipi.pilib.CommandCollection;
37 | import sermk.pipi.pilib.MClient;
38 |
39 |
40 | /**
41 | * A simple {@link Fragment} subclass.
42 | * Activities that contain this fragment must implement the
43 | */
44 | public class TestCV_Fragment extends Fragment {
45 |
46 | private final String TAG = "TestCV_Fragment";
47 |
48 | @Override
49 | public void onCreate(Bundle savedInstanceState) {
50 | super.onCreate(savedInstanceState);
51 | }
52 |
53 | private ToggleButton mStartStopButton;
54 | private ToggleButton mLearnButton;
55 | private ToggleButton mDrawButton;
56 | private CVMaskView mPlotPreview;
57 | SeekText posCallbackSeek;
58 | TextView text_hdiag_seek;
59 | TextView text_width_pulse_seek;
60 |
61 | TextView cpuView;
62 | TextView fpsView;
63 |
64 | private final CpuMonitor mCpuMonitor = new CpuMonitor();
65 | private FpsCounter mFpsCounter;
66 | private Timer mTimer;
67 |
68 | private EditText minWidthET;
69 | private EditText maxWidthET;
70 |
71 | @Override
72 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
73 | Bundle savedInstanceState) {
74 |
75 | final View rootView = inflater.inflate(R.layout.fragment_test_cv_, container, false);
76 |
77 | mStartStopButton = (ToggleButton)rootView.findViewById(R.id.start_test);
78 | mStartStopButton.setOnCheckedChangeListener(runAndStopUVC_listener);
79 |
80 | mLearnButton = (ToggleButton)rootView.findViewById(R.id.learn_enable);
81 | mDrawButton = (ToggleButton)rootView.findViewById(R.id.draw_disable);
82 |
83 | mPlotPreview = (CVMaskView)rootView.findViewById(R.id.capture_view);
84 |
85 | posCallbackSeek = (SeekText)rootView.findViewById(R.id.pos_seek);
86 | SeekText hDiagSeek = (SeekText)rootView.findViewById(R.id.hdiag_seek);
87 |
88 | TextView text_pos_seek = (TextView)rootView.findViewById(R.id.text_pos_seek);
89 | text_width_pulse_seek = (TextView)rootView.findViewById(R.id.text_width_pulse_seek);
90 | text_hdiag_seek = (TextView)rootView.findViewById(R.id.text_hdiag_seek);
91 |
92 | posCallbackSeek.setTv(text_pos_seek);
93 |
94 | hDiagSeek.setTv(text_hdiag_seek);
95 |
96 | ((Button)rootView.findViewById(R.id.clear_button))
97 | .setOnClickListener(new View.OnClickListener() {
98 | @Override
99 | public void onClick(View v) {
100 | mPlotPreview.clearMask();
101 | }
102 | });
103 |
104 | cpuView = (TextView)rootView.findViewById(R.id.cpu_view);
105 | fpsView = (TextView)rootView.findViewById(R.id.fps_view);
106 |
107 | minWidthET = (EditText)rootView.findViewById(R.id.min_widht_pulse_ET);
108 | maxWidthET = (EditText)rootView.findViewById(R.id.max_widht_pulse_ET);
109 |
110 | getActivity().getWindow().
111 | setSoftInputMode(WindowManager.
112 | LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
113 |
114 | initUISettings();
115 |
116 | mFpsCounter = new FpsCounter();
117 | mFpsCounter.reset();
118 |
119 | ((Button)rootView.findViewById(R.id.start_app)).setOnClickListener(new View.OnClickListener() {
120 | @Override
121 | public void onClick(View v) {
122 | ((LauncherAct)getActivity()).runGame();
123 | }
124 | });
125 |
126 | ((Button)rootView.findViewById(R.id.start_mclient)).setOnClickListener(new View.OnClickListener() {
127 | @Override
128 | public void onClick(View v) {
129 | if(!MClient.runMC(getActivity())) Toast.makeText(getActivity(), "not found mclient", Toast.LENGTH_LONG).show();
130 | }
131 | });
132 |
133 | ((Button)rootView.findViewById(R.id.save_mask)).setOnClickListener(new View.OnClickListener() {
134 | @Override
135 | public void onClick(View v) {
136 | saveSettings();
137 | }
138 | });
139 |
140 | ((Button)rootView.findViewById(R.id.confirm)).setOnClickListener(new View.OnClickListener() {
141 | @Override
142 | public void onClick(View v) {
143 | PiSettings.getInstance().confirmSettings(getActivity());
144 | }
145 | });
146 |
147 | ((Button)rootView.findViewById(R.id.clear_settings)).setOnClickListener(new View.OnClickListener() {
148 | @Override
149 | public void onClick(View v) {
150 | PiSettings.getInstance().clear(getActivity());
151 | }
152 | });
153 |
154 | ((Button)rootView.findViewById(R.id.click_vib)).setOnClickListener(new View.OnClickListener() {
155 | @Override
156 | public void onClick(View v) {
157 | PIService.external_trySignalVibration();
158 | }
159 | });
160 |
161 | ((Button)rootView.findViewById(R.id.not_start)).setOnClickListener(new View.OnClickListener() {
162 | @Override
163 | public void onClick(View v) {
164 | getActivity().sendBroadcast(new Intent(CommandCollection.ACTION_RECIVER_DPC_NOT_START_COSU_ONE));
165 | getActivity().sendBroadcast(new Intent("REBOOT"));
166 | }
167 | });
168 |
169 | ((Button)rootView.findViewById(R.id.confirm)).setOnClickListener(new View.OnClickListener() {
170 | @Override
171 | public void onClick(View v) {
172 | PiSettings.getInstance().confirmSettings(getActivity());
173 | }
174 | });
175 |
176 | EventBus.getDefault().register(this);
177 |
178 | // Inflate the layout for this fragment
179 | return rootView;
180 | }
181 |
182 | private int intervalValue(String val_str, int min, int max){
183 | int val = min;
184 | try {
185 | val = Integer.valueOf(val_str);
186 | } catch (Exception e){
187 | e.printStackTrace();
188 | }
189 |
190 | if(val < min) val = min;
191 | if(val > max) val = max;
192 |
193 | return val;
194 | }
195 |
196 | private void initUISettings(){
197 | final int min = PiSettings.getInstance().getCurrentSettings().behaviorSettings.MIN_PULSE_WIDTH;
198 | minWidthET.setText(String.valueOf(min));
199 |
200 | final int max = PiSettings.getInstance().getCurrentSettings().behaviorSettings.MAX_PULSE_WIDTH;
201 | maxWidthET.setText(String.valueOf(max));
202 | }
203 |
204 | private void saveSettings(){
205 | final int min = intervalValue(minWidthET.getText().toString(), 0,500);
206 | final int max = intervalValue(maxWidthET.getText().toString(), min + 1, 1000);
207 |
208 | PiSettings.getInstance().getCurrentSettings().
209 | behaviorSettings.MAX_PULSE_WIDTH = max;
210 |
211 | PiSettings.getInstance().getCurrentSettings().
212 | behaviorSettings.MIN_PULSE_WIDTH = min;
213 |
214 | PiSettings.getInstance().saveCurrentSettings(getActivity());
215 |
216 | PiSettings.getInstance().saveMaskInReceiver(getActivity(),
217 | mPlotPreview.getByteArrayMask(), mPlotPreview.getRectMaskByte());
218 |
219 | }
220 |
221 | @Override
222 | public void onStart() {
223 | super.onStart();
224 | }
225 |
226 | @Override
227 | public void onResume() {
228 | mTimer = new Timer("cpu_fps_timer");
229 | mTimer.schedule(new TimerTask() { // Определяем задачу
230 | @Override
231 | public void run() {
232 | cpuView.post(new Runnable() {
233 | @Override
234 | public void run() {
235 | cpuView.setText(String.format(Locale.US, "GPU:%3d/%3d/%3d",
236 | mCpuMonitor.getCpuCurrent(),
237 | mCpuMonitor.getCpuAvg3(),
238 | mCpuMonitor.getCpuAvgAll()));
239 | }
240 | });
241 | fpsView.post(new Runnable() {
242 | @Override
243 | public void run() {
244 | mFpsCounter.update();
245 | fpsView.setText(String.format(Locale.US, "CDR:%4.1f", mFpsCounter.getFps()));
246 | }
247 | });
248 | }
249 | }, 1111L,
250 | getResources().getInteger(R.integer.cpu_timer_period)); // интервал - 60000 миллисекунд, 0 миллисекунд до первого запуска.
251 | super.onResume();
252 | }
253 |
254 | @Override
255 | public void onAttach(Context context) {
256 | super.onAttach(context);
257 |
258 | }
259 |
260 | @Override
261 | public void onStop() {
262 | try {
263 | mTimer.cancel();
264 | //mTimer.purge();
265 | } catch (Exception e) {
266 | e.printStackTrace();
267 | }
268 | super.onStop();
269 | }
270 |
271 | @Override
272 | public void onDetach() {
273 | super.onDetach();
274 | }
275 |
276 | private final CompoundButton.OnCheckedChangeListener runAndStopUVC_listener = new CompoundButton.OnCheckedChangeListener() {
277 | @Override
278 | public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
279 | Log.v(TAG, "Test CV enable " + isChecked);
280 | if (isChecked) {
281 | mPlotPreview.setMask(
282 | PiSettings.getInstance().getCurrentSettings().rectMask,
283 | PiSettings.getInstance().getBytesMask());
284 | PIService.startUVCwithCallbackPosition(posCallback);
285 | } else {
286 | PIService.external_completeUVC();
287 | }
288 | }
289 | };
290 |
291 | final CVResolver.ICallbackPosition posCallback = new CVResolver.ICallbackPosition() {
292 | @Override
293 | public boolean callbackPosition(final int position, final int width, final CVResolver cvr) {
294 | if(position > 0){
295 | final int seek = mPlotPreview.relativePosition(position,posCallbackSeek.getMax());
296 | posCallbackSeek.setProgress(seek);
297 | Log.v(TAG,"p=" + String.valueOf(position));
298 | }
299 |
300 | getActivity().runOnUiThread(new Runnable() {
301 | @Override
302 | public void run() {
303 | text_width_pulse_seek.setText(String.valueOf(width));
304 | }
305 | });
306 |
307 | mFpsCounter.count();
308 |
309 | final boolean learnEnable = mLearnButton.isChecked();
310 | if(learnEnable){
311 | cvr.setMode(cvr.MODE_LEARN);
312 | } else {
313 | cvr.setMode(cvr.MODE_CAPTURE);
314 | }
315 |
316 | final boolean drawDisable = mDrawButton.isChecked();
317 | cvr.setDisablePlot(drawDisable);
318 |
319 | if(drawDisable){
320 | return true;
321 | }
322 | final String str = text_hdiag_seek.getText().toString();
323 | mPlotPreview.setHdiag(str);
324 |
325 | mPlotPreview.cvCallback(position,cvr);
326 | return true;
327 |
328 | }
329 | };
330 |
331 | @Override
332 | public void onDestroyView() {
333 | EventBus.getDefault().unregister(this);
334 | super.onDestroyView();
335 | }
336 |
337 | @Subscribe(threadMode = ThreadMode.MAIN)
338 | public void showInfoConnection(PIService.ATTACHMENT_USB_INFO info){
339 | Log.i(TAG, "info " + info);
340 | if(info == PIService.ATTACHMENT_USB_INFO.ATTACHED)
341 | mStartStopButton.setBackgroundColor(Color.GREEN);
342 | else
343 | mStartStopButton.setBackgroundColor(Color.WHITE);
344 | }
345 | }
346 |
--------------------------------------------------------------------------------