Needs
Recently, the product said that a license plate recognition function should be added to the APP. The user does not need to enter it manually. I said that there is no problem. The first reaction in my mind was the third-party SDK, and finally used the Baidu License Plate Recognition SDK to complete the requirements. For the integration method, please refer to the “Baidu SDK Document”. If the article is really over, the brother who carried the knife probably will cut me again. There is a party in the title, and he always does these fucking things, haha~~~. I’m very happy.
Problem
At the beginning, we did use Baidu license plate recognition, but the recognition rate was not too high, and the license plate image had to be uploaded to Baidu, which would also be affected by internet speed. The most important thing is that Baidu can only call 200 times a day, more than 200 times you have to pay for it. The product will say, can it be made into local recognition, yes, it can definitely be, but I am still a novice algorithm. What about this recognition algorithm? Finally, I found a few recognition platforms. For a parking platform, the opening cost was 80,000. They said that there is another authorization method for access. A machine is 400 yuan, and 20 units are sold. Although it’s a bit expensive, the recognition rate is really good. I want to take it directly to save trouble, but the company definitely doesn’t want to pay for it. In the end, let the development find a way. The hardest thing is to develop ~~~~.
Finding a method
I found a big circle on Baidu, most of which are the publicity of the recognition platform, and a few talk about recognition, but they are relatively vague. Provide the source code, some just earn points under the name of recognition, so when I write the article, I will only write some very practical things that can really help everyone. Let’s not talk more nonsense, go straight to the topic, and finally found it Two recognized libraries:
One, EasyPR EasyPR github has more than 5,000 stars on it, but because it has not been updated for a long time, New Energy License plates are not supported, so this library is not used.
Second, HyperLPR
The author of HyperLPR is still maintaining it. Not only Android also supports the recognition of other platforms. I finally chose this, but the author wrote about Android’s documentation There are not too many, so that many problems will be encountered in the integration process. Let’s do it step by step.
Realization
One, download OpenCV: OpenCV official website: opencv.org/ OpenCV Android 3.4.6 version download address: nchc.dl.sourceforge.net/project/ope… Use 3.4 The .6 version can be downloaded directly by opening the link. The downloading process is a bit slow. After downloading, decompress.
Second, create a new project, rely on OpenCV to create a new project name in AS, and then right-click on the APP New—–> Module Select Import Eclipse ADT Project in the pop-up window and click Next. Select the sdk/java directory in the OpenCV directory you just unzipped, click OK, then fill in the Module Name, I filled in “openCV” and click Next —–> Finish.
Next, the project will report an error. Open the AndroidManifest.xml of the newly imported OpenCV and delete <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" />< /code> This line of code.
@Override
public void onManagerConnected(int status) {
super. onManagerConnected(status);
if (status == LoaderCallbackInterface.SUCCESS) {
Log.d(TAG, "OpenCV loaded successfully");
} else {
Log.d (TAG, "OpenCV failed to load");
}
}
};
@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);
}
}
}
When you run the project, you can see that the log is loaded successfully. In fact, if OpenCV is not loaded successfully, a dialog box will prompt you.
Configure NDK, compile library files
Now the latest version of NDK should be r20, you can’t use the latest NDK, otherwise there will be problems with compiling, we go to the official website to download NDK-r14b The author should develop on this version, and attach the download link: NDK download link to download the NDK of the corresponding platform, be sure to download the NDK-r14b version. After configuring the NDK, we create a new jin directory under the main directory, then download the DemoLPR library, and add the include, src, and javaWarpper.cpp in the app/src/main/jni directory inside Copy the files to the jni directory, and copy all the files in the assets/lpr/ directory to the lpr folder in the assets directory of our project. As shown below:
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
//Select the corresponding cpu to be added Type of .so library.
abiFilters'armeabi-v7a'
// You can also add'x86','x86_64','mips','mips64'
}
externalNativeBuild {< br /> cmake {
cppFlags "-std=gnu++11"
// Attention! ! ! ! Notice! ! ! ! ! !
//If you are a user developed with Linux, do not change the following line of code. If you are a Win user, please comment the following line of code.
arguments "-DANDROID_TOOLCHAIN=gcc", "-DANDROID_ARM_NEON=TRUE ", "-DANDROID_STL_FORCE_FEATURES=OFF"
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"< br /> }
}
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.constraint: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')
}
OK, let’s create a new PlateRecognition class under the project 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 ReleasePlateRec ognizer(long object);
public static native String SimpleRecognization(long inputMat, long object);
}
If your package name is the same as mine Not the same, you must go to the javaWartpper.cpp file and modify it to correspond to 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 RECOG NIZATION_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; //Decompression file storage location
private static void CopyAssets(Context context, String assetDir, String dir) {
String[] files;
try {
// How many files are there to get Assets
files = context.getAssets().list(assetDir);
} catch (IOException e1) {
return;
}
File mWorkingPath = new File(dir);
// If the file path does not exist
if ( !mWorkingPath.exists()) {
// Create a folder
if (!mWorkingPath.mkdirs()) {
// Called when the folder is not created successfully
}< br /> }
for (String file: files) {
try {
// Determine whether it is a folder or a file according to the path
if (!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);
}< br />
OutputStream out = new FileOutputStream(ou tFile);
// 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);
}
//Initialize recognition resources
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 + FINEMAPPLING_CAFFEEM ;
String segmentation_prototxt = SDCARD_DIR + File.separator + SEGMENTATION_PROTOTXT;
String segmentation_caffemodel = SDCARD_DIR + File.separator + SEGMENTATION_CAFFEMODEL;
String character_prototxt = SDCARD_DIR + File.TNIZ; 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_DIRF + File.
//Call JNI to load resource function
return PlateRecognition.InitPlateRecognizer(
cascade_filename,
finemapping_prototxt, finemapping_caffemodel,
segmentation_prototxt, segmentation_caffemodel,
character_prototxt, character_caffemodel,
segmen tation_free_prototxt, segmentation_free_caffemodel);
}
}
Okay, now the recognition function is available, there is a difference in recognition interface
Recognition interface:
< p>The recognition interface is actually a camera interface. I just wrote one casually. I also made a recognition box but did not adapt the screen. I originally wanted to post the code in the article, but there is a little bit more, so let’s take a look. Inside the demo. Combine the demo to transplant the recognition function to your project.
Demo operation instructions
Demo address: LPR Open the project will definitely report an error, make the following changes
- Open with AS Project
- Set the project NDK to NDK-r14b
- First modify the CMakeLists.txt file, and modify line 19 to the corresponding path of your local OpenCV SDK.
- According to your own development platform, set whether to comment on line 23 of build.gradle under the app. After completing the above steps, run the project and there will be no problem.
Recommendation: Android learning PDF+architecture video+interview document+source notes
That’s it, if you have any questions, please leave a message and more articles. Stay tuned.
In addition, I also have a collection, sorting and classification of materials to share, Android learning PDF + architecture video + interview documents + source notes, advanced architecture technology advanced brain map, Android Develop interview special materials, as well as advanced advanced framework materials to share, hope to help everyone learn to improve their advanced level, and save everyone's time to search for materials on the Internet to learn, and it can also be shared with friends around you to learn together!
You can scan the WeChat QR code and I can get it for free