Rekor Scout™ Installation Samples

Installation samples to support the Rekor Scout™ image API

C

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

  1. Add alpr_c.h as an include file to your project.

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

  3. Include all other required shared libraries.

  4. 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.

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

Below is a simple example:

 
#include <stdio.h>
#include <stdlib.h>
#include <alpr_c.h>
#include <vehicle_classifier_c.h>
#include "json.hpp" // https://github.com/nlohmann/json
#include <iostream>

long read_file(const char* file_path, unsigned char** buffer)
{
FILE *fileptr;
long filelen;

fileptr = fopen(file_path, "rb"); // Open the file in binary mode
if (!fileptr)
return 0;

fseek(fileptr, 0, SEEK_END); // Jump to the end of the file
filelen = ftell(fileptr); // Get the current byte offset in the file
rewind(fileptr); // Jump back to the beginning of the file

*buffer = (unsigned char *)malloc((filelen+1)*sizeof(char)); // Enough memory for file + \0
fread(*buffer, filelen, 1, fileptr); // Read in the entire file
fclose(fileptr); // Close the file

return filelen;
}

int main(int argc, char *argv[])
{
OPENALPR* alpr_obj;
// Optional module to classify vehicle make/model/color
VEHICLECLASSIFIER* vehicle_classifier_obj;

if (argc != 2)
{
printf("Usage: %s [path to image file]\n", argv[0]);
return 1;
}

const char* file_path = argv[1];
const char* OPENALPR_LICENSE_KEY = "";
const char* COUNTRY = "us";
// Leave the config and runtime directory blank to look for these in the current directory.
alpr_obj = openalpr_init(COUNTRY, "", "", OPENALPR_LICENSE_KEY);
vehicle_classifier_obj = vehicleclassifier_init("", "", 0, 1, 0, OPENALPR_LICENSE_KEY);

if (!openalpr_is_loaded(alpr_obj))
{
std::cout << "Error loading the OpenALPR library" << std::endl;
return 1;
}
if (!vehicleclassifier_is_loaded(vehicle_classifier_obj))
{
std::cout << "Error loading the Vehicle Classifier library" << std::endl;
return 1;
}

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.
struct AlprCRegionOfInterest roi;
roi.x = 0;
roi.y = 0;
roi.width = 10000;
roi.height = 10000;

// Read the image file
unsigned char* buffer;
long long length = read_file(file_path, &buffer);

if (length == 0)
{
std::cout << "Unable to read file: " << file_path << std::endl;
return 1;
}

if (length > 0)
{
char* plate_response = openalpr_recognize_encodedimage(alpr_obj, buffer, length, roi);
//printf("Alpr response:\n%s\n", plate_response);

// Parse the JSON that comes back
nlohmann::json parsed_plate_data = nlohmann::json::parse(plate_response);
// Free the JSON string now that we are done with it
openalpr_free_response_string(plate_response);

// Iterate over each plate and print the results
for (nlohmann::json result : parsed_plate_data["results"])
{
std::cout << "plate: " << result["plate"].get<std::string>() << " - " << result["region"].get<std::string>() << " (" << result["confidence"].get<float>() << ")" << std::endl;

// Classify the vehicle -- set the region of interest based on where ALPR tells us the car is
VehicleClassifierCRegionOfInterest roi;
roi.x = result["vehicle_region"]["x"];
roi.y = result["vehicle_region"]["y"];
roi.width = result["vehicle_region"]["width"];
roi.height = result["vehicle_region"]["height"];
char* vehicle_response = vehicleclassifier_recognize_encodedimage(vehicle_classifier_obj, COUNTRY, buffer, length, roi);

// Parse the JSON that comes back
nlohmann::json parsed_vehicle_data = nlohmann::json::parse(vehicle_response);
//printf("Vehicle Response:\n%s\n", vehicle_response);
vehicleclassifier_free_response_string(vehicle_response);

// Write results to console
for (std::string category : {"make", "color", "orientation", "make_model", "body_type", "year"})
std::cout << " - " << category << ": " << parsed_vehicle_data[category][0]["name"].get<std::string>() << " (" << parsed_vehicle_data[category][0]["confidence"].get<float>() << ")" << std::endl;

}

}

free(buffer);

}

openalpr_cleanup(alpr_obj);
vehicleclassifier_cleanup(vehicle_classifier_obj);

return 0;
}

Output:

 
./alpr_c_sample  cameraimage.jpg
plate: 4PCI264 - us-ca (94.7616195678711)
- make: bmw (86.89132690429688)
- color: silver-gray (90.59030151367188)
- orientation: 180 (96.70639038085938)
- make_model: bmw_3-series (86.49954223632813)
- body_type: sedan-standard (96.80194854736328)
- year: 2000-2004 (52.97491455078125)

