Merge branch 'v2.0'

This commit is contained in:
Matt Hill
2014-10-23 17:40:21 -04:00
10 changed files with 9332 additions and 94 deletions

View File

@@ -4,8 +4,8 @@ project(src)
cmake_minimum_required (VERSION 2.6) cmake_minimum_required (VERSION 2.6)
# Set the OpenALPR version in cmake, and also add it as a DEFINE for the code to access # Set the OpenALPR version in cmake, and also add it as a DEFINE for the code to access
SET(OPENALPR_MAJOR_VERSION "1") SET(OPENALPR_MAJOR_VERSION "2")
SET(OPENALPR_MINOR_VERSION "2") SET(OPENALPR_MINOR_VERSION "0")
SET(OPENALPR_PATCH_VERSION "0") SET(OPENALPR_PATCH_VERSION "0")
SET(OPENALPR_VERSION ${OPENALPR_MAJOR_VERSION}.${OPENALPR_MINOR_VERSION}.${OPENALPR_PATCH_VERSION}) SET(OPENALPR_VERSION ${OPENALPR_MAJOR_VERSION}.${OPENALPR_MINOR_VERSION}.${OPENALPR_PATCH_VERSION})
@@ -95,8 +95,7 @@ IF (WITH_DAEMON)
add_subdirectory(misc_utilities) add_subdirectory(misc_utilities)
ENDIF() ENDIF()
add_subdirectory(tests)
add_subdirectory(openalpr) add_subdirectory(openalpr)
add_subdirectory(video) add_subdirectory(video)

View File

@@ -266,8 +266,11 @@ void streamRecognitionThread(void* arg)
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
cv::imencode(".bmp", latestFrame, buffer );
std::vector<AlprResult> results = alpr.recognize(buffer); std::vector<AlprRegionOfInterest> 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; timespec endTime;
getTime(&endTime); getTime(&endTime);
@@ -278,7 +281,7 @@ void streamRecognitionThread(void* arg)
LOG4CPLUS_INFO(logger, "Camera " << tdata->camera_id << " processed frame in: " << totalProcessingTime << " ms."); 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(); long epoch_time = getEpochTime();
@@ -297,7 +300,7 @@ void streamRecognitionThread(void* arg)
// Update the JSON content to include UUID and camera ID // 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 *root = cJSON_Parse(json.c_str());
cJSON_AddStringToObject(root, "uuid", uuid.c_str()); cJSON_AddStringToObject(root, "uuid", uuid.c_str());
@@ -315,9 +318,9 @@ void streamRecognitionThread(void* arg)
free(out); free(out);
// Push the results to the Beanstalk queue // 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); writeToQueue(response);

View File

@@ -37,7 +37,6 @@ const std::string MAIN_WINDOW_NAME = "ALPR main window";
const bool SAVE_LAST_VIDEO_STILL = false; const bool SAVE_LAST_VIDEO_STILL = false;
const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg"; const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg";
std::string getJson(Alpr* alpr, std::vector<AlprResult> results);
/** Function Headers */ /** Function Headers */
bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson); bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson);
@@ -272,13 +271,14 @@ int main( int argc, const char** argv )
bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson) bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson)
{ {
std::vector<uchar> buffer;
cv::imencode(".bmp", frame, buffer );
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
std::vector<AlprResult> results = alpr->recognize(buffer); std::vector<AlprRegionOfInterest> 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; timespec endTime;
getTime(&endTime); getTime(&endTime);
@@ -289,23 +289,23 @@ bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJso
if (writeJson) if (writeJson)
{ {
std::cout << alpr->toJson(results, totalProcessingTime) << std::endl; std::cout << alpr->toJson( results ) << std::endl;
} }
else 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].topNPlates.size() << " results";
if (measureProcessingTime) 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; 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; std::cout << " - " << results.plates[i].topNPlates[k].characters << "\t confidence: " << results.plates[i].topNPlates[k].overall_confidence;
if (templateRegion.size() > 0) if (templateRegion.size() > 0)
std::cout << "\t template_match: " << results[i].topNPlates[k].matches_template; std::cout << "\t template_match: " << results.plates[i].topNPlates[k].matches_template;
std::cout << std::endl; std::cout << std::endl;
} }
@@ -314,6 +314,6 @@ bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJso
return results.size() > 0; return results.plates.size() > 0;
} }

