NN ANPR & VMM SDK

Developer Guide

Automatic Number Plate Recognition and Vehicle Make & Model recognition for Windows applications, with native C/C++, C# and Delphi bindings, still-image and live-video pipelines, and support for CPU, GPU and edge AI accelerators.

Windows x64 SDK C/C++ · C# · Delphi Documentation v1.0 · July 2026

1Overview

The SDK provides two neural-network engines behind one simple C API exported by nnAnpr.dll:

ANPR — plate finding & reading

Detects number plates in an image (plate finder) and reads the characters (plate recognizer), returning the plate text, per-character confidences and coordinates, country and region, plate type and colour.

VMM — vehicle make & model

Detects vehicles (vehicle finder: car, bus, truck) and classifies the make and model (vehicle model recognizer) with a confidence score.

Video pipeline

Frame capture from video files, IP streams (RTSP/HTTP) and supported industrial cameras (GigE/USB3 vision), with synchronous or callback-driven asynchronous processing and a recognition accumulator for multi-frame voting.

Processing devices

One NNANPR_Device parameter selects the backend: Intel CPU, Intel GPU, Myriad VPU, NVIDIA GPU, Hailo accelerator, or the vendor cloud service.

Five geographic dataset families are included — Europe, Middle East, Africa, Asia & Australasia, USA & South America — selected per engine instance with the NNANPR_GeographicalArea parameter.

2Package contents

FolderContents
bin\The runtime: nnAnpr.dll plus all dependencies (OpenVINO, CUDA/cuDNN, Hailo runtime, camera-vendor runtimes), the data\ folder with encrypted neural-network datasets, ready-to-run demo executables, License Manager.exe, and testdata\ sample images.
Include\Everything an integration needs: C headers nnAnpr.h / nnVmm.h, the import library nnAnpr.lib, C# bindings nnAnpr.cs / nnVmm.cs, Delphi bindings nnAnpr.pas / nnVmm.pas.
Examples\Sample projects: C++ console and MFC GUI samples, C# WinForms samples, Delphi samples (Delphi 10.3 and Delphi 11 project versions). See section 12.
Datasets\full\Complete master/backup copy of all datasets. Nothing is loaded from here at runtime — the engine reads only bin\data (the data\ folder next to nnAnpr.dll). Use it to restore or complete a bin\data deployment.
Doc\This documentation.

3Requirements & setup

System requirements

  • OS: Windows 10 / Windows 11 / Windows Server, 64-bit only. All SDK binaries and bindings are x64; build your application as x64.
  • Runtime: Microsoft Visual C++ x64 redistributable (2015–2022).
  • CPU path: works on any modern x64 CPU via the bundled OpenVINO runtime — no extra installation.
  • NVIDIA GPU path (nndNvidiaGPU): a CUDA-capable NVIDIA GPU with a current driver. The required CUDA 11/12 and cuDNN 8/9 runtime DLLs are already included in bin\.
  • Intel GPU / Myriad (nndIntelGPU, nndMyriad): supported through the bundled OpenVINO runtime with the corresponding Intel drivers.
  • Hailo (nndHailo): a Hailo-8 accelerator with the Hailo driver; the libhailort runtime is included.
  • Industrial cameras: runtimes for supported GigE/USB3 vision cameras (Basler pylon, LUCID Arena, Daheng Galaxy) are included in bin\.
  • Cloud edition (nndIntertraffCloud): outbound internet access and an API key (section 4).

Setup

1

Copy the SDK folder

Copy the SDK to a writable location, e.g. C:\NNANPR-SDK\. Keep bin\ intact — nnAnpr.dll, its dependent DLLs and the data\ dataset folder must stay together.

2

Verify with a demo

Run bin\PlateRecognize.exe from a console: PlateRecognize.exe demo "testdata\EU2.jpg" (first argument is the API key — any text for local editions). A result window with the recognized plate confirms the runtime and datasets are working.

3

Make the DLLs reachable from your app

Your executable must be able to load nnAnpr.dll and its dependencies. Either run your EXE from bin\, copy the bin\ contents next to your EXE, or add the SDK bin\ folder to PATH. The data\ folder must sit next to nnAnpr.dll.

4Licensing & activation

The SDK is available in local (on-device) and cloud editions:

  • Local edition — processing runs on your machine. Licensing is file-based: use bin\License Manager.exe to view the machine identity and activate the license on the target computer. Error -18 NNANPR_LICENSE_ERROR indicates a missing or invalid license.
  • Trial builds — may require internet access for validation; without it the engine returns -17 NNANPR_TRIAL_VERSION_NO_INTERNET.
  • Cloud edition — recognition is performed by the vendor cloud (device nndIntertraffCloud). The cloud device applies only to the plate recognizer and the vehicle-model recognizer; the plate finder and vehicle finder always run locally (Intel CPU/GPU, Myriad, NVIDIA GPU or Hailo). Set your API key once at startup, before creating recognizers:
Set the cloud API key
NNANPR_SetStringParameter(L"APIKEY", L"<your-api-key>");

You can detect a cloud-only build at runtime with NNANPR_IsPlateRecognizerCloudVersion(). Server-side errors are reported as codes -11…-16, -19, -20 (section 15).

Note Contact your supplier for license purchase, trial keys and cloud quotas. [Vendor: insert contact details, license terms and quota table here.]

5Quick start (C++)

The complete still-image workflow — initialize once, create an engine pair, find plates, read each one, free everything:

Still-image recognition · C++
#include "nnAnpr.h"
#include <iostream>
#pragma comment(lib, "nnAnpr.lib")   // from Include\

int wmain()
{
    if (NNANPR_Init() != NNANPR_RESULT_SUCCESS)          // 1. initialize the engine once
        return -1;

    // NNANPR_SetStringParameter(L"APIKEY", L"...");     //    cloud edition only

    NNANPR_Image_ptr image = nullptr;                    // 2. load the input image
    NNANPR_CreateImage(&image);
    if (NNANPR_LoadImage(L"testdata\\EU2.jpg", image) != NNANPR_RESULT_SUCCESS)
        return -2;

    NNANPR_PlateFinder_ptr     finder     = nullptr;     // 3. create finder + recognizer
    NNANPR_PlateRecognizer_ptr recognizer = nullptr;     //    for your region and device
    NNANPR_CreatePlateFinder    (nngaEurope, nndIntelCPU, &finder);
    NNANPR_CreatePlateRecognizer(nngaEurope, nndIntelCPU, &recognizer);

    NNANPR_Object plates[30];                            // 4. find plates
    size_t        count = 30;                            //    in: capacity, out: found
    if (NNANPR_FindPlates(finder, image, plates, &count) == NNANPR_RESULT_SUCCESS)
    {
        for (size_t i = 0; i < count; ++i)               // 5. read each found plate
        {
            NNANPR_RecognizerResult rr{};
            if (NNANPR_RecognizePlate(recognizer, image, plates[i], &rr) == NNANPR_RESULT_SUCCESS)
                std::wcout << rr.Characters << L"   country: " << rr.Country
                           << L"   confidence: " << rr.CharacterConfidences[0] << L"\n";
        }
    }

    NNANPR_FreePlateRecognizer(recognizer);              // 6. release in reverse order
    NNANPR_FreePlateFinder(finder);
    NNANPR_FreeImage(image);
    return 0;
}
Build settings Platform x64 · add Include\ to the include path · link Include\nnAnpr.lib · run the EXE from the SDK bin\ folder (or copy the bin\ contents beside your EXE) so nnAnpr.dll and data\ are found.

To recognize a plate on an already-cropped plate image, pass 0 as the plate object. The same quick start in C# and Delphi is shown in section 11. The complete runnable project for this example is Examples\c++\PlateRecognize\ (see section 12 for every sample's folder).

6Core concepts

Handles and objects

Every engine entity — plate finder, plate recognizer, image, capture, window, accumulator, vehicle finder, vehicle model recognizer — is an opaque handle created by a NNANPR_Create… function and released by its matching NNANPR_Free… function. A found plate or vehicle is returned as a lightweight NNANPR_Object value; pass it to NNANPR_GetPlate / NNANPR_GetVehicle to read its position and confidence, or hand it directly to the recognizer.

