Added regions of interest to ALPR interface. Currently non-functional

This commit is contained in:
Matt Hill
2014-08-18 23:23:03 -04:00
parent d76f122ad6
commit aac6d61773
10 changed files with 102 additions and 24 deletions

View File

@@ -243,7 +243,8 @@ void streamRecognitionThread(void* arg)
while (daemon_active) while (daemon_active)
{ {
int response = videoBuffer.getLatestFrame(&latestFrame); std::vector<cv::Rect> regionsOfInterest;
int response = videoBuffer.getLatestFrame(&latestFrame, regionsOfInterest);
if (response != -1) if (response != -1)
{ {

View File

@@ -170,7 +170,8 @@ int main( int argc, const char** argv )
while (program_active) while (program_active)
{ {
int response = videoBuffer.getLatestFrame(&latestFrame); std::vector<cv::Rect> regionsOfInterest;
int response = videoBuffer.getLatestFrame(&latestFrame, regionsOfInterest);
if (response != -1) if (response != -1)
{ {

View File

@@ -34,16 +34,24 @@ Alpr::~Alpr()
std::vector<AlprResult> Alpr::recognize(std::string filepath) std::vector<AlprResult> Alpr::recognize(std::string filepath)
{ {
cv::Mat img = cv::imread(filepath, CV_LOAD_IMAGE_COLOR); std::vector<AlprRegionOfInterest> regionsOfInterest;
return impl->recognize(img); return this->recognize(filepath, regionsOfInterest);
}
std::vector<AlprResult> Alpr::recognize(std::string filepath, std::vector<AlprRegionOfInterest> regionsOfInterest)
{
return impl->recognize(filepath, regionsOfInterest);
} }
std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer) std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer)
{ {
// Not sure if this actually works std::vector<AlprRegionOfInterest> regionsOfInterest;
cv::Mat img = cv::imdecode(cv::Mat(imageBuffer), 1); return this->recognize(imageBuffer, regionsOfInterest);
}
return impl->recognize(img); 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) std::string Alpr::toJson(const std::vector< AlprResult > results, double processing_time_ms)

View File

@@ -39,6 +39,14 @@ struct AlprCoordinate
int y; int y;
}; };
struct AlprRegionOfInterest
{
int x;
int y;
int width;
int height;
};
class AlprResult class AlprResult
{ {
public: public:
@@ -71,7 +79,9 @@ class Alpr
void setDefaultRegion(std::string region); void setDefaultRegion(std::string region);
std::vector<AlprResult> recognize(std::string filepath); std::vector<AlprResult> recognize(std::string filepath);
std::vector<AlprResult> recognize(std::string filepath, std::vector<AlprRegionOfInterest> regionsOfInterest);
std::vector<AlprResult> recognize(std::vector<unsigned char> imageBuffer); 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); std::string toJson(const std::vector<AlprResult> results, double processing_time_ms = -1);

View File

@@ -67,10 +67,21 @@ bool AlprImpl::isLoaded()
} }
AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img) AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img)
{
std::vector<cv::Rect> regionsOfInterest;
regionsOfInterest.push_back(cv::Rect(0, 0, img.cols, img.rows));
return this->recognizeFullDetails(img, regionsOfInterest);
}
AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector<cv::Rect> regionsOfInterest)
{ {
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
if (regionsOfInterest.size() == 0)
regionsOfInterest.push_back(cv::Rect(0, 0, img.cols, img.rows));
AlprFullDetails response; AlprFullDetails response;
if (!img.data) if (!img.data)
@@ -89,7 +100,7 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img)
} }
// Find all the candidate regions // Find all the candidate regions
response.plateRegions = plateDetector->detect(img); response.plateRegions = plateDetector->detect(img, regionsOfInterest);
// Get the number of threads specified and make sure the value is sane (cannot be greater than CPU cores or less than 1) // Get the number of threads specified and make sure the value is sane (cannot be greater than CPU cores or less than 1)
int numThreads = config->multithreading_cores; int numThreads = config->multithreading_cores;
@@ -165,12 +176,27 @@ AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img)
return response; return response;
} }
std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
std::vector<AlprResult> AlprImpl::recognize(std::string filepath, std::vector<AlprRegionOfInterest> regionsOfInterest)
{ {
AlprFullDetails fullDetails = recognizeFullDetails(img); cv::Mat img = cv::imread(filepath, CV_LOAD_IMAGE_COLOR);
return fullDetails.results;
return this->recognize(img, this->convertRects(regionsOfInterest));
} }
std::vector<AlprResult> AlprImpl::recognize(std::vector<unsigned char> imageBuffer, std::vector<AlprRegionOfInterest> regionsOfInterest)
{
cv::Mat img = cv::imdecode(cv::Mat(imageBuffer), 1);
return this->recognize(img, this->convertRects(regionsOfInterest));
}
std::vector<AlprResult> AlprImpl::recognize(cv::Mat img, std::vector<cv::Rect> regionsOfInterest)
{
AlprFullDetails fullDetails = recognizeFullDetails(img, regionsOfInterest);
return fullDetails.results;
}
void plateAnalysisThread(void* arg) void plateAnalysisThread(void* arg)
{ {
PlateDispatcher* dispatcher = (PlateDispatcher*) arg; PlateDispatcher* dispatcher = (PlateDispatcher*) arg;
@@ -292,6 +318,17 @@ void plateAnalysisThread(void* arg)
cout << "Thread: " << tthread::this_thread::get_id() << " Complete" << endl; cout << "Thread: " << tthread::this_thread::get_id() << " Complete" << endl;
} }
std::vector<cv::Rect> AlprImpl::convertRects(std::vector<AlprRegionOfInterest> regionsOfInterest)
{
std::vector<cv::Rect> rectRegions;
for (int i = 0; i < regionsOfInterest.size(); i++)
{
rectRegions.push_back(cv::Rect(regionsOfInterest[i].x, regionsOfInterest[i].y, regionsOfInterest[i].width, regionsOfInterest[i].height));
}
return rectRegions;
}
string AlprImpl::toJson(const vector< AlprResult > results, double processing_time_ms) string AlprImpl::toJson(const vector< AlprResult > results, double processing_time_ms)
{ {
cJSON *root, *jsonResults; cJSON *root, *jsonResults;

View File

@@ -64,7 +64,11 @@ class AlprImpl
virtual ~AlprImpl(); virtual ~AlprImpl();
AlprFullDetails recognizeFullDetails(cv::Mat img); AlprFullDetails recognizeFullDetails(cv::Mat img);
std::vector<AlprResult> recognize(cv::Mat img); AlprFullDetails recognizeFullDetails(cv::Mat img, std::vector<cv::Rect> regionsOfInterest);
std::vector<AlprResult> recognize(std::string filepath, std::vector<AlprRegionOfInterest> regionsOfInterest);
std::vector<AlprResult> recognize(std::vector<unsigned char> imageBuffer, std::vector<AlprRegionOfInterest> regionsOfInterest);
std::vector<AlprResult> recognize(cv::Mat img, std::vector<cv::Rect> regionsOfInterest);
void applyRegionTemplate(AlprResult* result, std::string region); void applyRegionTemplate(AlprResult* result, std::string region);
@@ -89,6 +93,8 @@ class AlprImpl
bool detectRegion; bool detectRegion;
std::string defaultRegion; std::string defaultRegion;
std::vector<cv::Rect> convertRects(std::vector<AlprRegionOfInterest> regionsOfInterest);
cJSON* createJsonObj(const AlprResult* result); cJSON* createJsonObj(const AlprResult* result);
}; };

