Compare commits
2 Commits
a4d297fc33
...
6976f690ff
Author | SHA1 | Date | |
---|---|---|---|
6976f690ff | |||
d81d955a8b |
79
alpr_api.py
79
alpr_api.py
@ -1,14 +1,19 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from time import sleep
|
||||
|
||||
import ultimateAlprSdk
|
||||
from PIL import Image
|
||||
from flask import Flask, request, jsonify, render_template
|
||||
|
||||
# Setup logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
counter_lock = threading.Lock()
|
||||
counter = 0
|
||||
bundle_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__)))
|
||||
boot_time = time.time()
|
||||
@ -22,11 +27,15 @@ information. The server is created using Flask and the ultimateALPR SDK is used
|
||||
See the README.md file for more information on how to run this script.
|
||||
"""
|
||||
|
||||
# Defines the default JSON configuration. More information at
|
||||
# https://www.doubango.org/SDKs/anpr/docs/Configuration_options.html
|
||||
JSON_CONFIG = {
|
||||
"assets_folder": os.path.join(bundle_dir, "assets"), # don't change this
|
||||
|
||||
# Load configuration from a JSON file or environment variables
|
||||
CONFIG_PATH = os.path.join(bundle_dir,
|
||||
'config.json') # TODO: store config file outside of bundle (to avoid compilation by users)
|
||||
if os.path.exists(CONFIG_PATH):
|
||||
with open(CONFIG_PATH, 'r') as config_file:
|
||||
JSON_CONFIG = json.load(config_file)
|
||||
else:
|
||||
JSON_CONFIG = {
|
||||
"assets_folder": os.path.join(bundle_dir, "assets"),
|
||||
"charset": "latin",
|
||||
"car_noplate_detect_enabled": False,
|
||||
"ienv_enabled": False,
|
||||
@ -40,30 +49,24 @@ JSON_CONFIG = {
|
||||
"license_token_file": "",
|
||||
"license_token_data": "",
|
||||
|
||||
"debug_level": "info",
|
||||
"debug_level": "fatal",
|
||||
"debug_write_input_image_enabled": False,
|
||||
"debug_internal_data_path": ".",
|
||||
|
||||
"num_threads": -1,
|
||||
"gpgpu_enabled": True,
|
||||
"max_latency": -1,
|
||||
|
||||
"klass_vcr_gamma": 1.5,
|
||||
|
||||
"detect_roi": [0, 0, 0, 0],
|
||||
"detect_minscore": 0.35,
|
||||
|
||||
"car_noplate_detect_min_score": 0.8,
|
||||
|
||||
"pyramidal_search_enabled": False,
|
||||
"pyramidal_search_sensitivity": 0.38, # default 0.28
|
||||
"pyramidal_search_sensitivity": 0.38,
|
||||
"pyramidal_search_minscore": 0.8,
|
||||
"pyramidal_search_min_image_size_inpixels": 800,
|
||||
|
||||
"recogn_rectify_enabled": True, # heavy on cpu
|
||||
"recogn_rectify_enabled": True,
|
||||
"recogn_minscore": 0.4,
|
||||
"recogn_score_type": "min"
|
||||
}
|
||||
}
|
||||
|
||||
IMAGE_TYPES_MAPPING = {
|
||||
'RGB': ultimateAlprSdk.ULTALPR_SDK_IMAGE_TYPE_RGB24,
|
||||
@ -75,7 +78,9 @@ config = json.dumps(JSON_CONFIG)
|
||||
|
||||
|
||||
def start_backend_loop():
|
||||
global counter
|
||||
global boot_time, counter
|
||||
|
||||
while True:
|
||||
load_engine()
|
||||
|
||||
# loop for about an hour or 3000 requests then reload the engine (fix for trial license)
|
||||
@ -85,11 +90,14 @@ def start_backend_loop():
|
||||
if not is_engine_loaded():
|
||||
unload_engine() # just in case
|
||||
load_engine()
|
||||
|
||||
sleep(1)
|
||||
time.sleep(1)
|
||||
|
||||
unload_engine()
|
||||
start_backend_loop()
|
||||
|
||||
# Reset counter and boot_time to restart the loop
|
||||
with counter_lock:
|
||||
counter = 0
|
||||
boot_time = time.time()
|
||||
|
||||
|
||||
def is_engine_loaded():
|
||||
@ -111,6 +119,7 @@ def unload_engine():
|
||||
|
||||
def process_image(image: Image) -> str:
|
||||
global counter
|
||||
with counter_lock:
|
||||
counter += 1
|
||||
|
||||
width, height = image.size
|
||||
@ -120,7 +129,6 @@ def process_image(image: Image) -> str:
|
||||
else:
|
||||
raise ValueError("Invalid mode: %s" % image.mode)
|
||||
|
||||
# TODO: add check for if engine still loaded
|
||||
result = ultimateAlprSdk.UltAlprSdkEngine_process(
|
||||
image_type,
|
||||
image.tobytes(),
|
||||
@ -152,28 +160,25 @@ def create_rest_server_flask():
|
||||
interference = time.time()
|
||||
|
||||
if 'upload' not in request.files:
|
||||
return jsonify({'error': 'No image found'})
|
||||
if 'grid_size' in request.form and request.form['grid_size'].isdigit():
|
||||
grid_size = int(request.form['grid_size'])
|
||||
return jsonify({'error': 'No image found'}), 400
|
||||
|
||||
grid_size = int(request.form.get('grid_size', 3))
|
||||
wanted_cells = request.form.get('wanted_cells')
|
||||
if wanted_cells:
|
||||
wanted_cells = [int(cell) for cell in wanted_cells.split(',')]
|
||||
else:
|
||||
grid_size = None
|
||||
if 'wanted_cells' in request.form and request.form['wanted_cells']:
|
||||
wanted_cells = request.form['wanted_cells'].split(',')
|
||||
wanted_cells = [int(cell) for cell in wanted_cells]
|
||||
else:
|
||||
wanted_cells = None
|
||||
wanted_cells = list(range(1, grid_size * grid_size + 1))
|
||||
|
||||
image = request.files['upload']
|
||||
if image.filename == '':
|
||||
return jsonify({'error': 'No selected file'})
|
||||
return jsonify({'error': 'No selected file'}), 400
|
||||
|
||||
image = Image.open(image)
|
||||
result = process_image(image)
|
||||
result = convert_to_cpai_compatible(result)
|
||||
|
||||
if not result['predictions']:
|
||||
print("No plate found in the image, attempting to split the image")
|
||||
|
||||
logger.debug("No plate found in the image, attempting to split the image")
|
||||
predictions_found = find_best_plate_with_split(image, grid_size, wanted_cells)
|
||||
|
||||
if predictions_found:
|
||||
@ -234,9 +239,7 @@ def convert_to_cpai_compatible(result):
|
||||
return response
|
||||
|
||||
|
||||
def find_best_plate_with_split(image: Image, grid_size: int = None, wanted_cells: str = None):
|
||||
if grid_size is None:
|
||||
grid_size = 3
|
||||
def find_best_plate_with_split(image: Image, grid_size: int = 3, wanted_cells: list = None):
|
||||
if wanted_cells is None:
|
||||
wanted_cells = list(range(1, grid_size * grid_size + 1))
|
||||
|
||||
@ -282,8 +285,8 @@ def find_best_plate_with_split(image: Image, grid_size: int = None, wanted_cells
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
engine = threading.Thread(target=start_backend_loop, daemon=True)
|
||||
engine.start()
|
||||
engine_thread = threading.Thread(target=start_backend_loop, daemon=True)
|
||||
engine_thread.start()
|
||||
|
||||
app = create_rest_server_flask()
|
||||
app.run(host='0.0.0.0', port=5000)
|
||||
|
@ -1,2 +1,2 @@
|
||||
pyinstaller --noconfirm --console --add-data libs:. --add-data assets:assets --add-data static:static --add-data templates:templates --name easy-local-alpr-1.1.0-openvinocpu_linux_x86_64 "alpr_api.py"
|
||||
pyinstaller --noconfirm --console --add-data libs:. --add-data assets:assets --add-data static:static --add-data templates:templates --name easy-local-alpr-1.4.0-openvinocpu_linux_x86_64 "alpr_api.py"
|
||||
# optional: --onefile
|
Loading…
Reference in New Issue
Block a user