Always pair Create/Free correctly Each handle type has its own free function. In particular, vehicle finder and vehicle model recognizer handles must be released with NNANPR_FreeVehicleFinder / NNANPR_FreeVehicleModelRecognizer — never with the plate free functions. Handles are untyped pointers, so the compiler cannot catch a mismatch.

The recognition pipeline

Processing is a two-stage pipeline. Stage one (finder) locates plates or vehicles in the frame; stage two (recognizer) reads one found object. This split lets you decide per frame which plates to read, run the stages on different devices, and scale them independently.

The two-stage pipeline
image ──► PlateFinder ──► NNANPR_Object[] ──► PlateRecognizer ──► NNANPR_RecognizerResult
                                                (per object)       text · confidences · country · type

Synchronous vs asynchronous

Every processing step exists in two forms. The synchronous form (FindPlates, RecognizePlate…) blocks until the result is ready — simplest for still images and batch jobs. The asynchronous form (FindPlatesAsync, RecognizePlateAsync…) queues the frame on an internal worker thread and returns immediately; the result arrives later through your callback. If a new frame arrives while the worker is busy, the older queued frame is skipped and the engine processes the latest one — live video never falls behind. Increase this queue with SetPlateFinderQueueSize / SetPlateRecognizerQueueSize (1–10, default 1) if you prefer throughput over latency.

Callback rules

The five threading rules 1. Callbacks are invoked on SDK worker threads, never on your UI thread — marshal results to the UI (PostMessage / Control.Invoke / TThread.Synchronize) instead of touching controls directly.
2. Keep callbacks short; heavy work in a callback stalls the pipeline.
3. Never free a handle that an asynchronous pipeline may still be using. Stop capture (NNANPR_StopCaptureFrameAsync) and let in-flight callbacks finish before calling any Free… — including when the user changes settings and you re-create engines.
4. In .NET, store every callback delegate in a field for the lifetime of the engine object. If only the garbage collector holds it, the native engine will eventually call a collected delegate and crash the process.
5. Do not call Free… functions from inside a callback.

Multi-frame accumulation

On live video the same plate is seen many times. The recognition accumulator merges consecutive reads of the same plate and reports the best-voted result, dramatically reducing single-frame misreads. Create one with NNANPR_CreateRecognitionAccumulator, configure it with NNANPR_SetupRecognitionAccumulator (maximum accumulation time and frame count, minimum plate size, and the character-difference threshold used to decide that two reads are the same plate), then replace RecognizePlateAsync with NNANPR_RecognizePlateAsyncWithAccumulator. Your recognition callback then receives consolidated results.

Return codes

Every function returns an NNANPR_RESULT: 1 success, 0 a valid "nothing found / cannot recognize" outcome, negative values are errors (full table). Convert any code to text with NNANPR_GetErrorString; for engine-level diagnostics read NNANPR_GetLastFindPlatesMessage / NNANPR_GetLastPlateRecognizerMessage.

7Video & cameras

Video files and IP streams