View File

@@ -53,19 +53,18 @@ bool RegionDetector::isLoaded()
return this->loaded; return this->loaded;
} }
vector<PlateRegion> RegionDetector::detect(Mat frame) vector<PlateRegion> RegionDetector::detect(Mat frame, std::vector<cv::Rect> regionsOfInterest)
{ {
Mat frame_gray; Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY ); cvtColor( frame, frame_gray, CV_BGR2GRAY );
vector<PlateRegion> regionsOfInterest = doCascade(frame_gray); vector<PlateRegion> detectedRegions = doCascade(frame_gray, regionsOfInterest);
return regionsOfInterest; return detectedRegions;
} }
/** @function detectAndDisplay */ vector<PlateRegion> RegionDetector::doCascade(Mat frame, std::vector<cv::Rect> regionsOfInterest)
vector<PlateRegion> RegionDetector::doCascade(Mat frame)
{ {

View File

@@ -46,7 +46,7 @@ class RegionDetector
virtual ~RegionDetector(); virtual ~RegionDetector();
bool isLoaded(); bool isLoaded();
std::vector<PlateRegion> detect(cv::Mat frame); std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
private: private:
Config* config; Config* config;
@@ -56,7 +56,7 @@ class RegionDetector
bool loaded; bool loaded;
std::vector<PlateRegion> doCascade(cv::Mat frame); std::vector<PlateRegion> doCascade(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
std::vector<PlateRegion> aggregateRegions(std::vector<cv::Rect> regions); std::vector<PlateRegion> aggregateRegions(std::vector<cv::Rect> regions);
}; };

View File

@@ -72,12 +72,12 @@ void VideoBuffer::connect(std::string mjpeg_url, int fps)
} }
int VideoBuffer::getLatestFrame(cv::Mat* frame) int VideoBuffer::getLatestFrame(cv::Mat* frame, std::vector<cv::Rect>& regionsOfInterest)
{ {
if (dispatcher == NULL) if (dispatcher == NULL)
return -1; return -1;
return dispatcher->getLatestFrame(frame); return dispatcher->getLatestFrame(frame, regionsOfInterest);
} }