View File

@@ -32,32 +32,40 @@ Alpr::~Alpr()
delete impl; delete impl;
} }
std::vector<AlprResult> 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<char> buffer(pos);
ifs.seekg(0, std::ios::beg);
ifs.read(&buffer[0], pos);
return this->recognize( buffer );
}
AlprResults Alpr::recognize(std::vector<char> imageBytes)
{ {
std::vector<AlprRegionOfInterest> regionsOfInterest; std::vector<AlprRegionOfInterest> regionsOfInterest;
return this->recognize(filepath, regionsOfInterest); return impl->recognize(imageBytes, regionsOfInterest);
} }
std::vector<AlprResult> Alpr::recognize(std::string filepath, std::vector<AlprRegionOfInterest> regionsOfInterest) AlprResults Alpr::recognize(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest)
{ {
return impl->recognize(filepath, regionsOfInterest); return impl->recognize(pixelData, bytesPerPixel, imgWidth, imgHeight, regionsOfInterest);
} }
std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer) std::string Alpr::toJson( AlprResults results )
{ {
std::vector<AlprRegionOfInterest> regionsOfInterest; return impl->toJson(results);
return this->recognize(imageBuffer, regionsOfInterest);
} }
std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer, std::vector<AlprRegionOfInterest> regionsOfInterest) AlprResults Alpr::fromJson(std::string json) {
{ return impl->fromJson(json);
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);
}
void Alpr::setDetectRegion(bool detectRegion) void Alpr::setDetectRegion(bool detectRegion)
{ {
@@ -84,12 +92,4 @@ std::string Alpr::getVersion()
return AlprImpl::getVersion(); return AlprImpl::getVersion();
} }
// Results code
AlprResult::AlprResult()
{
}
AlprResult::~AlprResult()
{
}

View File

