mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-06 16:27:07 +08:00
Merge branch 'v2.0'
This commit is contained in:
@@ -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)
|
||||||
|
@@ -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);
|
||||||
|
24
src/main.cpp
24
src/main.cpp
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
@@ -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);
|
|
||||||
|
|
||||||
std::string toJson(const std::vector<AlprResult> results, double processing_time_ms = -1, long epoch_time = -1);
|
// 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 AlprResults results);
|
||||||
|
AlprResults fromJson(std::string json);
|
||||||
|
|
||||||
bool isLoaded();
|
bool isLoaded();
|
||||||
|
|
||||||
|
@@ -84,18 +84,22 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect
|
|||||||
|
|
||||||
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 );
|
||||||
|
cJSON_AddNumberToObject(root,"img_height", results.img_height );
|
||||||
|
cJSON_AddNumberToObject(root,"processing_time_ms", results.total_processing_time_ms );
|
||||||
|
|
||||||
if (processing_time_ms >= 0)
|
// 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)
|
||||||
{
|
{
|
||||||
|
@@ -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
11
src/tests/CMakeLists.txt
Normal 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
8997
src/tests/catch.hpp
Normal file
File diff suppressed because it is too large
Load Diff
91
src/tests/runtests.cpp
Normal file
91
src/tests/runtests.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user