Skip to content
State of the art ANPR/ALPR implementation for embedded devices (ARM) and desktops (x86) using deep learning
Java C# C++ Python Perl
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
assets Initial commit Nov 5, 2019
binaries Add information about the Android native libraries Nov 12, 2019
c++ Update comment about "ULTALPR_SDK_IMAGE_TYPE_RGB24" to explain how th… Nov 12, 2019
csharp Initial commit Nov 5, 2019
java Initial commit Nov 5, 2019
objc Initial commit Nov 5, 2019
perl Initial commit Nov 5, 2019
python Initial commit Nov 5, 2019
ruby Initial commit Nov 5, 2019
samples Initial commit Nov 5, 2019
.gitignore Initial commit Nov 5, 2019
LICENSE Initial commit Nov 5, 2019
README.md Update README.md Nov 10, 2019
SDK_TechnicalGuide_v2.0.pdf Initial commit Nov 5, 2019

README.md

  1. Sample applications
  2. Trying the samples
  3. Getting started
  4. Getting help

Have you ever seen a deep learning based ANPR/ALPR (Automatic Number/License Plate Recognition) engine running at 47fps on ARM device (Android, Snapdragon 855, 720p video resolution)?

With an average frame rate as high as 47 fps on ARM devices (Snapdragon 855) this is the fastest ANPR/ALPR implementation you'll find on the market. Being fast is important but being accurate is crucial. We use state of the art deep learning techniques to offer unmatched accuracy and precision. As a comparison this is #33 times faster than OpenALPR on Android. (see benchmark section for more information).

No need for special or dedicated GPUs, everything is running on CPU with SIMD ARM NEON optimizations, fixed-point math operations and multithreading. This opens the doors for the possibilities of running fully featured ITS (Intelligent Transportation System) solutions on a camera without soliciting a cloud. Being able to run all ITS applications on the device will significantly lower the cost to acquire, deploy and maintain such systems. Please check Device-based versus Cloud-based solution section for more information about how this would reduce the cost.


VideoParallel sample application on Android

We're already working to bring this frame rate at 64fps and add support for CMMDP (Color-Make Model-Direction-Prediction) before march 2020. We're confident that it's possible to have a complete ITS (license plate recognition, CMMDP, bus lane enforcement, red light enforcement, speed detection, congestion detection, double white line crossing detection, incident detection...) system running above 40fps on ARM device.

On high-end NVIDIA GPUs like the Tesla V100 the frame rate is 315 fps which means 3.17 millisecond inference time.

Don't take our word for it, come check our implementation. No registration, license key or internet connection is required, just clone the code and start coding/testing. Everything runs on the device, no data is leaving your computer. The code released here comes with many ready-to-use samples to help you get started easily.

You can also check our online cloud-based implementation (no registration required) to check out the accuracy and precision before starting to play with the SDK.

Please check full documentation at https://www.doubango.org/SDKs/anpr/docs/

Sample applications

The source code comes with #4 sample applications: Benchmark, VideoParallel, VideoSequential and ImageSnap.

Benchmark

This application is used to check everything is ok and running as fast as expected. The imformation about the maximum frame rate (47fps) on Snapdragon 855 devices could be checked using this application. It's open source and doesn't require registration or license key.

VideoParallel

This application should be used as reference code by any developer trying to add ultimateALPR to their products. It shows how to detect and recognize license plates in realtime using live video stream from the camera. Please check Parallel versus sequential processing section for more info about parellel mode.

VideoSequential

Same as VideoParallel but working on sequential mode which means slower. This application is provided to ease comparing the modes: Parallel versus Sequential.

ImageSnap

This application reads and display the live video stream from the camera but only recognize an image from the stream on demand.

Trying the samples

To try the sample applications on Android:

  1. Open Android Studio and select "Open an existing Android Studio project" alt text

  2. Navigate to ultimateALPR-SDK/samples, select android folder and click OK alt text

  3. Select the sample you want to try (e.g. videoparallel) and press run. Make sure to have the device on landscape mode for better experience. alt text

