The OpenALPR commercial SDK exposes APIs for identifying license plates in individual images, as well as videos or feeds of sequential images. The SDK can run on your hardware and integrate directly with your application.

The APIs are available as C/C++ library with additional bindings in C#, Java, and Python.

The OpenALPR C API recognizes license plates given individual images.
The library instance should be initialized once for each thread. There
is a significant initilization time (a few seconds) so you should not destroy
the instance until you are finished using it.

This instance is not threadsafe by design. An ALPR instance should be used on a single
thread and not shared across threads.

Update the prewarp setting without reloading the library. Since version 2.4.101, the accuracy at angles has improved that setting a prewarp value is no longer necessary or recommended. It may still help in some cases for simple image rotation to correct for a camera installed at an angle.

Parameters

prewarp_config: A specially constructed string produced by the openalpr_calibrate utility

Update the detection mask without reloading the library. The detection mask is used to improve processing efficiency (by ignoring areas for recognition) and to reduce false positives (by disqualifying plates found in areas where there could not be plates).

The Mask is simply a black/white image that should match the input resolution of the images. If it does not match, it will be stretched to fit. The white portions are areas that should be included for processing and the black areas will be ignored.

Specify a region to use when applying patterns. For example, if the camera is installed in Germany, and 90% of the license plates will be German plates, using a pattern of “de” would try to match the results against the German plate patterns and improve accuracy.

Parameters

region: The state/province to use as the default for pattern matching (e.g., md for USA/Maryland, be for Europe/Belgium).

Recognize a batch of images from raw pixel data. Batch processing is recommended when using a GPU for processing. Sending a batch of images allows the GPU to process them in parallel improving the overall efficiency.

Return

The results of the ALPR recognition for this image

Parameters

pixelData: raw image bytes for BGR channels

bytesPerPixel: Number of bytes for each pixel (e.g., 3)

imgWidth: Width of the image in pixels

imgHeight: Height of the image in pixels

num_images: The number of images in the batch

regionsOfInterest: an array of regions to recognize. Areas not covered by a region of interest would be ignored. You may pass an empty array to scan the entire image.

Specifies a region of interest to restrict the area that OpenALPR analyzes. The region(s) must be rectangular. The x,y positions are specified in pixels and correspond to the top left corners of the rectangle. The width and height are also specified in pixels. The coordinate system origin (0,0) is the top left of the image

Recognizes the encoded (e.g., JPEG, PNG) image. bytes are the raw bytes for the image data. Image is expected to be raw pixel data (BGR, 3 channels) Caller must call openalpr_free_response_string() on the returned object

Specifies a region of interest to restrict the area that OpenALPR analyzes. The region(s) must be rectangular. The x,y positions are specified in pixels and correspond to the top left corners of the rectangle. The width and height are also specified in pixels. The coordinate system origin (0,0) is the top left of the image

First, install the OpenALPR library on your target platform. Make sure the software runs by testing it with the alpr command-line executable.

Add “alpr_c.h” as an include file to your project.

Include the libopenalpr.dll (Windows) or libopenalpr.so (Unix) file with your binaries.

Include all other required shared libraries.

Insert the openalpr.conf and runtime_data directory in the same location as the binaries. Alternatively, you can specify the location of the runtime_data in openalpr.conf or directly in the code.

Add a commercial license key to the “license.conf” file in the same location as the binaries.

Below is a simple example of using the OpenALPR library with the C library:

#include<stdio.h>#include<stdlib.h>#include<alpr_c.h>longread_file(constchar*file_path,unsignedchar**buffer){FILE*fileptr;longfilelen;fileptr=fopen(file_path,"rb");// Open the file in binary modeif(!fileptr)return0;fseek(fileptr,0,SEEK_END);// Jump to the end of the filefilelen=ftell(fileptr);// Get the current byte offset in the filerewind(fileptr);// Jump back to the beginning of the file*buffer=(unsignedchar*)malloc((filelen+1)*sizeof(char));// Enough memory for file + \0fread(*buffer,filelen,1,fileptr);// Read in the entire filefclose(fileptr);// Close the filereturnfilelen;}intmain(intargc,char*argv[]){OPENALPR*alpr_obj;if(argc!=2){printf("Usage: %s [path to image file]\n",argv[0]);return1;}constchar*file_path=argv[1];// Leave the config and runtime directory blank to look for these in the current directory.alpr_obj=openalpr_init("us","","");if(openalpr_is_loaded(alpr_obj)){// We don't want to restrict the size of the recognition area, so we set this to an extremely large pixel size// rather than decode and find the actual image width/height.structAlprCRegionOfInterestroi;roi.x=0;roi.y=0;roi.width=10000;roi.height=10000;// Read the image fileunsignedchar*buffer;longlonglength=read_file(file_path,&buffer);printf("file size (bytes): %d\n",length);if(length>0){char*plate_response=openalpr_recognize_encodedimage(alpr_obj,buffer,length,roi);printf("Alpr response:\n%s\n",plate_response);openalpr_free_response_string(plate_response);}free(buffer);}openalpr_cleanup(alpr_obj);return0;}

