From 396737bd3dec797d65ed3e92abebadb91a3076aa Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Sun, 5 Oct 2014 16:27:56 -0400 Subject: [PATCH] Cleaned up API. No longer backwards compatible --- src/daemon.cpp | 15 ++++++----- src/main.cpp | 27 +++++++++---------- src/openalpr/alpr.cpp | 45 ++++++++++++++------------------ src/openalpr/alpr.h | 53 +++++++++++++++++++++++++++++++------- src/openalpr/alpr_impl.cpp | 53 ++++++++++++++++++++------------------ src/openalpr/alpr_impl.h | 14 +++++----- 6 files changed, 121 insertions(+), 86 deletions(-) diff --git a/src/daemon.cpp b/src/daemon.cpp index 356b27b..0e58bf0 100644 --- a/src/daemon.cpp +++ b/src/daemon.cpp @@ -250,8 +250,11 @@ void streamRecognitionThread(void* arg) timespec startTime; getTime(&startTime); - cv::imencode(".bmp", latestFrame, buffer ); - std::vector results = alpr.recognize(buffer); + + std::vector regionsOfInterest; + regionsOfInterest.push_back(AlprRegionOfInterest(0,0, latestFrame.cols, latestFrame.rows)); + + AlprResults results = alpr.recognize(latestFrame.data, latestFrame.elemSize(), latestFrame.cols, latestFrame.rows, regionsOfInterest); timespec endTime; getTime(&endTime); @@ -262,7 +265,7 @@ void streamRecognitionThread(void* arg) LOG4CPLUS_INFO(logger, "Camera " << tdata->camera_id << " processed frame in: " << totalProcessingTime << " ms."); } - if (results.size() > 0) + if (results.plates.size() > 0) { long epoch_time = getEpochTime(); @@ -280,7 +283,7 @@ void streamRecognitionThread(void* arg) // Update the JSON content to include UUID and camera ID - std::string json = alpr.toJson(results, totalProcessingTime, epoch_time); + std::string json = alpr.toJson(results); cJSON *root = cJSON_Parse(json.c_str()); cJSON_AddStringToObject(root, "uuid", uuid.str().c_str()); @@ -298,9 +301,9 @@ void streamRecognitionThread(void* arg) free(out); // Push the results to the Beanstalk queue - for (int j = 0; j < results.size(); j++) + for (int j = 0; j < results.plates.size(); j++) { - LOG4CPLUS_DEBUG(logger, "Writing plate " << results[j].bestPlate.characters << " (" << uuid << ") to queue."); + LOG4CPLUS_DEBUG(logger, "Writing plate " << results.plates[j].bestPlate.characters << " (" << uuid << ") to queue."); } writeToQueue(response); diff --git a/src/main.cpp b/src/main.cpp index 556398e..e0d470c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,7 +37,7 @@ const std::string MAIN_WINDOW_NAME = "ALPR main window"; const bool SAVE_LAST_VIDEO_STILL = false; const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg"; -std::string getJson(Alpr* alpr, std::vector results); + /** Function Headers */ bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson); @@ -272,14 +272,15 @@ int main( int argc, const char** argv ) bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson) { - std::vector buffer; - cv::imencode(".bmp", frame, buffer ); timespec startTime; getTime(&startTime); - - std::vector results = alpr->recognize(buffer); - + + std::vector regionsOfInterest; + regionsOfInterest.push_back(AlprRegionOfInterest(0,0, frame.cols, frame.rows)); + + AlprResults results = alpr->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, regionsOfInterest ); + timespec endTime; getTime(&endTime); double totalProcessingTime = diffclock(startTime, endTime); @@ -289,27 +290,27 @@ bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJso if (writeJson) { - std::cout << alpr->toJson(results, totalProcessingTime) << std::endl; + std::cout << alpr->toJson( results ) << std::endl; } else { - for (int i = 0; i < results.size(); i++) + for (int i = 0; i < results.plates.size(); i++) { - std::cout << "plate" << i << ": " << results[i].result_count << " results"; + std::cout << "plate" << i << ": " << results.plates[i].result_count << " results"; if (measureProcessingTime) - std::cout << " -- Processing Time = " << results[i].processing_time_ms << "ms."; + std::cout << " -- Processing Time = " << results.plates[i].processing_time_ms << "ms."; std::cout << std::endl; - for (int k = 0; k < results[i].topNPlates.size(); k++) + for (int k = 0; k < results.plates[i].topNPlates.size(); k++) { - std::cout << " - " << results[i].topNPlates[k].characters << "\t confidence: " << results[i].topNPlates[k].overall_confidence << "\t template_match: " << results[i].topNPlates[k].matches_template << std::endl; + std::cout << " - " << results.plates[i].topNPlates[k].characters << "\t confidence: " << results.plates[i].topNPlates[k].overall_confidence << "\t template_match: " << results.plates[i].topNPlates[k].matches_template << std::endl; } } } - return results.size() > 0; + return results.plates.size() > 0; } diff --git a/src/openalpr/alpr.cpp b/src/openalpr/alpr.cpp index 4666114..9446e1c 100644 --- a/src/openalpr/alpr.cpp +++ b/src/openalpr/alpr.cpp @@ -32,31 +32,34 @@ Alpr::~Alpr() delete impl; } -std::vector Alpr::recognize(std::string filepath) +AlprResults Alpr::recognize(std::string filepath) +{ + + std::ifstream ifs(filepath.c_str(), std::ios::binary|std::ios::ate); + std::ifstream::pos_type pos = ifs.tellg(); + + std::vector buffer(pos); + + ifs.seekg(0, std::ios::beg); + ifs.read(&buffer[0], pos); + + return this->recognize( buffer ); +} + +AlprResults Alpr::recognize(std::vector imageBytes) { std::vector regionsOfInterest; - return this->recognize(filepath, regionsOfInterest); + return impl->recognize(imageBytes, regionsOfInterest); } -std::vector Alpr::recognize(std::string filepath, std::vector regionsOfInterest) +AlprResults Alpr::recognize(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector regionsOfInterest) { - return impl->recognize(filepath, regionsOfInterest); + return impl->recognize(pixelData, bytesPerPixel, imgWidth, imgHeight, regionsOfInterest); } -std::vector Alpr::recognize(std::vector imageBuffer) +std::string Alpr::toJson( AlprResults results ) { - std::vector regionsOfInterest; - return this->recognize(imageBuffer, regionsOfInterest); -} - -std::vector Alpr::recognize(std::vector imageBuffer, std::vector regionsOfInterest) -{ - return impl->recognize(imageBuffer, regionsOfInterest); -} - -std::string Alpr::toJson(const std::vector< AlprResult > results, double processing_time_ms, long epoch_time) -{ - return impl->toJson(results, processing_time_ms, epoch_time); + return impl->toJson(results); } void Alpr::setDetectRegion(bool detectRegion) @@ -84,12 +87,4 @@ std::string Alpr::getVersion() return AlprImpl::getVersion(); } -// Results code -AlprResult::AlprResult() -{ -} - -AlprResult::~AlprResult() -{ -} diff --git a/src/openalpr/alpr.h b/src/openalpr/alpr.h index 14feaa9..61d1a6e 100644 --- a/src/openalpr/alpr.h +++ b/src/openalpr/alpr.h @@ -22,7 +22,7 @@ #include #include - +#include struct AlprPlate { @@ -38,19 +38,29 @@ struct AlprCoordinate int y; }; -struct AlprRegionOfInterest +class AlprRegionOfInterest { +public: + AlprRegionOfInterest(); + AlprRegionOfInterest(int x, int y, int width, int height) + { + this->x = x; + this->y = y; + this->width = width; + this->height = height; + }; + int x; int y; int width; int height; }; -class AlprResult +class AlprPlateResult { public: - AlprResult(); - virtual ~AlprResult(); + AlprPlateResult() {}; + virtual ~AlprPlateResult() {}; int requested_topn; int result_count; @@ -65,6 +75,24 @@ class AlprResult std::string region; }; +class AlprResults +{ + public: + AlprResults() {}; + virtual ~AlprResults() {}; + + long epoch_time; + int img_width; + int img_height; + int total_processing_time_ms; + + std::vector plates; + + std::vector regionsOfInterest; + +}; + + class AlprImpl; class Alpr { @@ -77,12 +105,17 @@ class Alpr void setTopN(int topN); void setDefaultRegion(std::string region); - std::vector recognize(std::string filepath); - std::vector recognize(std::string filepath, std::vector regionsOfInterest); - std::vector recognize(std::vector imageBuffer); - std::vector recognize(std::vector imageBuffer, std::vector regionsOfInterest); + // Recognize from an image on disk + AlprResults recognize(std::string filepath); + + // Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). + AlprResults recognize(std::vector imageBytes); + + // Recognize from raw pixel data. + AlprResults recognize(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector regionsOfInterest); - std::string toJson(const std::vector results, double processing_time_ms = -1, long epoch_time = -1); + + std::string toJson(const AlprResults results); bool isLoaded(); diff --git a/src/openalpr/alpr_impl.cpp b/src/openalpr/alpr_impl.cpp index 1fd273b..1432bba 100644 --- a/src/openalpr/alpr_impl.cpp +++ b/src/openalpr/alpr_impl.cpp @@ -90,12 +90,6 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vectorconfig->debugGeneral) std::cerr << "Invalid image" << std::endl; - vector emptyVector; - response.results = emptyVector; - - vector emptyVector2; - response.plateRegions = emptyVector2; - return response; } @@ -123,7 +117,7 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector 10) { - AlprResult plateResult; + AlprPlateResult plateResult; plateResult.region = defaultRegion; plateResult.regionConfidence = 0; @@ -183,7 +177,7 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector 0) { plateDetected = true; - response.results.push_back(plateResult); + response.results.plates.push_back(plateResult); } } @@ -217,11 +211,11 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector AlprImpl::recognize(std::string filepath, std::vector regionsOfInterest) -{ - cv::Mat img = cv::imread(filepath, CV_LOAD_IMAGE_COLOR); + +AlprResults AlprImpl::recognize( std::vector imageBytes, std::vector regionsOfInterest ) +{ + cv::Mat img = cv::imdecode(cv::Mat(imageBytes), 1); return this->recognize(img, this->convertRects(regionsOfInterest)); } -std::vector AlprImpl::recognize(std::vector imageBuffer, std::vector regionsOfInterest) +AlprResults AlprImpl::recognize( unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector regionsOfInterest) { - cv::Mat img = cv::imdecode(cv::Mat(imageBuffer), 1); + + int arraySize = imgWidth * imgHeight * bytesPerPixel; + cv::Mat imgData = cv::Mat(arraySize, 1, CV_8U, pixelData); + cv::Mat img = imgData.reshape(bytesPerPixel, imgHeight); + + if (regionsOfInterest.size() == 0) + { + AlprRegionOfInterest fullFrame(0,0, img.cols, img.rows); + + regionsOfInterest.push_back(fullFrame); + } return this->recognize(img, this->convertRects(regionsOfInterest)); } -std::vector AlprImpl::recognize(cv::Mat img, std::vector regionsOfInterest) +AlprResults AlprImpl::recognize(cv::Mat img, std::vector regionsOfInterest) { AlprFullDetails fullDetails = recognizeFullDetails(img, regionsOfInterest); @@ -281,26 +286,24 @@ std::vector AlprImpl::recognize(cv::Mat img, std::vector r return rectRegions; } -string AlprImpl::toJson(const vector results, double processing_time_ms, long epoch_time) +string AlprImpl::toJson( const AlprResults results ) { cJSON *root, *jsonResults; root = cJSON_CreateObject(); - if (epoch_time <= 0) - epoch_time = getEpochTime(); - cJSON_AddNumberToObject(root,"epoch_time", epoch_time ); + cJSON_AddNumberToObject(root,"epoch_time", results.epoch_time ); cJSON_AddNumberToObject(root,"version", 2 ); - if (processing_time_ms >= 0) + if (results.total_processing_time_ms >= 0) { - cJSON_AddNumberToObject(root,"processing_time_ms", processing_time_ms ); + cJSON_AddNumberToObject(root,"processing_time_ms", results.total_processing_time_ms ); } cJSON_AddItemToObject(root, "results", jsonResults=cJSON_CreateArray()); - for (uint i = 0; i < results.size(); i++) + for (uint i = 0; i < results.plates.size(); i++) { - cJSON *resultObj = createJsonObj( &results[i] ); + cJSON *resultObj = createJsonObj( &results.plates[i] ); cJSON_AddItemToArray(jsonResults, resultObj); } @@ -318,7 +321,7 @@ string AlprImpl::toJson(const vector results, double processing_tim -cJSON* AlprImpl::createJsonObj(const AlprResult* result) +cJSON* AlprImpl::createJsonObj(const AlprPlateResult* result) { cJSON *root, *coords, *candidates; diff --git a/src/openalpr/alpr_impl.h b/src/openalpr/alpr_impl.h index 598ce11..6886db8 100644 --- a/src/openalpr/alpr_impl.h +++ b/src/openalpr/alpr_impl.h @@ -56,7 +56,7 @@ struct AlprFullDetails { std::vector plateRegions; - std::vector results; + AlprResults results; }; class AlprImpl @@ -69,17 +69,17 @@ class AlprImpl AlprFullDetails recognizeFullDetails(cv::Mat img); AlprFullDetails recognizeFullDetails(cv::Mat img, std::vector regionsOfInterest); - std::vector recognize(std::string filepath, std::vector regionsOfInterest); - std::vector recognize(std::vector imageBuffer, std::vector regionsOfInterest); - std::vector recognize(cv::Mat img, std::vector regionsOfInterest); + AlprResults recognize( std::vector imageBytes, std::vector regionsOfInterest ); + AlprResults recognize( unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector regionsOfInterest ); + AlprResults recognize( cv::Mat img, std::vector regionsOfInterest ); - void applyRegionTemplate(AlprResult* result, std::string region); + void applyRegionTemplate(AlprPlateResult* result, std::string region); void setDetectRegion(bool detectRegion); void setTopN(int topn); void setDefaultRegion(std::string region); - std::string toJson(const std::vector results, double processing_time_ms = -1, long epoch_time = -1); + std::string toJson( const AlprResults results ); static std::string getVersion(); Config* config; @@ -98,7 +98,7 @@ class AlprImpl std::vector convertRects(std::vector regionsOfInterest); - cJSON* createJsonObj(const AlprResult* result); + cJSON* createJsonObj(const AlprPlateResult* result); };