mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-06 14:16:49 +08:00
Adding hierarchical plate regions. The goal is to minimize unnecessary processing of regions within regions
This commit is contained in:
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user