The C++ commercial SDK is available for Linux. For Windows computers, we recommend that you use the C library.

Add “alpr.h” as an include file to your project.

Below is a simple example of using the OpenALPR library with the C library:

#include<alpr.h>// Initialize the library using United States-style license plates.// You can use other countries/regions as well (for example: "eu", "au", or "kr").alpr::Alpropenalpr("us","/path/to/openalpr.conf");// Optionally, you can specify the top N possible plates to return (with confidences). The default is ten.openalpr.setTopN(20);// Optionally, you can provide the library with a region for pattern matching. This improves accuracy by// comparing the plate text with the regional pattern.openalpr.setDefaultRegion("md");// Make sure the library loads before continuing.// For example, it could fail if the config/runtime_data is not found.if(openalpr.isLoaded()==false){std::cerr<<"Error loading OpenALPR"<<std::endl;return1;}// Recognize an image file. Alternatively, you could provide the image bytes in-memory.alpr::AlprResultsresults=openalpr.recognize("/path/to/image.jpg");// Carefully observe the results. There may be multiple plates in an image,// and each plate returns the top N candidates.for(inti=0;i<results.plates.size();i++){alpr::AlprPlateResultplate=results.plates[i];std::cout<<"plate"<<i<<": "<<plate.topNPlates.size()<<" results"<<std::endl;for(intk=0;k<plate.topNPlates.size();k++){alpr::AlprPlatecandidate=plate.topNPlates[k];std::cout<<" - "<<candidate.characters<<"\t confidence: "<<candidate.overall_confidence;std::cout<<"\t pattern_match: "<<candidate.matches_template<<std::endl;}}

importcom.openalpr.jni.Alpr;importcom.openalpr.jni.AlprPlate;importcom.openalpr.jni.AlprPlateResult;importcom.openalpr.jni.AlprResults;Alpralpr=newAlpr("us","/path/to/openalpr.conf","/path/to/runtime_data");// Set top N candidates returned to 20.alpr.setTopN(20);// Set pattern to Maryland.alpr.setDefaultRegion("md");AlprResultsresults=alpr.recognize("/path/to/image.jpg");System.out.format(" %-15s%-8s\n","Plate Number","Confidence");for(AlprPlateResultresult:results.getPlates()){for(AlprPlateplate:result.getTopNPlates()){if(plate.isMatchesTemplate())System.out.print(" * ");elseSystem.out.print(" - ");System.out.format("%-15s%-8f\n",plate.getCharacters(),plate.getOverallConfidence());}}// Make sure to call this to release memory.alpr.unload();

OpenALPR AlprStream API is used for license plate recognition on videos or time-ordered image sequences.

The AlprStream API organizes video streams so that they can be efficiently processed
by OpenALPR. The library utilizes motion detection to improve performance, and groups
sequential plate results for each vehicle into a single result with the highest possible confidence.
AlprStream also buffers incoming video and handles cases where video input is faster than the available processing by
evenly dropping frames from the video buffer.

You may configure AlprStream to connect directly to a video feed (either an IP camera stream URL or a file).
AlprStream will create a background thread that constantly pulls from the source to keep the video buffer full.
You may also feed video frames directly. If sending video manually, you should do this on a separate thread.

AlprStream maintains a buffer of frames for processing. You may share an AlprStream object across threads.
Each thread should maintain its own Alpr object. Passing the Alpr object to AlprStream using a process_frame()
call performs a recognition and returns individual results. The AlprStream object keeps track of these results and
forms plate groups.

Plate Groups can be accessed at any time by popping or peeking from the active list. Once a plate group is
fully formed, and we are confident that the vehicle is no longer in the scene, it is available to be popped.
Otherwise, it will remain on the list that you can peek, until enough time has passed.

Vehicle recognition is optionally run on each AlprGroup after it has been popped.
The vehicle recognition is CPU/GPU intensive. AlprStream uses a region centered around the license plate
to perform the vehicle recognition.