@@ -22,7 +22,7 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <fstream>
struct AlprPlate struct AlprPlate
{ {
@@ -38,22 +38,31 @@ struct AlprCoordinate
int y; 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 x;
int y; int y;
int width; int width;
int height; int height;
}; };
class AlprResult class AlprPlateResult
{ {
public: public:
AlprResult(); AlprPlateResult() {};
virtual ~AlprResult(); virtual ~AlprPlateResult() {};
int requested_topn; int requested_topn;
int result_count;
AlprPlate bestPlate; AlprPlate bestPlate;
std::vector<AlprPlate> topNPlates; std::vector<AlprPlate> topNPlates;
@@ -65,6 +74,24 @@ class AlprResult
std::string region; 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<AlprPlateResult> plates;
std::vector<AlprRegionOfInterest> regionsOfInterest;
};
class AlprImpl; class AlprImpl;
class Alpr class Alpr
{ {
@@ -77,12 +104,18 @@ class Alpr
void setTopN(int topN); void setTopN(int topN);
void setDefaultRegion(std::string region); void setDefaultRegion(std::string region);
std::vector<AlprResult> recognize(std::string filepath); // Recognize from an image on disk
std::vector<AlprResult> recognize(std::string filepath, std::vector<AlprRegionOfInterest> regionsOfInterest); AlprResults recognize(std::string filepath);
std::vector<AlprResult> recognize(std::vector<unsigned char> imageBuffer);
std::vector<AlprResult> recognize(std::vector<unsigned char> imageBuffer, std::vector<AlprRegionOfInterest> regionsOfInterest); // Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
AlprResults recognize(std::vector<char> imageBytes);
// Recognize from raw pixel data.
AlprResults recognize(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest);
std::string toJson(const std::vector<AlprResult> results, double processing_time_ms = -1, long epoch_time = -1);
std::string toJson(const AlprResults results);
AlprResults fromJson(std::string json);
bool isLoaded(); bool isLoaded();

View File

@@ -83,19 +83,23 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
regionsOfInterest.push_back(cv::Rect(0, 0, img.cols, img.rows)); regionsOfInterest.push_back(cv::Rect(0, 0, img.cols, img.rows));
AlprFullDetails response; AlprFullDetails response;
response.results.epoch_time = getEpochTime();
response.results.img_width = img.cols;
response.results.img_height = img.rows;
for (uint i = 0; i < regionsOfInterest.size(); i++)
{
response.results.regionsOfInterest.push_back(AlprRegionOfInterest(regionsOfInterest[i].x, regionsOfInterest[i].y,
regionsOfInterest[i].width, regionsOfInterest[i].height));
}
if (!img.data) if (!img.data)
{ {
// Invalid image // Invalid image
if (this->config->debugGeneral) if (this->config->debugGeneral)
std::cerr << "Invalid image" << std::endl; std::cerr << "Invalid image" << std::endl;
vector<AlprResult> emptyVector;
response.results = emptyVector;
vector<PlateRegion> emptyVector2;
response.plateRegions = emptyVector2;
return response; return response;
} }
@@ -123,7 +127,7 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
bool plateDetected = false; bool plateDetected = false;
if (pipeline_data.plate_area_confidence > 10) if (pipeline_data.plate_area_confidence > 10)
{ {
AlprResult plateResult; AlprPlateResult plateResult;
plateResult.region = defaultRegion; plateResult.region = defaultRegion;
plateResult.regionConfidence = 0; plateResult.regionConfidence = 0;
@@ -171,7 +175,6 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
plateResult.topNPlates.push_back(aplate); plateResult.topNPlates.push_back(aplate);
} }
} }
plateResult.result_count = plateResult.topNPlates.size();
if (plateResult.topNPlates.size() > 0) if (plateResult.topNPlates.size() > 0)
plateResult.bestPlate = plateResult.topNPlates[bestPlateIndex]; plateResult.bestPlate = plateResult.topNPlates[bestPlateIndex];
@@ -180,10 +183,10 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
getTime(&plateEndTime); getTime(&plateEndTime);
plateResult.processing_time_ms = diffclock(platestarttime, plateEndTime); plateResult.processing_time_ms = diffclock(platestarttime, plateEndTime);
if (plateResult.result_count > 0) if (plateResult.topNPlates.size() > 0)
{ {
plateDetected = true; plateDetected = true;
response.results.push_back(plateResult); response.results.plates.push_back(plateResult);
} }
} }
@@ -202,11 +205,12 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
} }
timespec endTime;
getTime(&endTime);
response.results.total_processing_time_ms = diffclock(startTime, endTime);
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime;
getTime(&endTime);
cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << endl; cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << endl;
} }
@@ -217,11 +221,11 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
rectangle(img, response.plateRegions[i].rect, Scalar(0, 0, 255), 2); rectangle(img, response.plateRegions[i].rect, Scalar(0, 0, 255), 2);
} }
for (uint i = 0; i < response.results.size(); i++) for (uint i = 0; i < response.results.plates.size(); i++)
{ {
for (int z = 0; z < 4; z++) for (int z = 0; z < 4; z++)
{ {
AlprCoordinate* coords = response.results[i].plate_points; AlprCoordinate* coords = response.results.plates[i].plate_points;
Point p1(coords[z].x, coords[z].y); Point p1(coords[z].x, coords[z].y);
Point p2(coords[(z + 1) % 4].x, coords[(z + 1) % 4].y); Point p2(coords[(z + 1) % 4].x, coords[(z + 1) % 4].y);
line(img, p1, p2, Scalar(255,0,255), 2); line(img, p1, p2, Scalar(255,0,255), 2);
@@ -248,21 +252,32 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
} }
std::vector<AlprResult> AlprImpl::recognize(std::string filepath, std::vector<AlprRegionOfInterest> regionsOfInterest)
{ AlprResults AlprImpl::recognize( std::vector<char> imageBytes, std::vector<AlprRegionOfInterest> regionsOfInterest )
cv::Mat img = cv::imread(filepath, CV_LOAD_IMAGE_COLOR); {
cv::Mat img = cv::imdecode(cv::Mat(imageBytes), 1);
return this->recognize(img, this->convertRects(regionsOfInterest)); return this->recognize(img, this->convertRects(regionsOfInterest));
} }
std::vector<AlprResult> AlprImpl::recognize(std::vector<unsigned char> imageBuffer, std::vector<AlprRegionOfInterest> regionsOfInterest) AlprResults AlprImpl::recognize( unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> 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)); return this->recognize(img, this->convertRects(regionsOfInterest));
} }
std::vector<AlprResult> AlprImpl::recognize(cv::Mat img, std::vector<cv::Rect> regionsOfInterest) AlprResults AlprImpl::recognize(cv::Mat img, std::vector<cv::Rect> regionsOfInterest)
{ {
AlprFullDetails fullDetails = recognizeFullDetails(img, regionsOfInterest); AlprFullDetails fullDetails = recognizeFullDetails(img, regionsOfInterest);
@@ -281,26 +296,38 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img, std::vector<cv::Rect> r
return rectRegions; return rectRegions;
} }
string AlprImpl::toJson(const vector<AlprResult > results, double processing_time_ms, long epoch_time) string AlprImpl::toJson( const AlprResults results )
{ {
cJSON *root, *jsonResults; cJSON *root, *jsonResults;
root = cJSON_CreateObject(); 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 ); cJSON_AddNumberToObject(root,"version", 2 );
cJSON_AddNumberToObject(root,"img_width", results.img_width );
if (processing_time_ms >= 0) cJSON_AddNumberToObject(root,"img_height", results.img_height );
cJSON_AddNumberToObject(root,"processing_time_ms", results.total_processing_time_ms );
// Add the regions of interest to the JSON
cJSON *rois;
cJSON_AddItemToObject(root, "regions_of_interest", rois=cJSON_CreateArray());
for (uint i=0;i<results.regionsOfInterest.size();i++)
{ {
cJSON_AddNumberToObject(root,"processing_time_ms", processing_time_ms ); cJSON *roi_object;
roi_object = cJSON_CreateObject();
cJSON_AddNumberToObject(roi_object, "x", results.regionsOfInterest[i].x);
cJSON_AddNumberToObject(roi_object, "y", results.regionsOfInterest[i].y);
cJSON_AddNumberToObject(roi_object, "width", results.regionsOfInterest[i].width);
cJSON_AddNumberToObject(roi_object, "height", results.regionsOfInterest[i].height);
cJSON_AddItemToArray(rois, roi_object);
} }
cJSON_AddItemToObject(root, "results", jsonResults=cJSON_CreateArray()); 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); cJSON_AddItemToArray(jsonResults, resultObj);
} }
@@ -318,7 +345,7 @@ string AlprImpl::toJson(const vector<AlprResult > results, double processing_tim
cJSON* AlprImpl::createJsonObj(const AlprResult* result) cJSON* AlprImpl::createJsonObj(const AlprPlateResult* result)
{ {
cJSON *root, *coords, *candidates; cJSON *root, *coords, *candidates;
@@ -332,6 +359,7 @@ cJSON* AlprImpl::createJsonObj(const AlprResult* result)
cJSON_AddNumberToObject(root,"region_confidence", result->regionConfidence); cJSON_AddNumberToObject(root,"region_confidence", result->regionConfidence);
cJSON_AddNumberToObject(root,"processing_time_ms", result->processing_time_ms); cJSON_AddNumberToObject(root,"processing_time_ms", result->processing_time_ms);
cJSON_AddNumberToObject(root,"requested_topn", result->requested_topn);
cJSON_AddItemToObject(root, "coordinates", coords=cJSON_CreateArray()); cJSON_AddItemToObject(root, "coordinates", coords=cJSON_CreateArray());
for (int i=0;i<4;i++) for (int i=0;i<4;i++)
@@ -360,6 +388,81 @@ cJSON* AlprImpl::createJsonObj(const AlprResult* result)
return root; return root;
} }
AlprResults AlprImpl::fromJson(std::string json) {
AlprResults allResults;
cJSON* root = cJSON_Parse(json.c_str());
int version = cJSON_GetObjectItem(root, "version")->valueint;
allResults.epoch_time = (long) cJSON_GetObjectItem(root, "epoch_time")->valuedouble;
allResults.img_width = cJSON_GetObjectItem(root, "img_width")->valueint;
allResults.img_height = cJSON_GetObjectItem(root, "img_height")->valueint;
allResults.total_processing_time_ms = cJSON_GetObjectItem(root, "processing_time_ms")->valueint;
cJSON* rois = cJSON_GetObjectItem(root,"regions_of_interest");
int numRois = cJSON_GetArraySize(rois);
for (int c = 0; c < numRois; c++)
{
cJSON* roi = cJSON_GetArrayItem(rois, c);
int x = cJSON_GetObjectItem(roi, "x")->valueint;
int y = cJSON_GetObjectItem(roi, "y")->valueint;
int width = cJSON_GetObjectItem(roi, "width")->valueint;
int height = cJSON_GetObjectItem(roi, "height")->valueint;
AlprRegionOfInterest alprRegion(x,y,width,height);
allResults.regionsOfInterest.push_back(alprRegion);
}
cJSON* resultsArray = cJSON_GetObjectItem(root,"results");
int resultsSize = cJSON_GetArraySize(resultsArray);
for (int i = 0; i < resultsSize; i++)
{
cJSON* item = cJSON_GetArrayItem(resultsArray, i);
AlprPlateResult plate;
//plate.bestPlate = cJSON_GetObjectItem(item, "plate")->valuestring;
plate.processing_time_ms = cJSON_GetObjectItem(item, "processing_time_ms")->valuedouble;
plate.region = cJSON_GetObjectItem(item, "region")->valuestring;
plate.regionConfidence = cJSON_GetObjectItem(item, "region_confidence")->valueint;
plate.requested_topn = cJSON_GetObjectItem(item, "requested_topn")->valueint;
cJSON* coordinates = cJSON_GetObjectItem(item,"coordinates");
for (int c = 0; c < 4; c++)
{
cJSON* coordinate = cJSON_GetArrayItem(coordinates, c);
AlprCoordinate alprcoord;
alprcoord.x = cJSON_GetObjectItem(coordinate, "x")->valueint;
alprcoord.y = cJSON_GetObjectItem(coordinate, "y")->valueint;
plate.plate_points[c] = alprcoord;
}
cJSON* candidates = cJSON_GetObjectItem(item,"candidates");
int numCandidates = cJSON_GetArraySize(candidates);
for (int c = 0; c < numCandidates; c++)
{
cJSON* candidate = cJSON_GetArrayItem(candidates, c);
AlprPlate plateCandidate;
plateCandidate.characters = cJSON_GetObjectItem(candidate, "plate")->valuestring;
plateCandidate.overall_confidence = cJSON_GetObjectItem(candidate, "confidence")->valuedouble;
plateCandidate.matches_template = (cJSON_GetObjectItem(candidate, "matches_template")->valueint) != 0;
plate.topNPlates.push_back(plateCandidate);
}
allResults.plates.push_back(plate);
}
cJSON_Delete(root);
return allResults;
}
void AlprImpl::setDetectRegion(bool detectRegion) void AlprImpl::setDetectRegion(bool detectRegion)
{ {

View File

@@ -56,7 +56,7 @@
struct AlprFullDetails struct AlprFullDetails
{ {
std::vector<PlateRegion> plateRegions; std::vector<PlateRegion> plateRegions;
std::vector<AlprResult> results; AlprResults results;
}; };
class AlprImpl class AlprImpl
@@ -69,17 +69,18 @@ class AlprImpl
AlprFullDetails recognizeFullDetails(cv::Mat img); AlprFullDetails recognizeFullDetails(cv::Mat img);
AlprFullDetails recognizeFullDetails(cv::Mat img, std::vector<cv::Rect> regionsOfInterest); AlprFullDetails recognizeFullDetails(cv::Mat img, std::vector<cv::Rect> regionsOfInterest);
std::vector<AlprResult> recognize(std::string filepath, std::vector<AlprRegionOfInterest> regionsOfInterest); AlprResults recognize( std::vector<char> imageBytes, std::vector<AlprRegionOfInterest> regionsOfInterest );
std::vector<AlprResult> recognize(std::vector<unsigned char> imageBuffer, std::vector<AlprRegionOfInterest> regionsOfInterest); AlprResults recognize( unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest );
std::vector<AlprResult> recognize(cv::Mat img, std::vector<cv::Rect> regionsOfInterest); AlprResults recognize( cv::Mat img, std::vector<cv::Rect> regionsOfInterest );
void applyRegionTemplate(AlprResult* result, std::string region); void applyRegionTemplate(AlprPlateResult* result, std::string region);
void setDetectRegion(bool detectRegion); void setDetectRegion(bool detectRegion);
void setTopN(int topn); void setTopN(int topn);
void setDefaultRegion(std::string region); void setDefaultRegion(std::string region);
std::string toJson(const std::vector<AlprResult> results, double processing_time_ms = -1, long epoch_time = -1); std::string toJson( const AlprResults results );
AlprResults fromJson(std::string json);
static std::string getVersion(); static std::string getVersion();
Config* config; Config* config;
@@ -98,7 +99,7 @@ class AlprImpl
std::vector<cv::Rect> convertRects(std::vector<AlprRegionOfInterest> regionsOfInterest); std::vector<cv::Rect> convertRects(std::vector<AlprRegionOfInterest> regionsOfInterest);
cJSON* createJsonObj(const AlprResult* result); cJSON* createJsonObj(const AlprPlateResult* result);
}; };

11
src/tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,11 @@
enable_testing()
ADD_EXECUTABLE( unittests runtests.cpp )
TARGET_LINK_LIBRARIES(unittests
openalpr
)
add_test(unittests unittests)

8997
src/tests/catch.hpp Normal file

File diff suppressed because it is too large Load Diff

91
src/tests/runtests.cpp Normal file
View File

@@ -0,0 +1,91 @@
/*
* File: runtests.cpp
* Author: mhill
*
* Created on October 22, 2014, 11:11 PM
*/
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
#include <cstdlib>
#include "catch.hpp"
#include "alpr.h"
#include "support/timing.h"
using namespace std;
TEST_CASE( "JSON Serialization/Deserialization", "[json]" ) {
Alpr alpr("us");
AlprResults origResults;
origResults.epoch_time = getEpochTime();
origResults.img_width = 640;
origResults.img_height = 480;
origResults.total_processing_time_ms = 100;
origResults.regionsOfInterest.push_back(AlprRegionOfInterest(0,0,100,200));
origResults.regionsOfInterest.push_back(AlprRegionOfInterest(259,260,50,150));
AlprPlateResult apr;
for (int i = 0; i < 3; i++)
{
AlprPlate ap;
ap.characters = "abc";
ap.matches_template = i%2;
ap.overall_confidence = i * 10;
apr.topNPlates.push_back(ap);
}
apr.bestPlate = apr.topNPlates[0];
for (int i = 0; i < 4; i++)
{
AlprCoordinate ac;
ac.x = i;
ac.y = i;
apr.plate_points[i] = ac;
}
apr.processing_time_ms = 30;
apr.requested_topn = 10;
apr.region = "mo";
apr.regionConfidence = 80;
origResults.plates.push_back(apr);
std::string resultsJson = alpr.toJson(origResults);
AlprResults roundTrip = alpr.fromJson(resultsJson);
REQUIRE( roundTrip.epoch_time == origResults.epoch_time );
REQUIRE( roundTrip.img_width == origResults.img_width );
REQUIRE( roundTrip.img_height == origResults.img_height );
REQUIRE( roundTrip.total_processing_time_ms == origResults.total_processing_time_ms );
REQUIRE( roundTrip.regionsOfInterest.size() == origResults.regionsOfInterest.size() );
for (int i = 0; i < roundTrip.regionsOfInterest.size(); i++)
{
REQUIRE( roundTrip.regionsOfInterest[i].x == origResults.regionsOfInterest[i].x);
REQUIRE( roundTrip.regionsOfInterest[i].y == origResults.regionsOfInterest[i].y);
REQUIRE( roundTrip.regionsOfInterest[i].width == origResults.regionsOfInterest[i].width);
REQUIRE( roundTrip.regionsOfInterest[i].height == origResults.regionsOfInterest[i].height);
}
REQUIRE( roundTrip.plates.size() == origResults.plates.size() );
for (int i = 0; i < roundTrip.plates.size(); i++)
{
REQUIRE( roundTrip.plates[i].processing_time_ms == origResults.plates[i].processing_time_ms);
REQUIRE( roundTrip.plates[i].region == origResults.plates[i].region);
REQUIRE( roundTrip.plates[i].regionConfidence == origResults.plates[i].regionConfidence);
REQUIRE( roundTrip.plates[i].requested_topn == origResults.plates[i].requested_topn);
REQUIRE( roundTrip.plates[i].topNPlates.size() == origResults.plates[i].topNPlates.size());
for (int j = 0; j < roundTrip.plates[i].topNPlates.size(); j++)
{
REQUIRE( roundTrip.plates[i].topNPlates[j].characters == origResults.plates[i].topNPlates[j].characters);
REQUIRE( roundTrip.plates[i].topNPlates[j].matches_template == origResults.plates[i].topNPlates[j].matches_template);
REQUIRE( roundTrip.plates[i].topNPlates[j].overall_confidence == origResults.plates[i].topNPlates[j].overall_confidence);
}
}
}