The following sample uses Vehicle Recognition Stream API to recognize frames from a video. The video is fed into the library asynchronously, and the processing occurs on the main thread.
C
To use 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 <vehicle_classifier_c.h>
#include <alpr_c.h>
using namespace std;
int main(int argc, char** argv) {
cout << "Initializing" << endl;
const std::string LICENSEPLATE_COUNTRY = "eu";
// Video buffer frames controls the number of frames to buffer in memory.
const int VIDEO_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 frames
const int USE_MOTION_DETECTION = 1;
// The point in time (ms) to start in the video file
const int VIDEO_START_MS = 0;
OPENALPR* alpr = openalpr_init(LICENSEPLATE_COUNTRY.c_str(), "", "", "");
VEHICLECLASSIFIER* vehicle_classifier = vehicleclassifier_init("", "", 0,0, 0, "");
ALPRSTREAM* stream = alprstream_init(VIDEO_BUFFER_SIZE, USE_MOTION_DETECTION);
// Enable to see detailed debug messages related to video read/queue
putenv("GST_DEBUG=2");
// 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 yourself
alprstream_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 processed
while (true)
{
// If the buffer is empty wait for it to replenish
if (alprstream_get_queue_size(stream) <= 0)
Sleep(100);
// AlprStream will now perform recognition on the oldest video frame on the queue
AlprStreamRecognizedFrameC* response = alprstream_process_frame(stream, alpr);
cout << "Content: " << response->results_str << endl;
// Writes the image frame to a temp file on disk for demonstration purposes
if (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 response
alprstream_free_frame_response(response);
// Get Group results:
char* group_result = alprstream_pop_completed_groups_and_recognize_vehicle(stream, vehicle_classifier);
cout << "Groups: " << group_result << endl;
alprstream_free_response_string(group_result);
cout << "Stream queue size: " << alprstream_get_queue_size(stream) << endl;
}
cout << "Done" << endl;
// Cleanup the memory for the Alpr object
openalpr_cleanup(alpr);
// Cleanup the memory for the AlprStream object
alprstream_cleanup(stream);
return 0;
}
Python
Download our sample video file (http://download.openalpr.com/bench/720p.mp4) which has several cars with license plates in a parking lot (or take your own video in .mp4 format). Then, run the following code:
import sys
from alprstream import AlprStream
from openalpr import Alpr, VehicleClassifier
# See https://docs.rekor.ai/rekor-scout/scout-agent/nvidia-gpu-acceleration
# GPU processing must use a single Alpr object and single thread per GPU.
# CPU processing may use multiple threads, with one Alpr object/thread per CPU core.
USE_GPU = False
GPU_BATCH_SIZE = 10
GPU_ID = 0
TRACK_VEHICLES_WITHOUT_PLATES = True
OPENALPR_CONFIG = '' #'/path/to/openalpr.conf'
RUNTIME_DATA_PATH = '' #'/path/to/runtime_data'
ALPR_COUNTRY = 'us'
# Sample video available at http://download.openalpr.com/bench/720p.mp4
TEST_VIDEO_FILE_PATH = '/path/to/video.mp4'
# Initialize instances
alpr = Alpr(ALPR_COUNTRY, OPENALPR_CONFIG, RUNTIME_DATA_PATH, use_gpu=USE_GPU, gpu_id=GPU_ID, gpu_batch_size=GPU_BATCH_SIZE)
if not alpr.is_loaded():
print('Error loading Alpr')
sys.exit(1)
alpr_stream = AlprStream(frame_queue_size=GPU_BATCH_SIZE, use_motion_detection=True)
if not alpr_stream.is_loaded():
print('Error loading AlprStream')
sys.exit(1)
vehicle = VehicleClassifier(OPENALPR_CONFIG, RUNTIME_DATA_PATH)
if not vehicle.is_loaded():
print('Error loading VehicleClassifier')
sys.exit(1)
alpr.set_detect_vehicles(True, TRACK_VEHICLES_WITHOUT_PLATES)
# Speeds up GPU by copying video data to GPU memory while processing
if USE_GPU:
alpr_stream.set_gpu_async(GPU_ID)
# Connect to stream/video and process results
alpr_stream.connect_video_file(TEST_VIDEO_FILE_PATH, 0)
while alpr_stream.video_file_active() or alpr_stream.get_queue_size() > 0:
if alpr.use_gpu:
single_frame = alpr_stream.process_batch(alpr)
else:
single_frame = alpr_stream.process_frame(alpr)
active_groups = len(alpr_stream.peek_active_groups())
print('Active groups: {:<3} \tQueue size: {}'.format(active_groups, alpr_stream.get_queue_size()))
groups = alpr_stream.pop_completed_groups_and_recognize_vehicle(vehicle, alpr)
for group in groups:
print('=' * 40)
print('Group from frames {}-{}'.format(group['frame_start'], group['frame_end']))
if group['data_type'] == 'alpr_group':
print('Plate: {} ({:.2f}%)'.format(group['best_plate']['plate'], group['best_plate']['confidence']))
if group['data_type'] == 'vehicle' or group['data_type'] == 'alpr_group':
print('Vehicle attributes')
for attribute, candidates in group['vehicle'].items():
print('\t{}: {} ({:.2f}%)'.format(attribute.capitalize(), candidates[0]['name'], candidates[0]['confidence']))
print('=' * 40)
# Call when completely done to release memory
alpr.unload()
vehicle.unload()
Last Updated August 25, 2022