The AlprStream object should be initialized once for each video stream. The initialization time is minimal.
The AlprStream instance is threadsafe.

Spawns a thread that fills the processing queue with frames from a video file The thread will slow down to make sure that it does not overflow the queue The “video_start_time” is used to us with the epoch start time of of the video

Parameters

video_file_path: The location on disk to the video file.

video_start_time: The start time of the video in epoch ms. This time is used as an offset for identifying the epoch time for each frame in the video

Sets the format used for generating UUIDs. Default is “{time}-{random}” Valid options are: {time} - epoch_ms time the image was received {frame} - Frame number (starts at 0) {camera}, {company_uuid}, {agent_uid} - Any of the values specified in set_env_parameters {random} - a 16 character random string

Process the image at the front of the queue and return the individual results. This function is most useful when using GPU acceleration. Processing frames in a batch more efficiently uses GPU resources.

You should make sure that the video buffer size for this AlprStream object is greater than or equal to the configured GPU batch size (in openalpr.conf).

Return

An array of the results for all recognized frames that were processed

Parameters

alpr: The Alpr instance that you wish to use for processing the images

Configures the motion detection to watch recently moving regions for longer. For highway traffic where vehicles are constantly moving, this should be a lower number For places where the vehicles may stop and start, a higher value will prevent duplicate plate reads

Contains statistics for measuring the performance of the stream. The values returned show the amount of video entering the stream, the amount of video that contained motion and the amount of moving video that was recognized for license plates.

Gets the completed groups from the list and performs vehicle make/model/color/type recognition before returning vehicle results. This is a CPU or GPU intensive operation so it may be best to perform on a separate thread.

Return

a JSON-formatted string describing the list of completed group results. Each group result will contain vehicle information as well. Make sure to release the string memory using alprstream_free_response_string() after using it

Parameters

vehicle_classifier: An initialized instance of the VehicleClassifier that AlprStream will use to perform vehicle recognition

The following sample uses AlprStream API to recognize frames from a video. The Video is fed into the library asynchronously,
and the processing occurs on the main thread.

To use ALPR on multiple CPU cores, you should create multiple threads that call the alprstream_process_frame() function.
Each thread should have its own Alpr object, but can share the AlprStream object across threads.

// System imports#include<cstdlib>#include<vector>#include<string>#include<string.h>#include<sstream>#include<iostream>// Import OpenALPR alprstream_c (also pulls in alpr_c.h and vehicleclassifier_c.h)#include<alprstream_c.h>#include<alpr_c.h>usingnamespacestd;intmain(intargc,char**argv){cout<<"Initializing"<<endl;conststd::stringLICENSEPLATE_COUNTRY="eu";// Video buffer frames controls the number of frames to buffer in memory.constintVIDEO_BUFFER_SIZE=15;// The stream will assume sequential frames. If there is no motion from frame to frame, then// processing can be skipped for some framesconstintUSE_MOTION_DETECTION=1;// The point in time (ms) to start in the video fileconstintVIDEO_START_MS=0;OPENALPR*alpr=openalpr_init(LICENSEPLATE_COUNTRY.c_str(),"","");ALPRSTREAM*stream=alprstream_init(VIDEO_BUFFER_SIZE,USE_MOTION_DETECTION);// AlprStream will spawn a background thread to read the eu-clip.mp4 video file// and push to the queue. Alternatively, you may connect to a stream URL, or// push individual image frames into the alprstream object yourselfalprstream_connect_video_file(stream,"C:\\Temp\\eu-clip.mp4",VIDEO_START_MS);// Process until the video file is done and all remaining frames in the buffer have been processedwhile(true){// If the buffer is empty wait for it to replenishif(alprstream_get_queue_size(stream)<=0)Sleep(100);// AlprStream will now perform recognition on the oldest video frame on the queueAlprStreamRecognizedFrameC*response=alprstream_process_frame(stream,alpr);cout<<"Content: "<<response->results_str<<endl;// Writes the image frame to a temp file on disk for demonstration purposesif(response->image_available){FILE*file=fopen("c:\\temp\\test.jpg","wb");fwrite(response->jpeg_bytes,sizeof(char),response->jpeg_bytes_size,file);fclose(file);}// Free the memory for each responsealprstream_free_frame_response(response);cout<<"Stream queue size: "<<alprstream_get_queue_size(stream)<<endl;}cout<<"Done"<<endl;// Cleanup the memory for the Alpr objectopenalpr_cleanup(alpr);// Cleanup the memory for the AlprStream objectalprstream_cleanup(stream);return0;}