demand
Recently, the product side said that the APP would add a license plate recognition function, so users do not have to manually input. I said no problem, just add it. The first reaction in my mind is the third-party SDK, and I finally used Baidu license plate recognition SDK to complete the requirements. For the integration method, see “Baidu SDK document”. Well, the article can end here. If the article is really over, the brother with the knife will probably cut me down again, a title party, always do these things to take off pants and fart, haha ~ ~ ~. It was fun to skin.
The problem
At first we do use baidu license plate recognition, but the recognition rate is not high, and the license plate images to upload the baidu over there, also will be affected by the speed, the most important thing is, baidu can call 200 times a day, more than 200 secondary pay, products over there said, can make local recognition, oh, yes, certainly can, but I was a small white algorithm, How to do this recognition algorithm? Finally, I found several recognition platforms, a parking platform, and asked for 80,000 yuan. They said that there was another way of authorization for access. Although expensive a bit, but identification rate is really ok, I pour want to receive directly come over, much save trouble, but the company certainly does not want to draw out this money ah, still let development think of method finally. The most helpless pain or development ~~~~.
Find a method
Found a big circle on baidu, most are wide recognition platform, there are also several said to the recognition, but said that the comparison of fuzzy, also do not provide source code, there are only in identifying name to earn points, so I wrote the article, only can write some very practical, can really help to everybody, please donate said, to the point, finally found the two recognition library:
EasyPR Github star has more than 5000, but because there is no update for a long time, the new energy license plate is not supported, so we do not use this library.
The author of HyperLPR is still maintaining, not only Android but also support the recognition of other platforms, and finally chose this, but the author of the documentation on Android is not too much, so that in the integration process will encounter a lot of problems. So let’s do it step by step.
implementation
A, download OpenCV: OpenCV website: opencv.org/ OpenCV Android 3.4.6 version download address: nchc.dl.sourceforge.net/project/ope… Using version 3.4.6, directly open the link to download, the download process is a little slow, I can’t help it, please wait, I also downloaded for a long time. Download and decompress.
2, create a New Project, depending on OpenCV to create a New Project in AS, then right-click on the APP New—–> Module, select Import Eclipse ADT Project in the popup window and click Next. Select the SDK/Java directory in the OpenCV directory you just unzipped, click OK, then fill in Module Name, I typed “OpenCV” and click Next —–> Finish.
The next project will report an error,
Build. Gradle = build. Gradle = build. Gradle = build. Gradle = build. Gradle = build.
Add implementation Project (Path: ‘:openCV’) OK in APP build.gradle, now synchronize project. Also add the SO file in buidl. Gradle of your App under defaultConfig
NDK {// Select the.so library to add for the CPU type. abiFilters'armeabi-v7a'// It can be added'x86'.'x86_64'.'mips'.'mips64'
}
Copy the code
Create a jinLibs directory under main, copy the SDK /native/libs/armeabi-v7a directory from OpenCV SDK to jniLibs.
The code in MainActivity:
public class MainActivity extends AppCompatActivity {
private final String TAG = getClass().getSimpleName();
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@SuppressLint("StaticFieldLeak")
@Override
public void onManagerConnected(int status) {
super.onManagerConnected(status);
if (status == LoaderCallbackInterface.SUCCESS) {
Log.d(TAG, "OpenCV loaded successfully");
} else {
Log.d(TAG, "OpenCV load failed"); }}}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
if(! OpenCVLoader.initDebug()) { Log.d(TAG,"Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_4_0, getApplicationContext(), mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!"); mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS); }}}Copy the code
If you run the project, it will be ok to see that the log has loaded successfully. In fact, if OpenCV has not loaded successfully, there will be a dialog box indicating that.
Configure the NDK and compile the library file
Now the latest version of NDK should be R20, you can’t use the latest NDK, otherwise there will be a problem of compilation, we go to the official website to download ndK-R14B version, the author should be developed on this version, attached download address: NDK Download Address To download the NDK of the corresponding platform, you must download the NDK-R14B version. After configuring the NDK, we will create a new jin directory under the main directory and download the Demo**LPR** library. Copy include, SRC and javawarpper. CPP files from app/ SRC /main/jni to jni, and copy all files from assets/ LPR/to LPR folder in assets of our project. The diagram below:
We create a new cmakelists. TXT file under the project app file, the content is as follows:
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lowerCmake_minimum_required (VERSION 3.4.1 track)# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.
include_directories(src/main/jni/include)
include_directories(src/main/jni)
aux_source_directory(src/main/jni SOURCE_FILES)
aux_source_directory(src/main/jni/src SOURCE_FILES_CORE)
list(APPEND SOURCE_FILES ${SOURCE_FILES_CORE})
# Modify the JNI path for your own Opencv-Android-SDK
set(OpenCV_DIR /home/aleyn/Android/TestProject/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
add_library( # Sets the name of the library.
lpr
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
${SOURCE_FILES})
# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
lpr
${OpenCV_LIBS}
# Links the target library to the log library
# included in the NDK.
${log-lib})
Copy the code
I am using Linux environment development, the path above is the path of Linux directory, must be replaced by your decompressed OpenCV SDK JNI corresponding local directory
Gradle = build.gradle = build.gradle = build.gradle = build.gradle = build.gradle = build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.pcl.lpr"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"NDK {// Select the.so library to add for the CPU type. abiFilters'armeabi-v7a'// It can be added'x86'.'x86_64'.'mips'.'mips64'
}
externalNativeBuild {
cmake {
cppFlags "-std=gnu++11"// Note !!!! Note !!!!!! // If you are developing on Linux, leave the following line of code untouchedinPlease comment arguments on the following line of code"-DANDROID_TOOLCHAIN=gcc"."-DANDROID_ARM_NEON=TRUE"."-DANDROID_STL_FORCE_FEATURES=OFF"
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com. Android. Support: appcompat - v7:28.0.0'
implementation 'com. Android. Support. The constraint, the constraint - layout: 1.1.3'
testImplementation 'junit: junit: 4.12'
androidTestImplementation 'com. Android. Support. Test: runner: 1.0.2'
androidTestImplementation 'com. Android. Support. Test. Espresso: espresso - core: 3.0.2'
implementation project(path: ':openCV')}Copy the code
OK, we create a new PlateRecognition class and DeepAssetUtil: PlateRecognition:
package com.pcl.lpr.utils;
/**
* @auther : Aleyn
* time : 2019/04/24
*/
public class PlateRecognition {
static {
System.loadLibrary("lpr");
}
static native long InitPlateRecognizer(String casacde_detection,
String finemapping_prototxt, String finemapping_caffemodel,
String segmentation_prototxt, String segmentation_caffemodel,
String charRecognization_proto, String charRecognization_caffemodel,
String segmentation_free_prototxt, String segmentation_free_caffemodel);
static native void ReleasePlateRecognizer(long object);
public static native String SimpleRecognization(long inputMat, long object);
}
Copy the code
If your package name is different from mine, be sure to go to the javawartpper. CPP file and change it to match yours.
DeepAssetUtil:
package com.pcl.lpr.utils;
import android.content.Context;
import android.os.Environment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class DeepAssetUtil {
public static final String ApplicationDir = "lpr";
public static final String CASCADE_FILENAME = "cascade.xml";
public static final String FINEMAPPING_PROTOTXT = "HorizonalFinemapping.prototxt";
public static final String FINEMAPPING_CAFFEMODEL = "HorizonalFinemapping.caffemodel";
public static final String SEGMENTATION_PROTOTXT = "Segmentation.prototxt";
public static final String SEGMENTATION_CAFFEMODEL = "Segmentation.caffemodel";
public static final String RECOGNIZATION_PROTOTXT = "CharacterRecognization.prototxt";
public static final String RECOGNIZATION_CAFFEMODEL = "CharacterRecognization.caffemodel";
public static final String FREE_INCEPTION_PROTOTXT = "SegmenationFree-Inception.prototxt";
public static final String FREE_INCEPTION_CAFFEMODEL = "SegmenationFree-Inception.caffemodel"; public static final String SDCARD_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + ApplicationDir; Private static void CopyAssets(Context Context, String assetDir, String dir) {String[] files; Try {// Get the total number of Assets files. Files = context.getAssets().list(assetDir); } catch (IOException e1) {return; } File mWorkingPath = new File(dir); // If the file path does not existif(! Mworkingpath.exists ()) {// Create a folderif(! Mworkingpath.mkdirs ()) {// called when folder creation failed}}for(String file: files) {try {// Determine whether it is a folder or a file according to the pathif(! file.contains(".")) {
if (0 == assetDir.length()) {
CopyAssets(context, file, dir + file + "/");
} else {
CopyAssets(context, assetDir + "/" + file, dir + "/" + file + "/");
}
continue;
}
File outFile = new File(mWorkingPath, file);
if (outFile.exists())
continue;
InputStream in;
if (0 != assetDir.length()) {
in = context.getAssets().open(assetDir + "/" + file);
} else {
in = context.getAssets().open(file);
}
OutputStream out = new FileOutputStream(outFile);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } private static void copyFilesFromAssets(Context context) { DeepAssetUtil.CopyAssets(context, ApplicationDir, SDCARD_DIR); Public static long initRecognizer(Context Context) {String cascade_filename = SDCARD_DIR + file.separator + CASCADE_FILENAME; String finemapping_prototxt = SDCARD_DIR + File.separator + FINEMAPPING_PROTOTXT; String finemapping_caffemodel = SDCARD_DIR + File.separator + FINEMAPPING_CAFFEMODEL; String segmentation_prototxt = SDCARD_DIR + File.separator + SEGMENTATION_PROTOTXT; String segmentation_caffemodel = SDCARD_DIR + File.separator + SEGMENTATION_CAFFEMODEL; String character_prototxt = SDCARD_DIR + File.separator + RECOGNIZATION_PROTOTXT; String character_caffemodel = SDCARD_DIR + File.separator + RECOGNIZATION_CAFFEMODEL; String segmentation_free_prototxt = SDCARD_DIR + File.separator + FREE_INCEPTION_PROTOTXT; String segmentation_free_caffemodel = SDCARD_DIR + File.separator + FREE_INCEPTION_CAFFEMODEL; copyFilesFromAssets(context); // Call the JNI load resource functionreturnPlateRecognition.InitPlateRecognizer( cascade_filename, finemapping_prototxt, finemapping_caffemodel, segmentation_prototxt, segmentation_caffemodel, character_prototxt, character_caffemodel, segmentation_free_prototxt, segmentation_free_caffemodel); }}Copy the code
Okay, now the recognition function is working, minus the recognition screen
Recognition interface:
The recognition interface is actually a camera interface, I wrote a random one, and I made a recognition box, but I didn’t make a screen adaptation, and I wanted to post all the code in the article, but it’s a little bit too much, so I’ll give you a look at the Demo. Integrate the recognition capabilities into your project with the Demo.
Demo Operation Description
Demo address: LPR open project will definitely error, make the following changes
- Open the project with AS
- Set the project NDK to NDK-R14B
- First modify the cmakelists. TXT file and change line 19 to the corresponding path of your local OpenCV SDK.
- Set line 23 of build.gradle in app to comment based on your development platform. Run the project after completing the above steps, and there should be no problems.
Thank you
Thanks to cloud View Zeusees for open source