diff --git a/bindings/python/.gitignore b/bindings/python/.gitignore new file mode 100644 index 0000000..e25437f --- /dev/null +++ b/bindings/python/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.so +.idea/ diff --git a/bindings/python/make.sh b/bindings/python/make.sh new file mode 100755 index 0000000..8ea9053 --- /dev/null +++ b/bindings/python/make.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +OPENALPR_INCLUDE_DIR=/storage/projects/alpr/src/openalpr/ +OPENALPR_LIB_DIR=/storage/projects/alpr/src/build/openalpr/ + +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.:${OPENALPR_LIB_DIR} + +g++ -Wall -L${OPENALPR_LIB_DIR} -I${OPENALPR_INCLUDE_DIR} -shared -fPIC -o libopenalprpy.so openalprpy.cpp -lopenalpr + +python test.py \ No newline at end of file diff --git a/bindings/python/openalpr.py b/bindings/python/openalpr.py new file mode 100644 index 0000000..a39be4a --- /dev/null +++ b/bindings/python/openalpr.py @@ -0,0 +1,91 @@ +import ctypes +import json +import platform + +class Alpr(): + def __init__(self, country, config_file, runtime_dir): + + # Load the .dll for Windows and the .so for Unix-based + if platform.system().lower().find("windows") != -1: + self._openalprpy_lib = ctypes.cdll.LoadLibrary("openalprpy.dll") + else: + self._openalprpy_lib = ctypes.cdll.LoadLibrary("libopenalprpy.so") + + + self._initialize_func = self._openalprpy_lib.initialize + self._initialize_func.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p] + + self._dispose_func = self._openalprpy_lib.dispose + + self._is_loaded_func = self._openalprpy_lib.isLoaded + self._is_loaded_func.restype = ctypes.c_bool + + self._recognize_file_func = self._openalprpy_lib.recognizeFile + self._recognize_file_func.restype = ctypes.c_void_p + self._recognize_file_func.argtypes = [ctypes.c_char_p] + + self._recognize_array_func = self._openalprpy_lib.recognizeArray + self._recognize_array_func.restype = ctypes.c_void_p + self._recognize_array_func.argtypes = [ctypes.POINTER(ctypes.c_ubyte), ctypes.c_uint] + + self._free_json_mem_func = self._openalprpy_lib.freeJsonMem + + + self._set_default_region_func = self._openalprpy_lib.setDefaultRegion + self._set_default_region_func.argtypes = [ctypes.c_char_p] + + self._set_detect_region_func = self._openalprpy_lib.setDetectRegion + self._set_detect_region_func.argtypes = [ctypes.c_bool] + + + self._set_top_n_func = self._openalprpy_lib.setTopN + self._set_top_n_func.argtypes = [ctypes.c_int] + + self._get_version_func = self._openalprpy_lib.getVersion + self._get_version_func.restype = ctypes.c_void_p + + self._initialize_func(country, config_file, runtime_dir) + + + def unload(self): + self._openalprpy_lib.dispose() + + def is_loaded(self): + return self._is_loaded_func() + + def recognize_file(self, file_path): + ptr = self._recognize_file_func(file_path) + json_data = ctypes.cast(ptr, ctypes.c_char_p).value + response_obj = json.loads(json_data) + self._free_json_mem_func(ptr) + + return response_obj + + def recognize_array(self, byte_array): + + pb = ctypes.cast(byte_array, ctypes.POINTER(ctypes.c_ubyte)) + ptr = self._recognize_array_func(pb, len(byte_array)) + json_data = ctypes.cast(ptr, ctypes.c_char_p).value + response_obj = json.loads(json_data) + self._free_json_mem_func(ptr) + + return response_obj + + def get_version(self): + + ptr = self._get_version_func() + version_number = ctypes.cast(ptr, ctypes.c_char_p).value + self._free_json_mem_func(ptr) + + return version_number + + def set_top_n(self, topn): + self._set_top_n_func(topn) + + def set_default_region(self, region): + self._set_default_region_func(region) + + def set_detect_region(self, enabled): + self._set_detect_region_func(enabled) + + diff --git a/bindings/python/openalprpy.cpp b/bindings/python/openalprpy.cpp new file mode 100644 index 0000000..bbd1e54 --- /dev/null +++ b/bindings/python/openalprpy.cpp @@ -0,0 +1,129 @@ +#include +#include +#include + +#include + +extern "C" { + + using namespace alpr; + + bool initialized = false; + static Alpr* nativeAlpr; + + void initialize(char* ccountry, char* cconfigFile, char* cruntimeDir) + { + //printf("Initialize"); + + // Convert strings from char* to string + std::string country(ccountry); + std::string configFile(cconfigFile); + std::string runtimeDir(cruntimeDir); + + //std::cout << country << std::endl << configFile << std::endl << runtimeDir << std::endl; + nativeAlpr = new alpr::Alpr(country, configFile, runtimeDir); + + initialized = true; + return; + } + + + + + void dispose() + { + //printf("Dispose"); + initialized = false; + delete nativeAlpr; + } + + + bool isLoaded() + { + //printf("IS LOADED"); + + if (!initialized) + return false; + + return nativeAlpr->isLoaded(); + + } + + char* recognizeFile(char* cimageFile) + { + //printf("Recognize file"); + + // Convert strings from java to C++ and release resources + std::string imageFile(cimageFile); + + AlprResults results = nativeAlpr->recognize(imageFile); + + std::string json = Alpr::toJson(results); + + int strsize = sizeof(char) * (strlen(json.c_str()) + 1); + char* membuffer = (char*)malloc(strsize); + strcpy(membuffer, json.c_str()); + //printf("allocated address: %p\n", membuffer); + + return membuffer; + } + + void freeJsonMem(char* ptr) + { + //printf("freeing address: %p\n", ptr); + free( ptr ); + } + + + char* recognizeArray(unsigned char* buf, int len) + { + //printf("Recognize byte array"); + //printf("buffer pointer: %p\n", buf); + //printf("buffer length: %d\n", len); + + + std::vector cvec(buf, buf+len); + + AlprResults results = nativeAlpr->recognize(cvec); + std::string json = Alpr::toJson(results); + + int strsize = sizeof(char) * (strlen(json.c_str()) + 1); + char* membuffer = (char*)malloc(strsize); + strcpy(membuffer, json.c_str()); + //printf("allocated address: %p\n", membuffer); + + return membuffer; + } + + void setDefaultRegion(char* cdefault_region) + { + // Convert strings from java to C++ and release resources + std::string default_region(cdefault_region); + + nativeAlpr->setDefaultRegion(default_region); + } + + void setDetectRegion(bool detect_region) + { + nativeAlpr->setDetectRegion(detect_region); + } + + void setTopN(int top_n) + { + nativeAlpr->setTopN(top_n); + } + + char* getVersion() + { + std::string version = nativeAlpr->getVersion(); + + int strsize = sizeof(char) * (strlen(version.c_str()) + 1); + char* membuffer = (char*)malloc(strsize); + strcpy(membuffer, version.c_str()); + //printf("allocated address: %p\n", membuffer); + + return membuffer; + } + + +} \ No newline at end of file diff --git a/bindings/python/test.py b/bindings/python/test.py new file mode 100644 index 0000000..9523632 --- /dev/null +++ b/bindings/python/test.py @@ -0,0 +1,40 @@ +from openalpr import Alpr + + +try: + alpr = Alpr("us", "/etc/openalpr/openalpr.conf", "/usr/share/openalpr/runtime_data") + + if not alpr.is_loaded(): + print("Error loading OpenALPR") + else: + print("Using OpenALPR " + alpr.get_version()) + + alpr.set_top_n(7) + alpr.set_default_region("wa") + alpr.set_detect_region(False) + jpeg_bytes = open("/storage/projects/alpr/samples/testing/car1.jpg", "rb").read() + results = alpr.recognize_array(jpeg_bytes) + + # Uncomment to see the full results structure + # import pprint + # pprint.pprint(results) + + print("Image size: %dx%d" %(results['img_width'], results['img_height'])) + print("Processing Time: %f" % results['processing_time_ms']) + + i = 0 + for plate in results['results']: + i += 1 + print("Plate #%d" % i) + print(" %12s %12s" % ("Plate", "Confidence")) + for candidate in plate['candidates']: + prefix = "-" + if candidate['matches_template']: + prefix = "*" + + print(" %s %12s%12f" % (prefix, candidate['plate'], candidate['confidence'])) + + + +finally: + alpr.unload() \ No newline at end of file