From a52fa6d5f9c3347a6b6439de5665cb15daa2e9df Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 14:14:38 -0400 Subject: [PATCH 01/12] Added pipeline_data class --- src/openalpr/pipeline_data.cpp | 13 +++++++++ src/openalpr/pipeline_data.h | 48 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/openalpr/pipeline_data.cpp create mode 100644 src/openalpr/pipeline_data.h diff --git a/src/openalpr/pipeline_data.cpp b/src/openalpr/pipeline_data.cpp new file mode 100644 index 0000000..8db07ad --- /dev/null +++ b/src/openalpr/pipeline_data.cpp @@ -0,0 +1,13 @@ +#include "pipeline_data.h" + +using namespace cv; +using namespace std; + +PipelineData::PipelineData(Mat colorImage, Rect regionOfInterest, Config* config) +{ + this->colorImg = colorImage; + cvtColor(this->colorImg, this->grayImg, CV_BGR2GRAY); + + this->regionOfInterest = regionOfInterest; + this->config = config; +} \ No newline at end of file diff --git a/src/openalpr/pipeline_data.h b/src/openalpr/pipeline_data.h new file mode 100644 index 0000000..e9a0b0a --- /dev/null +++ b/src/openalpr/pipeline_data.h @@ -0,0 +1,48 @@ + +#ifndef OPENALPR_PIPELINEDATA_H +#define OPENALPR_PIPELINEDATA_H + +#include "segmentation/segment.h" +#include "segmentation/segmentationgroup.h" + +class PipelineData +{ + + public: + PipelineData(cv::Mat colorImage, cv::Rect regionOfInterest, Config* config); + virtual ~PipelineData(); + + // Inputs + Config* config; + + cv::Mat colorImg; + cv::Mat grayImg; + cv::Rect regionOfInterest; + + + cv::Mat crop_gray; + cv::Mat plate_mask; + + // Outputs + std::string region_code; + float region_confidence; + + float overall_confidence; + + std::vector thresholds; + + + // Plate Lines + std::vector horizontalLines; + std::vector verticalLines; + + // Segmentation + std::vector segments; + std::vector segmentGroups; + + // OCR + +}; + + +#endif // OPENALPR_PIPELINEDATA_H \ No newline at end of file From 092e1bb3d57d38d4afd4608e11ddde2546cb7c07 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 17:19:16 -0400 Subject: [PATCH 02/12] Updated pipeline.cpp to compile --- src/openalpr/CMakeLists.txt | 1 + src/openalpr/pipeline_data.cpp | 4 ++++ src/openalpr/pipeline_data.h | 9 ++++----- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/openalpr/CMakeLists.txt b/src/openalpr/CMakeLists.txt index 9046926..aba5435 100644 --- a/src/openalpr/CMakeLists.txt +++ b/src/openalpr/CMakeLists.txt @@ -21,6 +21,7 @@ set(lpr_source_files colorfilter.cpp characteranalysis.cpp verticalhistogram.cpp + pipeline_data.cpp trex.c cjson.c ) diff --git a/src/openalpr/pipeline_data.cpp b/src/openalpr/pipeline_data.cpp index 8db07ad..0d8ab04 100644 --- a/src/openalpr/pipeline_data.cpp +++ b/src/openalpr/pipeline_data.cpp @@ -10,4 +10,8 @@ PipelineData::PipelineData(Mat colorImage, Rect regionOfInterest, Config* config this->regionOfInterest = regionOfInterest; this->config = config; +} + +PipelineData::~PipelineData() +{ } \ No newline at end of file diff --git a/src/openalpr/pipeline_data.h b/src/openalpr/pipeline_data.h index e9a0b0a..39e6c52 100644 --- a/src/openalpr/pipeline_data.h +++ b/src/openalpr/pipeline_data.h @@ -2,8 +2,9 @@ #ifndef OPENALPR_PIPELINEDATA_H #define OPENALPR_PIPELINEDATA_H -#include "segmentation/segment.h" -#include "segmentation/segmentationgroup.h" +#include "opencv2/imgproc/imgproc.hpp" +#include "utility.h" +#include "config.h" class PipelineData { @@ -36,9 +37,7 @@ class PipelineData std::vector horizontalLines; std::vector verticalLines; - // Segmentation - std::vector segments; - std::vector segmentGroups; + // OCR From 552caf5a056863c82572fc1fd4c646dbfd0cddb2 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 17:25:06 -0400 Subject: [PATCH 03/12] Updated state_identifier to use pipeline_data --- src/openalpr/stateidentifier.cpp | 28 ++++++++++++---------------- src/openalpr/stateidentifier.h | 4 ++-- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/openalpr/stateidentifier.cpp b/src/openalpr/stateidentifier.cpp index dde5611..0a84c91 100644 --- a/src/openalpr/stateidentifier.cpp +++ b/src/openalpr/stateidentifier.cpp @@ -43,26 +43,18 @@ StateIdentifier::~StateIdentifier() delete featureMatcher; } -int StateIdentifier::recognize(Mat img, Rect frame, char* stateCode) -{ - Mat croppedImage = Mat(img, frame); - return this->recognize(croppedImage, stateCode); -} -// Attempts to recognize the plate. Returns a confidence level. Updates teh "stateCode" variable -// with the value of the country/state -int StateIdentifier::recognize(Mat img, char* stateCode) +// Attempts to recognize the plate. Returns a confidence level. Updates the region code and confidence +// If region is found, returns true. +bool StateIdentifier::recognize(PipelineData* pipeline_data) { timespec startTime; getTime(&startTime); - cvtColor(img, img, CV_BGR2GRAY); + Mat plateImg = Mat(pipeline_data->grayImg, pipeline_data->regionOfInterest); - resize(img, img, getSizeMaintainingAspect(img, config->stateIdImageWidthPx, config->stateIdimageHeightPx)); + resize(plateImg, plateImg, getSizeMaintainingAspect(plateImg, config->stateIdImageWidthPx, config->stateIdimageHeightPx)); - Mat plateImg(img.size(), img.type()); - //plateImg = equalizeBrightness(img); - img.copyTo(plateImg); Mat debugImg(plateImg.size(), plateImg.type()); plateImg.copyTo(debugImg); @@ -87,7 +79,11 @@ int StateIdentifier::recognize(Mat img, char* stateCode) if (result.haswinner == false) return 0; - strcpy(stateCode, result.winner.c_str()); - - return result.confidence; + pipeline_data->region_code = result.winner; + pipeline_data->region_confidence = result.confidence; + + if (result.confidence >= 10) + return true; + + return false; } diff --git a/src/openalpr/stateidentifier.h b/src/openalpr/stateidentifier.h index e0c8c0b..3092a67 100644 --- a/src/openalpr/stateidentifier.h +++ b/src/openalpr/stateidentifier.h @@ -25,6 +25,7 @@ #include "featurematcher.h" #include "utility.h" #include "config.h" +#include "pipeline_data.h" class StateIdentifier { @@ -33,8 +34,7 @@ class StateIdentifier StateIdentifier(Config* config); virtual ~StateIdentifier(); - int recognize(cv::Mat img, cv::Rect frame, char* stateCode); - int recognize(cv::Mat img, char* stateCode); + bool recognize(PipelineData* pipeline_data); //int confidence; From b9422dc0630937d7894ce490330a1e3a094523bd Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 17:44:39 -0400 Subject: [PATCH 04/12] Inserted pipeline_data into additional places --- src/misc_utilities/benchmark/benchmark.cpp | 9 ++++-- src/misc_utilities/sortstate.cpp | 23 ++++++---------- src/openalpr/alpr_impl.cpp | 6 ++-- src/openalpr/alpr_impl.h | 2 ++ src/openalpr/charactersegmenter.cpp | 4 +-- src/openalpr/licenseplatecandidate.cpp | 32 ++++++++++------------ src/openalpr/licenseplatecandidate.h | 8 ++---- 7 files changed, 38 insertions(+), 46 deletions(-) diff --git a/src/misc_utilities/benchmark/benchmark.cpp b/src/misc_utilities/benchmark/benchmark.cpp index 7a4f23b..51ead18 100644 --- a/src/misc_utilities/benchmark/benchmark.cpp +++ b/src/misc_utilities/benchmark/benchmark.cpp @@ -211,16 +211,19 @@ int main( int argc, const char** argv ) for (int z = 0; z < regions.size(); z++) { + + PipelineData pipeline_data(frame, regions[z].rect, &config); + getTime(&startTime); - char temp[5]; - stateIdentifier.recognize(frame, regions[z].rect, temp); + + stateIdentifier.recognize(&pipeline_data); getTime(&endTime); double stateidTime = diffclock(startTime, endTime); cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl; stateIdTimes.push_back(stateidTime); getTime(&startTime); - LicensePlateCandidate lp(frame, regions[z].rect, &config); + LicensePlateCandidate lp(&pipeline_data); lp.recognize(); getTime(&endTime); double analysisTime = diffclock(startTime, endTime); diff --git a/src/misc_utilities/sortstate.cpp b/src/misc_utilities/sortstate.cpp index 68770ef..eff5229 100644 --- a/src/misc_utilities/sortstate.cpp +++ b/src/misc_utilities/sortstate.cpp @@ -79,31 +79,26 @@ int main( int argc, const char** argv ) cout << fullpath << endl; frame = imread( fullpath.c_str() ); - char code[4]; - int confidence = identifier.recognize(frame, code); + PipelineData pipeline_data(frame, Rect(0, 0, frame.cols, frame.rows), &config); + identifier.recognize(&pipeline_data); - if (confidence <= 20) + if (pipeline_data.region_confidence <= 20) { - code[0] = 'z'; - code[1] = 'z'; - confidence = 100; + pipeline_data.region_code = 'zz'; + pipeline_data.region_confidence = 100; } - - //imshow("Plate", frame); - if (confidence > 20) - { - cout << confidence << " : " << code; + else + { + cout << pipeline_data.region_confidence << " : " << pipeline_data.region_code; ostringstream convert; // stream used for the conversion convert << i; // insert the textual representation of 'Number' in the characters in the stream - string copyCommand = "cp \"" + fullpath + "\" " + outDir + code + convert.str() + ".png"; + string copyCommand = "cp \"" + fullpath + "\" " + outDir + pipeline_data.region_code + convert.str() + ".png"; system( copyCommand.c_str() ); waitKey(50); //while ((char) waitKey(50) != 'c') { } } - else - waitKey(50); } } } diff --git a/src/openalpr/alpr_impl.cpp b/src/openalpr/alpr_impl.cpp index 2aa42e6..42d297b 100644 --- a/src/openalpr/alpr_impl.cpp +++ b/src/openalpr/alpr_impl.cpp @@ -186,12 +186,12 @@ void plateAnalysisThread(void* arg) if (dispatcher->config->debugGeneral) cout << "Thread: " << tthread::this_thread::get_id() << " loop " << ++loop_count << endl; - Mat img = dispatcher->getImageCopy(); + PipelineData pipeline_data(dispatcher->getImageCopy(), plateRegion.rect, dispatcher->config); timespec platestarttime; getTime(&platestarttime); - LicensePlateCandidate lp(img, plateRegion.rect, dispatcher->config); + LicensePlateCandidate lp(&pipeline_data); lp.recognize(); @@ -220,7 +220,7 @@ void plateAnalysisThread(void* arg) if (dispatcher->detectRegion) { char statecode[4]; - plateResult.regionConfidence = dispatcher->stateIdentifier->recognize(img, plateRegion.rect, statecode); + plateResult.regionConfidence = dispatcher->stateIdentifier->recognize(&pipeline_data); if (plateResult.regionConfidence > 0) { plateResult.region = statecode; diff --git a/src/openalpr/alpr_impl.h b/src/openalpr/alpr_impl.h index 64f8a7b..77db817 100644 --- a/src/openalpr/alpr_impl.h +++ b/src/openalpr/alpr_impl.h @@ -37,6 +37,8 @@ #include "cjson.h" +#include "pipeline_data.h" + #include diff --git a/src/openalpr/charactersegmenter.cpp b/src/openalpr/charactersegmenter.cpp index 9a07c95..87007a1 100644 --- a/src/openalpr/charactersegmenter.cpp +++ b/src/openalpr/charactersegmenter.cpp @@ -22,7 +22,7 @@ using namespace cv; using namespace std; -CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* config) +CharacterSegmenter::CharacterSegmenter(Mat img_gray, bool invertedColors, Config* config) { this->config = config; @@ -36,8 +36,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con timespec startTime; getTime(&startTime); - Mat img_gray(img.size(), CV_8U); - cvtColor( img, img_gray, CV_BGR2GRAY ); medianBlur(img_gray, img_gray, 3); diff --git a/src/openalpr/licenseplatecandidate.cpp b/src/openalpr/licenseplatecandidate.cpp index b15fad0..15a40c6 100644 --- a/src/openalpr/licenseplatecandidate.cpp +++ b/src/openalpr/licenseplatecandidate.cpp @@ -22,12 +22,11 @@ using namespace std; using namespace cv; -LicensePlateCandidate::LicensePlateCandidate(Mat frame, Rect regionOfInterest, Config* config) +LicensePlateCandidate::LicensePlateCandidate(PipelineData* pipeline_data) { - this->config = config; + this->pipeline_data = pipeline_data; + this->config = pipeline_data->config; - this->frame = frame; - this->plateRegion = regionOfInterest; } LicensePlateCandidate::~LicensePlateCandidate() @@ -42,19 +41,16 @@ void LicensePlateCandidate::recognize() this->confidence = 0; - int expandX = round(this->plateRegion.width * 0.20); - int expandY = round(this->plateRegion.height * 0.15); + int expandX = round(this->pipeline_data->regionOfInterest.width * 0.20); + int expandY = round(this->pipeline_data->regionOfInterest.height * 0.15); // expand box by 15% in all directions - Rect expandedRegion = expandRect( this->plateRegion, expandX, expandY, frame.cols, frame.rows) ; + Rect expandedRegion = expandRect( this->pipeline_data->regionOfInterest, expandX, expandY, this->pipeline_data->grayImg.cols, this->pipeline_data->grayImg.rows) ; - Mat plate_bgr = Mat(frame, expandedRegion); - resize(plate_bgr, plate_bgr, Size(config->templateWidthPx, config->templateHeightPx)); - - Mat plate_gray; - cvtColor(plate_bgr, plate_gray, CV_BGR2GRAY); + pipeline_data->crop_gray = Mat(this->pipeline_data->grayImg, expandedRegion); + resize(pipeline_data->crop_gray, pipeline_data->crop_gray, Size(config->templateWidthPx, config->templateHeightPx)); - CharacterRegion charRegion(plate_bgr, config); + CharacterRegion charRegion(pipeline_data->crop_gray, config); if (charRegion.confidence > 10) { @@ -62,16 +58,16 @@ void LicensePlateCandidate::recognize() //Mat boogedy = charRegion.getPlateMask(); plateLines.processImage(charRegion.getPlateMask(), &charRegion, 1.10); - plateLines.processImage(plate_gray, &charRegion, 0.9); + plateLines.processImage(pipeline_data->crop_gray, &charRegion, 0.9); - PlateCorners cornerFinder(plate_bgr, &plateLines, &charRegion, config); + PlateCorners cornerFinder(pipeline_data->crop_gray, &plateLines, &charRegion, config); vector smallPlateCorners = cornerFinder.findPlateCorners(); if (cornerFinder.confidence > 0) { - this->plateCorners = transformPointsToOriginalImage(frame, plate_bgr, expandedRegion, smallPlateCorners); + this->plateCorners = transformPointsToOriginalImage(this->pipeline_data->grayImg, pipeline_data->crop_gray, expandedRegion, smallPlateCorners); - this->deskewed = deSkewPlate(frame, this->plateCorners); + this->deskewed = deSkewPlate(this->pipeline_data->grayImg, this->plateCorners); charSegmenter = new CharacterSegmenter(deskewed, charRegion.thresholdsInverted(), config); @@ -122,7 +118,7 @@ Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector corners) width = round(((float) height) * aspect); } - Mat deskewed(height, width, frame.type()); + Mat deskewed(height, width, this->pipeline_data->grayImg.type()); // Corners of the destination image vector quad_pts; diff --git a/src/openalpr/licenseplatecandidate.h b/src/openalpr/licenseplatecandidate.h index e12be32..1e71b62 100644 --- a/src/openalpr/licenseplatecandidate.h +++ b/src/openalpr/licenseplatecandidate.h @@ -34,7 +34,7 @@ #include "charactersegmenter.h" #include "platecorners.h" #include "config.h" - +#include "pipeline_data.h" //vector getCharacterRegions(Mat frame, vector regionsOfInterest); //vector getCharSegmentsBetweenLines(Mat img, vector > contours, LineSegment top, LineSegment bottom); @@ -43,7 +43,7 @@ class LicensePlateCandidate { public: - LicensePlateCandidate(cv::Mat frame, cv::Rect regionOfInterest, Config* config); + LicensePlateCandidate(PipelineData* pipeline_data); virtual ~LicensePlateCandidate(); float confidence; // 0-100 @@ -56,11 +56,9 @@ class LicensePlateCandidate CharacterSegmenter* charSegmenter; private: - + PipelineData* pipeline_data; Config* config; - cv::Mat frame; - cv::Rect plateRegion; cv::Mat filterByCharacterHue(std::vector > charRegionContours); std::vector findPlateCorners(cv::Mat inputImage, PlateLines plateLines, CharacterRegion charRegion); // top-left, top-right, bottom-right, bottom-left From a0af4093d6ae5e3b34441233d54bde4dc51553c7 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 18:26:01 -0400 Subject: [PATCH 05/12] Added pipeline_data to character analaysis and character segmentation --- src/misc_utilities/benchmark/benchmark.cpp | 7 ++++-- src/misc_utilities/classifychars.cpp | 6 +++-- src/openalpr/alpr_impl.cpp | 4 ++-- src/openalpr/characteranalysis.cpp | 28 ++++------------------ src/openalpr/characteranalysis.h | 7 +++--- src/openalpr/characterregion.cpp | 16 ++++--------- src/openalpr/characterregion.h | 7 ++---- src/openalpr/charactersegmenter.cpp | 13 +++++----- src/openalpr/charactersegmenter.h | 5 ++-- src/openalpr/licenseplatecandidate.cpp | 10 ++++---- src/openalpr/licenseplatecandidate.h | 2 -- src/openalpr/pipeline_data.cpp | 2 ++ src/openalpr/pipeline_data.h | 9 ++++--- 13 files changed, 49 insertions(+), 67 deletions(-) diff --git a/src/misc_utilities/benchmark/benchmark.cpp b/src/misc_utilities/benchmark/benchmark.cpp index 51ead18..106689d 100644 --- a/src/misc_utilities/benchmark/benchmark.cpp +++ b/src/misc_utilities/benchmark/benchmark.cpp @@ -104,6 +104,8 @@ int main( int argc, const char** argv ) plateCoords.y = 0; plateCoords.width = frame.cols; plateCoords.height = frame.rows; + + PipelineData pipeline_data(frame, plateCoords, config); char statecode[3]; statecode[0] = files[i][0]; @@ -111,7 +113,7 @@ int main( int argc, const char** argv ) statecode[2] = '\0'; string statecodestr(statecode); - CharacterRegion charRegion(frame, config); + CharacterRegion charRegion(&pipeline_data); if (abs(charRegion.getTopLine().angle) > 4) { @@ -124,9 +126,10 @@ int main( int argc, const char** argv ) warpAffine( frame, rotated, rot_mat, frame.size() ); 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->postProcessor->analyze(statecode, 25); diff --git a/src/misc_utilities/classifychars.cpp b/src/misc_utilities/classifychars.cpp index e90e35d..b41041e 100644 --- a/src/misc_utilities/classifychars.cpp +++ b/src/misc_utilities/classifychars.cpp @@ -124,13 +124,14 @@ int main( int argc, const char** argv ) imshow ("Original", frame); + PipelineData pipeline_data(frame, Rect(0, 0, frame.cols, frame.rows), &config); char statecode[3]; statecode[0] = files[i][0]; statecode[1] = files[i][1]; statecode[2] = '\0'; string statecodestr(statecode); - CharacterRegion regionizer(frame, &config); + CharacterRegion regionizer(&pipeline_data); if (abs(regionizer.getTopLine().angle) > 4) { @@ -143,9 +144,10 @@ int main( int argc, const char** argv ) warpAffine( frame, rotated, rot_mat, frame.size() ); rotated.copyTo(frame); + pipeline_data.crop_gray = rotated; } - CharacterSegmenter charSegmenter(frame, regionizer.thresholdsInverted(), &config); + CharacterSegmenter charSegmenter(&pipeline_data); //ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters); diff --git a/src/openalpr/alpr_impl.cpp b/src/openalpr/alpr_impl.cpp index 42d297b..ff63d1a 100644 --- a/src/openalpr/alpr_impl.cpp +++ b/src/openalpr/alpr_impl.cpp @@ -213,8 +213,8 @@ void plateAnalysisThread(void* arg) for (int pointidx = 0; pointidx < 4; pointidx++) { - plateResult.plate_points[pointidx].x = (int) lp.plateCorners[pointidx].x; - plateResult.plate_points[pointidx].y = (int) lp.plateCorners[pointidx].y; + plateResult.plate_points[pointidx].x = (int) pipeline_data.plate_corners[pointidx].x; + plateResult.plate_points[pointidx].y = (int) pipeline_data.plate_corners[pointidx].y; } if (dispatcher->detectRegion) diff --git a/src/openalpr/characteranalysis.cpp b/src/openalpr/characteranalysis.cpp index c146504..26d6403 100644 --- a/src/openalpr/characteranalysis.cpp +++ b/src/openalpr/characteranalysis.cpp @@ -22,22 +22,16 @@ using namespace cv; 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; if (this->config->debugCharAnalysis) 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() @@ -51,21 +45,9 @@ CharacterAnalysis::~CharacterAnalysis() 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; 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)); - this->linePolygon = getBestVotedLines(img_gray, bestContours, bestCharSegments); + this->linePolygon = getBestVotedLines(pipeline_data->crop_gray, bestContours, bestCharSegments); if (this->linePolygon.size() > 0) { diff --git a/src/openalpr/characteranalysis.h b/src/openalpr/characteranalysis.h index 588cb21..b9d66ad 100644 --- a/src/openalpr/characteranalysis.h +++ b/src/openalpr/characteranalysis.h @@ -24,13 +24,13 @@ #include "constants.h" #include "utility.h" #include "config.h" - +#include "pipeline_data.h" class CharacterAnalysis { public: - CharacterAnalysis(cv::Mat img, Config* config); + CharacterAnalysis(PipelineData* pipeline_data); virtual ~CharacterAnalysis(); bool hasPlateMask; @@ -64,10 +64,9 @@ class CharacterAnalysis cv::Mat getCharacterMask(); private: + PipelineData* pipeline_data; Config* config; - cv::Mat img_gray; - cv::Mat findOuterBoxMask( ); bool isPlateInverted(); diff --git a/src/openalpr/characterregion.cpp b/src/openalpr/characterregion.cpp index 6fc4af6..b6e2953 100644 --- a/src/openalpr/characterregion.cpp +++ b/src/openalpr/characterregion.cpp @@ -22,9 +22,9 @@ using namespace cv; 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->confidence = 0; @@ -35,8 +35,10 @@ CharacterRegion::CharacterRegion(Mat img, Config* config) timespec startTime; getTime(&startTime); - charAnalysis = new CharacterAnalysis(img, config); + charAnalysis = new CharacterAnalysis(pipeline_data); charAnalysis->analyze(); + pipeline_data->plate_inverted = charAnalysis->thresholdsInverted; + pipeline_data->plate_mask = charAnalysis->plateMask; if (this->debug && charAnalysis->linePolygon.size() > 0) { @@ -100,10 +102,6 @@ CharacterRegion::~CharacterRegion() delete(charAnalysis); } -Mat CharacterRegion::getPlateMask() -{ - return charAnalysis->plateMask; -} LineSegment CharacterRegion::getTopLine() { @@ -140,7 +138,3 @@ LineSegment CharacterRegion::getCharBoxRight() return charAnalysis->charBoxRight; } -bool CharacterRegion::thresholdsInverted() -{ - return charAnalysis->thresholdsInverted; -} diff --git a/src/openalpr/characterregion.h b/src/openalpr/characterregion.h index 4826bae..a4eabe4 100644 --- a/src/openalpr/characterregion.h +++ b/src/openalpr/characterregion.h @@ -25,23 +25,21 @@ #include "utility.h" #include "characteranalysis.h" #include "config.h" - +#include "pipeline_data.h" class CharacterRegion { public: - CharacterRegion(cv::Mat img, Config* config); + CharacterRegion(PipelineData* pipeline_data); virtual ~CharacterRegion(); CharacterAnalysis *charAnalysis; int confidence; - cv::Mat getPlateMask(); LineSegment getTopLine(); LineSegment getBottomLine(); - //vector getLinePolygon(); std::vector getCharArea(); LineSegment getCharBoxTop(); @@ -49,7 +47,6 @@ class CharacterRegion LineSegment getCharBoxLeft(); LineSegment getCharBoxRight(); - bool thresholdsInverted(); protected: Config* config; diff --git a/src/openalpr/charactersegmenter.cpp b/src/openalpr/charactersegmenter.cpp index 87007a1..04cf417 100644 --- a/src/openalpr/charactersegmenter.cpp +++ b/src/openalpr/charactersegmenter.cpp @@ -22,9 +22,10 @@ using namespace cv; 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; @@ -37,12 +38,12 @@ CharacterSegmenter::CharacterSegmenter(Mat img_gray, bool invertedColors, Config getTime(&startTime); - medianBlur(img_gray, img_gray, 3); + medianBlur(pipeline_data->crop_gray, pipeline_data->crop_gray, 3); - if (invertedColors) - bitwise_not(img_gray, img_gray); + if (pipeline_data->plate_inverted) + bitwise_not(pipeline_data->crop_gray, pipeline_data->crop_gray); - charAnalysis = new CharacterAnalysis(img_gray, config); + charAnalysis = new CharacterAnalysis(pipeline_data); charAnalysis->analyze(); if (this->config->debugCharSegmenter) diff --git a/src/openalpr/charactersegmenter.h b/src/openalpr/charactersegmenter.h index bea17b2..6b958bd 100644 --- a/src/openalpr/charactersegmenter.h +++ b/src/openalpr/charactersegmenter.h @@ -44,7 +44,7 @@ class CharacterSegmenter { public: - CharacterSegmenter(cv::Mat img, bool invertedColors, Config* config); + CharacterSegmenter(PipelineData* pipeline_data); virtual ~CharacterSegmenter(); std::vector characters; @@ -54,7 +54,8 @@ class CharacterSegmenter private: Config* config; - + PipelineData* pipeline_data; + CharacterAnalysis* charAnalysis; LineSegment top; diff --git a/src/openalpr/licenseplatecandidate.cpp b/src/openalpr/licenseplatecandidate.cpp index 15a40c6..f318727 100644 --- a/src/openalpr/licenseplatecandidate.cpp +++ b/src/openalpr/licenseplatecandidate.cpp @@ -50,14 +50,14 @@ void LicensePlateCandidate::recognize() 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) { PlateLines plateLines(config); //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); PlateCorners cornerFinder(pipeline_data->crop_gray, &plateLines, &charRegion, config); @@ -65,11 +65,11 @@ void LicensePlateCandidate::recognize() 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; //strcpy(this->recognizedText, ocr.recognizedText); diff --git a/src/openalpr/licenseplatecandidate.h b/src/openalpr/licenseplatecandidate.h index 1e71b62..f63375e 100644 --- a/src/openalpr/licenseplatecandidate.h +++ b/src/openalpr/licenseplatecandidate.h @@ -48,11 +48,9 @@ class LicensePlateCandidate float confidence; // 0-100 //vector points; // top-left, top-right, bottom-right, bottom-left - std::vector plateCorners; void recognize(); - cv::Mat deskewed; CharacterSegmenter* charSegmenter; private: diff --git a/src/openalpr/pipeline_data.cpp b/src/openalpr/pipeline_data.cpp index 0d8ab04..d0ccb71 100644 --- a/src/openalpr/pipeline_data.cpp +++ b/src/openalpr/pipeline_data.cpp @@ -10,6 +10,8 @@ PipelineData::PipelineData(Mat colorImage, Rect regionOfInterest, Config* config this->regionOfInterest = regionOfInterest; this->config = config; + + plate_inverted = false; } PipelineData::~PipelineData() diff --git a/src/openalpr/pipeline_data.h b/src/openalpr/pipeline_data.h index 39e6c52..b4853ab 100644 --- a/src/openalpr/pipeline_data.h +++ b/src/openalpr/pipeline_data.h @@ -20,18 +20,21 @@ class PipelineData cv::Mat grayImg; cv::Rect regionOfInterest; - cv::Mat crop_gray; cv::Mat plate_mask; + std::vector thresholds; + + std::vector plate_corners; + // Outputs + bool plate_inverted; + std::string region_code; float region_confidence; float overall_confidence; - std::vector thresholds; - // Plate Lines std::vector horizontalLines; From 7e12ca1500b1df3c02446e826cb0a2539667a561 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 18:52:53 -0400 Subject: [PATCH 06/12] Rearranged threshold data to be contained in pipeline_data --- src/misc_utilities/benchmark/benchmark.cpp | 4 +-- src/misc_utilities/classifychars.cpp | 32 +++++++++--------- src/openalpr/alpr_impl.cpp | 2 +- src/openalpr/characteranalysis.cpp | 37 ++++++++++---------- src/openalpr/characteranalysis.h | 1 - src/openalpr/characterregion.cpp | 6 ++-- src/openalpr/charactersegmenter.cpp | 39 ++++++++++------------ src/openalpr/charactersegmenter.h | 1 - src/openalpr/licenseplatecandidate.h | 2 +- src/openalpr/ocr.cpp | 16 +++++---- src/openalpr/ocr.h | 3 +- src/openalpr/pipeline_data.cpp | 11 +++++- src/openalpr/pipeline_data.h | 3 ++ 13 files changed, 82 insertions(+), 75 deletions(-) diff --git a/src/misc_utilities/benchmark/benchmark.cpp b/src/misc_utilities/benchmark/benchmark.cpp index 106689d..d09efce 100644 --- a/src/misc_utilities/benchmark/benchmark.cpp +++ b/src/misc_utilities/benchmark/benchmark.cpp @@ -130,7 +130,7 @@ int main( int argc, const char** argv ) } CharacterSegmenter charSegmenter(&pipeline_data); - ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters); + ocr->performOCR(&pipeline_data); ocr->postProcessor->analyze(statecode, 25); cout << files[i] << "," << statecode << "," << ocr->postProcessor->bestChars << endl; @@ -237,7 +237,7 @@ int main( int argc, const char** argv ) lpAnalysisPositiveTimes.push_back(analysisTime); getTime(&startTime); - ocr.performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters); + ocr.performOCR(&pipeline_data); getTime(&endTime); double ocrTime = diffclock(startTime, endTime); cout << "\tRegion " << z << ": OCR time: " << ocrTime << "ms." << endl; diff --git a/src/misc_utilities/classifychars.cpp b/src/misc_utilities/classifychars.cpp index b41041e..09fc44a 100644 --- a/src/misc_utilities/classifychars.cpp +++ b/src/misc_utilities/classifychars.cpp @@ -151,12 +151,12 @@ int main( int argc, const char** argv ) //ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters); - ocr.performOCR(charSegmenter.getThresholds(), charSegmenter.characters); + ocr.performOCR(&pipeline_data); ocr.postProcessor->analyze(statecodestr, 25); cout << "OCR results: " << ocr.postProcessor->bestChars << endl; - vector selectedBoxes(charSegmenter.getThresholds().size()); - for (int z = 0; z < charSegmenter.getThresholds().size(); z++) + vector selectedBoxes(pipeline_data.thresholds.size()); + for (int z = 0; z < pipeline_data.thresholds.size(); z++) selectedBoxes[z] = false; int curDashboardSelection = 0; @@ -166,7 +166,7 @@ int main( int argc, const char** argv ) for (int z = 0; z < charSegmenter.characters.size(); z++) humanInputs[z] = ' '; - showDashboard(charSegmenter.getThresholds(), selectedBoxes, 0); + showDashboard(pipeline_data.thresholds, selectedBoxes, 0); char waitkey = (char) waitKey(50); @@ -176,50 +176,50 @@ int main( int argc, const char** argv ) { if (curDashboardSelection > 0) curDashboardSelection--; - showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); + showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection); } else if (waitkey == RIGHT_ARROW_KEY) // right arrow key { - if (curDashboardSelection < charSegmenter.getThresholds().size() - 1) + if (curDashboardSelection < pipeline_data.thresholds.size() - 1) curDashboardSelection++; - showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); + showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection); } else if (waitkey == DOWN_ARROW_KEY) { - if (curDashboardSelection + DASHBOARD_COLUMNS <= charSegmenter.getThresholds().size() - 1) + if (curDashboardSelection + DASHBOARD_COLUMNS <= pipeline_data.thresholds.size() - 1) curDashboardSelection += DASHBOARD_COLUMNS; - showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); + showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection); } else if (waitkey == UP_ARROW_KEY) { if (curDashboardSelection - DASHBOARD_COLUMNS >= 0) curDashboardSelection -= DASHBOARD_COLUMNS; - showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); + showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection); } else if (waitkey == ENTER_KEY) { - vector tempdata = showCharSelection(charSegmenter.getThresholds()[curDashboardSelection], charSegmenter.characters, statecodestr); + vector tempdata = showCharSelection(pipeline_data.thresholds[curDashboardSelection], charSegmenter.characters, statecodestr); for (int c = 0; c < charSegmenter.characters.size(); c++) humanInputs[c] = tempdata[c]; } else if (waitkey == SPACE_KEY) { selectedBoxes[curDashboardSelection] = !selectedBoxes[curDashboardSelection]; - showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); + showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection); } else if (waitkey == 's' || waitkey == 'S' || waitkey == 'W') { if (waitkey == 'W') { selectedBoxes[curDashboardSelection] = true; - showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); + showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection); const std::string& ocr_str = ocr.postProcessor->bestChars; humanInputs.assign(ocr_str.begin(), ocr_str.end()); } bool somethingSelected = false; bool chardataTagged = false; - for (int c = 0; c < charSegmenter.getThresholds().size(); c++) + for (int c = 0; c < pipeline_data.thresholds.size(); c++) { if (selectedBoxes[c]) { @@ -243,13 +243,13 @@ int main( int argc, const char** argv ) if (humanInputs[c] == ' ') continue; - for (int t = 0; t < charSegmenter.getThresholds().size(); t++) + for (int t = 0; t < pipeline_data.thresholds.size(); t++) { if (selectedBoxes[t] == false) continue; stringstream filename; - Mat cropped = charSegmenter.getThresholds()[t](charSegmenter.characters[c]); + Mat cropped = pipeline_data.thresholds[t](charSegmenter.characters[c]); filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i]; imwrite(filename.str(), cropped); cout << "Writing char image: " << filename.str() << endl; diff --git a/src/openalpr/alpr_impl.cpp b/src/openalpr/alpr_impl.cpp index ff63d1a..e79bbad 100644 --- a/src/openalpr/alpr_impl.cpp +++ b/src/openalpr/alpr_impl.cpp @@ -230,7 +230,7 @@ void plateAnalysisThread(void* arg) // Tesseract OCR does not appear to be threadsafe dispatcher->ocrMutex.lock(); - dispatcher->ocr->performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters); + dispatcher->ocr->performOCR(&pipeline_data); dispatcher->ocr->postProcessor->analyze(plateResult.region, dispatcher->topN); const vector ppResults = dispatcher->ocr->postProcessor->getResults(); dispatcher->ocrMutex.unlock(); diff --git a/src/openalpr/characteranalysis.cpp b/src/openalpr/characteranalysis.cpp index 26d6403..c70691f 100644 --- a/src/openalpr/characteranalysis.cpp +++ b/src/openalpr/characteranalysis.cpp @@ -36,29 +36,26 @@ CharacterAnalysis::CharacterAnalysis(PipelineData* pipeline_data) CharacterAnalysis::~CharacterAnalysis() { - for (int i = 0; i < thresholds.size(); i++) - { - thresholds[i].release(); - } - thresholds.clear(); + } void CharacterAnalysis::analyze() { - thresholds = produceThresholds(pipeline_data->crop_gray, config); + pipeline_data->clearThresholds(); + pipeline_data->thresholds = produceThresholds(pipeline_data->crop_gray, config); timespec startTime; getTime(&startTime); - for (int i = 0; i < thresholds.size(); i++) + for (int i = 0; i < pipeline_data->thresholds.size(); i++) { vector > contours; vector hierarchy; - Mat tempThreshold(thresholds[i].size(), CV_8U); - thresholds[i].copyTo(tempThreshold); + Mat tempThreshold(pipeline_data->thresholds[i].size(), CV_8U); + pipeline_data->thresholds[i].copyTo(tempThreshold); findContours(tempThreshold, contours, // a vector of contours hierarchy, @@ -79,9 +76,9 @@ void CharacterAnalysis::analyze() getTime(&startTime); - for (int i = 0; i < thresholds.size(); i++) + for (int i = 0; i < pipeline_data->thresholds.size(); i++) { - vector goodIndices = this->filter(thresholds[i], allContours[i], allHierarchy[i]); + vector goodIndices = this->filter(pipeline_data->thresholds[i], allContours[i], allHierarchy[i]); charSegments.push_back(goodIndices); if (config->debugCharAnalysis) @@ -100,7 +97,7 @@ void CharacterAnalysis::analyze() if (hasPlateMask) { // Filter out bad contours now that we have an outer box mask... - for (int i = 0; i < thresholds.size(); i++) + for (int i = 0; i < pipeline_data->thresholds.size(); i++) { charSegments[i] = filterByOuterMask(allContours[i], allHierarchy[i], charSegments[i]); } @@ -108,7 +105,7 @@ void CharacterAnalysis::analyze() int bestFitScore = -1; int bestFitIndex = -1; - for (int i = 0; i < thresholds.size(); i++) + for (int i = 0; i < pipeline_data->thresholds.size(); i++) { //vector goodIndices = this->filter(thresholds[i], allContours[i], allHierarchy[i]); //charSegments.push_back(goodIndices); @@ -120,7 +117,7 @@ void CharacterAnalysis::analyze() bestFitScore = segmentCount; bestFitIndex = i; bestCharSegments = charSegments[i]; - bestThreshold = thresholds[i]; + bestThreshold = pipeline_data->thresholds[i]; bestContours = allContours[i]; bestHierarchy = allHierarchy[i]; bestCharSegmentsCount = segmentCount; @@ -272,7 +269,7 @@ Mat CharacterAnalysis::findOuterBoxMask() } } - Mat mask = Mat::zeros(thresholds[winningIndex].size(), CV_8U); + Mat mask = Mat::zeros(pipeline_data->thresholds[winningIndex].size(), CV_8U); // get rid of the outline by drawing a 1 pixel width black line drawContours(mask, allContours[winningIndex], @@ -316,7 +313,7 @@ Mat CharacterAnalysis::findOuterBoxMask() if (biggestContourIndex != -1) { - mask = Mat::zeros(thresholds[winningIndex].size(), CV_8U); + mask = Mat::zeros(pipeline_data->thresholds[winningIndex].size(), CV_8U); vector smoothedMaskPoints; approxPolyDP(contoursSecondRound[biggestContourIndex], smoothedMaskPoints, 2, true); @@ -337,12 +334,12 @@ Mat CharacterAnalysis::findOuterBoxMask() if (this->config->debugCharAnalysis) { vector debugImgs; - Mat debugImgMasked = Mat::zeros(thresholds[winningIndex].size(), CV_8U); + Mat debugImgMasked = Mat::zeros(pipeline_data->thresholds[winningIndex].size(), CV_8U); - thresholds[winningIndex].copyTo(debugImgMasked, mask); + pipeline_data->thresholds[winningIndex].copyTo(debugImgMasked, mask); debugImgs.push_back(mask); - debugImgs.push_back(thresholds[winningIndex]); + debugImgs.push_back(pipeline_data->thresholds[winningIndex]); debugImgs.push_back(debugImgMasked); Mat dashboard = drawImageDashboard(debugImgs, CV_8U, 1); @@ -354,7 +351,7 @@ Mat CharacterAnalysis::findOuterBoxMask() } hasPlateMask = false; - Mat fullMask = Mat::zeros(thresholds[0].size(), CV_8U); + Mat fullMask = Mat::zeros(pipeline_data->thresholds[0].size(), CV_8U); bitwise_not(fullMask, fullMask); return fullMask; } diff --git a/src/openalpr/characteranalysis.h b/src/openalpr/characteranalysis.h index b9d66ad..92d0c2b 100644 --- a/src/openalpr/characteranalysis.h +++ b/src/openalpr/characteranalysis.h @@ -54,7 +54,6 @@ class CharacterAnalysis bool thresholdsInverted; - std::vector thresholds; std::vector > > allContours; std::vector > allHierarchy; std::vector > charSegments; diff --git a/src/openalpr/characterregion.cpp b/src/openalpr/characterregion.cpp index b6e2953..15106f7 100644 --- a/src/openalpr/characterregion.cpp +++ b/src/openalpr/characterregion.cpp @@ -43,10 +43,10 @@ CharacterRegion::CharacterRegion(PipelineData* pipeline_data) if (this->debug && charAnalysis->linePolygon.size() > 0) { vector tempDash; - for (int z = 0; z < charAnalysis->thresholds.size(); z++) + for (int z = 0; z < pipeline_data->thresholds.size(); z++) { - Mat tmp(charAnalysis->thresholds[z].size(), charAnalysis->thresholds[z].type()); - charAnalysis->thresholds[z].copyTo(tmp); + Mat tmp(pipeline_data->thresholds[z].size(), pipeline_data->thresholds[z].type()); + pipeline_data->thresholds[z].copyTo(tmp); cvtColor(tmp, tmp, CV_GRAY2BGR); tempDash.push_back(tmp); diff --git a/src/openalpr/charactersegmenter.cpp b/src/openalpr/charactersegmenter.cpp index 04cf417..62a99fe 100644 --- a/src/openalpr/charactersegmenter.cpp +++ b/src/openalpr/charactersegmenter.cpp @@ -48,7 +48,7 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) if (this->config->debugCharSegmenter) { - displayImage(config, "CharacterSegmenter Thresholds", drawImageDashboard(charAnalysis->thresholds, CV_8U, 3)); + displayImage(config, "CharacterSegmenter Thresholds", drawImageDashboard(pipeline_data->thresholds, CV_8U, 3)); } if (this->config->debugCharSegmenter && charAnalysis->linePolygon.size() > 0) @@ -106,7 +106,7 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) float avgCharWidth = median(charWidths.data(), charWidths.size()); float avgCharHeight = median(charHeights.data(), charHeights.size()); - removeSmallContours(charAnalysis->thresholds, charAnalysis->allContours, avgCharWidth, avgCharHeight); + removeSmallContours(pipeline_data->thresholds, charAnalysis->allContours, avgCharWidth, avgCharHeight); // Do the histogram analysis to figure out char regions @@ -118,11 +118,11 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) vector allBoxes; for (int i = 0; i < charAnalysis->allContours.size(); i++) { - Mat histogramMask = Mat::zeros(charAnalysis->thresholds[i].size(), CV_8U); + Mat histogramMask = Mat::zeros(pipeline_data->thresholds[i].size(), CV_8U); fillConvexPoly(histogramMask, charAnalysis->linePolygon.data(), charAnalysis->linePolygon.size(), Scalar(255,255,255)); - VerticalHistogram vertHistogram(charAnalysis->thresholds[i], histogramMask); + VerticalHistogram vertHistogram(pipeline_data->thresholds[i], histogramMask); if (this->config->debugCharSegmenter) { @@ -172,16 +172,16 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) } //ColorFilter colorFilter(img, charAnalysis->getCharacterMask()); - vector candidateBoxes = getBestCharBoxes(charAnalysis->thresholds[0], allBoxes, medianCharWidth); + vector candidateBoxes = getBestCharBoxes(pipeline_data->thresholds[0], allBoxes, medianCharWidth); if (this->config->debugCharSegmenter) { // Setup the dashboard images to show the cleaning filters - for (int i = 0; i < charAnalysis->thresholds.size(); i++) + for (int i = 0; i < pipeline_data->thresholds.size(); i++) { - Mat cleanImg = Mat::zeros(charAnalysis->thresholds[i].size(), charAnalysis->thresholds[i].type()); - Mat boxMask = getCharBoxMask(charAnalysis->thresholds[i], candidateBoxes); - charAnalysis->thresholds[i].copyTo(cleanImg); + Mat cleanImg = Mat::zeros(pipeline_data->thresholds[i].size(), pipeline_data->thresholds[i].type()); + Mat boxMask = getCharBoxMask(pipeline_data->thresholds[i], candidateBoxes); + pipeline_data->thresholds[i].copyTo(cleanImg); bitwise_and(cleanImg, boxMask, cleanImg); cvtColor(cleanImg, cleanImg, CV_GRAY2BGR); @@ -193,19 +193,19 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) getTime(&startTime); - filterEdgeBoxes(charAnalysis->thresholds, candidateBoxes, medianCharWidth, avgCharHeight); + filterEdgeBoxes(pipeline_data->thresholds, candidateBoxes, medianCharWidth, avgCharHeight); - candidateBoxes = filterMostlyEmptyBoxes(charAnalysis->thresholds, candidateBoxes); + candidateBoxes = filterMostlyEmptyBoxes(pipeline_data->thresholds, candidateBoxes); candidateBoxes = combineCloseBoxes(candidateBoxes, medianCharWidth); - cleanCharRegions(charAnalysis->thresholds, candidateBoxes); - cleanMostlyFullBoxes(charAnalysis->thresholds, candidateBoxes); + cleanCharRegions(pipeline_data->thresholds, candidateBoxes); + cleanMostlyFullBoxes(pipeline_data->thresholds, candidateBoxes); //cleanBasedOnColor(thresholds, colorFilter.colorMask, candidateBoxes); - candidateBoxes = filterMostlyEmptyBoxes(charAnalysis->thresholds, candidateBoxes); - this->characters = candidateBoxes; + candidateBoxes = filterMostlyEmptyBoxes(pipeline_data->thresholds, candidateBoxes); + pipeline_data->charRegions = candidateBoxes; if (config->debugTiming) { @@ -216,7 +216,7 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) if (this->config->debugCharSegmenter) { - Mat imgDash = drawImageDashboard(charAnalysis->thresholds, CV_8U, 3); + Mat imgDash = drawImageDashboard(pipeline_data->thresholds, CV_8U, 3); displayImage(config, "Segmentation after cleaning", imgDash); Mat generalDash = drawImageDashboard(this->imgDbgGeneral, this->imgDbgGeneral[0].type(), 2); @@ -490,7 +490,7 @@ vector CharacterSegmenter::combineCloseBoxes( vector charBoxes, floa newCharBoxes.push_back(bigRect); if (this->config->debugCharSegmenter) { - for (int z = 0; z < charAnalysis->thresholds.size(); z++) + for (int z = 0; z < pipeline_data->thresholds.size(); z++) { Point center(bigRect.x + bigRect.width / 2, bigRect.y + bigRect.height / 2); RotatedRect rrect(center, Size2f(bigRect.width, bigRect.height + (bigRect.height / 2)), 0); @@ -1140,7 +1140,4 @@ Mat CharacterSegmenter::getCharBoxMask(Mat img_threshold, vector charBoxes return mask; } -vector CharacterSegmenter::getThresholds() -{ - return charAnalysis->thresholds; -} + diff --git a/src/openalpr/charactersegmenter.h b/src/openalpr/charactersegmenter.h index 6b958bd..9b9c9ac 100644 --- a/src/openalpr/charactersegmenter.h +++ b/src/openalpr/charactersegmenter.h @@ -50,7 +50,6 @@ class CharacterSegmenter std::vector characters; int confidence; - std::vector getThresholds(); private: Config* config; diff --git a/src/openalpr/licenseplatecandidate.h b/src/openalpr/licenseplatecandidate.h index f63375e..6ec0c71 100644 --- a/src/openalpr/licenseplatecandidate.h +++ b/src/openalpr/licenseplatecandidate.h @@ -51,12 +51,12 @@ class LicensePlateCandidate void recognize(); - CharacterSegmenter* charSegmenter; private: PipelineData* pipeline_data; Config* config; + CharacterSegmenter* charSegmenter; cv::Mat filterByCharacterHue(std::vector > charRegionContours); std::vector findPlateCorners(cv::Mat inputImage, PlateLines plateLines, CharacterRegion charRegion); // top-left, top-right, bottom-right, bottom-left diff --git a/src/openalpr/ocr.cpp b/src/openalpr/ocr.cpp index 5e43e0d..776ea6b 100644 --- a/src/openalpr/ocr.cpp +++ b/src/openalpr/ocr.cpp @@ -52,7 +52,7 @@ OCR::~OCR() delete tesseract; } -void OCR::performOCR(vector thresholds, vector charRegions) +void OCR::performOCR(PipelineData* pipeline_data) { timespec startTime; getTime(&startTime); @@ -60,18 +60,20 @@ void OCR::performOCR(vector thresholds, vector charRegions) postProcessor->clear(); // Don't waste time on OCR processing if it is impossible to get sufficient characters - if (charRegions.size() < config->postProcessMinCharacters) + if (pipeline_data->charRegions.size() < config->postProcessMinCharacters) return; - for (int i = 0; i < thresholds.size(); i++) + for (int i = 0; i < pipeline_data->thresholds.size(); i++) { // Make it black text on white background - bitwise_not(thresholds[i], thresholds[i]); - tesseract->SetImage((uchar*) thresholds[i].data, thresholds[i].size().width, thresholds[i].size().height, thresholds[i].channels(), thresholds[i].step1()); + bitwise_not(pipeline_data->thresholds[i], pipeline_data->thresholds[i]); + tesseract->SetImage((uchar*) pipeline_data->thresholds[i].data, + pipeline_data->thresholds[i].size().width, pipeline_data->thresholds[i].size().height, + pipeline_data->thresholds[i].channels(), pipeline_data->thresholds[i].step1()); - for (int j = 0; j < charRegions.size(); j++) + for (int j = 0; j < pipeline_data->charRegions.size(); j++) { - Rect expandedRegion = expandRect( charRegions[j], 2, 2, thresholds[i].cols, thresholds[i].rows) ; + Rect expandedRegion = expandRect( pipeline_data->charRegions[j], 2, 2, pipeline_data->thresholds[i].cols, pipeline_data->thresholds[i].rows) ; tesseract->SetRectangle(expandedRegion.x, expandedRegion.y, expandedRegion.width, expandedRegion.height); tesseract->Recognize(NULL); diff --git a/src/openalpr/ocr.h b/src/openalpr/ocr.h index 0c9c080..444cb81 100644 --- a/src/openalpr/ocr.h +++ b/src/openalpr/ocr.h @@ -26,6 +26,7 @@ #include "utility.h" #include "postprocess.h" #include "config.h" +#include "pipeline_data.h" #include "constants.h" #include "opencv2/imgproc/imgproc.hpp" @@ -39,7 +40,7 @@ class OCR OCR(Config* config); virtual ~OCR(); - void performOCR(std::vector thresholds, std::vector charRegions); + void performOCR(PipelineData* pipeline_data); PostProcess* postProcessor; //string recognizedText; diff --git a/src/openalpr/pipeline_data.cpp b/src/openalpr/pipeline_data.cpp index d0ccb71..414510d 100644 --- a/src/openalpr/pipeline_data.cpp +++ b/src/openalpr/pipeline_data.cpp @@ -16,4 +16,13 @@ PipelineData::PipelineData(Mat colorImage, Rect regionOfInterest, Config* config PipelineData::~PipelineData() { -} \ No newline at end of file +} + +void PipelineData::clearThresholds() +{ + for (int i = 0; i < thresholds.size(); i++) + { + thresholds[i].release(); + } + thresholds.clear(); +} diff --git a/src/openalpr/pipeline_data.h b/src/openalpr/pipeline_data.h index b4853ab..b403b10 100644 --- a/src/openalpr/pipeline_data.h +++ b/src/openalpr/pipeline_data.h @@ -13,6 +13,8 @@ class PipelineData PipelineData(cv::Mat colorImage, cv::Rect regionOfInterest, Config* config); virtual ~PipelineData(); + void clearThresholds(); + // Inputs Config* config; @@ -35,6 +37,7 @@ class PipelineData float overall_confidence; + std::vector charRegions; // Plate Lines std::vector horizontalLines; From 717f1f0e7e565825d2f94ad2cd62136337e69ad6 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 19:00:15 -0400 Subject: [PATCH 07/12] Remove thresholds when pipeline_data goes out of scope --- src/openalpr/pipeline_data.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/openalpr/pipeline_data.cpp b/src/openalpr/pipeline_data.cpp index 414510d..6aec753 100644 --- a/src/openalpr/pipeline_data.cpp +++ b/src/openalpr/pipeline_data.cpp @@ -16,6 +16,7 @@ PipelineData::PipelineData(Mat colorImage, Rect regionOfInterest, Config* config PipelineData::~PipelineData() { + clearThresholds(); } void PipelineData::clearThresholds() From 0708523131c768ea3a2d72bf99fcd79255078158 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 19:01:22 -0400 Subject: [PATCH 08/12] Moved public variable to private --- src/openalpr/characterregion.h | 2 +- src/openalpr/platelines.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openalpr/characterregion.h b/src/openalpr/characterregion.h index a4eabe4..ee2a8f0 100644 --- a/src/openalpr/characterregion.h +++ b/src/openalpr/characterregion.h @@ -34,7 +34,6 @@ class CharacterRegion CharacterRegion(PipelineData* pipeline_data); virtual ~CharacterRegion(); - CharacterAnalysis *charAnalysis; int confidence; @@ -52,6 +51,7 @@ class CharacterRegion Config* config; bool debug; + CharacterAnalysis *charAnalysis; cv::Mat findOuterBoxMask(std::vector thresholds, std::vector > > allContours, std::vector > allHierarchy); std::vector filter(cv::Mat img, std::vector > contours, std::vector hierarchy); diff --git a/src/openalpr/platelines.cpp b/src/openalpr/platelines.cpp index 10e13fc..df53cab 100644 --- a/src/openalpr/platelines.cpp +++ b/src/openalpr/platelines.cpp @@ -67,7 +67,7 @@ void PlateLines::processImage(Mat inputImage, CharacterRegion* charRegion, float // Create a mask that is dilated based on the detected characters vector > polygons; - polygons.push_back(charRegion->charAnalysis->charArea); + polygons.push_back(charRegion->getCharArea()); Mat mask = Mat::zeros(inputImage.size(), CV_8U); fillPoly(mask, polygons, Scalar(255,255,255)); From c8f52ccb48f7933526def962866d35dad4b1a577 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 19:02:53 -0400 Subject: [PATCH 09/12] Removed redundant variable --- src/misc_utilities/classifychars.cpp | 14 +++++++------- src/openalpr/charactersegmenter.h | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/misc_utilities/classifychars.cpp b/src/misc_utilities/classifychars.cpp index 09fc44a..ff49541 100644 --- a/src/misc_utilities/classifychars.cpp +++ b/src/misc_utilities/classifychars.cpp @@ -161,9 +161,9 @@ int main( int argc, const char** argv ) int curDashboardSelection = 0; - vector humanInputs(charSegmenter.characters.size()); + vector humanInputs(pipeline_data.charRegions.size()); - for (int z = 0; z < charSegmenter.characters.size(); z++) + for (int z = 0; z < pipeline_data.charRegions.size(); z++) humanInputs[z] = ' '; showDashboard(pipeline_data.thresholds, selectedBoxes, 0); @@ -198,8 +198,8 @@ int main( int argc, const char** argv ) } else if (waitkey == ENTER_KEY) { - vector tempdata = showCharSelection(pipeline_data.thresholds[curDashboardSelection], charSegmenter.characters, statecodestr); - for (int c = 0; c < charSegmenter.characters.size(); c++) + vector tempdata = showCharSelection(pipeline_data.thresholds[curDashboardSelection], pipeline_data.charRegions, statecodestr); + for (int c = 0; c < pipeline_data.charRegions.size(); c++) humanInputs[c] = tempdata[c]; } else if (waitkey == SPACE_KEY) @@ -227,7 +227,7 @@ int main( int argc, const char** argv ) break; } } - for (int c = 0; c < charSegmenter.characters.size(); c++) + for (int c = 0; c < pipeline_data.charRegions.size(); c++) { if (humanInputs[c] != ' ') { @@ -238,7 +238,7 @@ int main( int argc, const char** argv ) // Save if (somethingSelected && chardataTagged) { - for (int c = 0; c < charSegmenter.characters.size(); c++) + for (int c = 0; c < pipeline_data.charRegions.size(); c++) { if (humanInputs[c] == ' ') continue; @@ -249,7 +249,7 @@ int main( int argc, const char** argv ) continue; stringstream filename; - Mat cropped = pipeline_data.thresholds[t](charSegmenter.characters[c]); + Mat cropped = pipeline_data.thresholds[t](pipeline_data.charRegions[c]); filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i]; imwrite(filename.str(), cropped); cout << "Writing char image: " << filename.str() << endl; diff --git a/src/openalpr/charactersegmenter.h b/src/openalpr/charactersegmenter.h index 9b9c9ac..12373fd 100644 --- a/src/openalpr/charactersegmenter.h +++ b/src/openalpr/charactersegmenter.h @@ -47,7 +47,6 @@ class CharacterSegmenter CharacterSegmenter(PipelineData* pipeline_data); virtual ~CharacterSegmenter(); - std::vector characters; int confidence; From cff0df3648dfac40cf5f64fd40b3e21ff5fe92c0 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 19:30:57 -0400 Subject: [PATCH 10/12] Moved plate confidence up to pipeline_data --- src/misc_utilities/benchmark/benchmark.cpp | 2 +- src/openalpr/alpr_impl.cpp | 2 +- src/openalpr/licenseplatecandidate.cpp | 5 ++--- src/openalpr/licenseplatecandidate.h | 2 -- src/openalpr/pipeline_data.h | 6 ++---- src/openalpr/platecorners.cpp | 4 ---- 6 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/misc_utilities/benchmark/benchmark.cpp b/src/misc_utilities/benchmark/benchmark.cpp index d09efce..eb1e3fa 100644 --- a/src/misc_utilities/benchmark/benchmark.cpp +++ b/src/misc_utilities/benchmark/benchmark.cpp @@ -232,7 +232,7 @@ int main( int argc, const char** argv ) double analysisTime = diffclock(startTime, endTime); cout << "\tRegion " << z << ": Analysis time: " << analysisTime << "ms." << endl; - if (lp.confidence > 10) + if (pipeline_data.plate_area_confidence > 10) { lpAnalysisPositiveTimes.push_back(analysisTime); diff --git a/src/openalpr/alpr_impl.cpp b/src/openalpr/alpr_impl.cpp index e79bbad..ae72216 100644 --- a/src/openalpr/alpr_impl.cpp +++ b/src/openalpr/alpr_impl.cpp @@ -196,7 +196,7 @@ void plateAnalysisThread(void* arg) lp.recognize(); - if (lp.confidence <= 10) + if (pipeline_data.plate_area_confidence <= 10) { // Not a valid plate // Check if this plate has any children, if so, send them back up to the dispatcher for processing diff --git a/src/openalpr/licenseplatecandidate.cpp b/src/openalpr/licenseplatecandidate.cpp index f318727..8058a0f 100644 --- a/src/openalpr/licenseplatecandidate.cpp +++ b/src/openalpr/licenseplatecandidate.cpp @@ -39,7 +39,7 @@ void LicensePlateCandidate::recognize() { charSegmenter = NULL; - this->confidence = 0; + pipeline_data->plate_area_confidence = 0; int expandX = round(this->pipeline_data->regionOfInterest.width * 0.20); int expandY = round(this->pipeline_data->regionOfInterest.height * 0.15); @@ -55,7 +55,6 @@ void LicensePlateCandidate::recognize() if (charRegion.confidence > 10) { PlateLines plateLines(config); - //Mat boogedy = charRegion.getPlateMask(); plateLines.processImage(pipeline_data->plate_mask, &charRegion, 1.10); plateLines.processImage(pipeline_data->crop_gray, &charRegion, 0.9); @@ -74,7 +73,7 @@ void LicensePlateCandidate::recognize() //this->recognizedText = ocr->recognizedText; //strcpy(this->recognizedText, ocr.recognizedText); - this->confidence = 100; + pipeline_data->plate_area_confidence = 100; } charRegion.confidence = 0; } diff --git a/src/openalpr/licenseplatecandidate.h b/src/openalpr/licenseplatecandidate.h index 6ec0c71..e64adee 100644 --- a/src/openalpr/licenseplatecandidate.h +++ b/src/openalpr/licenseplatecandidate.h @@ -46,8 +46,6 @@ class LicensePlateCandidate LicensePlateCandidate(PipelineData* pipeline_data); virtual ~LicensePlateCandidate(); - float confidence; // 0-100 - //vector points; // top-left, top-right, bottom-right, bottom-left void recognize(); diff --git a/src/openalpr/pipeline_data.h b/src/openalpr/pipeline_data.h index b403b10..6e21438 100644 --- a/src/openalpr/pipeline_data.h +++ b/src/openalpr/pipeline_data.h @@ -35,13 +35,11 @@ class PipelineData std::string region_code; float region_confidence; - float overall_confidence; + + float plate_area_confidence; std::vector charRegions; - // Plate Lines - std::vector horizontalLines; - std::vector verticalLines; diff --git a/src/openalpr/platecorners.cpp b/src/openalpr/platecorners.cpp index 453a930..bdec822 100644 --- a/src/openalpr/platecorners.cpp +++ b/src/openalpr/platecorners.cpp @@ -40,10 +40,6 @@ PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegi Point bottomPoint = charRegion->getBottomLine().closestPointOnSegmentTo(topPoint); this->charHeight = distanceBetweenPoints(topPoint, bottomPoint); - //this->charHeight = distanceBetweenPoints(charRegion->getCharArea()[0], charRegion->getCharArea()[3]); - //this->charHeight = this->charHeight - 2; // Adjust since this height is a box around our char. - // Adjust the char height for the difference in size... - //this->charHeight = ((float) inputImage.size().height / (float) TEMPLATE_PLATE_HEIGHT) * this->charHeight; this->charAngle = angleBetweenPoints(charRegion->getCharArea()[0], charRegion->getCharArea()[1]); } From 43b025b6233717f60da3aa177cabfb0174f349c0 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 1 Jul 2014 19:34:59 -0400 Subject: [PATCH 11/12] Added segment/segmentationgroup --- src/openalpr/segmentation/segment.cpp | 50 +++++++++++++++++++ src/openalpr/segmentation/segment.h | 41 +++++++++++++++ .../segmentation/segmentationgroup.cpp | 49 ++++++++++++++++++ src/openalpr/segmentation/segmentationgroup.h | 50 +++++++++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 src/openalpr/segmentation/segment.cpp create mode 100644 src/openalpr/segmentation/segment.h create mode 100644 src/openalpr/segmentation/segmentationgroup.cpp create mode 100644 src/openalpr/segmentation/segmentationgroup.h diff --git a/src/openalpr/segmentation/segment.cpp b/src/openalpr/segmentation/segment.cpp new file mode 100644 index 0000000..1650cc5 --- /dev/null +++ b/src/openalpr/segmentation/segment.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 New Designs Unlimited, LLC + * Opensource Automated License Plate Recognition [http://www.openalpr.com] + * + * This file is part of OpenAlpr. + * + * OpenAlpr is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License + * version 3 as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +*/ + +#include "segment.h" + +Segment::Segment(cv::Rect newSegment) +{ + this->segment = newSegment; +} + +Segment::~Segment() +{ + +} + +bool Segment::matches(cv::Rect newSegment) +{ + // Compare the two segments with a given leniency + const float WIDTH_LENIENCY_MIN = 0.25; + const float WIDTH_LENIENCY_MAX = 0.20; + + float left_min = segment.x - (((float)segment.width) * WIDTH_LENIENCY_MIN); + float left_max = segment.x + (((float)segment.width) * WIDTH_LENIENCY_MAX); + float right_min = (segment.x + segment.width) - (((float)segment.width) * WIDTH_LENIENCY_MIN); + float right_max = (segment.x + segment.width) + (((float)segment.width) * WIDTH_LENIENCY_MAX); + + int newSegRight = newSegment.x + newSegment.width; + if (newSegment.x >= left_min && newSegment.x <= left_max && + newSegRight >= right_min && newSegRight <= right_max) + return true; + + return false; +} + diff --git a/src/openalpr/segmentation/segment.h b/src/openalpr/segmentation/segment.h new file mode 100644 index 0000000..7743ab6 --- /dev/null +++ b/src/openalpr/segmentation/segment.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 New Designs Unlimited, LLC + * Opensource Automated License Plate Recognition [http://www.openalpr.com] + * + * This file is part of OpenAlpr. + * + * OpenAlpr is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License + * version 3 as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +*/ + +#ifndef OPENALPR_SEGMENT_H +#define OPENALPR_SEGMENT_H + +#include +#include + +#include "opencv2/imgproc/imgproc.hpp" + +class Segment +{ + + public: + Segment(cv::Rect newSegment); + virtual ~Segment(); + + cv::Rect segment; + + bool matches(cv::Rect newSegment); + +}; + +#endif // OPENALPR_SEGMENTATIONGROUP_H diff --git a/src/openalpr/segmentation/segmentationgroup.cpp b/src/openalpr/segmentation/segmentationgroup.cpp new file mode 100644 index 0000000..a146364 --- /dev/null +++ b/src/openalpr/segmentation/segmentationgroup.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 New Designs Unlimited, LLC + * Opensource Automated License Plate Recognition [http://www.openalpr.com] + * + * This file is part of OpenAlpr. + * + * OpenAlpr is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License + * version 3 as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +*/ + +#include "segmentationgroup.h" + +SegmentationGroup::SegmentationGroup() +{ + +} + +SegmentationGroup::~SegmentationGroup() +{ + +} + +void SegmentationGroup::add(int segmentID) +{ + this->segmentIDs.push_back(segmentID); +} + +bool SegmentationGroup::equals(SegmentationGroup otherGroup) +{ + if (segmentIDs.size() != otherGroup.segmentIDs.size()) + return false; + + for (int i = 0; i < segmentIDs.size(); i++) + { + if (otherGroup.segmentIDs[i] != segmentIDs[i]) + return false; + } + + return true; +} \ No newline at end of file diff --git a/src/openalpr/segmentation/segmentationgroup.h b/src/openalpr/segmentation/segmentationgroup.h new file mode 100644 index 0000000..d9cc633 --- /dev/null +++ b/src/openalpr/segmentation/segmentationgroup.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 New Designs Unlimited, LLC + * Opensource Automated License Plate Recognition [http://www.openalpr.com] + * + * This file is part of OpenAlpr. + * + * OpenAlpr is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License + * version 3 as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +*/ + +#ifndef OPENALPR_SEGMENTATIONGROUP_H +#define OPENALPR_SEGMENTATIONGROUP_H + +#include +#include + +#include "opencv2/imgproc/imgproc.hpp" + +#include "segment.h" + + +class SegmentationGroup +{ + + public: + SegmentationGroup(); + virtual ~SegmentationGroup(); + + void add(int segmentID); + + std::vector segmentIDs; + + bool equals(SegmentationGroup otherGroup); + + + private: + float strength; // Debuggin purposes -- how many threshold segmentations match this one perfectly + +}; + +#endif // OPENALPR_SEGMENTATIONGROUP_H From 344b51ead83103d5b48024ac45bf4837cc633ac4 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Sun, 29 Jun 2014 13:16:32 -0400 Subject: [PATCH 12/12] Moved character segmentation code to its own directory Conflicts: src/openalpr/CMakeLists.txt --- src/openalpr/CMakeLists.txt | 4 ++-- src/openalpr/alpr_impl.h | 2 +- src/openalpr/licenseplatecandidate.h | 2 +- src/openalpr/{ => segmentation}/charactersegmenter.cpp | 0 src/openalpr/{ => segmentation}/charactersegmenter.h | 0 src/openalpr/{ => segmentation}/verticalhistogram.cpp | 0 src/openalpr/{ => segmentation}/verticalhistogram.h | 0 7 files changed, 4 insertions(+), 4 deletions(-) rename src/openalpr/{ => segmentation}/charactersegmenter.cpp (100%) rename src/openalpr/{ => segmentation}/charactersegmenter.h (100%) rename src/openalpr/{ => segmentation}/verticalhistogram.cpp (100%) rename src/openalpr/{ => segmentation}/verticalhistogram.h (100%) diff --git a/src/openalpr/CMakeLists.txt b/src/openalpr/CMakeLists.txt index aba5435..b5e2056 100644 --- a/src/openalpr/CMakeLists.txt +++ b/src/openalpr/CMakeLists.txt @@ -16,11 +16,11 @@ set(lpr_source_files binarize_wolf.cpp platelines.cpp characterregion.cpp - charactersegmenter.cpp + segmentation/charactersegmenter.cpp + segmentation/verticalhistogram.cpp platecorners.cpp colorfilter.cpp characteranalysis.cpp - verticalhistogram.cpp pipeline_data.cpp trex.c cjson.c diff --git a/src/openalpr/alpr_impl.h b/src/openalpr/alpr_impl.h index 77db817..7263812 100644 --- a/src/openalpr/alpr_impl.h +++ b/src/openalpr/alpr_impl.h @@ -30,7 +30,7 @@ #include "regiondetector.h" #include "licenseplatecandidate.h" #include "stateidentifier.h" -#include "charactersegmenter.h" +#include "segmentation/charactersegmenter.h" #include "ocr.h" #include "constants.h" diff --git a/src/openalpr/licenseplatecandidate.h b/src/openalpr/licenseplatecandidate.h index e64adee..9143efe 100644 --- a/src/openalpr/licenseplatecandidate.h +++ b/src/openalpr/licenseplatecandidate.h @@ -31,7 +31,7 @@ #include "constants.h" #include "platelines.h" #include "characterregion.h" -#include "charactersegmenter.h" +#include "segmentation/charactersegmenter.h" #include "platecorners.h" #include "config.h" #include "pipeline_data.h" diff --git a/src/openalpr/charactersegmenter.cpp b/src/openalpr/segmentation/charactersegmenter.cpp similarity index 100% rename from src/openalpr/charactersegmenter.cpp rename to src/openalpr/segmentation/charactersegmenter.cpp diff --git a/src/openalpr/charactersegmenter.h b/src/openalpr/segmentation/charactersegmenter.h similarity index 100% rename from src/openalpr/charactersegmenter.h rename to src/openalpr/segmentation/charactersegmenter.h diff --git a/src/openalpr/verticalhistogram.cpp b/src/openalpr/segmentation/verticalhistogram.cpp similarity index 100% rename from src/openalpr/verticalhistogram.cpp rename to src/openalpr/segmentation/verticalhistogram.cpp diff --git a/src/openalpr/verticalhistogram.h b/src/openalpr/segmentation/verticalhistogram.h similarity index 100% rename from src/openalpr/verticalhistogram.h rename to src/openalpr/segmentation/verticalhistogram.h