Getting started

The SDK works on many platforms and comes with support for many programming languages but this section focus on Android and Java. Please check the previous section for more information on how to use the sample applications.

Adding the SDK to your project (Android)

The SDK is distributed as an Android Studio module and you can add it as reference or you can also build it and add the AAR to your project. But, the easiest way to add the SDK to your project is by directly including the source.

In your build.gradle file add:

android {

      # This is the block to add within "android { } " section
      sourceSets {
         main {
             jniLibs.srcDirs += ['path-to-your-ultimateALPR-SDK/binaries/android/jniLibs']
             java.srcDirs += ['path-to-your-ultimateALPR-SDK/java/android']
             assets.srcDirs += ['path-to-your-ultimateALPR-SDK/assets/models']
         }
      }
}

Using the API (Android)

It's hard to be lost when you try to use the API as there are only 3 useful functions: init, process and deInit.

The C++ API is defined here.

	import org.doubango.ultimateAlpr.Sdk.ULTALPR_SDK_IMAGE_TYPE;
	import org.doubango.ultimateAlpr.Sdk.UltAlprSdkEngine;
	import org.doubango.ultimateAlpr.Sdk.UltAlprSdkParallelDeliveryCallback;
	import org.doubango.ultimateAlpr.Sdk.UltAlprSdkResult;

	final static String CONFIG = "{" +
		"\"debug_level\": \"info\"," + 
		"\"gpgpu_enabled\": true," + 

		"\"detect_minscore\": 0.1," + 
		"\"detect_quantization_enabled\": true," + 

		"\"recogn_score_type\": \"min\"," + 
		"\"recogn_minscore\": 0.3," + 
		"\"recogn_rectify_enabled\": false," + 
		"\"recogn_quantization_enabled\": true" + 
	"}";

	/**
	* Parallel callback delivery function used to notify about new results.
	* This callback will be called few milliseconds (before next frame is completely processed)
	* after process function is called.
	*/
	static class MyUltAlprSdkParallelDeliveryCallback extends UltAlprSdkParallelDeliveryCallback {
		@Override
		public void onNewResult(UltAlprSdkResult result) { }
	}

	final MyUltAlprSdkParallelDeliveryCallback mCallback = new MyUltAlprSdkParallelDeliveryCallback(); // set to null to disable parallel mode

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		

		// Initialize the engine
		assert UltAlprSdkEngine.init(
				getAssets(),
				CONFIG,
				mCallback
		).isOK();
	}

	// Camera listener: https://developer.android.com/reference/android/media/ImageReader.OnImageAvailableListener
	final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {

		@Override
		public void onImageAvailable(ImageReader reader) {
				try {
				    final Image image = reader.acquireLatestImage();
				    if (image == null) {
				        return;
				    }

				    // ANPR/ALPR recognition
				    final Image.Plane[] planes = image.getPlanes();
				    final UltAlprSdkResult result = UltAlprSdkEngine.process(
				        ULTALPR_SDK_IMAGE_TYPE.ULTALPR_SDK_IMAGE_TYPE_YUV420P,
				        planes[0].getBuffer(),
				        planes[1].getBuffer(),
				        planes[2].getBuffer(),
				        image.getWidth(),
				        image.getHeight(),
				        planes[0].getRowStride(),
				        planes[1].getRowStride(),
				        planes[2].getRowStride(),
				        planes[1].getPixelStride()
				    );
				    assert result.isOK();

				    image.close();

				} catch (final Exception e) {
				   e.printStackTrace();
				}
		}
	};

	@Override
	public void onDestroy() {
		// DeInitialize the engine
		assert UltAlprSdkEngine.deInit().isOK();

		super.onDestroy();
	}

Again, please check the sample applications and full documentation for more information.

Technical questions

Please check our discussion group or twitter account

You can’t perform that action at this time.