C++

The C++ Rekor Scout 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:

 
#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::Alpr openalpr("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;
return 1;
}

// Recognize an image file. Alternatively, you could provide the image bytes in-memory.
alpr::AlprResults results = 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 (int i = 0; i < results.plates.size(); i++)
{
alpr::AlprPlateResult plate = results.plates[i];
std::cout << "plate" << i << ": " << plate.topNPlates.size() << " results" << std::endl;

for (int k = 0; k < plate.topNPlates.size(); k++)
{
alpr::AlprPlate candidate = plate.topNPlates[k];
std::cout << " - " << candidate.characters << "\t confidence: " << candidate.overall_confidence;
std::cout << "\t pattern_match: " << candidate.matches_template << std::endl;
}
}

C and VB.NET

Source code: https://github.com/openalpr/openalpr/tree/master/src/bindings/csharp

 
using AlprNet;

var alpr = new Alpr("us", "/path/to/openalpr.conf", "/path/to/runtime_data");
alpr.Initialize();
if (!alpr.IsLoaded())
{
Console.WriteLine("OpenAlpr failed to load!");
return;
}

var frame_lpr_data = alpr.Recognize("C:/path/to/imagefile/infiniti.jpg");
int i = 0;
foreach (var result in frame_lpr_data.results)
{
Console.WriteLine("Plate {0}: {1} result(s)", ++i, result.candidates.Count);
Console.WriteLine(" Processing Time: {0} msec(s)", result.processing_time_ms);
foreach (var plate in result.candidates)
{
Console.WriteLine(" - {0}\t Confidence: {1}\tMatches Template: {2}", plate.plate,
plate.confidence, plate.matches_template);
}
}

Python

Source code: https://github.com/openalpr/openalpr/tree/master/src/bindings/python

 
import sys
from openalpr import Alpr
from vehicleclassifier import VehicleClassifier

COUNTRY = 'us'
IMAGE_PATH = '/path/to/image.jpg'

# Initialize instances
alpr = Alpr(COUNTRY, '/path/to/openalpr.conf', '/path/to/runtime_data')
if not alpr.is_loaded():
print('Error loading Alpr')
sys.exit(1)
vehicle = VehicleClassifier('/path/to/openalpr.conf', '/path/to/runtime_data')
if not vehicle.is_loaded():
print('Error loading VehicleClassifier')
sys.exit(1)

# Set additional detection parameters (optional)
alpr.set_top_n(5)
alpr.set_default_region('md')

# Gather and print results
plate_results = alpr.recognize_file(IMAGE_PATH)
for i, plate in enumerate(plate_results['results']):
print('Plate {:-<30}'.format(i))
for c in plate['candidates']:
display = '\t{:>7} {}'.format('{:.2f}%'.format(c['confidence']), c['plate'])
if c['matches_template']:
display += ' *'
print(display)

vehicle_results = vehicle.recognize_file(COUNTRY, IMAGE_PATH)
best = [v[0]['name'] for k, v in vehicle_results.items() if k != 'make']
print('\nTop vehicle: {} oriented at {} degrees'.format(' '.join(best[:-1]), best[-1]))
for attribute, candidates in vehicle_results.items():
print('\n{:-<30}'.format(attribute.capitalize()))
for c in candidates:
label = c['name']
if c['name'] == 'missing':
label = 'unknown'
print('\t{:>7} {}'.format('{:.2f}%'.format(c['confidence']), label))

# Call when completely done to release memory
alpr.unload()
vehicle.unload()

Java

Source code: https://github.com/openalpr/openalpr/tree/master/src/bindings/java

 
import com.openalpr.jni.Alpr;
import com.openalpr.jni.AlprPlate;
import com.openalpr.jni.AlprPlateResult;
import com.openalpr.jni.AlprResults;

Alpr alpr = new Alpr("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");

AlprResults results = alpr.recognize("/path/to/image.jpg");
System.out.format(" %-15s%-8s\n", "Plate Number", "Confidence");
for (AlprPlateResult result : results.getPlates())
{
for (AlprPlate plate : result.getTopNPlates()) {
if (plate.isMatchesTemplate())
System.out.print(" * ");
else
System.out.print(" - ");
System.out.format("%-15s%-8f\n", plate.getCharacters(), plate.getOverallConfidence());
}
}

// Make sure to call this to release memory.
alpr.unload();

Node.js

A Node.js binding to Scout is available here: https://www.npmjs.com/package/node-openalpr

The source code is available here: https://github.com/netPark/node-openalpr

 
Last updated August 25, 2022