NNANPR_CreateVideoCapture opens a video file path or a stream URL (e.g. rtsp://user:pass@host/stream). Then either pull frames yourself with NNANPR_CaptureFrame in a loop, or let the SDK push them to you with NNANPR_StartCaptureFrameAsync and an OnFrame callback. Always call NNANPR_StopCaptureFrameAsync before freeing the capture.

Frame pacing NNANPR_GetVideoFPS reports the stream FPS when the container provides it. Live cameras and some RTSP streams report no FPS — check the return code and fall back to a default (e.g. 25) before dividing by it in your frame-timing code.

The typical live pipeline

Live pipeline overview
StartCaptureFrameAsync ─► OnFrame:      draw frame; FindPlatesAsync(frame)
                          OnPlateFound: for the best plate → RecognizePlateAsyncWithAccumulator(...)
                          OnRecognition: post result to UI thread (plate text, country, image)

By default the plate-found callback fires only when at least one plate was detected. To receive a callback for every processed frame (useful for smooth overlay drawing), enable:

Callback on every frame
NNANPR_SetUIntParameter(L"CALL PF ASYNC CALLBACK EVEN NO RESULT", 1);

and check the result count inside your callback before using the array.

Industrial cameras (GigE / USB3 Vision)

Enumerate supported connected cameras with NNANPR_GetSpecialVideoCaptureList and open one by name with NNANPR_CreateSpecialVideoCapture. Camera features (exposure, gain, trigger mode…) are set and read with NNANPR_SetVideoCaptureParameterUInt / NNANPR_GetVideoCaptureParameterUInt / NNANPR_SetVideoCaptureParameterString; parameter names follow the camera vendor's feature naming. For cameras in software-trigger mode, request the next frame with NNANPR_PulseSoftwareTrigger. Runtimes for Basler (pylon), LUCID (Arena) and Daheng (Galaxy) cameras ship in bin\.

8Vehicle make & model (VMM)

The VMM API (nnVmm.h) mirrors the ANPR pattern without the geographic-area parameter:

Vehicle make &amp; model · C++
NNANPR_VehicleFinder_ptr          vf  = nullptr;
NNANPR_VehicleModelRecognizer_ptr vmr = nullptr;
NNANPR_CreateVehicleFinder(nndIntelCPU, &vf);
NNANPR_SetupVehicleFinder(vf, 0.5);                    // detection threshold, 0.5 default
NNANPR_CreateVehicleModelRecognizer(nndIntelCPU, &vmr);

NNANPR_Object vehicles[30]; size_t n = 30;
if (NNANPR_FindVehicles(vf, image, vehicles, &n) == NNANPR_RESULT_SUCCESS)
    for (size_t i = 0; i < n; ++i)
    {
        NNANPR_Vehicle v{};  NNANPR_GetVehicle(vehicles[i], v);   // classId: 1 car, 2 bus, 3 truck
        NNANPR_ModelRecognizerResult mr{};
        if (NNANPR_RecognizeVehicleModel(vmr, image, vehicles[i], &mr) == NNANPR_RESULT_SUCCESS)
            std::wcout << mr.ModelName << L"  " << mr.Confidence << L"\n";
    }

NNANPR_FreeVehicleModelRecognizer(vmr);                 // VMM handles use VMM free functions
NNANPR_FreeVehicleFinder(vf);
  • Pass 0 instead of a vehicle object to classify a full image that already contains one vehicle.
  • Vehicle classes: NNANPR_VEHICLE_CAR (1), NNANPR_VEHICLE_BUS (2), NNANPR_VEHICLE_TRUCK (3), NNANPR_VEHICLE_UNKNOWN (0).
  • Asynchronous variants NNANPR_FindVehiclesAsync / NNANPR_RecognizeVehicleModelAsync follow the same callback rules as ANPR.
  • Model-recognition failure is reported as -121 NNANPR_RECOGNIZING_VEHICLE_MODEL_FAILED.
  • NNANPR_DrawText draws a label onto an image — handy for overlaying the model name.

9Tuning & parameters

Detection and recognition tuning

SettingFunctionRange / defaultEffect
Finder thresholdNNANPR_SetupPlateFinder0.0–1.0Minimum detection confidence. Raise to suppress false plates, lower to catch difficult ones.
Minimum plate heightNNANPR_SetupPlateFinder0–1000 pxIgnores plates smaller than this height — filters distant vehicles and speeds up recognition.
Recognizer thresholdNNANPR_SetupPlateRecognizer0.0–1.0Minimum character confidence for accepting a read.
Detection zoneNNANPR_SetPlateFinderCroppingRegionpixels or %Restricts detection to a region (e.g. one lane). Pixel coordinates win over percent; pass all-zero rectangles to disable.
Overlap merging (IoU)NNANPR_SetPlateFinderIoU1–100, default 40Intersection-over-union percentage used to merge overlapping detections.
Async queue depthNNANPR_SetPlateFinderQueueSize / NNANPR_SetPlateRecognizerQueueSize1–10, default 1Frames buffered per pipeline. 1 = lowest latency (skip old frames); higher = higher throughput.
Vehicle finder thresholdNNANPR_SetupVehicleFinder0.0–1.0, default 0.5Minimum vehicle-detection confidence.
VMM thresholdNNANPR_SetupVehicleModelRecognizer0.0–1.0Minimum make/model classification confidence.

Specific engine variants

Several finder/recognizer variants may be installed per region (optimised for different scenes or accelerators). List them with NNANPR_GetPlateFinderSpecificNames / NNANPR_GetPlateRecognizerSpecificNames — the buffer returns one name per line — and pass a name as the last argument of the corresponding Create… call, or nullptr for the default. Query the active variant with NNANPR_GetPlateFinderInfo / NNANPR_GetPlateRecognizerInfo.

Global engine parameters

ParameterSet withValuesPurpose
APIKEYNNANPR_SetStringParameterkey stringCloud-edition authentication. Set once at startup.
CALL PF ASYNC CALLBACK EVEN NO RESULTNNANPR_SetUIntParameter0 / 11 = plate/vehicle-found callback fires for every processed frame, even with zero results.
ENABLE LOG FILESNNANPR_SetUIntParameter0 / 1Writes engine log files for support diagnostics.

Syntax templates — fixing confusable characters

Characters like O/0, I/1, Z/2, B/8, S/5 are visually ambiguous. A syntax template tells the recognizer the legal character pattern of a country's plates so ambiguous characters resolve to the right class. Load one with NNANPR_SetPlateRecognizerSyntaxTemplate — pass either the file content or a file path. Template format (see bin\data\UK.syntax):

UK.syntax
d=0123456789                ← define character class "d" (digits)
l=ABCDEFGHIJKLMNOPQRSTUVWXYZ  ← define character class "l" (letters)
template=llddlll            ← a legal plate pattern: 2 letters, 2 digits, 3 letters
template=ldddlll            ← list every legal pattern on its own line

10Datasets & regions

The engine loads datasets only from the data\ folder next to nnAnpr.dll (that is, bin\data). Datasets\full\ is a complete master/backup copy of every model — nothing is loaded from it at runtime; use it only to restore or complete a bin\data deployment. Datasets are encrypted — do not rename, edit or substitute files. File families:

FilesPurpose
ww_pf1 … ww_pf4Worldwide plate finder models (internal files behind the selectable finder variants).
eu_pr1, eu_pr2Plate recognizer models — Europe (nngaEurope).
me_pr1, me_pr2Plate recognizer models — Middle East (nngaMiddleEast).
us_pr1, us_pr2Plate recognizer models — USA & South America (nngaUSA_SouthAmerica).
aa_pr1Plate recognizer — Asia & Australasia (nngaAsia_Australasia).
af_pr1Plate recognizer — Africa (nngaAfrica).
vmm, vmm8, vmm8_4, vmm8_cpu, vmmv4Vehicle make & model models (per device variants).
ps_sr1, tr_ck1, tr_ck2, wn_sh1Auxiliary engine models (internal stages).
UK.syntaxExample syntax template (section 9).

These are internal, encrypted file names — you never pass them to the API. A build's region is chosen with the NNANPR_GeographicalArea enum. To pick a specific finder or recognizer variant, call NNANPR_GetPlateFinderSpecificNames / NNANPR_GetPlateRecognizerSpecificNames to obtain the friendly display names the SDK exposes (for example "ME OV V7") and pass one as the pSpecificName argument to NNANPR_CreatePlateFinder / NNANPR_CreatePlateRecognizer (null = default). An unknown name returns -8 NNANPR_INCORRECT_SPECIFIC_NAME.

Each model ships in several runtime formats and the engine picks the one matching your selected device: .xml/.bin (OpenVINO — Intel CPU/GPU/Myriad), .hef (Hailo), .cfg/.weights/.classes (NVIDIA GPU builds), with .json metadata. Missing dataset files for the chosen region/device produce error -10 NNANPR_DATASET_IS_NOT_INSTALLED.

11Language bindings

C / C++

Include Include\nnAnpr.h (and nnVmm.h for VMM), link Include\nnAnpr.lib, build x64. Works from console, Win32, MFC and service applications — see the quick start.

C# (.NET)

Add Include\nnAnpr.cs (and nnVmm.cs) to your project. The bindings are P/Invoke declarations over nnAnpr.dll; no COM registration is needed.

  • Set the project platform to x64 (not AnyCPU) — the native DLL is 64-bit.
  • Make sure nnAnpr.dll and its bin\ dependencies are next to your EXE or on PATH.
  • Root your callback delegates. Store each delegate in a field that lives as long as the pipeline; passing a method group or lambda directly leaves the delegate to the garbage collector, and the native engine will eventually call a collected delegate and terminate the process.
Rooting callback delegates · C#
public sealed class AnprEngine
{
    // Delegates kept in fields: the native engine calls them from its worker
    // threads for as long as the pipeline exists. If only the garbage collector
    // held them, a collected delegate would crash the process.
    private readonly NNANPROnPlateFoundCallback  _onPlates;
    private readonly NNANPROnRecognitionCallback _onRead;
    private IntPtr _finder, _recognizer;                 // handles are IntPtr, not ulong

    public AnprEngine()
    {
        _onPlates = OnPlatesFound;          // field assignment = GC-rooted
        _onRead   = OnPlateRead;
        nnAnpr.NNANPR_Init();
        nnAnpr.NNANPR_CreatePlateFinder(NNANPR_GeographicalArea.nngaEurope,
                                        NNANPR_Device.nndIntelCPU, ref _finder);
        nnAnpr.NNANPR_CreatePlateRecognizer(NNANPR_GeographicalArea.nngaEurope,
                                        NNANPR_Device.nndIntelCPU, ref _recognizer);
    }

    public void ProcessFrame(IntPtr image) =>
        nnAnpr.NNANPR_FindPlatesAsync(_finder, image, _onPlates, IntPtr.Zero);

    private void OnPlatesFound(ulong[] plates, ulong count, IntPtr image, IntPtr ctx)
    {
        if (count > 0)
            nnAnpr.NNANPR_RecognizePlateAsync(_recognizer, image, plates[0], _onRead, IntPtr.Zero);
    }

    private void OnPlateRead(ref NNANPR_RecognizerResult rr, IntPtr image, IntPtr ctx)
    {
        string plate = new string(rr.Characters).TrimEnd('\0');
        // marshal to the UI thread before touching controls:
        // form.BeginInvoke((Action)(() => label.Text = plate));
    }
}

Delphi

Add Include\nnAnpr.pas (and nnVmm.pas) to your project. The bindings target Win64 only — keep the project platform on Win64; do not add a Win32 target. Callbacks arrive on engine threads: hand results to the VCL thread with TThread.Synchronize/TThread.Queue or PostMessage, exactly as the shipped Delphi samples do. Sample projects are provided for Delphi 12.

12Sample projects

All samples live in Examples\; ready-built demos are in bin\. Build samples as x64 and run them from bin\ (or copy the bin\ contents beside the built EXE).

SampleLanguageShowsRun
PlateRecognizeC++ consoleStill-image recognition, synchronous pipeline, result drawing.PlateRecognize.exe <apikey> <image>
VehicleModelRecognizeC++ consoleVehicle make & model on a still image; optional vehicle detection first.VehicleModelRecognize.exe [-findcar] <apikey> <image>
MulticamerasC++ consoleSeveral streams in parallel, asynchronous pipelines per camera, result files.configure sources in the project, then run
VideoSampleC++ MFCLive video with the synchronous API on worker threads; crop zone selection; camera list.GUI — open Settings first
VideoAsyncC++ MFCLive video with the asynchronous API and the recognition accumulator.GUI — open Settings first
VideoAsyncVMMC++ MFCLive vehicle make & model recognition on video.GUI
BatchFinderAndRecognizerC++ MFCFolder batch processing with per-image result files and accuracy statistics; syntax-template selection.GUI — pick a folder of images
VideoSampleCSC# WinFormsLive video, synchronous API on worker threads; crop selection.GUI
VideoAsyncCSC# WinFormsLive video, asynchronous API + accumulator; API-key entry for cloud.GUI
VehicleModelRecognizerCSC# consoleVMM on a still image.VehicleModelRecognizerCS.exe [-findcar] <apikey> <image>
VideoSample / VideoAsync / VehicleModelRecognizerDelphi 12The same three scenarios in Delphi/VCL, including correct thread marshaling.GUI / console

Test images for all regions are provided in bin\testdata\.

Where each project lives Every sample sits under Examples\ in a subfolder that matches its Sample name above — C / C++ in Examples\c++\, C# in Examples\c#\, Delphi in Examples\Delphi 12\. Per scenario:
• Plate from image: Examples\c++\PlateRecognize\ · Examples\c#\VideoSampleCS\ (Open-image button) · Examples\Delphi 12\VideoSample\
• Live ANPR on video / RTSP: Examples\c++\VideoAsync\ · Examples\c#\VideoAsyncCS\ · Examples\Delphi 12\VideoAsync\
• Vehicle make & model: Examples\c++\VehicleModelRecognize\ (and live VideoAsyncVMM\) · Examples\c#\VehicleModelRecognizerCS\ · Examples\Delphi 12\VehicleModelRecognizer\

13Deployment checklist

  1. Build your application x64.
  2. Ship the contents of bin\ (in particular nnAnpr.dll, all dependent DLLs and the data\ folder) next to your executable, or install the SDK bin\ to a fixed path and add it to PATH. data\ must stay next to nnAnpr.dll.
  3. Install the Microsoft Visual C++ x64 redistributable on the target machine.
  4. Device drivers where used: NVIDIA driver for nndNvidiaGPU, Intel GPU driver for nndIntelGPU, Hailo driver for nndHailo, camera vendor drivers for GigE/USB3 cameras.
  5. Activate the license on the target with License Manager.exe (local editions), or configure the APIKEY (cloud edition).
  6. Verify on the target by running a bin\ demo against testdata\ before starting your application.
  7. For support cases, enable engine logs: NNANPR_SetUIntParameter(L"ENABLE LOG FILES", 1).

14API reference

All functions return NNANPR_RESULT (1 success, 0 valid "no result", negative = error). Strings are wide (wchar_t* / UTF-16). The tables list the parameters only.

Engine & global

FunctionParametersDescription
NNANPR_Init(void)Initializes the engine. Call once, before any other SDK call.
NNANPR_GetErrorString(errCode, wchar_t* buffer, size_t buffSize)Returns the text message for a result code.
NNANPR_SetStringParameter(const wchar_t* name, const wchar_t* value)Sets a global engine parameter, e.g. APIKEY.
NNANPR_SetUIntParameter(const wchar_t* name, size_t value)Sets a numeric engine parameter (see section 9).
NNANPR_IsPlateRecognizerCloudVersion(void)Returns success if this DLL build is cloud-only.

Plate finder

FunctionParametersDescription
NNANPR_CreatePlateFinder(GeographicalArea ga, Device device, PlateFinder_ptr* out, const wchar_t* specificName = null)Creates a plate finder for a region on a local device (not nndIntertraffCloud); optional specific variant name from NNANPR_GetPlateFinderSpecificNames.
NNANPR_GetPlateFinderSpecificNames(GeographicalArea ga, wchar_t* buffer, size_t buffSize)Lists installed finder variants (one per line).
NNANPR_SetupPlateFinder(finder, double threshold 0–1, DWORD minPlateHeight 0–1000)Detection confidence threshold and minimum plate height.
NNANPR_SetPlateFinderCroppingRegion(finder, RECT pixelCoords, RECT percentCoords)Restricts detection to a zone; zero rects disable; pixels win over percent.
NNANPR_SetPlateFinderIoU(finder, size_t ioU 1–100)Overlap-merge threshold in percent (default 40).
NNANPR_SetPlateFinderQueueSize(finder, size_t queueSize 1–10)Async input queue depth (default 1).
NNANPR_FindPlates(finder, image, NNANPR_Object* array, size_t* sizeInOut)Synchronous detection. In: buffer capacity; out: number found.
NNANPR_FindPlatesAsync(finder, image, OnPlateFoundCallback*, void* addInfo)Queues detection on the finder thread; results via callback.
NNANPR_GetPlate(NNANPR_Object plateObj, NNANPR_Plate& out)Reads position/confidence/class of a found plate object.
NNANPR_GetPlateFinderInfo(finder, wchar_t* buffer, size_t buffSize)Returns the finder variant/version string.
NNANPR_GetLastFindPlatesMessage(finder, wchar_t* buffer, size_t buffSize)Last diagnostic message of the finder.
NNANPR_FreePlateFinder(finder)Releases the finder. Stop async work first.

Plate recognizer

FunctionParametersDescription
NNANPR_CreatePlateRecognizer(GeographicalArea ga, Device device, PlateRecognizer_ptr* out, const wchar_t* specificName = null)Creates a plate recognizer for a region on a device.
NNANPR_GetPlateRecognizerSpecificNames(GeographicalArea ga, wchar_t* buffer, size_t buffSize)Lists installed recognizer variants (one per line).
NNANPR_SetupPlateRecognizer(recognizer, double threshold 0–1)Minimum character confidence.
NNANPR_SetPlateRecognizerQueueSize(recognizer, size_t queueSize 1–10)Async input queue depth (default 1).
NNANPR_SetPlateRecognizerSyntaxTemplate(recognizer, const wchar_t* fileBody, const wchar_t* filePath)Loads a syntax template (content or path) to resolve confusable characters.
NNANPR_RecognizePlate(recognizer, image, NNANPR_Object plate | 0, RecognizerResult* out)Synchronous read of one plate; pass 0 to read a pre-cropped plate image.
NNANPR_RecognizePlateAsync(recognizer, image, plate | 0, OnRecognitionCallback*, void* addInfo)Queues recognition; result via callback.
NNANPR_GetPlateRecognizerInfo(recognizer, wchar_t* buffer, size_t buffSize)Returns the recognizer variant/version string.
NNANPR_GetLastPlateRecognizerMessage(recognizer, wchar_t* buffer, size_t buffSize)Last diagnostic message of the recognizer.
NNANPR_FreePlateRecognizer(recognizer)Releases the recognizer. Stop async work first.

Recognition accumulator

FunctionParametersDescription
NNANPR_CreateRecognitionAccumulator(RecognitionAccumulator_ptr* out)Creates a multi-frame voting accumulator.
NNANPR_SetupRecognitionAccumulator(acc, size_t maxTimeMs, size_t maxFrames, size_t minPlateSize, size_t maxDifference)Voting window: max time and frames per plate, minimum plate size to use, max character difference to treat two reads as the same plate.
NNANPR_RecognizePlateAsyncWithAccumulator(recognizer, acc, image, plate, OnRecognitionCallback*, void* addInfo)Like RecognizePlateAsync, with results consolidated by the accumulator.
NNANPR_FreeRecognitionAccumulator(acc)Releases the accumulator.

Images

FunctionParametersDescription
NNANPR_CreateImage(Image_ptr* out)Creates an empty image object.
NNANPR_LoadImage(const wchar_t* path, image)Loads an image file into the object.
NNANPR_SaveImage(const wchar_t* path, image)Saves the image to file.
NNANPR_CloneImage(source, destination)Copies one image into another (create both first).
NNANPR_CropImage(image, RECT r)Crops the image in place.
NNANPR_ResizeImage(image, DWORD newWidth, DWORD newHeight)Resizes the image in place.
NNANPR_GetImageData(image, ImageFormat, DWORD* w, DWORD* h, void* buffer | null, size_t bufferSize)Copies pixels out (U8 BGR triplets); pass null buffer to query dimensions.
NNANPR_SetImageData(image, ImageFormat, DWORD w, DWORD h, void* data)Fills the image from a pixel buffer.
NNANPR_SetImageDataVerticalFlip(image, ImageFormat, DWORD w, DWORD h, void* data)Same as SetImageData with a vertical flip (bottom-up sources).
NNANPR_GetImageTime(image, double* sampleTime)Returns the frame timestamp (for captured frames).
NNANPR_DrawRect(image, RECT r, COLORREF rgb, int thickness)Draws a rectangle on the image.
NNANPR_DrawPlateRect(image, NNANPR_Object plate, COLORREF rgb, int thickness)Draws the bounding box of a found plate/vehicle.
NNANPR_DrawText(image, long x, long y, const wchar_t* text, COLORREF rgb)Draws a text label on the image (declared in nnVmm.h).
NNANPR_FreeImage(image)Releases the image object.

Display windows

FunctionParametersDescription
NNANPR_CreateImageWindow(HWND parent | null, ImageWindow_ptr* out)Creates a display window; null parent creates a standalone dialog.
NNANPR_DrawImage(window, image)Presents the image in the window.
NNANPR_WaitImageWindow(window, DWORD autoCloseMs, bool closeByAnyKey)Blocks until close/key/timeout (parentless windows only).
NNANPR_ImageWindowStartDrawCrop(window, OnCropSelectedCallback*, void* addInfo)Lets the user drag a crop/zone rectangle; result via callback.
NNANPR_ImageWindowStopDrawCrop(window)Ends crop-selection mode.
NNANPR_ImageWindowShowCrop(window, bool show)Shows/hides the crop overlay.
NNANPR_FreeImageWindow(window)Closes and releases the window.

Video & cameras

FunctionParametersDescription
NNANPR_CreateVideoCapture(ImageCapture_ptr* out, const wchar_t* fileOrUrl)Opens a video file or stream URL (RTSP/HTTP).
NNANPR_CaptureFrame(capture, image)Grabs the next frame synchronously.
NNANPR_StartCaptureFrameAsync(capture, OnFrameCallback*, void* addInfo)Starts the capture thread; each frame arrives via callback.
NNANPR_StopCaptureFrameAsync(capture)Stops the capture thread. Call before freeing.
NNANPR_GetVideoFPS(capture, double* fps)Stream FPS if available — check the return code; may be unavailable for live sources.
NNANPR_GetSpecialVideoCaptureList(wchar_t* buffer, size_t buffSize)Lists supported industrial cameras connected to this PC.
NNANPR_CreateSpecialVideoCapture(ImageCapture_ptr* out, const wchar_t* cameraName)Opens an industrial camera by its listed name.
NNANPR_SetVideoCaptureParameterUInt(capture, const wchar_t* name, size_t value)Sets a numeric camera feature (vendor feature names).
NNANPR_GetVideoCaptureParameterUInt(capture, const wchar_t* name, size_t& value)Reads a numeric camera feature.
NNANPR_SetVideoCaptureParameterString(capture, const wchar_t* name, const wchar_t* value)Sets a string camera feature.
NNANPR_PulseSoftwareTrigger(capture, bool adjustSensorOnly)Fires a software trigger on cameras in SW-trigger mode.
NNANPR_FreeVideoCapture(capture)Releases the capture.

Vehicle make & model (nnVmm.h)

FunctionParametersDescription
NNANPR_CreateVehicleFinder(Device device, VehicleFinder_ptr* out, const wchar_t* specificName = null)Creates a vehicle detector on a local device (not nndIntertraffCloud).
NNANPR_SetupVehicleFinder(vehicleFinder, double threshold 0–1)Detection confidence threshold (default 0.5).
NNANPR_FindVehicles(vehicleFinder, image, NNANPR_Object* array, size_t* sizeInOut)Synchronous vehicle detection.
NNANPR_FindVehiclesAsync(vehicleFinder, image, OnVehicleFoundCallback*, void* addInfo)Asynchronous vehicle detection via callback.
NNANPR_GetVehicle(NNANPR_Object vehicleObj, NNANPR_Vehicle& out)Reads class (car/bus/truck), position, confidence.
NNANPR_FreeVehicleFinder(vehicleFinder)Releases the vehicle finder (VMM-specific free).
NNANPR_CreateVehicleModelRecognizer(Device device, VehicleModelRecognizer_ptr* out, const wchar_t* specificName = null)Creates a make/model classifier.
NNANPR_SetupVehicleModelRecognizer(vmr, double threshold 0–1)Minimum classification confidence.
NNANPR_RecognizeVehicleModel(vmr, image, NNANPR_Object vehicle | 0, ModelRecognizerResult* out)Synchronous make/model classification; 0 = whole image.
NNANPR_RecognizeVehicleModelAsync(vmr, image, vehicle | 0, OnVehicleModelRecognitionCallback*, void* addInfo)Asynchronous classification via callback.
NNANPR_FreeVehicleModelRecognizer(vmr)Releases the classifier (VMM-specific free).

Types at a glance

TypeFields / values
NNANPR_RecognizerResultCharacters[50] plate text · CharacterConfidences[50] · CharacterCoordinates[50] · Country[50] · CountryRegion[50] · PlateType · Color · platePosition · ErrorCode
NNANPR_Plate / NNANPR_VehicleclassId (plate type / vehicle class) · Position RECT · Confidence
NNANPR_ModelRecognizerResultModelName[50] · Confidence · VehiclePosition · ErrorCode
NNANPR_DevicenndIntelCPU 0 · nndIntelGPU 1 · nndMyriad 2 · nndIntertraffCloud 3 · nndNvidiaGPU 4 · nndHailo 5. nndIntertraffCloud is valid only for the plate and vehicle-model recognizers; finders use a local device.
NNANPR_GeographicalAreanngaEurope 0 · nngaMiddleEast 1 · nngaAfrica 2 · nngaAsia_Australasia 3 · nngaUSA_SouthAmerica 4
NNANPR_PlateTypennptNotDefined 0 · nnptTaxi 1 · nnptDiplomatic 2
CallbacksOnFrame(image, ctx) · OnPlateFound(objects, count, image, ctx) · OnRecognition(result*, image, ctx) · OnVehicleFound(objects, count, image, ctx) · OnVehicleModelRecognition(result*, image, ctx) · OnCropSelected(rect, ctx)

15Error codes

CodeNameMeaning / action
1NNANPR_RESULT_SUCCESSOperation succeeded.
0NNANPR_RESULT_FALSEValid outcome, nothing found / cannot recognize this input.
−1NNANPR_FAILEDGeneral failure — check GetLast…Message diagnostics.
−2NNANPR_FILE_READING_ERRORFile/path could not be read.
−3NNANPR_NOT_IMPLEMENTEDFeature not available in this build.
−4NNANPR_PARAMETER_IS_INCORRECTInvalid argument (null handle, out-of-range value…).
−5NNANPR_FINDING_PLATE_FAILEDPlate detection failed on this image.
−6NNANPR_BUFFER_TOO_SMALLGrow the output buffer / object array and retry.
−7NNANPR_RECOGNIZING_PLATE_FAILEDPlate reading failed on this plate.
−8NNANPR_INCORRECT_SPECIFIC_NAMEUnknown finder/recognizer variant name — list names first.
−9NNANPR_NOT_SUPPORTED_REGIONRegion not supported by this installation.
−10NNANPR_DATASET_IS_NOT_INSTALLEDDataset files missing — restore data\ from Datasets\full\.
−11NNANPR_SERVER_AUTHORIZATION_FAILEDCloud: API key missing/invalid — set APIKEY.
−12 / −13 / −19…LIMIT_PER_DAY / _SECOND / _MINUTE…Cloud: quota reached — throttle or upgrade plan.
−14NNANPR_SERVER_BUSYCloud: retry with backoff.
−15NNANPR_SERVER_CONNECTION_ERRORCloud: no connectivity to the service.
−16NNANPR_SERVER_TOTAL_LIMIT_REACHEDCloud: total quota exhausted.
−17NNANPR_TRIAL_VERSION_NO_INTERNETTrial build needs internet for validation.
−18NNANPR_LICENSE_ERRORLocal license missing/invalid — activate with License Manager.
−20NNANPR_SERVER_INCORRECT_PRODUCTCloud: key belongs to a different product.
−121NNANPR_RECOGNIZING_VEHICLE_MODEL_FAILEDVMM classification failed on this vehicle.

16Troubleshooting & FAQ

SymptomLikely cause → fix
App fails to start: nnAnpr.dll not foundThe EXE cannot see bin\ → run from bin\, copy its contents beside the EXE, or add it to PATH.
Error −10 on createdata\ folder missing or incomplete next to nnAnpr.dll → restore from Datasets\full\.
Error −11 in cloud modeAPIKEY not set or overwritten later → set once at startup, before creating engines.
No finder/recognizer names listed; empty dropdownsNNANPR_Init() was not called first.
Random crash after minutes (C# async)Callback delegate collected by GC → store delegates in fields (section 11).
Crash when changing settings during live videoEngines freed while pipelines still running → stop capture and let callbacks drain before Free…/re-create.
100% of one CPU core / crash on RTSPFrame pacing divides by FPS = 0 → check GetVideoFPS result and use a fallback FPS.
Plate found but text is wrong for O/0, I/1…Load a country syntax template (section 9).
Slow first recognitionFirst call loads and initializes datasets on the device — warm up at startup with one dummy image.

FAQ

Local or cloud?

Local editions process on-device (license file); the cloud edition sends images to the vendor service (nndIntertraffCloud + APIKEY). NNANPR_IsPlateRecognizerCloudVersion() tells you which build you have.

Several cameras?

Create one capture per stream. You can share one finder/recognizer (frames queue), or create one pair per stream for full parallelism — see the Multicameras sample.

32-bit application?

Not supported — the SDK is 64-bit only.

Which regions are covered?

Europe, Middle East, Africa, Asia & Australasia, USA & South America — one recognizer per NNANPR_GeographicalArea.

Data protection

In local editions images never leave the machine. In cloud mode frames are transmitted to the recognition service — review your data-protection obligations (e.g. GDPR) for your deployment.

17Code samples

Complete, copy-paste programs for the most common scenarios. Each is self-contained and built exactly against the shipped bindings. Build x64 and run from the SDK bin\ folder (or with bin\ on PATH). The C++ still-image quick start is in section 5. Every snippet below also ships as a full, runnable project — see section 12 for the exact Examples\ folder of each language and scenario.

C# — still-image recognition (console)

The C# equivalent of the quick start. Add Include\nnAnpr.cs to the project and build x64.

Still-image recognition · C#
using System;

class Program
{
    static int Main()
    {
        if (nnAnpr.NNANPR_Init() != nnAnpr.NNANPR_RESULT_SUCCESS)          // 1. initialize once
            return -1;

        // nnAnpr.NNANPR_SetStringParameter("APIKEY", "...");             //    cloud edition only

        IntPtr image = IntPtr.Zero;                                       // 2. load the input image
        nnAnpr.NNANPR_CreateImage(ref image);
        if (nnAnpr.NNANPR_LoadImage(@"testdata\EU2.jpg", image) != nnAnpr.NNANPR_RESULT_SUCCESS)
            return -2;

        IntPtr finder = IntPtr.Zero, recognizer = IntPtr.Zero;            // 3. create finder + recognizer
        nnAnpr.NNANPR_CreatePlateFinder(NNANPR_GeographicalArea.nngaEurope,
                                        NNANPR_Device.nndIntelCPU, ref finder);
        nnAnpr.NNANPR_CreatePlateRecognizer(NNANPR_GeographicalArea.nngaEurope,
                                        NNANPR_Device.nndIntelCPU, ref recognizer);

        ulong[] plates = new ulong[30];                                   // 4. find plates
        ulong   count  = (ulong)plates.Length;                           //    in: capacity, out: found
        if (nnAnpr.NNANPR_FindPlates(finder, image, ref plates[0], ref count) == nnAnpr.NNANPR_RESULT_SUCCESS)
        {
            for (ulong i = 0; i < count; i++)                            // 5. read each found plate
            {
                var rr = new NNANPR_RecognizerResult();
                if (nnAnpr.NNANPR_RecognizePlate(recognizer, image, plates[i], ref rr) == nnAnpr.NNANPR_RESULT_SUCCESS)
                    Console.WriteLine(PlateText(rr.Characters) + "   country: " + PlateText(rr.Country));
            }
        }

        nnAnpr.NNANPR_FreePlateRecognizer(recognizer);                    // 6. release in reverse order
        nnAnpr.NNANPR_FreePlateFinder(finder);
        nnAnpr.NNANPR_FreeImage(image);
        return 0;
    }

    // The result fields are fixed 50-char buffers; trim at the first NUL.
    static string PlateText(char[] a) => new string(a).TrimEnd('\0');
}
Binding note Handles are IntPtr; the found-plate buffer is passed as ref plates[0]; the per-character confidence field in the C# struct is named CharacterConfinedces (a spelling kept for binding compatibility).

Delphi — still-image recognition (console)

Add Include\nnAnpr.pas to the project; keep the platform on Win64.

Still-image recognition · Delphi
program PlateQuickStart;
{$APPTYPE CONSOLE}
uses
  System.SysUtils, nnAnpr;

var
  image      : NNANPR_Image_ptr;
  finder     : NNANPR_PlateFinder_ptr;
  recognizer : NNANPR_PlateRecognizer_ptr;
  objs       : PNNANPR_Object;
  count, i   : UInt64;
  rr         : NNANPR_RecognizerResult;
  plateStr, countryStr : string;
begin
  if NNANPR_Init <> NNANPR_RESULT_SUCCESS then            // 1. initialize once
    Halt(1);

  // NNANPR_SetStringParameter('APIKEY', '...');           //    cloud edition only

  NNANPR_CreateImage(image);                               // 2. load the input image
  if NNANPR_LoadImage('testdata\EU2.jpg', image) <> NNANPR_RESULT_SUCCESS then
    Halt(2);

  NNANPR_CreatePlateFinder(nngaEurope, nndIntelCPU, finder);        // 3. create finder + recognizer
  NNANPR_CreatePlateRecognizer(nngaEurope, nndIntelCPU, recognizer);

  count := 30;                                             // 4. find plates (in: capacity, out: found)
  if NNANPR_FindPlates(finder, image, objs, count) = NNANPR_RESULT_SUCCESS then
    for i := 0 to count - 1 do                             // 5. read each found plate
      if NNANPR_RecognizePlate(recognizer, image, objs[i], rr) = NNANPR_RESULT_SUCCESS then
      begin
        plateStr   := PChar(@rr.Characters[1]);            // fixed buffers are NUL-terminated
        countryStr := PChar(@rr.Country[1]);
        Writeln(plateStr, '   country: ', countryStr);
      end;

  NNANPR_FreePlateRecognizer(recognizer);                  // 6. release in reverse order
  NNANPR_FreePlateFinder(finder);
  NNANPR_FreeImage(image);
end.

C++ — live ANPR on video (asynchronous + accumulator)

The real-world pipeline: capture frames from a stream, detect and read plates on SDK worker threads, and consolidate repeated reads of the same plate with the accumulator. Note the correct teardown order — stop capture before freeing anything — and the result-count guard.

Live ANPR on video · C++
#include "nnAnpr.h"
#include <iostream>

struct App {
    NNANPR_PlateFinder_ptr            finder      = nullptr;
    NNANPR_PlateRecognizer_ptr        recognizer  = nullptr;
    NNANPR_RecognitionAccumulator_ptr accumulator = nullptr;
    NNANPR_ImageWindow_ptr            window      = nullptr;
    NNANPR_ImageCapture_ptr           capture     = nullptr;
};

// Runs on an SDK worker thread once a plate has been read (consolidated).
void OnRecognition(const NNANPR_RecognizerResult* rr, const NNANPR_Image_ptr image, void* ctx) {
    if (rr->ErrorCode != NNANPR_RESULT_SUCCESS) return;
    std::wcout << L"Plate: " << rr->Characters << L"  (" << rr->Country << L")\n";
    // In a GUI app, marshal to the UI thread here (PostMessage / Invoke) before touching controls.
}

// Runs on the finder thread once detection completes.
void OnPlateFound(const NNANPR_Object* plates, size_t count, const NNANPR_Image_ptr image, void* ctx) {
    App* a = static_cast<App*>(ctx);
    if (count == 0) return;                              // guard on the COUNT, never the pointer
    NNANPR_RecognizePlateAsyncWithAccumulator(a->recognizer, a->accumulator, image, plates[0],
                                             OnRecognition, ctx);
}

// Runs on the capture thread for every frame.
void OnFrame(const NNANPR_Image_ptr image, void* ctx) {
    App* a = static_cast<App*>(ctx);
    NNANPR_DrawImage(a->window, image);                 // show the live frame
    NNANPR_FindPlatesAsync(a->finder, image, OnPlateFound, ctx);
}

int wmain() {
    if (NNANPR_Init() != NNANPR_RESULT_SUCCESS) return -1;

    App app;
    NNANPR_CreatePlateFinder    (nngaEurope, nndIntelCPU, &app.finder);
    NNANPR_CreatePlateRecognizer(nngaEurope, nndIntelCPU, &app.recognizer);
    NNANPR_CreateRecognitionAccumulator(&app.accumulator);
    NNANPR_SetupRecognitionAccumulator(app.accumulator, 2000, 5, 20, 3); // 2 s / 5 frames / min 20 px / diff 3
    NNANPR_CreateImageWindow(nullptr, &app.window);

    if (NNANPR_CreateVideoCapture(&app.capture, L"rtsp://user:pass@192.168.1.10/stream")
            != NNANPR_RESULT_SUCCESS)
        return -2;

    NNANPR_StartCaptureFrameAsync(app.capture, OnFrame, &app);   // callbacks now run on SDK threads
    NNANPR_WaitImageWindow(app.window, 0, true);                 // block until the window is closed

    NNANPR_StopCaptureFrameAsync(app.capture);          // 1. stop capture FIRST
    NNANPR_FreeVideoCapture(app.capture);               // 2. then free, in reverse order
    NNANPR_FreeRecognitionAccumulator(app.accumulator);
    NNANPR_FreePlateRecognizer(app.recognizer);
    NNANPR_FreePlateFinder(app.finder);
    NNANPR_FreeImageWindow(app.window);
    return 0;
}

C++ — batch-process a folder of images (CSV report)

Reads every image in a folder, writes one CSV row per plate. Reads all plates per image, not just the first.

Batch folder → CSV · C++
#include "nnAnpr.h"
#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;

int wmain(int argc, wchar_t* argv[]) {
    if (argc < 2) { std::wcout << L"usage: batch <folder>\n"; return -1; }
    if (NNANPR_Init() != NNANPR_RESULT_SUCCESS) return -1;

    NNANPR_PlateFinder_ptr     finder     = nullptr;
    NNANPR_PlateRecognizer_ptr recognizer = nullptr;
    NNANPR_CreatePlateFinder    (nngaEurope, nndIntelCPU, &finder);
    NNANPR_CreatePlateRecognizer(nngaEurope, nndIntelCPU, &recognizer);
    NNANPR_SetupPlateFinder(finder, 0.5, 0);

    NNANPR_Image_ptr image = nullptr;
    NNANPR_CreateImage(&image);

    std::wofstream report(L"results.csv");
    report << L"file,plate,country\n";

    for (auto& entry : fs::directory_iterator(argv[1])) {
        auto ext = entry.path().extension().wstring();
        if (ext != L".jpg" && ext != L".png" && ext != L".bmp") continue;
        if (NNANPR_LoadImage(entry.path().c_str(), image) != NNANPR_RESULT_SUCCESS) continue;

        NNANPR_Object plates[30]; size_t count = 30;
        if (NNANPR_FindPlates(finder, image, plates, &count) != NNANPR_RESULT_SUCCESS) continue;

        for (size_t i = 0; i < count; ++i) {            // every plate, not just the first
            NNANPR_RecognizerResult rr{};
            if (NNANPR_RecognizePlate(recognizer, image, plates[i], &rr) == NNANPR_RESULT_SUCCESS)
                report << entry.path().filename().wstring() << L',' << rr.Characters
                       << L',' << rr.Country << L'\n';
        }
    }

    NNANPR_FreeImage(image);
    NNANPR_FreePlateRecognizer(recognizer);
    NNANPR_FreePlateFinder(finder);
    std::wcout << L"Done. Results in results.csv\n";
    return 0;
}
Tip For make & model instead of plates, swap the finder/recognizer for NNANPR_CreateVehicleFinder / NNANPR_CreateVehicleModelRecognizer and call NNANPR_FindVehicles / NNANPR_RecognizeVehicleModel — the structure is identical (see section 8).

C# — live ANPR on video (RTSP)

Open an rtsp:// stream and read plates asynchronously with the accumulator. The callback delegates are stored in fields so the garbage collector cannot collect them while the engine is still calling them.

Live ANPR on video · C#
using System;

class LiveAnpr
{
    // delegates kept in fields for the whole run (GC-rooted)
    readonly NNANPROnFrameCallback       _onFrame;
    readonly NNANPROnPlateFoundCallback  _onPlates;
    readonly NNANPROnRecognitionCallback _onRead;
    IntPtr _finder, _recognizer, _accum, _window, _capture;

    LiveAnpr() { _onFrame = OnFrame; _onPlates = OnPlatesFound; _onRead = OnPlateRead; }

    void OnFrame(IntPtr image, IntPtr ctx) {
        nnAnpr.NNANPR_DrawImage(_window, image);
        nnAnpr.NNANPR_FindPlatesAsync(_finder, image, _onPlates, IntPtr.Zero);
    }
    void OnPlatesFound(ulong[] plates, ulong count, IntPtr image, IntPtr ctx) {
        if (count > 0)
            nnAnpr.NNANPR_RecognizePlateAsyncWithAccumulator(_recognizer, _accum, image, plates[0], _onRead, IntPtr.Zero);
    }
    void OnPlateRead(ref NNANPR_RecognizerResult rr, IntPtr image, IntPtr ctx) {
        if (rr.ErrorCode == nnAnpr.NNANPR_RESULT_SUCCESS)
            Console.WriteLine(new string(rr.Characters).TrimEnd('\0'));
    }

    static void Main() {
        if (nnAnpr.NNANPR_Init() != nnAnpr.NNANPR_RESULT_SUCCESS) return;
        var app = new LiveAnpr();
        nnAnpr.NNANPR_CreatePlateFinder(NNANPR_GeographicalArea.nngaEurope, NNANPR_Device.nndIntelCPU, ref app._finder);
        nnAnpr.NNANPR_CreatePlateRecognizer(NNANPR_GeographicalArea.nngaEurope, NNANPR_Device.nndIntelCPU, ref app._recognizer);
        nnAnpr.NNANPR_CreateRecognitionAccumulator(ref app._accum);
        nnAnpr.NNANPR_SetupRecognitionAccumulator(app._accum, 2000, 5, 20, 3);
        nnAnpr.NNANPR_CreateImageWindow(IntPtr.Zero, ref app._window);
        if (nnAnpr.NNANPR_CreateVideoCapture(ref app._capture, "rtsp://user:pass@192.168.1.10/stream") != nnAnpr.NNANPR_RESULT_SUCCESS) return;

        nnAnpr.NNANPR_StartCaptureFrameAsync(app._capture, app._onFrame, IntPtr.Zero);
        nnAnpr.NNANPR_WaitImageWindow(app._window, 0, true);      // block until closed

        nnAnpr.NNANPR_StopCaptureFrameAsync(app._capture);        // stop FIRST, then free
        nnAnpr.NNANPR_FreeVideoCapture(app._capture);
        nnAnpr.NNANPR_FreeRecognitionAccumulator(app._accum);
        nnAnpr.NNANPR_FreePlateRecognizer(app._recognizer);
        nnAnpr.NNANPR_FreePlateFinder(app._finder);
        nnAnpr.NNANPR_FreeImageWindow(app._window);
    }
}
Root the delegates Storing each callback in a field (as above) is mandatory. Passing a method group or lambda directly lets the GC collect the thunk, and the native engine will later crash calling a dead delegate. In a WinForms app, marshal to the UI thread with Control.BeginInvoke before touching controls.

C# — vehicle make & model

Detect vehicles and classify make & model with the nnVmm binding.

Vehicle make &amp; model · C#
using System;

class Vmm
{
    static int Main()
    {
        if (nnAnpr.NNANPR_Init() != nnAnpr.NNANPR_RESULT_SUCCESS) return -1;

        IntPtr image = IntPtr.Zero;
        nnAnpr.NNANPR_CreateImage(ref image);
        if (nnAnpr.NNANPR_LoadImage(@"testdata\Traker1.jpg", image) != nnAnpr.NNANPR_RESULT_SUCCESS) return -2;

        IntPtr vf = IntPtr.Zero, vmr = IntPtr.Zero;
        nnVmm.NNANPR_CreateVehicleFinder(NNANPR_Device.nndIntelCPU, ref vf);
        nnVmm.NNANPR_SetupVehicleFinder(vf, 0.5);
        nnVmm.NNANPR_CreateVehicleModelRecognizer(NNANPR_Device.nndIntelCPU, ref vmr);

        ulong[] vehicles = new ulong[30];
        ulong   count    = (ulong)vehicles.Length;
        if (nnVmm.NNANPR_FindVehicles(vf, image, ref vehicles[0], ref count) == nnAnpr.NNANPR_RESULT_SUCCESS)
            for (ulong i = 0; i < count; i++) {
                var mr = new NNANPR_ModelRecognizerResult();
                if (nnVmm.NNANPR_RecognizeVehicleModel(vmr, image, vehicles[i], ref mr) == nnAnpr.NNANPR_RESULT_SUCCESS)
                    Console.WriteLine($"{new string(mr.ModelName).TrimEnd('\0')}  {mr.Confidence:0.00}");
            }

        nnVmm.NNANPR_FreeVehicleModelRecognizer(vmr);
        nnVmm.NNANPR_FreeVehicleFinder(vf);
        nnAnpr.NNANPR_FreeImage(image);
        return 0;
    }
}
Note The C# model struct field is Confidence (spelled correctly in the C# binding). Pass 0 instead of a vehicle object to classify a whole image. For live vehicle recognition, use NNANPR_FindVehiclesAsync + NNANPR_RecognizeVehicleModelAsync with rooted delegates, exactly as the ANPR RTSP sample above.

Delphi — live ANPR on video (RTSP)

Open an rtsp:// stream and read plates continuously using global cdecl callbacks.

Live ANPR on video · Delphi
program LiveAnpr;
{$APPTYPE CONSOLE}
uses System.SysUtils, nnAnpr;
var
  Finder     : NNANPR_PlateFinder_ptr;
  Recognizer : NNANPR_PlateRecognizer_ptr;
  Accum      : NNANPR_RecognitionAccumulator_ptr;
  Window     : NNANPR_ImageWindow_ptr;
  Capture    : NNANPR_ImageCapture_ptr;

procedure OnRecognition(rr: PNNANPR_RecognizerResult; image: NNANPR_Image_ptr; ctx: Pointer); cdecl;
begin
  if rr^.ErrorCode = NNANPR_RESULT_SUCCESS then
    Writeln(string(PChar(@rr^.Characters[1])), '  (', string(PChar(@rr^.Country[1])), ')');
end;

procedure OnPlateFound(plates: PNNANPR_Object; count: UInt64; image: NNANPR_Image_ptr; ctx: Pointer); cdecl;
begin
  if count = 0 then Exit;                          // guard on the count
  NNANPR_RecognizePlateAsyncWithAccumulator(Recognizer, Accum, image, plates[0], OnRecognition, nil);
end;

procedure OnFrame(image: NNANPR_Image_ptr; ctx: Pointer); cdecl;
begin
  NNANPR_DrawImage(Window, image);
  NNANPR_FindPlatesAsync(Finder, image, OnPlateFound, nil);
end;

begin
  if NNANPR_Init <> NNANPR_RESULT_SUCCESS then Halt(1);
  NNANPR_CreatePlateFinder(nngaEurope, nndIntelCPU, Finder);
  NNANPR_CreatePlateRecognizer(nngaEurope, nndIntelCPU, Recognizer);
  NNANPR_CreateRecognitionAccumulator(Accum);
  NNANPR_SetupRecognitionAccumulator(Accum, 2000, 5, 20, 3);
  NNANPR_CreateImageWindow(0, Window);
  if NNANPR_CreateVideoCapture(Capture, 'rtsp://user:pass@192.168.1.10/stream') <> NNANPR_RESULT_SUCCESS then Halt(2);

  NNANPR_StartCaptureFrameAsync(Capture, OnFrame, nil);   // callbacks run on SDK threads
  NNANPR_WaitImageWindow(Window, 0, True);                // block until the window is closed

  NNANPR_StopCaptureFrameAsync(Capture);                  // stop FIRST, then free
  NNANPR_FreeVideoCapture(Capture);
  NNANPR_FreeRecognitionAccumulator(Accum);
  NNANPR_FreePlateRecognizer(Recognizer);
  NNANPR_FreePlateFinder(Finder);
  NNANPR_FreeImageWindow(Window);
end.
VCL apps These callbacks run on SDK threads — never touch VCL controls from them. Marshal to the UI with TThread.Queue/TThread.Synchronize or PostMessage, as the shipped VideoAsync sample does.

Delphi — vehicle make & model

Detect vehicles and classify make & model with the nnVmm unit.

Vehicle make &amp; model · Delphi
program VehicleModel;
{$APPTYPE CONSOLE}
uses System.SysUtils, nnAnpr, nnVmm;
var
  image    : NNANPR_Image_ptr;
  vf       : NNANPR_VehicleFinder_ptr;
  vmr      : NNANPR_VehicleModelRecognizer_ptr;
  vehicles : PNNANPR_Object;
  count, i : UInt64;
  mr       : NNANPR_ModelRecognizerResult;
begin
  if NNANPR_Init <> NNANPR_RESULT_SUCCESS then Halt(1);

  NNANPR_CreateImage(image);
  if NNANPR_LoadImage('testdata\Traker1.jpg', image) <> NNANPR_RESULT_SUCCESS then Halt(2);

  NNANPR_CreateVehicleFinder(nndIntelCPU, vf);
  NNANPR_SetupVehicleFinder(vf, 0.5);
  NNANPR_CreateVehicleModelRecognizer(nndIntelCPU, vmr);

  count := 30;
  if NNANPR_FindVehicles(vf, image, vehicles, count) = NNANPR_RESULT_SUCCESS then
    for i := 0 to count - 1 do
      if NNANPR_RecognizeVehicleModel(vmr, image, vehicles[i], mr) = NNANPR_RESULT_SUCCESS then
        Writeln(string(PChar(@mr.ModelName[1])), '  ', FormatFloat('0.00', mr.Confinedce));

  NNANPR_FreeVehicleModelRecognizer(vmr);
  NNANPR_FreeVehicleFinder(vf);
  NNANPR_FreeImage(image);
end.
Field name The Delphi model struct field is spelled Confinedce in nnVmm.pas. Free VMM handles with the VMM free functions; pass 0 to classify a whole image.

18Support

[Vendor: insert support email, phone, ticket portal and SLA here.] When contacting support, include: SDK build date, Windows version, selected device (NNANPR_Device), the error code and the text from NNANPR_GetErrorString, plus engine logs (ENABLE LOG FILES = 1, see section 9).

Need a hand integrating the SDK? Contact support and a real engineer will get back to you.

NN ANPR & VMM SDK — Developer Guide · Documentation v1.0 · July 2026 · Applies to the Windows x64 SDK build of July 2026.
© [Vendor name]. All product names are trademarks of their respective owners.

Something went wrong. Reload ✕