mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-06 17:07:39 +08:00
Added pipeline_data to character analaysis and character segmentation
This commit is contained in:
@@ -104,6 +104,8 @@ int main( int argc, const char** argv )
|
|||||||
plateCoords.y = 0;
|
plateCoords.y = 0;
|
||||||
plateCoords.width = frame.cols;
|
plateCoords.width = frame.cols;
|
||||||
plateCoords.height = frame.rows;
|
plateCoords.height = frame.rows;
|
||||||
|
|
||||||
|
PipelineData pipeline_data(frame, plateCoords, config);
|
||||||
|
|
||||||
char statecode[3];
|
char statecode[3];
|
||||||
statecode[0] = files[i][0];
|
statecode[0] = files[i][0];
|
||||||
@@ -111,7 +113,7 @@ int main( int argc, const char** argv )
|
|||||||
statecode[2] = '\0';
|
statecode[2] = '\0';
|
||||||
string statecodestr(statecode);
|
string statecodestr(statecode);
|
||||||
|
|
||||||
CharacterRegion charRegion(frame, config);
|
CharacterRegion charRegion(&pipeline_data);
|
||||||
|
|
||||||
if (abs(charRegion.getTopLine().angle) > 4)
|
if (abs(charRegion.getTopLine().angle) > 4)
|
||||||
{
|
{
|
||||||
@@ -124,9 +126,10 @@ int main( int argc, const char** argv )
|
|||||||
warpAffine( frame, rotated, rot_mat, frame.size() );
|
warpAffine( frame, rotated, rot_mat, frame.size() );
|
||||||
|
|
||||||
rotated.copyTo(frame);
|
rotated.copyTo(frame);
|
||||||
|
pipeline_data.crop_gray = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharacterSegmenter charSegmenter(frame, charRegion.thresholdsInverted(), config);
|
CharacterSegmenter charSegmenter(&pipeline_data);
|
||||||
ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters);
|
ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters);
|
||||||
ocr->postProcessor->analyze(statecode, 25);
|
ocr->postProcessor->analyze(statecode, 25);
|
||||||
|
|
||||||
|
@@ -124,13 +124,14 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
imshow ("Original", frame);
|
imshow ("Original", frame);
|
||||||
|
|
||||||
|
PipelineData pipeline_data(frame, Rect(0, 0, frame.cols, frame.rows), &config);
|
||||||
char statecode[3];
|
char statecode[3];
|
||||||
statecode[0] = files[i][0];
|
statecode[0] = files[i][0];
|
||||||
statecode[1] = files[i][1];
|
statecode[1] = files[i][1];
|
||||||
statecode[2] = '\0';
|
statecode[2] = '\0';
|
||||||
string statecodestr(statecode);
|
string statecodestr(statecode);
|
||||||
|
|
||||||
CharacterRegion regionizer(frame, &config);
|
CharacterRegion regionizer(&pipeline_data);
|
||||||
|
|
||||||
if (abs(regionizer.getTopLine().angle) > 4)
|
if (abs(regionizer.getTopLine().angle) > 4)
|
||||||
{
|
{
|
||||||
@@ -143,9 +144,10 @@ int main( int argc, const char** argv )
|
|||||||
warpAffine( frame, rotated, rot_mat, frame.size() );
|
warpAffine( frame, rotated, rot_mat, frame.size() );
|
||||||
|
|
||||||
rotated.copyTo(frame);
|
rotated.copyTo(frame);
|
||||||
|
pipeline_data.crop_gray = rotated;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharacterSegmenter charSegmenter(frame, regionizer.thresholdsInverted(), &config);
|
CharacterSegmenter charSegmenter(&pipeline_data);
|
||||||
|
|
||||||
//ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters);
|
//ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters);
|
||||||
|
|
||||||
|
@@ -213,8 +213,8 @@ void plateAnalysisThread(void* arg)
|
|||||||
|
|
||||||
for (int pointidx = 0; pointidx < 4; pointidx++)
|
for (int pointidx = 0; pointidx < 4; pointidx++)
|
||||||
{
|
{
|
||||||
plateResult.plate_points[pointidx].x = (int) lp.plateCorners[pointidx].x;
|
plateResult.plate_points[pointidx].x = (int) pipeline_data.plate_corners[pointidx].x;
|
||||||
plateResult.plate_points[pointidx].y = (int) lp.plateCorners[pointidx].y;
|
plateResult.plate_points[pointidx].y = (int) pipeline_data.plate_corners[pointidx].y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dispatcher->detectRegion)
|
if (dispatcher->detectRegion)
|
||||||
|
@@ -22,22 +22,16 @@
|
|||||||
using namespace cv;
|
using namespace cv;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CharacterAnalysis::CharacterAnalysis(Mat img, Config* config)
|
CharacterAnalysis::CharacterAnalysis(PipelineData* pipeline_data)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->pipeline_data = pipeline_data;
|
||||||
|
this->config = pipeline_data->config;
|
||||||
|
|
||||||
this->hasPlateMask = false;
|
this->hasPlateMask = false;
|
||||||
|
|
||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
cout << "Starting CharacterAnalysis identification" << endl;
|
cout << "Starting CharacterAnalysis identification" << endl;
|
||||||
|
|
||||||
if (img.type() != CV_8U)
|
|
||||||
cvtColor( img, this->img_gray, CV_BGR2GRAY );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
img_gray = Mat(img.size(), img.type());
|
|
||||||
img.copyTo(img_gray);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CharacterAnalysis::~CharacterAnalysis()
|
CharacterAnalysis::~CharacterAnalysis()
|
||||||
@@ -51,21 +45,9 @@ CharacterAnalysis::~CharacterAnalysis()
|
|||||||
|
|
||||||
void CharacterAnalysis::analyze()
|
void CharacterAnalysis::analyze()
|
||||||
{
|
{
|
||||||
thresholds = produceThresholds(img_gray, config);
|
thresholds = produceThresholds(pipeline_data->crop_gray, config);
|
||||||
|
|
||||||
/*
|
|
||||||
// Morph Close the gray image to make it easier to detect blobs
|
|
||||||
int morph_elem = 1;
|
|
||||||
int morph_size = 1;
|
|
||||||
Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
|
||||||
|
|
||||||
for (int i = 0; i < thresholds.size(); i++)
|
|
||||||
{
|
|
||||||
//morphologyEx( mask, mask, MORPH_CLOSE, element );
|
|
||||||
morphologyEx( thresholds[i], thresholds[i], MORPH_OPEN, element );
|
|
||||||
//dilate( thresholds[i], thresholds[i], element );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
@@ -181,7 +163,7 @@ void CharacterAnalysis::analyze()
|
|||||||
|
|
||||||
//charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP));
|
//charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP));
|
||||||
|
|
||||||
this->linePolygon = getBestVotedLines(img_gray, bestContours, bestCharSegments);
|
this->linePolygon = getBestVotedLines(pipeline_data->crop_gray, bestContours, bestCharSegments);
|
||||||
|
|
||||||
if (this->linePolygon.size() > 0)
|
if (this->linePolygon.size() > 0)
|
||||||
{
|
{
|
||||||
|
@@ -24,13 +24,13 @@
|
|||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "pipeline_data.h"
|
||||||
|
|
||||||
class CharacterAnalysis
|
class CharacterAnalysis
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CharacterAnalysis(cv::Mat img, Config* config);
|
CharacterAnalysis(PipelineData* pipeline_data);
|
||||||
virtual ~CharacterAnalysis();
|
virtual ~CharacterAnalysis();
|
||||||
|
|
||||||
bool hasPlateMask;
|
bool hasPlateMask;
|
||||||
@@ -64,10 +64,9 @@ class CharacterAnalysis
|
|||||||
cv::Mat getCharacterMask();
|
cv::Mat getCharacterMask();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PipelineData* pipeline_data;
|
||||||
Config* config;
|
Config* config;
|
||||||
|
|
||||||
cv::Mat img_gray;
|
|
||||||
|
|
||||||
cv::Mat findOuterBoxMask( );
|
cv::Mat findOuterBoxMask( );
|
||||||
|
|
||||||
bool isPlateInverted();
|
bool isPlateInverted();
|
||||||
|
@@ -22,9 +22,9 @@
|
|||||||
using namespace cv;
|
using namespace cv;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CharacterRegion::CharacterRegion(Mat img, Config* config)
|
CharacterRegion::CharacterRegion(PipelineData* pipeline_data)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = pipeline_data->config;
|
||||||
this->debug = config->debugCharRegions;
|
this->debug = config->debugCharRegions;
|
||||||
|
|
||||||
this->confidence = 0;
|
this->confidence = 0;
|
||||||
@@ -35,8 +35,10 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
|||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
charAnalysis = new CharacterAnalysis(img, config);
|
charAnalysis = new CharacterAnalysis(pipeline_data);
|
||||||
charAnalysis->analyze();
|
charAnalysis->analyze();
|
||||||
|
pipeline_data->plate_inverted = charAnalysis->thresholdsInverted;
|
||||||
|
pipeline_data->plate_mask = charAnalysis->plateMask;
|
||||||
|
|
||||||
if (this->debug && charAnalysis->linePolygon.size() > 0)
|
if (this->debug && charAnalysis->linePolygon.size() > 0)
|
||||||
{
|
{
|
||||||
@@ -100,10 +102,6 @@ CharacterRegion::~CharacterRegion()
|
|||||||
delete(charAnalysis);
|
delete(charAnalysis);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat CharacterRegion::getPlateMask()
|
|
||||||
{
|
|
||||||
return charAnalysis->plateMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
LineSegment CharacterRegion::getTopLine()
|
LineSegment CharacterRegion::getTopLine()
|
||||||
{
|
{
|
||||||
@@ -140,7 +138,3 @@ LineSegment CharacterRegion::getCharBoxRight()
|
|||||||
return charAnalysis->charBoxRight;
|
return charAnalysis->charBoxRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterRegion::thresholdsInverted()
|
|
||||||
{
|
|
||||||
return charAnalysis->thresholdsInverted;
|
|
||||||
}
|
|
||||||
|
@@ -25,23 +25,21 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "characteranalysis.h"
|
#include "characteranalysis.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "pipeline_data.h"
|
||||||
|
|
||||||
class CharacterRegion
|
class CharacterRegion
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CharacterRegion(cv::Mat img, Config* config);
|
CharacterRegion(PipelineData* pipeline_data);
|
||||||
virtual ~CharacterRegion();
|
virtual ~CharacterRegion();
|
||||||
|
|
||||||
CharacterAnalysis *charAnalysis;
|
CharacterAnalysis *charAnalysis;
|
||||||
|
|
||||||
int confidence;
|
int confidence;
|
||||||
cv::Mat getPlateMask();
|
|
||||||
|
|
||||||
LineSegment getTopLine();
|
LineSegment getTopLine();
|
||||||
LineSegment getBottomLine();
|
LineSegment getBottomLine();
|
||||||
//vector<Point> getLinePolygon();
|
|
||||||
std::vector<cv::Point> getCharArea();
|
std::vector<cv::Point> getCharArea();
|
||||||
|
|
||||||
LineSegment getCharBoxTop();
|
LineSegment getCharBoxTop();
|
||||||
@@ -49,7 +47,6 @@ class CharacterRegion
|
|||||||
LineSegment getCharBoxLeft();
|
LineSegment getCharBoxLeft();
|
||||||
LineSegment getCharBoxRight();
|
LineSegment getCharBoxRight();
|
||||||
|
|
||||||
bool thresholdsInverted();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Config* config;
|
Config* config;
|
||||||
|
@@ -22,9 +22,10 @@
|
|||||||
using namespace cv;
|
using namespace cv;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CharacterSegmenter::CharacterSegmenter(Mat img_gray, bool invertedColors, Config* config)
|
CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->pipeline_data = pipeline_data;
|
||||||
|
this->config = pipeline_data->config;
|
||||||
|
|
||||||
this->confidence = 0;
|
this->confidence = 0;
|
||||||
|
|
||||||
@@ -37,12 +38,12 @@ CharacterSegmenter::CharacterSegmenter(Mat img_gray, bool invertedColors, Config
|
|||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
medianBlur(img_gray, img_gray, 3);
|
medianBlur(pipeline_data->crop_gray, pipeline_data->crop_gray, 3);
|
||||||
|
|
||||||
if (invertedColors)
|
if (pipeline_data->plate_inverted)
|
||||||
bitwise_not(img_gray, img_gray);
|
bitwise_not(pipeline_data->crop_gray, pipeline_data->crop_gray);
|
||||||
|
|
||||||
charAnalysis = new CharacterAnalysis(img_gray, config);
|
charAnalysis = new CharacterAnalysis(pipeline_data);
|
||||||
charAnalysis->analyze();
|
charAnalysis->analyze();
|
||||||
|
|
||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
|
@@ -44,7 +44,7 @@ class CharacterSegmenter
|
|||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CharacterSegmenter(cv::Mat img, bool invertedColors, Config* config);
|
CharacterSegmenter(PipelineData* pipeline_data);
|
||||||
virtual ~CharacterSegmenter();
|
virtual ~CharacterSegmenter();
|
||||||
|
|
||||||
std::vector<cv::Rect> characters;
|
std::vector<cv::Rect> characters;
|
||||||
@@ -54,7 +54,8 @@ class CharacterSegmenter
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Config* config;
|
Config* config;
|
||||||
|
PipelineData* pipeline_data;
|
||||||
|
|
||||||
CharacterAnalysis* charAnalysis;
|
CharacterAnalysis* charAnalysis;
|
||||||
|
|
||||||
LineSegment top;
|
LineSegment top;
|
||||||
|
@@ -50,14 +50,14 @@ void LicensePlateCandidate::recognize()
|
|||||||
resize(pipeline_data->crop_gray, pipeline_data->crop_gray, Size(config->templateWidthPx, config->templateHeightPx));
|
resize(pipeline_data->crop_gray, pipeline_data->crop_gray, Size(config->templateWidthPx, config->templateHeightPx));
|
||||||
|
|
||||||
|
|
||||||
CharacterRegion charRegion(pipeline_data->crop_gray, config);
|
CharacterRegion charRegion(pipeline_data);
|
||||||
|
|
||||||
if (charRegion.confidence > 10)
|
if (charRegion.confidence > 10)
|
||||||
{
|
{
|
||||||
PlateLines plateLines(config);
|
PlateLines plateLines(config);
|
||||||
//Mat boogedy = charRegion.getPlateMask();
|
//Mat boogedy = charRegion.getPlateMask();
|
||||||
|
|
||||||
plateLines.processImage(charRegion.getPlateMask(), &charRegion, 1.10);
|
plateLines.processImage(pipeline_data->plate_mask, &charRegion, 1.10);
|
||||||
plateLines.processImage(pipeline_data->crop_gray, &charRegion, 0.9);
|
plateLines.processImage(pipeline_data->crop_gray, &charRegion, 0.9);
|
||||||
|
|
||||||
PlateCorners cornerFinder(pipeline_data->crop_gray, &plateLines, &charRegion, config);
|
PlateCorners cornerFinder(pipeline_data->crop_gray, &plateLines, &charRegion, config);
|
||||||
@@ -65,11 +65,11 @@ void LicensePlateCandidate::recognize()
|
|||||||
|
|
||||||
if (cornerFinder.confidence > 0)
|
if (cornerFinder.confidence > 0)
|
||||||
{
|
{
|
||||||
this->plateCorners = transformPointsToOriginalImage(this->pipeline_data->grayImg, pipeline_data->crop_gray, expandedRegion, smallPlateCorners);
|
pipeline_data->plate_corners = transformPointsToOriginalImage(this->pipeline_data->grayImg, pipeline_data->crop_gray, expandedRegion, smallPlateCorners);
|
||||||
|
|
||||||
this->deskewed = deSkewPlate(this->pipeline_data->grayImg, this->plateCorners);
|
pipeline_data->crop_gray = deSkewPlate(this->pipeline_data->grayImg, pipeline_data->plate_corners);
|
||||||
|
|
||||||
charSegmenter = new CharacterSegmenter(deskewed, charRegion.thresholdsInverted(), config);
|
charSegmenter = new CharacterSegmenter(pipeline_data);
|
||||||
|
|
||||||
//this->recognizedText = ocr->recognizedText;
|
//this->recognizedText = ocr->recognizedText;
|
||||||
//strcpy(this->recognizedText, ocr.recognizedText);
|
//strcpy(this->recognizedText, ocr.recognizedText);
|
||||||
|
@@ -48,11 +48,9 @@ class LicensePlateCandidate
|
|||||||
|
|
||||||
float confidence; // 0-100
|
float confidence; // 0-100
|
||||||
//vector<Point> points; // top-left, top-right, bottom-right, bottom-left
|
//vector<Point> points; // top-left, top-right, bottom-right, bottom-left
|
||||||
std::vector<cv::Point2f> plateCorners;
|
|
||||||
|
|
||||||
void recognize();
|
void recognize();
|
||||||
|
|
||||||
cv::Mat deskewed;
|
|
||||||
CharacterSegmenter* charSegmenter;
|
CharacterSegmenter* charSegmenter;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -10,6 +10,8 @@ PipelineData::PipelineData(Mat colorImage, Rect regionOfInterest, Config* config
|
|||||||
|
|
||||||
this->regionOfInterest = regionOfInterest;
|
this->regionOfInterest = regionOfInterest;
|
||||||
this->config = config;
|
this->config = config;
|
||||||
|
|
||||||
|
plate_inverted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineData::~PipelineData()
|
PipelineData::~PipelineData()
|
||||||
|
@@ -20,18 +20,21 @@ class PipelineData
|
|||||||
cv::Mat grayImg;
|
cv::Mat grayImg;
|
||||||
cv::Rect regionOfInterest;
|
cv::Rect regionOfInterest;
|
||||||
|
|
||||||
|
|
||||||
cv::Mat crop_gray;
|
cv::Mat crop_gray;
|
||||||
cv::Mat plate_mask;
|
cv::Mat plate_mask;
|
||||||
|
std::vector<cv::Mat> thresholds;
|
||||||
|
|
||||||
|
std::vector<cv::Point2f> plate_corners;
|
||||||
|
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
|
bool plate_inverted;
|
||||||
|
|
||||||
std::string region_code;
|
std::string region_code;
|
||||||
float region_confidence;
|
float region_confidence;
|
||||||
|
|
||||||
float overall_confidence;
|
float overall_confidence;
|
||||||
|
|
||||||
std::vector<cv::Mat> thresholds;
|
|
||||||
|
|
||||||
|
|
||||||
// Plate Lines
|
// Plate Lines
|
||||||
std::vector<LineSegment> horizontalLines;
|
std::vector<LineSegment> horizontalLines;
|
||||||
|
Reference in New Issue
Block a user