View File

@@ -25,7 +25,7 @@ class VideoDispatcher
} }
int getLatestFrame(cv::Mat* frame) int getLatestFrame(cv::Mat* frame, std::vector<cv::Rect>& regionsOfInterest)
{ {
tthread::lock_guard<tthread::mutex> guard(mMutex); tthread::lock_guard<tthread::mutex> guard(mMutex);
@@ -37,6 +37,10 @@ class VideoDispatcher
this->lastFrameRead = this->latestFrameNumber; this->lastFrameRead = this->latestFrameNumber;
// Copy the regionsOfInterest array
for (int i = 0; i < this->latestRegionsOfInterest.size(); i++)
regionsOfInterest.push_back(this->latestRegionsOfInterest[i]);
return this->lastFrameRead; return this->lastFrameRead;
} }
@@ -44,6 +48,7 @@ class VideoDispatcher
{ {
//tthread::lock_guard<tthread::mutex> guard(mMutex); //tthread::lock_guard<tthread::mutex> guard(mMutex);
this->latestFrame = frame; this->latestFrame = frame;
this->latestRegionsOfInterest = calculateRegionsOfInterest(frame);
this->latestFrameNumber++; this->latestFrameNumber++;
} }
@@ -57,6 +62,16 @@ class VideoDispatcher
std::cerr << error << std::endl; std::cerr << error << std::endl;
} }
std::vector<cv::Rect> calculateRegionsOfInterest(cv::Mat* frame)
{
cv::Rect rect(0, 0, frame->cols, frame->rows);
std::vector<cv::Rect> rois;
rois.push_back(rect);
return rois;
}
bool active; bool active;
int latestFrameNumber; int latestFrameNumber;
@@ -68,7 +83,7 @@ class VideoDispatcher
private: private:
cv::Mat* latestFrame; cv::Mat* latestFrame;
std::vector<cv::Rect> latestRegionsOfInterest;
}; };
class VideoBuffer class VideoBuffer
@@ -83,7 +98,8 @@ class VideoBuffer
// If a new frame is available, the function sets "frame" to it and returns the frame number // If a new frame is available, the function sets "frame" to it and returns the frame number
// If no frames are available, or the latest has already been grabbed, returns -1. // If no frames are available, or the latest has already been grabbed, returns -1.
int getLatestFrame(cv::Mat* frame); // regionsOfInterest is set to a list of good regions to check for license plates. Default is one rectangle for the entire frame.
int getLatestFrame(cv::Mat* frame, std::vector<cv::Rect>& regionsOfInterest);
void disconnect(); void disconnect();