Adding hierarchical plate regions. The goal is to minimize unnecessary processing of regions within regions

This commit is contained in:
Matt Hill
2014-04-04 15:37:06 -05:00
parent e722f8a184
commit 59ffed9b23
5 changed files with 51 additions and 21 deletions

View File

@@ -150,7 +150,7 @@ int main( int argc, const char** argv )
string fullpath = inDir + "/" + files[i]; string fullpath = inDir + "/" + files[i];
frame = imread( fullpath.c_str() ); frame = imread( fullpath.c_str() );
vector<Rect> regions = plateDetector.detect(frame); vector<PlateRegion> regions = plateDetector.detect(frame);
imshow("Current LP", frame); imshow("Current LP", frame);
waitKey(5); waitKey(5);
@@ -200,7 +200,7 @@ int main( int argc, const char** argv )
endToEndTimes.push_back(endToEndTime); endToEndTimes.push_back(endToEndTime);
getTime(&startTime); getTime(&startTime);
vector<Rect> regions = plateDetector.detect(frame); vector<PlateRegion> regions = plateDetector.detect(frame);
getTime(&endTime); getTime(&endTime);
double regionDetectionTime = diffclock(startTime, endTime); double regionDetectionTime = diffclock(startTime, endTime);
@@ -211,14 +211,14 @@ int main( int argc, const char** argv )
{ {
getTime(&startTime); getTime(&startTime);
char temp[5]; char temp[5];
stateIdentifier.recognize(frame, regions[z], temp); stateIdentifier.recognize(frame, regions[z].rect, temp);
getTime(&endTime); getTime(&endTime);
double stateidTime = diffclock(startTime, endTime); double stateidTime = diffclock(startTime, endTime);
cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl; cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl;
stateIdTimes.push_back(stateidTime); stateIdTimes.push_back(stateidTime);
getTime(&startTime); getTime(&startTime);
LicensePlateCandidate lp(frame, regions[z], &config); LicensePlateCandidate lp(frame, regions[z].rect, &config);
lp.recognize(); lp.recognize();
getTime(&endTime); getTime(&endTime);
double analysisTime = diffclock(startTime, endTime); double analysisTime = diffclock(startTime, endTime);

View File

@@ -79,7 +79,7 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
// Find all the candidate regions // Find all the candidate regions
vector<Rect> plateRegions = plateDetector->detect(img); vector<PlateRegion> plateRegions = plateDetector->detect(img);
// 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;
@@ -120,7 +120,7 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
{ {
for (int i = 0; i < plateRegions.size(); i++) for (int i = 0; i < plateRegions.size(); i++)
{ {
rectangle(img, plateRegions[i], Scalar(0, 0, 255), 2); rectangle(img, plateRegions[i].rect, Scalar(0, 0, 255), 2);
} }
for (int i = 0; i < dispatcher.getRecognitionResults().size(); i++) for (int i = 0; i < dispatcher.getRecognitionResults().size(); i++)
@@ -137,8 +137,9 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
displayImage(config, "Main Image", img); displayImage(config, "Main Image", img);
// Pause indefinitely until they press a key // Pause indefinitely until they press a key
while ((char) cv::waitKey(50) == -1) cv::waitKey(1);
{} //while ((char) cv::waitKey(50) == -1)
// {}
} }
@@ -163,7 +164,7 @@ void plateAnalysisThread(void* arg)
cout << "Thread: " << tthread::this_thread::get_id() << " loop " << ++loop_count << endl; cout << "Thread: " << tthread::this_thread::get_id() << " loop " << ++loop_count << endl;
// Get a single plate region from the queue // Get a single plate region from the queue
Rect plateRegion = dispatcher->nextPlate(); PlateRegion plateRegion = dispatcher->nextPlate();
Mat img = dispatcher->getImageCopy(); Mat img = dispatcher->getImageCopy();
@@ -172,7 +173,7 @@ void plateAnalysisThread(void* arg)
timespec platestarttime; timespec platestarttime;
getTime(&platestarttime); getTime(&platestarttime);
LicensePlateCandidate lp(img, plateRegion, dispatcher->config); LicensePlateCandidate lp(img, plateRegion.rect, dispatcher->config);
lp.recognize(); lp.recognize();
@@ -192,7 +193,7 @@ void plateAnalysisThread(void* arg)
if (dispatcher->detectRegion) if (dispatcher->detectRegion)
{ {
char statecode[4]; char statecode[4];
plateResult.regionConfidence = dispatcher->stateIdentifier->recognize(img, plateRegion, statecode); plateResult.regionConfidence = dispatcher->stateIdentifier->recognize(img, plateRegion.rect, statecode);
if (plateResult.regionConfidence > 0) if (plateResult.regionConfidence > 0)
{ {
plateResult.region = statecode; plateResult.region = statecode;

View File

@@ -78,7 +78,7 @@ class AlprImpl
class PlateDispatcher class PlateDispatcher
{ {
public: public:
PlateDispatcher(vector<Rect> plateRegions, cv::Mat* image, PlateDispatcher(vector<PlateRegion> plateRegions, cv::Mat* image,
Config* config, Config* config,
StateIdentifier* stateIdentifier, StateIdentifier* stateIdentifier,
OCR* ocr, OCR* ocr,
@@ -113,11 +113,11 @@ class PlateDispatcher
mMutex.unlock(); mMutex.unlock();
return plateAvailable; return plateAvailable;
} }
Rect nextPlate() PlateRegion nextPlate()
{ {
tthread::lock_guard<tthread::mutex> guard(mMutex); tthread::lock_guard<tthread::mutex> guard(mMutex);
Rect plateRegion = plateRegions[plateRegions.size() - 1]; PlateRegion plateRegion = plateRegions[plateRegions.size() - 1];
plateRegions.pop_back(); plateRegions.pop_back();
return plateRegion; return plateRegion;
@@ -147,7 +147,7 @@ class PlateDispatcher
tthread::mutex mMutex; tthread::mutex mMutex;
cv::Mat* frame; cv::Mat* frame;
vector<Rect> plateRegions; vector<PlateRegion> plateRegions;
vector<AlprResult> recognitionResults; vector<AlprResult> recognitionResults;
}; };

View File

@@ -57,19 +57,19 @@ bool RegionDetector::isLoaded()
return this->loaded; return this->loaded;
} }
vector<Rect> RegionDetector::detect(Mat frame) vector<PlateRegion> RegionDetector::detect(Mat frame)
{ {
Mat frame_gray; Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY ); cvtColor( frame, frame_gray, CV_BGR2GRAY );
vector<Rect> regionsOfInterest = doCascade(frame_gray); vector<PlateRegion> regionsOfInterest = doCascade(frame_gray);
return regionsOfInterest; return regionsOfInterest;
} }
/** @function detectAndDisplay */ /** @function detectAndDisplay */
vector<Rect> RegionDetector::doCascade(Mat frame) vector<PlateRegion> RegionDetector::doCascade(Mat frame)
{ {
//float scale_factor = 1; //float scale_factor = 1;
int w = frame.size().width; int w = frame.size().width;
@@ -116,6 +116,28 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
plates[i].height = plates[i].height / scale_factor; plates[i].height = plates[i].height / scale_factor;
} }
return plates; vector<PlateRegion> orderedRegions = aggregateRegions(plates);
return orderedRegions;
} }
vector<PlateRegion> RegionDetector::aggregateRegions(vector<Rect> regions)
{
// Combines overlapping regions into a parent->child order.
// The largest regions will be parents, and they will have children if they are within them.
// This way, when processing regions later, we can process the parents first, and only delve into the children
// If there was no plate match. Otherwise, we would process everything and that would be wasteful.
vector<PlateRegion> orderedRegions;
// For now, just return a full list with no children, so I can get the plumbing sorted.
for (int i = 0; i < regions.size(); i++)
{
PlateRegion newRegion;
newRegion.rect = regions[i];
orderedRegions.push_back(newRegion);
}
return orderedRegions;
}

View File

@@ -33,6 +33,12 @@
#include "support/timing.h" #include "support/timing.h"
#include "constants.h" #include "constants.h"
struct PlateRegion
{
Rect rect;
vector<PlateRegion> children;
};
class RegionDetector class RegionDetector
{ {
@@ -41,7 +47,7 @@ class RegionDetector
virtual ~RegionDetector(); virtual ~RegionDetector();
bool isLoaded(); bool isLoaded();
vector<Rect> detect(Mat frame); vector<PlateRegion> detect(Mat frame);
private: private:
Config* config; Config* config;
@@ -51,8 +57,9 @@ class RegionDetector
bool loaded; bool loaded;
vector<Rect> doCascade(Mat frame); vector<PlateRegion> doCascade(Mat frame);
vector<PlateRegion> aggregateRegions(vector<Rect> regions);
}; };
#endif // REGIONDETECTOR_H #endif // REGIONDETECTOR_H