├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── android
│ │ └── guocheng
│ │ └── easypr
│ │ └── MainActivity.java
│ └── res
│ ├── layout
│ └── activity_main.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── libEasyPR
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ ├── aiseminar
│ │ └── EasyPR
│ │ │ └── PlateRecognizer.java
│ │ └── fosung
│ │ └── libeasypr
│ │ ├── EasyPrBiz.java
│ │ ├── EasyPrPath.java
│ │ ├── util
│ │ ├── BitmapUtil.java
│ │ ├── CameraManager.java
│ │ ├── FileUtil.java
│ │ ├── FlashLightUtils.java
│ │ └── ScreenUtil.java
│ │ └── view
│ │ ├── EasyPRPreSurfaceView.java
│ │ ├── EasyPRPreView.java
│ │ └── EasyPRPreViewMaskLayer.java
│ ├── jniLibs
│ ├── arm64-v8a
│ │ ├── libEasyPR.so
│ │ └── libopencv_java3.so
│ ├── armeabi-v7a
│ │ ├── libEasyPR.so
│ │ └── libopencv_java3.so
│ ├── armeabi
│ │ ├── libEasyPR.so
│ │ └── libopencv_java3.so
│ ├── mips
│ │ ├── libEasyPR.so
│ │ └── libopencv_java3.so
│ ├── mips64
│ │ ├── libEasyPR.so
│ │ └── libopencv_java3.so
│ ├── x86
│ │ ├── libEasyPR.so
│ │ └── libopencv_java3.so
│ └── x86_64
│ │ ├── libEasyPR.so
│ │ └── libopencv_java3.so
│ └── res
│ ├── raw
│ ├── easypr_ann.xml
│ └── easypr_svm.xml
│ └── values
│ └── easypr_colors.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EasyPRForAndroid
2 | 车牌识别库EasyPR移植Android版本。
3 | 基于OpenCV开源库,使用Android Studio进行构建。
4 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 | defaultConfig {
7 | applicationId "com.android.guocheng.easypr"
8 | minSdkVersion 15
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support:appcompat-v7:25.3.1'
28 | testCompile 'junit:junit:4.12'
29 | compile project(':libEasyPR')
30 | }
31 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/android/guocheng/easypr/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.android.guocheng.easypr;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import android.widget.TextView;
8 | import android.widget.Toast;
9 | import com.fosung.libeasypr.view.EasyPRPreSurfaceView;
10 | import com.fosung.libeasypr.view.EasyPRPreView;
11 |
12 | public class MainActivity extends AppCompatActivity {
13 |
14 | private EasyPRPreView easyPRPreView;
15 | private Button btnShutter;
16 | private TextView text;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_main);
22 |
23 | easyPRPreView = (EasyPRPreView) findViewById(R.id.preSurfaceView);
24 | btnShutter = (Button) findViewById(R.id.btnShutter);
25 | text = (TextView) findViewById(R.id.text);
26 | initListener();
27 | }
28 |
29 | @Override
30 | protected void onStart() {
31 | super.onStart();
32 | if (easyPRPreView != null) {
33 | easyPRPreView.onStart();
34 | }
35 | }
36 |
37 | @Override
38 | protected void onStop() {
39 | super.onStop();
40 | if (easyPRPreView != null) {
41 | easyPRPreView.onStop();
42 | }
43 | }
44 |
45 | @Override
46 | protected void onDestroy() {
47 | super.onDestroy();
48 | if (easyPRPreView != null) {
49 | easyPRPreView.onDestroy();
50 | }
51 | }
52 |
53 | private void initListener() {
54 | easyPRPreView.setRecognizedListener(new EasyPRPreSurfaceView.OnRecognizedListener() {
55 | @Override
56 | public void onRecognized(String result) {
57 | if (result == null || result.equals("0")) {
58 | Toast.makeText(MainActivity.this, "换个姿势试试!", Toast.LENGTH_SHORT).show();
59 | } else {
60 | Toast.makeText(MainActivity.this, "识别成功", Toast.LENGTH_SHORT).show();
61 | text.setText(result);
62 | }
63 | }
64 | });
65 | btnShutter.setOnClickListener(new View.OnClickListener() {
66 | @Override
67 | public void onClick(View view) {
68 | easyPRPreView.recognize();//开始识别
69 | }
70 | });
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
24 |
25 |
34 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 | #FFFFFF
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | EasyPR
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/libEasyPR/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/libEasyPR/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.3"
6 |
7 | defaultConfig {
8 | }
9 | buildTypes {
10 | release {
11 | minifyEnabled false
12 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
13 | }
14 | }
15 | }
16 |
17 | dependencies {
18 | compile fileTree(dir: 'libs', include: ['*.jar'])
19 | compile 'com.android.support:appcompat-v7:24.2.1'
20 | }
21 |
--------------------------------------------------------------------------------
/libEasyPR/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\as_android_sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/aiseminar/EasyPR/PlateRecognizer.java:
--------------------------------------------------------------------------------
1 | package com.aiseminar.EasyPR;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import com.fosung.libeasypr.EasyPrPath;
7 | import com.fosung.libeasypr.R;
8 | import com.fosung.libeasypr.util.FileUtil;
9 |
10 | import java.io.File;
11 | import java.io.UnsupportedEncodingException;
12 |
13 | /**
14 | * 车牌识别Jni调用类
15 | */
16 | public class PlateRecognizer {
17 | private Context context;
18 | private long mRecognizerPtr; //so库是否初始化成功 !=0 为成功
19 | private String svmFilePath;//svm的存储路径
20 | private String annFilePath;//ann的存储路径
21 |
22 | static {
23 | try {
24 | System.loadLibrary("EasyPR"); // 加载车牌识别库
25 | } catch (UnsatisfiedLinkError ule) {
26 | Log.e("PlateRecognizer", "WARNING: Could not load EasyPR library!");
27 | }
28 | }
29 |
30 | public static native String stringFromJNI();
31 |
32 | public static native long initPR(String svmpath, String annpath);
33 |
34 | public static native long uninitPR(long recognizerPtr);
35 |
36 | public static native byte[] plateRecognize(long recognizerPtr, String imgpath);
37 |
38 |
39 | public PlateRecognizer(Context context) {
40 | this(context, EasyPrPath.getSvmFile(context), EasyPrPath.getAnnFile(context));
41 | }
42 |
43 | public PlateRecognizer(Context context, String svmFilePath, String annFilePath) {
44 | this.context = context;
45 | this.svmFilePath = svmFilePath;
46 | this.annFilePath = annFilePath;
47 |
48 | checkAndUpdateModelFile();
49 | mRecognizerPtr = initPR(EasyPrPath.getSvmFile(context), EasyPrPath.getAnnFile(context));
50 | }
51 |
52 | /**
53 | * 检查本地SD卡是否已经保存了机器学习文件,如果没有,则从raw文件夹拷贝
54 | */
55 | private void checkAndUpdateModelFile() {
56 | FileUtil.copyFileFromRaw(context, EasyPrPath.getSvmFile(context), R.raw.easypr_svm);
57 | FileUtil.copyFileFromRaw(context, EasyPrPath.getAnnFile(context), R.raw.easypr_ann);
58 | }
59 |
60 | /**
61 | * so库是否初始化成功
62 | */
63 | private boolean isLoadSoSuccessful() {
64 | return mRecognizerPtr != 0;
65 | }
66 |
67 | /**
68 | * 车牌识别函数,调用jni实现
69 | *
70 | * @param imagePath 需要识别的图片路径
71 | */
72 | public String recognize(String imagePath) {
73 | File imageFile = new File(imagePath);
74 | if (!isLoadSoSuccessful() || !imageFile.exists()) {
75 | return null;
76 | }
77 |
78 | byte[] retBytes = plateRecognize(mRecognizerPtr, imagePath);
79 | String result = null;
80 | try {
81 | result = new String(retBytes, "utf-8");
82 | } catch (UnsupportedEncodingException e) {
83 | e.printStackTrace();
84 | }
85 | return result;
86 | }
87 |
88 | public void destroyRes() {
89 | uninitPR(mRecognizerPtr);
90 | mRecognizerPtr = 0;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/EasyPrBiz.java:
--------------------------------------------------------------------------------
1 | package com.fosung.libeasypr;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 |
6 | import com.fosung.libeasypr.util.ScreenUtil;
7 |
8 | /**
9 | *
10 | */
11 | public class EasyPrBiz {
12 |
13 | /**
14 | * 获取默认的预览区
15 | */
16 | public static Rect getDefRectFrame(Context context) {
17 | int screenWidth = ScreenUtil.getScreenWidth(context);
18 | int screenHeight = ScreenUtil.getScreenHeight(context);
19 | int rectLeft = screenWidth / 9;
20 | int rectTop = screenHeight * 6 / 14;
21 | int rectRight = screenWidth * 8 / 9;
22 | int rectBottom = screenHeight * 8 / 14;
23 | return new Rect(rectLeft, rectTop, rectRight, rectBottom);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/EasyPrPath.java:
--------------------------------------------------------------------------------
1 | package com.fosung.libeasypr;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * 文件在SD卡的暂存路径
7 | */
8 | public class EasyPrPath {
9 |
10 | public static String getPhotoTempFilePath(Context context, String suffix) {
11 | return context.getExternalCacheDir() + "/easy_pr/temp/CarNumber_" + suffix + ".jpg";
12 | }
13 |
14 | public static String getPhotoTempFolderPath(Context context) {
15 | return context.getExternalCacheDir() + "/easy_pr/temp/";
16 | }
17 |
18 | public static String getSvmFile(Context context) {
19 | return context.getExternalFilesDir(null) + "/easy_pr/svm.xml";
20 | }
21 |
22 | public static String getAnnFile(Context context) {
23 | return context.getExternalFilesDir(null) + "/easy_pr/ann.xml";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/util/BitmapUtil.java:
--------------------------------------------------------------------------------
1 | /***********************************************************
2 | * author colin
3 | * company fosung
4 | * email wanglin2046@126.com
5 | * date 16-7-15 下午4:41
6 | **********************************************************/
7 |
8 | /*
9 | *
10 | * @author : WangLin
11 | * @Company: :FCBN
12 | * @date : 2015年5月13日
13 | * @version : V1.0
14 | */
15 | package com.fosung.libeasypr.util;
16 |
17 | import android.content.res.Resources;
18 | import android.graphics.Bitmap;
19 | import android.graphics.Bitmap.Config;
20 | import android.graphics.BitmapFactory;
21 | import android.graphics.Canvas;
22 | import android.graphics.LinearGradient;
23 | import android.graphics.Matrix;
24 | import android.graphics.Paint;
25 | import android.graphics.PixelFormat;
26 | import android.graphics.PorterDuff.Mode;
27 | import android.graphics.PorterDuffXfermode;
28 | import android.graphics.Rect;
29 | import android.graphics.RectF;
30 | import android.graphics.Shader.TileMode;
31 | import android.graphics.drawable.BitmapDrawable;
32 | import android.graphics.drawable.Drawable;
33 | import android.view.ViewGroup.LayoutParams;
34 | import android.widget.ImageView;
35 |
36 | import java.io.ByteArrayOutputStream;
37 | import java.io.File;
38 | import java.io.FileOutputStream;
39 |
40 | /**
41 | * 图片操作工具类
42 | */
43 | public class BitmapUtil {
44 | /**
45 | * 存储图片
46 | *
47 | * @param tagPath 目标路径
48 | */
49 | public static void savePic(Bitmap bitmap, String tagPath) {
50 | File file = new File(tagPath);
51 | FileUtil.checkFilePath(file, false);
52 | try {
53 | FileOutputStream out = new FileOutputStream(file);
54 | if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {
55 | out.flush();
56 | out.close();
57 | }
58 | } catch (Exception e) {
59 | e.printStackTrace();
60 | }
61 | }
62 | /**
63 | * 根据文件路径返回Bitmap
64 | *
65 | * @param fileName 文件路径
66 | * @return Bitmap对象
67 | */
68 | public static Bitmap decodeBitmap(String fileName) {
69 | return BitmapFactory.decodeFile(fileName);
70 | }
71 |
72 | /**
73 | * 图片缩放(不按比例拉伸)
74 | *
75 | * @param resID 源图片资源
76 | * @param newWidth 缩放后宽度
77 | * @param newHeight 缩放后高度
78 | * @return 缩放后的Bitmap对象
79 | */
80 | public static Bitmap zoomImage(Resources res, int resID, int newWidth, int newHeight) {
81 | Bitmap map = BitmapFactory.decodeResource(res, resID);
82 | return Bitmap.createScaledBitmap(map, newWidth, newHeight, false);
83 | }
84 |
85 | /**
86 | * 图片缩放(不按比例拉伸)
87 | *
88 | * @param width 缩放后宽度
89 | * @param height 缩放后高度
90 | * @return 缩放后的Bitmap对象
91 | */
92 | public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
93 | return Bitmap.createScaledBitmap(bitmap, width, height, false);
94 | }
95 |
96 | /***
97 | * 图片缩放(不按比例拉伸)
98 | *
99 | * @param width 缩放后宽度
100 | * @param height 缩放后高度
101 | * @return drawable 缩放后的Bitmap对象
102 | */
103 | @SuppressWarnings("deprecation")
104 | public static Drawable zoomDrawable(Drawable drawable, int width, int height) {
105 | Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
106 | return new BitmapDrawable(zoomBitmap(bitmap, width, height));
107 | }
108 |
109 | /**
110 | * 图片缩放(等比缩放)
111 | *
112 | * @param resID 源图片资源
113 | * @param width 缩放后宽度
114 | * @param height 缩放后高度
115 | * @return 缩放后的Bitmap对象
116 | */
117 | public static Bitmap decodeBitmap(Resources res, int resID, int width, int height) {
118 | final BitmapFactory.Options options = new BitmapFactory.Options();
119 | // 设为true,BitmapFactory.decodeFile(Stringpath, Options opt)并不会真的返回一个Bitmap给你,仅会把它的宽,高取回
120 | options.inJustDecodeBounds = true;
121 | BitmapFactory.decodeResource(res, resID, options);
122 |
123 | // 计算缩放比例
124 | options.inSampleSize = calculateOriginal(options, width, height);
125 | options.inJustDecodeBounds = false;
126 | return BitmapFactory.decodeResource(res, resID, options);
127 | }
128 |
129 | /**
130 | * 图片缩放(等比缩放)
131 | *
132 | * @param fileName 图片文件路径
133 | */
134 | public static Bitmap decodeBitmap(String fileName, int width, int height) {
135 | final BitmapFactory.Options options = new BitmapFactory.Options();
136 | // 设为true,BitmapFactory.decodeFile(Stringpath, Options opt)并不会真的返回一个Bitmap给你,仅会把它的宽,高取回
137 | options.inJustDecodeBounds = true;
138 | BitmapFactory.decodeFile(fileName, options);
139 |
140 | // 计算缩放比例
141 | options.inSampleSize = calculateOriginal(options, width, height);
142 | options.inJustDecodeBounds = false;
143 | System.out.println("samplesize:" + options.inSampleSize);
144 | return BitmapFactory.decodeFile(fileName, options);
145 | }
146 |
147 | /**
148 | * 图片缩放(等比缩放)
149 | *
150 | */
151 | public static Bitmap decodeBitmap(byte[] arrByte, int width, int height) {
152 | final BitmapFactory.Options options = new BitmapFactory.Options();
153 | // 设为true,BitmapFactory.decodeFile(Stringpath, Options opt)并不会真的返回一个Bitmap给你,仅会把它的宽,高取回
154 | options.inJustDecodeBounds = true;
155 | BitmapFactory.decodeByteArray(arrByte, 0, arrByte.length, options);
156 |
157 | // 计算缩放比例
158 | options.inSampleSize = calculateOriginal(options, width, height);
159 | options.inJustDecodeBounds = false;
160 | System.out.println("samplesize:" + options.inSampleSize);
161 | return BitmapFactory.decodeByteArray(arrByte, 0, arrByte.length, options);
162 | }
163 |
164 |
165 | /**
166 | * 图片缩放ImageView大小
167 | *
168 | * @param fileName 图片文件路径
169 | * @return 缩放后的图片
170 | */
171 | public static Bitmap decodeBitmap(String fileName, ImageView imageView) {
172 | LayoutParams lay = imageView.getLayoutParams();
173 | int width = lay.width;
174 | int height = lay.height;
175 | final BitmapFactory.Options options = new BitmapFactory.Options();
176 |
177 | // 设为true,BitmapFactory.decodeFile(Stringpath, Options opt)并不会真的返回一个Bitmap给你,仅会把它的宽,高取回
178 | options.inJustDecodeBounds = true;
179 | BitmapFactory.decodeFile(fileName, options);
180 |
181 | // 计算缩放比例
182 | options.inSampleSize = calculateOriginal(options, width, height);
183 | options.inJustDecodeBounds = false;
184 | return BitmapFactory.decodeFile(fileName, options);
185 | }
186 |
187 | /**
188 | * 计算图片缩放比例,只能缩放2的指数
189 | *
190 | * @param reqWidth 缩放后的宽度
191 | * @param reqHeight 缩放后的高度
192 | * @return 计算的缩放比例
193 | */
194 | public static int calculateOriginal(BitmapFactory.Options options, int reqWidth, int reqHeight) {
195 | final int height = options.outHeight;
196 | final int width = options.outWidth;
197 | int inSampleSize = 1;
198 | if (height > reqHeight || width > reqWidth) {
199 | final int halfHeight = height / 2;
200 | final int halfWidth = width / 2;
201 | while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
202 | inSampleSize *= 2;
203 | }
204 |
205 | long totalPixels = width/ inSampleSize * height / inSampleSize;
206 | final long totalReqPixelsCap = reqWidth * reqHeight;
207 | while (totalPixels > totalReqPixelsCap) {
208 | inSampleSize *= 2;
209 | totalPixels /= 4;
210 | }
211 | }
212 | return inSampleSize;
213 | }
214 |
215 | /**
216 | * Drawable转换为Bitmap
217 | *
218 | * @param drawable drawable对象
219 | * @return Bitmap对象
220 | */
221 | public static Bitmap drawableToBitmap(Drawable drawable) {
222 | // 取 drawable 的长宽
223 | int w = drawable.getIntrinsicWidth();
224 | int h = drawable.getIntrinsicHeight();
225 |
226 | // 取 drawable 的颜色格式
227 | Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888 : Config.RGB_565;
228 |
229 | // 建立对应 bitmap
230 | Bitmap bitmap = Bitmap.createBitmap(w, h, config);
231 |
232 | // 建立对应 bitmap 的画布
233 | Canvas canvas = new Canvas(bitmap);
234 | drawable.setBounds(0, 0, w, h);
235 |
236 | // 把 drawable 内容画到画布中
237 | drawable.draw(canvas);
238 | return bitmap;
239 | }
240 |
241 | /**
242 | * Bitmap对象转为Drawable对象
243 | *
244 | * @param bitmap bitmap对象
245 | * @return Drawable对象
246 | */
247 | public static Drawable bitmapToDrawable(Resources res, Bitmap bitmap) {
248 | return new BitmapDrawable(res, bitmap);
249 | }
250 |
251 | /**
252 | * 获取圆角图片
253 | *
254 | * @param roundPx 圆角度数
255 | */
256 | public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
257 | int w = bitmap.getWidth();
258 | int h = bitmap.getHeight();
259 | Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
260 | Canvas canvas = new Canvas(output);
261 | final int color = 0xff424242;
262 | final Paint paint = new Paint();
263 | final Rect rect = new Rect(0, 0, w, h);
264 | final RectF rectF = new RectF(rect);
265 | paint.setAntiAlias(true);
266 | canvas.drawARGB(0, 0, 0, 0);
267 | paint.setColor(color);
268 | canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
269 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
270 | canvas.drawBitmap(bitmap, rect, rect, paint);
271 | return output;
272 | }
273 |
274 | /**
275 | * 获取带倒影的图片
276 | */
277 | public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
278 | final int reflectionGap = 4;
279 | int w = bitmap.getWidth();
280 | int h = bitmap.getHeight();
281 | Matrix matrix = new Matrix();
282 | matrix.preScale(1, -1);
283 | Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, h / 2, w, h / 2, matrix, false);
284 | Bitmap bitmapWithReflection = Bitmap.createBitmap(w, (h + h / 2), Config.ARGB_8888);
285 | Canvas canvas = new Canvas(bitmapWithReflection);
286 | canvas.drawBitmap(bitmap, 0, 0, null);
287 | Paint deafalutPaint = new Paint();
288 | canvas.drawRect(0, h, w, h + reflectionGap, deafalutPaint);
289 | canvas.drawBitmap(reflectionImage, 0, h + reflectionGap, null);
290 | Paint paint = new Paint();
291 | LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
292 | paint.setShader(shader);
293 | // Set the Transfer mode to be porter duff and destination in
294 | paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
295 | // Draw a rectangle using the paint with our linear gradient
296 | canvas.drawRect(0, h, w, bitmapWithReflection.getHeight() + reflectionGap, paint);
297 | return bitmapWithReflection;
298 | }
299 |
300 | /**
301 | * 将Bitmap转为Byte[]
302 | *
303 | * @param bm Bitmap对象
304 | * @return byte[]
305 | */
306 | public byte[] Bitmap2Bytes(Bitmap bm) {
307 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
308 | bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
309 | return baos.toByteArray();
310 | }
311 |
312 | /**
313 | * 将Byte[]转为Bitmap
314 | *
315 | * @param b byte[]
316 | * @return Bitmap对象
317 | */
318 | public Bitmap Bytes2Bimap(byte[] b) {
319 | if (b.length != 0) {
320 | return BitmapFactory.decodeByteArray(b, 0, b.length);
321 | } else {
322 | return null;
323 | }
324 | }
325 | }
326 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/util/CameraManager.java:
--------------------------------------------------------------------------------
1 | package com.fosung.libeasypr.util;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.ImageFormat;
6 | import android.hardware.Camera;
7 | import android.view.SurfaceHolder;
8 | import android.widget.Toast;
9 |
10 | import java.io.IOException;
11 |
12 | /**
13 | * Created by guocheng on 2017/4/20.
14 | */
15 |
16 | public class CameraManager {
17 |
18 | private Camera mCamera;
19 | private static CameraManager cameraManager;
20 |
21 | public static CameraManager get() {
22 | if(cameraManager == null)
23 | cameraManager = new CameraManager();
24 | return cameraManager;
25 | }
26 |
27 | public void openDevice(SurfaceHolder holder, Context context){
28 | if (null == mCamera) {
29 | try {
30 | mCamera = Camera.open();
31 | Camera.Parameters parameters = mCamera.getParameters();
32 | parameters.setPictureFormat(ImageFormat.JPEG);
33 | // parameters.setPictureSize(surfaceView.getWidth(),
34 | // surfaceView.getHeight()); // 部分定制手机,无法正常识别该方法。
35 | // parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);//闪光灯
36 | parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 1连续对焦
37 | parameters.setRotation(90);
38 | mCamera.setParameters(parameters);
39 | mCamera.setDisplayOrientation(90);
40 | reStartPreView(holder);
41 | mCamera.cancelAutoFocus();// 2如果要实现连续的自动对焦,这一句必须加上
42 | } catch (Exception e) {
43 | Toast.makeText(context, "摄像头开启失败, 可能是没有获取到摄像头权限,请检查.", Toast.LENGTH_SHORT)
44 | .show();
45 | if (context instanceof Activity) {
46 | ((Activity) context).finish();
47 | }
48 | }
49 | } else {
50 | reStartPreView(holder);
51 | }
52 | }
53 |
54 | public void closeDvice(){
55 | if (mCamera != null) {
56 | mCamera.setPreviewCallback(null);
57 | mCamera.stopPreview();
58 | mCamera.release();
59 | mCamera = null;
60 | }
61 | }
62 |
63 | /**
64 | * 重新开始识别
65 | */
66 | public void reStartPreView(SurfaceHolder holder) {
67 | if (mCamera != null) {
68 | try {
69 | mCamera.setPreviewDisplay(holder);
70 | mCamera.startPreview();
71 | } catch (IOException e) {
72 | e.printStackTrace();
73 | }
74 | }
75 | }
76 |
77 | public Camera getCamera() {
78 | return mCamera;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/util/FileUtil.java:
--------------------------------------------------------------------------------
1 | /***********************************************************
2 | * author colin
3 | * company fosung
4 | * email wanglin2046@126.com
5 | * date 16-7-15 下午4:41
6 | **********************************************************/
7 |
8 | package com.fosung.libeasypr.util;
9 |
10 | import android.content.Context;
11 | import android.database.Cursor;
12 | import android.net.Uri;
13 |
14 | import java.io.BufferedInputStream;
15 | import java.io.BufferedOutputStream;
16 | import java.io.BufferedReader;
17 | import java.io.BufferedWriter;
18 | import java.io.ByteArrayOutputStream;
19 | import java.io.Closeable;
20 | import java.io.File;
21 | import java.io.FileInputStream;
22 | import java.io.FileOutputStream;
23 | import java.io.FileReader;
24 | import java.io.FileWriter;
25 | import java.io.IOException;
26 | import java.io.InputStream;
27 | import java.io.InputStreamReader;
28 | import java.util.zip.ZipEntry;
29 | import java.util.zip.ZipInputStream;
30 |
31 | /**
32 | * 文件操作工具类
33 | */
34 | public class FileUtil {
35 |
36 | /**
37 | * 重命名文件, 在同级目录下成功,否则失败
38 | *
39 | * @param sourcePath 源文件路径
40 | * @param targetPaht 目标文件路径
41 | */
42 | public static void renameFileInSameDir(String sourcePath, String targetPaht) {
43 | File fileSource = new File(sourcePath);
44 | File fileTarget = new File(targetPaht);
45 | renameFileInSameDir(fileSource, fileTarget);
46 | }
47 |
48 | /**
49 | * 重命名文件, 在同级目录下成功,否则失败
50 | *
51 | * @param sourceFile 源文件
52 | * @param targetFile 目标文件
53 | */
54 | public static void renameFileInSameDir(File sourceFile, File targetFile) {
55 | if (sourceFile.exists()) {
56 | sourceFile.renameTo(targetFile);
57 | }
58 | }
59 |
60 | /**
61 | * 删除文件 (如果是文件夹,遍历删除文件夹下的文件)
62 | *
63 | * @param file 要删除的文件对象
64 | */
65 | public static void delete(File file) {
66 | if (file.exists()) {
67 | if (file.isFile()) {
68 | file.delete();
69 | } else if (file.isDirectory()) {
70 | File files[] = file.listFiles();
71 | if (files != null) {
72 | for (int i = 0; i < files.length; i++) {
73 | delete(files[i]);
74 | }
75 | }
76 | file.delete();
77 | }
78 | }
79 | }
80 |
81 | /**
82 | * 复制文件
83 | *
84 | * @param sourceDir 源文件路径
85 | * @param targetDir 目标文件路径
86 | */
87 | public static void copyFile(String sourceDir, String targetDir) throws IOException {
88 | File fileSource = new File(sourceDir);
89 | File fileTarget = new File(targetDir);
90 | copyFile(fileSource, fileTarget);
91 | }
92 |
93 | /**
94 | * 复制文件
95 | *
96 | * @param sourceFile 源文件
97 | * @param targetFile 目标文件
98 | */
99 | public static void copyFile(File sourceFile, File targetFile) throws IOException {
100 | InputStream input = new FileInputStream(sourceFile);
101 | copyFile(input, targetFile);
102 | }
103 |
104 | /**
105 | * 复制文件
106 | *
107 | * @param input 文件输入流
108 | * @param targetFile 目标文件
109 | */
110 | public static void copyFile(InputStream input, File targetFile) throws IOException {
111 | checkFilePath(targetFile, false);
112 | BufferedInputStream inBuff = null;
113 | BufferedOutputStream outBuff = null;
114 |
115 | try {
116 | inBuff = new BufferedInputStream(input);
117 | outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));
118 |
119 | byte[] b = new byte[1024 * 5];
120 | int len;
121 | while ((len = inBuff.read(b)) != -1) {
122 | outBuff.write(b, 0, len);
123 | }
124 |
125 | outBuff.flush();
126 | } finally {
127 | colseStreamWithCatchException(inBuff);
128 | colseStreamWithCatchException(outBuff);
129 | }
130 | }
131 |
132 | /**
133 | * 复制文件夹
134 | *
135 | * @param sourceDir 源文件夹
136 | * @param targetDir 目标文件夹
137 | */
138 | public static void copyDirectiory(String sourceDir, String targetDir) throws IOException {
139 | copyDirectiory(sourceDir, targetDir, null);
140 | }
141 |
142 | /**
143 | * 复制文件夹
144 | *
145 | * @param sourceDir 源文件夹
146 | * @param targetDir 目标文件夹
147 | * @param arrExcept 需要剔除的文件路径
148 | */
149 | public static void copyDirectiory(String sourceDir, String targetDir, String[] arrExcept) throws IOException {
150 | // 新建目标目录
151 | File fileDir = new File(targetDir);
152 | checkFilePath(fileDir, true);
153 | // 获取源文件夹当前下的文件或目录
154 | File fileSource = new File(sourceDir);
155 | File[] files = fileSource.listFiles();
156 | if (files != null) {
157 | for (File file : files) {
158 | // 需要剔除的文件列表
159 | if (arrExcept != null && arrExcept.length > 0) {
160 | boolean flag = false;
161 | for (String strExc : arrExcept) {
162 | if (strExc.equals(file.getAbsolutePath())) {
163 | flag = true;
164 | break;
165 | }
166 | }
167 |
168 | if (flag) {
169 | continue;
170 | }
171 | }
172 |
173 | if (file.isFile()) {
174 | File sourceFile = file;
175 | File targetFile = new File(fileDir.getAbsolutePath() + File.separator + file.getName());
176 | copyFile(sourceFile, targetFile);
177 | } else if (file.isDirectory()) {
178 | /*递归复制文件夹*/
179 | String dir1 = sourceDir + File.separator + file.getName();
180 | String dir2 = targetDir + File.separator + file.getName();
181 | copyDirectiory(dir1, dir2, arrExcept);
182 | }
183 | }
184 | }
185 | }
186 |
187 | /**
188 | * 从Raw文件夹复制到指定路径
189 | *
190 | * @param filePath 文件路径
191 | * @param rawID 文件资源
192 | * @return 是否拷贝成功
193 | */
194 | public static boolean copyFileFromRaw(Context context, String filePath, int rawID) {
195 | boolean flag = false;
196 | File file = new File(filePath);
197 | if (!file.exists()) {
198 | InputStream input;
199 | try {
200 | input = context.getResources()
201 | .openRawResource(rawID);
202 | copyFile(input, file);
203 | flag = true;
204 | } catch (IOException e) {
205 | e.printStackTrace();
206 | }
207 | }
208 | return flag;
209 | }
210 |
211 | /**
212 | * 创建文件 当文件不存在的时候就创建一个文件,否则直接返回文件
213 | */
214 | public static File createFile(String path) {
215 | File file = new File(path);
216 | checkFilePath(file, false);
217 | // 创建目标文件
218 | try {
219 | if (!file.exists()) {
220 | file.createNewFile();
221 | return file;
222 | } else {
223 | return file;
224 | }
225 | } catch (IOException e) {
226 | e.printStackTrace();
227 | }
228 | return null;
229 | }
230 |
231 | /**
232 | * 从Assets文件夹复制到指定路径
233 | *
234 | * @param assetDir 原文件夹路径
235 | * @param targetDir 目标文件夹路径
236 | */
237 | public static void copyDirFromAssets(Context context, String assetDir, String targetDir) {
238 | String[] files;
239 | try {
240 | files = context.getResources()
241 | .getAssets()
242 | .list(assetDir);
243 | } catch (IOException e1) {
244 | return;
245 | }
246 | checkFilePath(new File(targetDir), true);
247 | for (String fileName : files) {
248 | if (!fileName.contains(".")) {
249 | copyDirFromAssets(context, assetDir + "/" + fileName, targetDir + "/" + fileName);
250 | } else {
251 | copyFileFromAssets(context, assetDir + "/" + fileName, targetDir + "/" + fileName);
252 | }
253 | }
254 | }
255 |
256 | /**
257 | * 从 Assets中拷贝文件
258 | *
259 | * @param assetPath 原文件路径
260 | * @param targetPath 目标文件夹路径
261 | */
262 | public static void copyFileFromAssets(Context context, String assetPath, String targetPath) {
263 | File outFile = new File(targetPath);
264 | InputStream in;
265 | try {
266 | in = context.getAssets()
267 | .open(assetPath);
268 | copyFile(in, outFile);
269 | } catch (IOException e) {
270 | e.printStackTrace();
271 | }
272 | }
273 |
274 | /**
275 | * 将内容读取成字符串
276 | *
277 | * @param in 输入流
278 | * @return 从文件读取的内容
279 | */
280 | public static String readFileStr(InputStream in) {
281 | BufferedReader br = null;
282 | StringBuffer strbuf = new StringBuffer();
283 | try {
284 | br = new BufferedReader(new InputStreamReader(in));
285 | String str = null;
286 | while ((str = br.readLine()) != null) {
287 | strbuf.append(str);
288 | }
289 | } catch (IOException e) {
290 | e.printStackTrace();
291 | } finally {
292 | colseStreamWithCatchException(br);
293 | }
294 | return strbuf.toString();
295 | }
296 |
297 | /**
298 | * 将文件内容读取成字符串
299 | *
300 | * @param path 文件路径
301 | * @return 从文件读取的内容
302 | */
303 | public static String readFileStr(String path) {
304 | File file = new File(path);
305 | BufferedReader br = null;
306 | StringBuffer strbuf = new StringBuffer();
307 | if (file.exists()) {
308 | try {
309 | //可以换成工程目录下的其他文本文件
310 | br = new BufferedReader(new FileReader(file));
311 | String str = null;
312 | while ((str = br.readLine()) != null) {
313 | strbuf.append(str);
314 | }
315 | } catch (IOException e) {
316 | e.printStackTrace();
317 | } finally {
318 | colseStreamWithCatchException(br);
319 | }
320 | }
321 | return strbuf.toString();
322 | }
323 |
324 | /**
325 | * 将字符串写入文件
326 | *
327 | * @param path 文件路径
328 | * @param str 要写入的内容
329 | * @return 是否写入成功
330 | */
331 | public static boolean writeFileStr(String path, String str) {
332 | return writeFileStr(path, str, false);
333 | }
334 |
335 | /**
336 | * 将字符串写入文件
337 | *
338 | * @param path 文件路径
339 | * @param str 要写入的内容
340 | * @param isAppend 是否追加到文件中
341 | * @return 是否写入成功
342 | */
343 | public static boolean writeFileStr(String path, String str, boolean isAppend) {
344 | boolean isSucc = false;
345 | File file = new File(path);
346 | checkFilePath(file, false);
347 | BufferedWriter br = null;
348 | try {
349 | br = new BufferedWriter(new FileWriter(file, isAppend));
350 | if (isAppend) {
351 | br.newLine();
352 | }
353 | br.write(str);
354 | br.flush();
355 | isSucc = true;
356 | } catch (IOException e) {
357 | e.printStackTrace();
358 | } finally {
359 | colseStreamWithCatchException(br);
360 | }
361 | return isSucc;
362 | }
363 |
364 | /**
365 | * 将文件读入到字节数组中
366 | *
367 | * @param f 文件对象
368 | * @param start 开始读取的位置
369 | * @param len 读取的长度
370 | * @return 存储读取内容的字节数组
371 | */
372 | public static byte[] readToByteArray(File f, long start, int len) {
373 | byte[] ib = new byte[len];
374 | FileInputStream fis = null;
375 | try {
376 | fis = new FileInputStream(f);// pathStr 文件路径
377 | fis.skip(start);
378 | fis.read(ib, 0, len);
379 | } catch (IOException e) {
380 | e.printStackTrace();
381 | } finally {
382 | colseStreamWithCatchException(fis);
383 | }
384 | return ib;
385 | }
386 |
387 | /**
388 | * 将文件读入到字节数组中
389 | *
390 | * @param f 文件对象
391 | * @return 存储读取内容的字节数组
392 | */
393 | public static byte[] readToByteArray(File f) {
394 | ByteArrayOutputStream out = null;
395 | FileInputStream fis = null;
396 | try {
397 | fis = new FileInputStream(f);
398 | out = new ByteArrayOutputStream();
399 |
400 | byte[] byteArrary = new byte[1024];
401 | int count;
402 | while ((count = fis.read(byteArrary)) != -1) {
403 | out.write(byteArrary, 0, count);
404 | }
405 | } catch (IOException e) {
406 | e.printStackTrace();
407 | } finally {
408 | colseStreamWithCatchException(fis);
409 | colseStreamWithCatchException(out);
410 | }
411 | return out.toByteArray();
412 | }
413 |
414 | /**
415 | * 从Uri中获取path
416 | *
417 | * @param uri Uri
418 | * @return 读取的内容
419 | */
420 | public static String getPathFroUri(Context context, Uri uri) {
421 | if ("content".equalsIgnoreCase(uri.getScheme())) {
422 | String[] projection = {"_data"};
423 | Cursor cursor = null;
424 | try {
425 | cursor = context.getContentResolver()
426 | .query(uri, projection, null, null, null);
427 | int column_index = cursor.getColumnIndexOrThrow("_data");
428 | if (cursor.moveToFirst()) {
429 | return cursor.getString(column_index);
430 | }
431 | } catch (Exception e) {
432 | e.printStackTrace();
433 | }
434 | } else if ("file".equalsIgnoreCase(uri.getScheme())) {
435 | return uri.getPath();
436 | }
437 | return "";
438 | }
439 |
440 | /**
441 | * 检查目录是否存在,不存在创建
442 | *
443 | * @param path 文件路径
444 | * @param isDir 是否是文件夹
445 | */
446 | public static void checkFilePath(String path, boolean isDir) {
447 | File file = new File(path);
448 | checkFilePath(file, isDir);
449 | }
450 |
451 | /**
452 | * 检查目录是否存在,不存在创建
453 | *
454 | * @param file File对象
455 | * @param isDir 是否是文件夹
456 | */
457 | public static void checkFilePath(File file, boolean isDir) {
458 | if (file != null) {
459 | if (!isDir) {
460 | file = file.getParentFile();
461 | }
462 |
463 | if (file != null && !file.exists()) {
464 | file.mkdirs();
465 | }
466 | }
467 | }
468 |
469 | /**
470 | * 判断文件是否存在
471 | *
472 | * @param path 文件路径
473 | * @return 文件是否存在
474 | */
475 | public static boolean exist(String path) {
476 | File file = new File(path);
477 | return file.exists();
478 | }
479 |
480 | /**
481 | * 解压一个压缩文档 到指定位置
482 | *
483 | * @param zipFilePath 压缩包的路径
484 | * @param outPath 解压指定的路径
485 | */
486 | public static void unZipFolder(String zipFilePath, String outPath) throws Exception {
487 | ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFilePath));
488 | ZipEntry zipEntry;
489 | String szName = "";
490 |
491 | while ((zipEntry = inZip.getNextEntry()) != null) {
492 | szName = zipEntry.getName();
493 | if (zipEntry.isDirectory()) {
494 | // get the folder name of the widget
495 | szName = szName.substring(0, szName.length() - 1);
496 | File folder = new File(outPath + File.separator + szName);
497 | folder.mkdirs();
498 | } else {
499 |
500 | File file = new File(outPath + File.separator + szName);
501 | file.createNewFile();
502 | // get the output stream of the file
503 | FileOutputStream out = new FileOutputStream(file);
504 | int len;
505 | byte[] buffer = new byte[1024];
506 | // read (len) bytes into buffer
507 | while ((len = inZip.read(buffer)) != -1) {
508 | // write (len) byte from buffer at the position 0
509 | out.write(buffer, 0, len);
510 | out.flush();
511 | }
512 | out.close();
513 | }
514 | }//end of while
515 |
516 | inZip.close();
517 | }
518 |
519 | /**
520 | * 关闭输入/输出流,捕获异常不抛出
521 | */
522 | public static void colseStreamWithCatchException(Closeable closeable) {
523 | if (closeable != null) {
524 | try {
525 | closeable.close();
526 | } catch (IOException e) {
527 | e.printStackTrace();
528 | }
529 | }
530 | }
531 | }
532 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/util/FlashLightUtils.java:
--------------------------------------------------------------------------------
1 | package com.fosung.libeasypr.util;
2 |
3 | import android.hardware.Camera;
4 |
5 | /**
6 | * Created by guocheng on 2017/4/20.
7 | */
8 |
9 | public class FlashLightUtils {
10 |
11 | public static void isLightEnable(boolean isEnable) {
12 | if (isEnable) {
13 | Camera camera = CameraManager.get().getCamera();
14 | if (camera != null) {
15 | Camera.Parameters parameter = camera.getParameters();
16 | parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
17 | camera.setParameters(parameter);
18 | }
19 | } else {
20 | Camera camera = CameraManager.get().getCamera();
21 | if (camera != null) {
22 | Camera.Parameters parameter = camera.getParameters();
23 | parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
24 | camera.setParameters(parameter);
25 | }
26 | }
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/util/ScreenUtil.java:
--------------------------------------------------------------------------------
1 | /***********************************************************
2 | * author colin
3 | * company fosung
4 | * email wanglin2046@126.com
5 | * date 16-7-15 下午4:41
6 | **********************************************************/
7 | package com.fosung.libeasypr.util;
8 |
9 | import android.annotation.TargetApi;
10 | import android.app.Activity;
11 | import android.content.ContentResolver;
12 | import android.content.Context;
13 | import android.content.res.Configuration;
14 | import android.content.res.Resources;
15 | import android.graphics.Bitmap;
16 | import android.graphics.ColorMatrix;
17 | import android.graphics.ColorMatrixColorFilter;
18 | import android.graphics.Paint;
19 | import android.graphics.Rect;
20 | import android.net.Uri;
21 | import android.os.Build;
22 | import android.provider.Settings;
23 | import android.util.DisplayMetrics;
24 | import android.view.View;
25 | import android.view.WindowManager;
26 |
27 | /**
28 | * 屏幕工具
29 | */
30 | public class ScreenUtil {
31 |
32 | /**
33 | * 获取屏幕宽度
34 | */
35 | public static int getScreenWidth(Context context) {
36 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
37 | DisplayMetrics outMetrics = new DisplayMetrics();
38 | wm.getDefaultDisplay()
39 | .getMetrics(outMetrics);
40 | return outMetrics.widthPixels;
41 | }
42 |
43 |
44 | /**
45 | * 获取屏幕高度
46 | */
47 | public static int getScreenHeight(Context context) {
48 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
49 | DisplayMetrics outMetrics = new DisplayMetrics();
50 | wm.getDefaultDisplay()
51 | .getMetrics(outMetrics);
52 | return outMetrics.heightPixels;
53 | }
54 |
55 | /**
56 | * 获取当前窗口的高度, 该高度是不包含导航栏和状态栏的
57 | */
58 | public static int getWindowHeight(Activity activity) {
59 | return activity.getWindow()
60 | .getWindowManager()
61 | .getDefaultDisplay()
62 | .getHeight();
63 | }
64 |
65 | /**
66 | * 精确获取屏幕尺寸(例如:3.5、4.0、5.0寸屏幕)
67 | *
68 | * @return 设备尺寸
69 | */
70 | public static double getScreenPhysicalSize(Activity activity) {
71 | DisplayMetrics dm = activity.getResources()
72 | .getDisplayMetrics();
73 | double diagonalPixels = Math.sqrt(Math.pow(dm.widthPixels, 2) + Math.pow(dm.heightPixels, 2));
74 | return diagonalPixels / (dm.densityDpi);
75 | }
76 |
77 | /**
78 | * 判断是否是平板(官方用法)
79 | */
80 | public static boolean isTablet(Context context) {
81 | return (context.getResources()
82 | .getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
83 | }
84 |
85 | /**
86 | * 获取导航栏高度
87 | */
88 | public static int getNavigationBarHeight(Context context) {
89 | Resources resources = context.getResources();
90 | int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
91 | if (resourceId > 0) {
92 | return resources.getDimensionPixelSize(resourceId);
93 | }
94 | return 0;
95 | }
96 |
97 | /**
98 | * 用于获取状态栏的高度。
99 | *
100 | * @return 返回状态栏高度的像素值。
101 | */
102 | public static int getStatusBarHeight(Activity context) {
103 | int statusBarHeight = 0;
104 |
105 | try {
106 | Resources res = context.getResources();
107 | int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
108 | if (resourceId > 0) {
109 | statusBarHeight = res.getDimensionPixelSize(resourceId);
110 | }
111 | } catch (Exception e) {
112 | e.printStackTrace();
113 | }
114 |
115 | if (statusBarHeight == 0) {
116 | Rect frame = new Rect();
117 | context.getWindow()
118 | .getDecorView()
119 | .getWindowVisibleDisplayFrame(frame);
120 | statusBarHeight = frame.top;
121 | }
122 | return statusBarHeight;
123 | }
124 |
125 | /**
126 | * 获取当前屏幕截图,包含状态栏
127 | */
128 | public static Bitmap snapShotWithStatusBar(Activity activity) {
129 | View view = activity.getWindow()
130 | .getDecorView();
131 | view.setDrawingCacheEnabled(true);
132 | view.buildDrawingCache();
133 | Bitmap bmp = view.getDrawingCache();
134 | int width = getScreenWidth(activity);
135 | int height = getScreenHeight(activity);
136 | Bitmap bp = null;
137 | bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
138 | view.destroyDrawingCache();
139 | return bp;
140 | }
141 |
142 | /**
143 | * 获取当前屏幕截图,不包含状态栏
144 | */
145 | public static Bitmap snapShotWithoutStatusBar(Activity activity) {
146 | View view = activity.getWindow()
147 | .getDecorView();
148 | view.setDrawingCacheEnabled(true);
149 | view.buildDrawingCache();
150 | Bitmap bmp = view.getDrawingCache();
151 | Rect frame = new Rect();
152 | activity.getWindow()
153 | .getDecorView()
154 | .getWindowVisibleDisplayFrame(frame);
155 | int statusBarHeight = frame.top;
156 | int width = getScreenWidth(activity);
157 | int height = getScreenHeight(activity);
158 | Bitmap bp = null;
159 | bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight);
160 | view.destroyDrawingCache();
161 | return bp;
162 | }
163 |
164 | /**
165 | * 设置灰度
166 | *
167 | * @param greyScale true:灰度
168 | */
169 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
170 | public static void setGreyScale(View v, boolean greyScale) {
171 | if (greyScale) {
172 | // Create a paint object with 0 saturation (black and white)
173 | ColorMatrix cm = new ColorMatrix();
174 | cm.setSaturation(0);
175 | Paint greyScalePaint = new Paint();
176 | greyScalePaint.setColorFilter(new ColorMatrixColorFilter(cm));
177 | // Create a hardware layer with the greyScale paint
178 | v.setLayerType(View.LAYER_TYPE_HARDWARE, greyScalePaint);
179 | } else {
180 | // Remove the hardware layer
181 | v.setLayerType(View.LAYER_TYPE_NONE, null);
182 | }
183 | }
184 |
185 | /**
186 | * 判断是否开启了自动亮度调节
187 | */
188 | public static boolean isAutoBrightness(ContentResolver aContentResolver) {
189 | boolean automicBrightness = false;
190 | try {
191 | automicBrightness = Settings.System.getInt(aContentResolver,
192 | Settings.System.SCREEN_BRIGHTNESS_MODE) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
193 | } catch (Settings.SettingNotFoundException e) {
194 | e.printStackTrace();
195 | }
196 | return automicBrightness;
197 | }
198 |
199 | /**
200 | * 获取屏幕的亮度
201 | */
202 | public static float getScreenBrightness(Activity activity) {
203 | int nowBrightnessValue = 0;
204 | ContentResolver resolver = activity.getContentResolver();
205 | try {
206 | nowBrightnessValue = Settings.System.getInt(
207 | resolver, Settings.System.SCREEN_BRIGHTNESS);
208 | } catch (Exception e) {
209 | e.printStackTrace();
210 | }
211 | return nowBrightnessValue;
212 | }
213 |
214 | /**
215 | * 设置亮度(手动设置亮度,需要关闭自动设置亮度的开关)
216 | *
217 | * @param brightness 0-1
218 | */
219 | public static void setBrightness(Activity activity, float brightness) {
220 | stopAutoBrightness(activity);
221 | WindowManager.LayoutParams lp = activity.getWindow()
222 | .getAttributes();
223 | lp.screenBrightness = brightness * (1f / 255f);
224 | activity.getWindow()
225 | .setAttributes(lp);
226 | }
227 |
228 | /**
229 | * 停止自动亮度调节
230 | */
231 | public static void stopAutoBrightness(Activity activity) {
232 | Settings.System.putInt(activity.getContentResolver(),
233 | Settings.System.SCREEN_BRIGHTNESS_MODE,
234 | Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
235 | }
236 |
237 | /**
238 | * 开启亮度自动调节
239 | */
240 | public static void startAutoBrightness(Activity activity) {
241 | Settings.System.putInt(activity.getContentResolver(),
242 | Settings.System.SCREEN_BRIGHTNESS_MODE,
243 | Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
244 | }
245 |
246 | /**
247 | * 保存亮度设置状态
248 | */
249 | public static void saveBrightness(ContentResolver resolver, int brightness) {
250 | Uri uri = Settings.System
251 | .getUriFor("screen_brightness");
252 | Settings.System.putInt(resolver, "screen_brightness",
253 | brightness);
254 | // resolver.registerContentObserver(uri, true, myContentObserver);
255 | resolver.notifyChange(uri, null);
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/view/EasyPRPreSurfaceView.java:
--------------------------------------------------------------------------------
1 | package com.fosung.libeasypr.view;
2 |
3 | import android.app.Activity;
4 | import android.app.ProgressDialog;
5 | import android.content.Context;
6 | import android.graphics.Bitmap;
7 | import android.graphics.Rect;
8 | import android.hardware.Camera;
9 | import android.os.AsyncTask;
10 | import android.util.AttributeSet;
11 | import android.view.SurfaceHolder;
12 | import android.view.SurfaceView;
13 |
14 | import com.aiseminar.EasyPR.PlateRecognizer;
15 | import com.fosung.libeasypr.EasyPrBiz;
16 | import com.fosung.libeasypr.EasyPrPath;
17 | import com.fosung.libeasypr.util.BitmapUtil;
18 | import com.fosung.libeasypr.util.CameraManager;
19 |
20 | import java.io.File;
21 | import java.util.ArrayList;
22 | import java.util.HashMap;
23 | import java.util.Map;
24 | import java.util.regex.Matcher;
25 | import java.util.regex.Pattern;
26 |
27 | /**
28 | * 车牌预览view
29 | */
30 | public class EasyPRPreSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
31 |
32 | //private Camera mCamera;
33 | private Camera.PictureCallback rawCallback;
34 | private Camera.ShutterCallback shutterCallback;
35 | private Camera.PictureCallback pictureCallback;
36 |
37 | private Rect mastLayerFrame;//选取框Rect
38 | private OnRecognizedListener recognizedListener; //车牌识别完毕回调
39 | private OnPictureTakenListener pictureTakenListener; //拍照回调
40 | private PlateRecognizer plateRecognizer; //车牌识别处理对象
41 | private ProgressDialog progressDialog;//车牌识别时弹出的度条
42 |
43 | private boolean isOnRecognizedRestart = true;//识别完成是否重新开始
44 | private boolean isRecognized = true;//防止连续识别,做个标识
45 | private boolean isInit;
46 | private Context context;
47 |
48 | public EasyPRPreSurfaceView(Context context) {
49 | this(context, null);
50 | }
51 |
52 | public EasyPRPreSurfaceView(Context context, AttributeSet attrs) {
53 | this(context, attrs, 0);
54 | }
55 |
56 | public EasyPRPreSurfaceView(Context context, AttributeSet attrs, int defStyle) {
57 | super(context, attrs, defStyle);
58 | this.context = context;
59 |
60 | plateRecognizer = new PlateRecognizer(context);
61 | setDrawingCacheEnabled(false);
62 |
63 | }
64 |
65 | /**
66 | * 设置识别完成监听
67 | */
68 | public EasyPRPreSurfaceView setRecognizedListener(OnRecognizedListener recognizedListener) {
69 | this.recognizedListener = recognizedListener;
70 | return this;
71 | }
72 |
73 | /**
74 | * 设置拍照完成监听
75 | */
76 | public EasyPRPreSurfaceView setPictureTakenListener(OnPictureTakenListener pictureTakenListener) {
77 | this.pictureTakenListener = pictureTakenListener;
78 | return this;
79 | }
80 |
81 | /**
82 | * 获取结果后是否重新开始取景
83 | */
84 | public EasyPRPreSurfaceView setIsOnRecognizedRestart(boolean isOnRecognizedRestart) {
85 | this.isOnRecognizedRestart = isOnRecognizedRestart;
86 | return this;
87 | }
88 |
89 | /**
90 | * 设置选取框,选取框大小需要和{@link EasyPRPreViewMaskLayer#setMastLayerFrame(Rect)}的Rect大小一样
91 | */
92 | public EasyPRPreSurfaceView setMastLayerFrame(Rect frame) {
93 | this.mastLayerFrame = frame;
94 | return this;
95 | }
96 |
97 | /**
98 | * 设置解析时的ProgressDialog
99 | */
100 | public EasyPRPreSurfaceView setProgressDialog(ProgressDialog progressDialog) {
101 | this.progressDialog = progressDialog;
102 | return this;
103 | }
104 |
105 |
106 | /**
107 | * 车牌识别执行
108 | */
109 | public void recognize() {
110 | if (isRecognized) {
111 | if (shutterCallback == null || rawCallback == null || pictureCallback == null) {
112 | throw new IllegalStateException("没有调用initPreView()");
113 | }
114 |
115 | isRecognized = false;
116 | if (CameraManager.get().getCamera() != null) {
117 | CameraManager.get().getCamera().takePicture(shutterCallback, rawCallback, pictureCallback);
118 | }
119 | }
120 | }
121 |
122 | /**
123 | * 开始执行, 在Activity或者Fragment 的 onStart中调用
124 | */
125 | public void onStart() {
126 | if (!isInit) {
127 | init();
128 | }
129 |
130 | CameraManager.get().openDevice(getHolder(),context);
131 | /*if (null == mCamera) {
132 | try {
133 | mCamera = Camera.open();
134 | Camera.Parameters parameters = mCamera.getParameters();
135 | parameters.setPictureFormat(ImageFormat.JPEG);
136 | // parameters.setPictureSize(surfaceView.getWidth(),
137 | // surfaceView.getHeight()); // 部分定制手机,无法正常识别该方法。
138 | // parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);//闪光灯
139 | parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 1连续对焦
140 | parameters.setRotation(90);
141 | mCamera.setParameters(parameters);
142 | mCamera.setDisplayOrientation(90);
143 | reStartPreView();
144 | mCamera.cancelAutoFocus();// 2如果要实现连续的自动对焦,这一句必须加上
145 | } catch (Exception e) {
146 | Toast.makeText(context, "摄像头开启失败, 可能是没有获取到摄像头权限,请检查.", Toast.LENGTH_SHORT)
147 | .show();
148 | if (context instanceof Activity) {
149 | ((Activity) context).finish();
150 | }
151 | }
152 | } else {
153 | reStartPreView();
154 | }*/
155 | }
156 |
157 | /**
158 | * 释放Camera,在onStop中调用
159 | */
160 | public void onStop() {
161 | CameraManager.get().closeDvice();
162 | /*if (mCamera != null) {
163 | mCamera.setPreviewCallback(null);
164 | mCamera.stopPreview();
165 | mCamera.release();
166 | mCamera = null;
167 | }*/
168 | }
169 |
170 | /**
171 | * 销毁资源,在onDestroy中调用
172 | */
173 | public void onDestroy() {
174 | plateRecognizer.destroyRes();
175 | }
176 |
177 |
178 | /**
179 | * 重新开始识别
180 | */
181 | /*private void reStartPreView() {
182 | if (mCamera != null) {
183 | try {
184 | mCamera.setPreviewDisplay(getHolder());
185 | mCamera.startPreview();
186 | } catch (IOException e) {
187 | e.printStackTrace();
188 | }
189 | }
190 | }*/
191 |
192 | /**
193 | * 开始执行取景
194 | */
195 | private void init() {
196 | if (!isInit) {
197 | isInit = true;
198 | if (progressDialog == null) {
199 | progressDialog = new ProgressDialog(context);
200 | }
201 |
202 | if (mastLayerFrame == null) {
203 | mastLayerFrame = EasyPrBiz.getDefRectFrame(context);
204 | }
205 |
206 | rawCallback = new Camera.PictureCallback() {
207 | public void onPictureTaken(byte[] data, Camera camera) {
208 |
209 | }
210 | };
211 |
212 | shutterCallback = new Camera.ShutterCallback() {
213 | public void onShutter() {
214 |
215 | }
216 | };
217 |
218 | pictureCallback = new Camera.PictureCallback() {
219 | public void onPictureTaken(byte[] data, Camera camera) {
220 | if (CameraManager.get().getCamera() == null || getContext() == null || ((Activity) getContext()).isFinishing()) {
221 | return;
222 | }
223 |
224 | if (progressDialog != null) {
225 | progressDialog.show();
226 | progressDialog.setCancelable(false);
227 | progressDialog.setMessage("正在识别……");
228 | }
229 |
230 | Bitmap map = BitmapUtil.decodeBitmap(data, getWidth(), getHeight());
231 | float scaleX = (float) map.getWidth() / getWidth();
232 | float scaleY = (float) map.getHeight() / getHeight();
233 |
234 | String[] paths = new String[4];
235 | try {
236 | //不同的选取照片会识别出不同结果,所以多次取景
237 | BitmapUtil.savePic(map, EasyPrPath.getPhotoTempFilePath(context, ""));//把没有经过通过选取框裁剪的保存
238 | int yOffSet = (map.getHeight() - mastLayerFrame.height()) / 2;
239 | for (int i = 0; i < paths.length; i++) {
240 | int translateY = yOffSet / paths.length * i;
241 | Bitmap newMap = Bitmap.createBitmap(map, (int) (mastLayerFrame.left * scaleX), (int) (mastLayerFrame.top * scaleY - translateY),
242 | (int) (mastLayerFrame.width() * scaleX), (int) (mastLayerFrame.height() * scaleY + translateY * 2), null, false);
243 | paths[i] = EasyPrPath.getPhotoTempFilePath(context, String.valueOf(i + 1));
244 | BitmapUtil.savePic(newMap, paths[i]);
245 | newMap.recycle();
246 | }
247 | } catch (Exception e) {
248 | e.printStackTrace();
249 | } finally {
250 | map.recycle();
251 | }
252 |
253 |
254 | if (pictureTakenListener != null) {
255 | pictureTakenListener.onPictureTaken(paths);
256 | }
257 |
258 | if (getContext() == null || ((Activity) getContext()).isFinishing()) {
259 | return;
260 | }
261 |
262 | new RecognizeTask().execute(0);
263 | if (CameraManager.get().getCamera() != null) {
264 | CameraManager.get().getCamera().stopPreview();
265 | }
266 |
267 | }
268 | };
269 | getHolder().addCallback(this);
270 | }
271 | }
272 |
273 | @Override
274 | public void surfaceCreated(SurfaceHolder holder) {
275 | onStart();
276 | }
277 |
278 | @Override
279 | public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
280 | if (CameraManager.get().getCamera() != null) {
281 | try {
282 | // 实现自动对焦
283 | CameraManager.get().getCamera().autoFocus(new Camera.AutoFocusCallback() {
284 | @Override
285 | public void onAutoFocus(boolean success, Camera arg1) {
286 | if (success) {
287 | CameraManager.get().reStartPreView(getHolder());
288 | CameraManager.get().getCamera().cancelAutoFocus();// 只有加上了这一句,才会自动对焦。
289 | }
290 | }
291 | });
292 | } catch (Exception e) {
293 | e.printStackTrace();
294 | }
295 | }
296 | }
297 |
298 | @Override
299 | public void surfaceDestroyed(SurfaceHolder holder) {
300 | onStop();
301 | }
302 |
303 |
304 | /**
305 | * 车牌识别相对耗时,需要异步进行
306 | */
307 | class RecognizeTask extends AsyncTask {
308 | @Override
309 | protected String doInBackground(Integer... params) {
310 | // 进行车牌识别
311 | File file = new File(EasyPrPath.getPhotoTempFolderPath(context));
312 | File[] files = file.listFiles();
313 | String[] results = null;
314 | if (files != null && files.length > 0) {
315 | results = new String[files.length];
316 | for (int i = 0; i < files.length; i++) {
317 | results[i] = plateRecognizer.recognize(files[i].getPath());
318 | System.out.println(results[i]);
319 | }
320 | }
321 |
322 | return getCorrectText(results);
323 | }
324 |
325 | @Override
326 | protected void onPreExecute() {
327 | super.onPreExecute();
328 | }
329 |
330 | @Override
331 | protected void onPostExecute(String str) {
332 | super.onPostExecute(str);
333 | progressDialog.dismiss();
334 | isRecognized = true;
335 |
336 | if (recognizedListener != null) {
337 | recognizedListener.onRecognized(str);
338 | }
339 |
340 | if (isOnRecognizedRestart && CameraManager.get().getCamera() != null) {
341 | CameraManager.get().getCamera().startPreview();
342 | }
343 | }
344 |
345 | /**
346 | * 获取多次取样对比之后修正后的结果
347 | */
348 | private String getCorrectText(String[] results) {
349 | StringBuilder resultBuilder = new StringBuilder();
350 | if (results != null && results.length > 0) {
351 | ArrayList> list = new ArrayList<>();//list是每个位置上的记录,HashMap存的是出现的字key和次数value
352 | final int startIndex = 3;
353 | for (int i = startIndex; i < startIndex + 7; i++) {//车牌固定为7位
354 | HashMap map = new HashMap<>();
355 | list.add(map);
356 | for (String str : results) {
357 | if (str != null && str.length() > i) {//识别出的结果有可能比普通的字少
358 | String c = String.valueOf(str.charAt(i));
359 | if ((i > startIndex && isNumOrLetter(c)) || (i == startIndex && !isNumOrLetter(c))) {
360 | int count = map.get(c) == null ? 0 : map.get(c);
361 | map.put(c, count + 1);
362 | }
363 | }
364 | }
365 | }
366 |
367 | //上面的操作将出现的字和次数已经放入到list中,现在开始进行选取
368 | for (HashMap map : list) {
369 | int maxCount = 0;
370 | String text = "";
371 | for (Map.Entry entry : map.entrySet()) {
372 | int count = entry.getValue();
373 | if (count > maxCount) {
374 | maxCount = count;
375 | text = entry.getKey();
376 | }
377 | }
378 |
379 | if (text.length() > 0) {
380 | resultBuilder.append(text);
381 | }
382 | }
383 | }
384 | return resultBuilder.length() > 0 ? resultBuilder.toString() : null;
385 | }
386 |
387 | private boolean isNumOrLetter(CharSequence str) {
388 | Pattern p = Pattern.compile("[A-Z0-9]");
389 | Matcher m = p.matcher(str);
390 | return m.matches();
391 | }
392 | }
393 |
394 | /**
395 | * 车牌识别完成回调
396 | */
397 | public interface OnRecognizedListener {
398 | void onRecognized(String result);
399 | }
400 |
401 | /**
402 | * 拍照完成回调
403 | */
404 | public interface OnPictureTakenListener {
405 | void onPictureTaken(String[] paths);
406 | }
407 |
408 | }
409 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/view/EasyPRPreView.java:
--------------------------------------------------------------------------------
1 | package com.fosung.libeasypr.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.support.annotation.Nullable;
6 | import android.util.AttributeSet;
7 | import android.widget.FrameLayout;
8 |
9 |
10 | /**
11 | * 预览的遮罩层
12 | */
13 | public class EasyPRPreView extends FrameLayout {
14 |
15 | private EasyPRPreSurfaceView surfaceView;
16 | private EasyPRPreViewMaskLayer maskLayer;
17 |
18 | public EasyPRPreView(Context context) {
19 | this(context, null);
20 | }
21 |
22 | public EasyPRPreView(Context context, @Nullable AttributeSet attrs) {
23 | this(context, attrs, 0);
24 | }
25 |
26 | public EasyPRPreView(Context context, @Nullable AttributeSet attrs, int defStylesAttr) {
27 | super(context, attrs, defStylesAttr);
28 |
29 | surfaceView = new EasyPRPreSurfaceView(context);
30 | maskLayer = new EasyPRPreViewMaskLayer(context);
31 | addView(surfaceView);
32 | addView(maskLayer);
33 | }
34 |
35 | /**
36 | * 设置识别完成监听
37 | */
38 | public EasyPRPreView setRecognizedListener(EasyPRPreSurfaceView.OnRecognizedListener recognizedListener) {
39 | surfaceView.setRecognizedListener(recognizedListener);
40 | return this;
41 | }
42 |
43 | /**
44 | * 设置拍照完成监听
45 | */
46 | public EasyPRPreView setPictureTakenListener(EasyPRPreSurfaceView.OnPictureTakenListener pictureTakenListener) {
47 | surfaceView.setPictureTakenListener(pictureTakenListener);
48 | return this;
49 | }
50 |
51 | /**
52 | * 获取结果后是否重新开始取景
53 | */
54 | public EasyPRPreView setIsOnRecognizedRestart(boolean isOnRecognizedRestart) {
55 | surfaceView.setIsOnRecognizedRestart(isOnRecognizedRestart);
56 | return this;
57 | }
58 |
59 | /**
60 | * 设置选取框,选取框大小需要和{@link EasyPRPreViewMaskLayer#setMastLayerFrame(Rect)}的Rect大小一样
61 | */
62 | public EasyPRPreView setMastLayerFrame(Rect frame) {
63 | surfaceView.setMastLayerFrame(frame);
64 | maskLayer.setMastLayerFrame(frame);
65 | return this;
66 | }
67 |
68 | /**
69 | * 框颜色
70 | */
71 | public EasyPRPreView setFrameColor(int frameColor) {
72 | maskLayer.setFrameColor(frameColor);
73 | return this;
74 | }
75 |
76 | /**
77 | * 激光线颜色
78 | */
79 | public EasyPRPreView setLaserColor(int laserColor) {
80 | maskLayer.setLaserColor(laserColor);
81 | return this;
82 | }
83 |
84 | /**
85 | * 遮罩层颜色
86 | */
87 | public EasyPRPreView setMaskColor(int maskColor) {
88 | maskLayer.setMaskColor(maskColor);
89 | return this;
90 | }
91 |
92 | /**
93 | * 开始执行, 在Activity或者Fragment 的 onStart中调用
94 | */
95 | public void onStart() {
96 | surfaceView.onStart();
97 | maskLayer.onStart();
98 | }
99 |
100 | /**
101 | * 车牌识别执行
102 | */
103 | public void recognize() {
104 | surfaceView.recognize();
105 | }
106 |
107 | /**
108 | * 开始执行, 在Activity或者Fragment 的 onStop中调用
109 | */
110 | public void onStop() {
111 | surfaceView.onStop();
112 | maskLayer.onStop();
113 | }
114 |
115 | /**
116 | * 开始执行, 在Activity或者Fragment 的 onDestroy中调用
117 | */
118 | public void onDestroy() {
119 | surfaceView.onDestroy();
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/java/com/fosung/libeasypr/view/EasyPRPreViewMaskLayer.java:
--------------------------------------------------------------------------------
1 | package com.fosung.libeasypr.view;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
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.View;
12 |
13 | import com.fosung.libeasypr.EasyPrBiz;
14 |
15 |
16 | /**
17 | * 预览的遮罩层
18 | */
19 | public class EasyPRPreViewMaskLayer extends View {
20 |
21 | private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
22 | private static final long ANIMATION_DELAY = 30L; //屏幕刷新时间
23 |
24 | private int scannerAlpha;
25 | private Rect mastLayerFrame;//选取框Rect
26 | private Paint paint;
27 | private int frameColor;
28 | private int laserColor;
29 | private int maskColor;
30 | private int laserYOffSet;//激光线的Y偏移
31 | private boolean isStart;//是否开始
32 | private Context context;
33 |
34 | public EasyPRPreViewMaskLayer(Context context) {
35 | this(context, null);
36 | }
37 |
38 | public EasyPRPreViewMaskLayer(Context context, @Nullable AttributeSet attrs) {
39 | super(context, attrs);
40 | this.context = context;
41 | paint = new Paint(Paint.ANTI_ALIAS_FLAG);
42 | Resources resources = getResources();
43 | frameColor = Color.parseColor("#000000");
44 | laserColor = Color.parseColor("#FF7FFF00");
45 | maskColor = Color.parseColor("#66000000");
46 |
47 | }
48 |
49 | /**
50 | * 设置选取框,选取框大小需要和{@link EasyPRPreSurfaceView#setMastLayerFrame(Rect)}的Rect大小一样
51 | */
52 | public EasyPRPreViewMaskLayer setMastLayerFrame(Rect frame) {
53 | this.mastLayerFrame = frame;
54 | return this;
55 | }
56 |
57 | /**
58 | * 框颜色
59 | */
60 | public EasyPRPreViewMaskLayer setFrameColor(int frameColor) {
61 | this.frameColor = frameColor;
62 | return this;
63 | }
64 |
65 | /**
66 | * 激光线颜色
67 | */
68 | public EasyPRPreViewMaskLayer setLaserColor(int laserColor) {
69 | this.laserColor = laserColor;
70 | return this;
71 | }
72 |
73 | /**
74 | * 遮罩层颜色
75 | */
76 | public EasyPRPreViewMaskLayer setMaskColor(int maskColor) {
77 | this.maskColor = maskColor;
78 | return this;
79 | }
80 |
81 | /**
82 | * 开始执行, 在Activity或者Fragment 的 onStart中调用
83 | */
84 | public void onStart() {
85 | if (mastLayerFrame == null) {
86 | setMastLayerFrame(EasyPrBiz.getDefRectFrame(context));
87 | }
88 | isStart = true;
89 | postInvalidate();
90 | }
91 |
92 | /**
93 | * 结束执行 在Activity或者Fragment 的 onStop中调用
94 | */
95 | public void onStop() {
96 | isStart = false;
97 | }
98 |
99 |
100 | @Override
101 | protected void onDraw(Canvas canvas) {
102 |
103 | if (mastLayerFrame != null && isStart) {
104 | int width = canvas.getWidth();
105 | int height = canvas.getHeight();
106 |
107 | //画半透明遮罩层区域,遮罩分四块
108 | paint.setColor(maskColor);
109 | paint.setStyle(Paint.Style.FILL);
110 | canvas.drawRect(0, 0, width, mastLayerFrame.top - 1, paint);//上部遮罩
111 | canvas.drawRect(0, mastLayerFrame.top - 1, mastLayerFrame.left - 1, mastLayerFrame.bottom + 1, paint);//左边遮罩
112 | canvas.drawRect(mastLayerFrame.right + 1, mastLayerFrame.top - 1, width, mastLayerFrame.bottom + 1, paint);//右边遮罩
113 | canvas.drawRect(0, mastLayerFrame.bottom + 1, width, height, paint);//下部遮罩
114 |
115 | //画红框
116 | paint.setColor(frameColor);
117 | paint.setStyle(Paint.Style.STROKE);
118 | canvas.drawRect(mastLayerFrame.left, mastLayerFrame.top, mastLayerFrame.right, mastLayerFrame.bottom, paint);
119 |
120 | //画中间动画的线
121 | /* paint.setColor(laserColor);
122 | paint.setStyle(Paint.Style.FILL);
123 | // paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
124 | scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
125 | laserYOffSet = laserYOffSet >= 60f ? 0 : laserYOffSet;
126 | int laserY = (int) (mastLayerFrame.top + mastLayerFrame.height() / 60f * laserYOffSet);
127 | laserY = laserY < mastLayerFrame.top + 1 ? mastLayerFrame.top + 1 : laserY;
128 | laserY = laserY > mastLayerFrame.bottom - 1 ? mastLayerFrame.bottom - 1 : laserY;
129 | canvas.drawRect(mastLayerFrame.left + 2, laserY - 1, mastLayerFrame.right - 2, laserY + 1, paint);
130 |
131 | laserYOffSet++;
132 | //规定时间强制重绘制定区域,实现动画效果
133 | postInvalidateDelayed(ANIMATION_DELAY, mastLayerFrame.left + 2, mastLayerFrame.top, mastLayerFrame.right - 2, mastLayerFrame.bottom);*/
134 | }
135 | super.onDraw(canvas);
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/arm64-v8a/libEasyPR.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/arm64-v8a/libEasyPR.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/arm64-v8a/libopencv_java3.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/arm64-v8a/libopencv_java3.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/armeabi-v7a/libEasyPR.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/armeabi-v7a/libEasyPR.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/armeabi-v7a/libopencv_java3.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/armeabi-v7a/libopencv_java3.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/armeabi/libEasyPR.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/armeabi/libEasyPR.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/armeabi/libopencv_java3.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/armeabi/libopencv_java3.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/mips/libEasyPR.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/mips/libEasyPR.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/mips/libopencv_java3.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/mips/libopencv_java3.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/mips64/libEasyPR.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/mips64/libEasyPR.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/mips64/libopencv_java3.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/mips64/libopencv_java3.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/x86/libEasyPR.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/x86/libEasyPR.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/x86/libopencv_java3.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/x86/libopencv_java3.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/x86_64/libEasyPR.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/x86_64/libEasyPR.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/jniLibs/x86_64/libopencv_java3.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guocheng0606/EasyPRForAndroid/0432ba8cc92caf34e6896566050de06f011f0aa8/libEasyPR/src/main/jniLibs/x86_64/libopencv_java3.so
--------------------------------------------------------------------------------
/libEasyPR/src/main/res/values/easypr_colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF0000
4 | #ff7FFF00
5 | #407CFC00
6 |
7 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':libEasyPR'
2 |
--------------------------------------------------------------------------------