Added pipeline_data to character analaysis and character segmentation

This commit is contained in:
Matt Hill
2014-07-01 18:26:01 -04:00
parent b9422dc063
commit a0af4093d6
13 changed files with 49 additions and 67 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)
{ {

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);

View File

@@ -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:

View File

@@ -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()

View File

@@ -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;