Cleaned up API. No longer backwards compatible

This commit is contained in:
Matt Hill
2014-10-05 16:27:56 -04:00
parent fa96f53dbf
commit 396737bd3d
6 changed files with 121 additions and 86 deletions

View File

@@ -250,8 +250,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);
@@ -262,7 +265,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();
@@ -280,7 +283,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.str().c_str()); cJSON_AddStringToObject(root, "uuid", uuid.str().c_str());
@@ -298,9 +301,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,7 @@ 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,14 +272,15 @@ 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);
double totalProcessingTime = diffclock(startTime, endTime); double totalProcessingTime = diffclock(startTime, endTime);
@@ -289,27 +290,27 @@ 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].result_count << " 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 << "\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;
} }

View File

@@ -32,31 +32,34 @@ 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)
{
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 +87,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,19 +38,29 @@ 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; int result_count;
@@ -65,6 +75,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 +105,17 @@ 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);
bool isLoaded(); bool isLoaded();

View File

@@ -90,12 +90,6 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
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 +117,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;
@@ -183,7 +177,7 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
if (plateResult.result_count > 0) if (plateResult.result_count > 0)
{ {
plateDetected = true; 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<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 +242,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 +286,24 @@ 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 );
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()); 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 +321,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;

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,17 @@ 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 );
static std::string getVersion(); static std::string getVersion();
Config* config; Config* config;
@@ -98,7 +98,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);
}; };