diff --git a/config/openalpr.conf.in b/config/openalpr.conf.in
index b7761ff..d8db036 100644
--- a/config/openalpr.conf.in
+++ b/config/openalpr.conf.in
@@ -57,7 +57,6 @@ timing = 0
state_id = 0
plate_lines = 0
plate_corners = 0
-char_regions = 0
char_segment = 0
char_analysis = 0
color_filter = 0
diff --git a/src/misc_utilities/benchmarks/benchmark.cpp b/src/misc_utilities/benchmarks/benchmark.cpp
index ccc24c3..35b3f7f 100644
--- a/src/misc_utilities/benchmarks/benchmark.cpp
+++ b/src/misc_utilities/benchmarks/benchmark.cpp
@@ -114,7 +114,7 @@ int main( int argc, const char** argv )
statecode[2] = '\0';
string statecodestr(statecode);
- CharacterRegion charRegion(&pipeline_data);
+ CharacterAnalysis charRegion(&pipeline_data);
if (pipeline_data.textLines.size() > 0 &&
abs(pipeline_data.textLines[0].angle) > 4)
diff --git a/src/misc_utilities/classifychars.cpp b/src/misc_utilities/classifychars.cpp
index 27448aa..a92723a 100644
--- a/src/misc_utilities/classifychars.cpp
+++ b/src/misc_utilities/classifychars.cpp
@@ -132,7 +132,7 @@ int main( int argc, const char** argv )
statecode[2] = '\0';
string statecodestr(statecode);
- CharacterRegion regionizer(&pipeline_data);
+ CharacterAnalysis regionizer(&pipeline_data);
if (abs(pipeline_data.textLines[0].angle) > 4)
{
diff --git a/src/openalpr/CMakeLists.txt b/src/openalpr/CMakeLists.txt
index 2467186..ec4ac95 100644
--- a/src/openalpr/CMakeLists.txt
+++ b/src/openalpr/CMakeLists.txt
@@ -16,7 +16,6 @@ set(lpr_source_files
postprocess.cpp
binarize_wolf.cpp
platelines.cpp
- characterregion.cpp
segmentation/charactersegmenter.cpp
segmentation/verticalhistogram.cpp
platecorners.cpp
diff --git a/src/openalpr/characterregion.cpp b/src/openalpr/characterregion.cpp
deleted file mode 100644
index e3e3e1c..0000000
--- a/src/openalpr/characterregion.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2014 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 "characterregion.h"
-
-using namespace cv;
-using namespace std;
-
-CharacterRegion::CharacterRegion(PipelineData* pipeline_data)
-{
- this->config = pipeline_data->config;
- this->debug = config->debugCharRegions;
-
- this->confidence = 0;
-
- if (this->debug)
- cout << "Starting CharacterRegion identification" << endl;
-
- timespec startTime;
- getTime(&startTime);
-
- charAnalysis = new CharacterAnalysis(pipeline_data);
- charAnalysis->analyze();
- pipeline_data->plate_inverted = charAnalysis->thresholdsInverted;
-
- if (this->debug && pipeline_data->textLines.size() > 0)
- {
- vector tempDash;
- for (uint z = 0; z < pipeline_data->thresholds.size(); z++)
- {
- 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);
- }
-
- Mat bestVal(charAnalysis->bestThreshold.size(), charAnalysis->bestThreshold.type());
- charAnalysis->bestThreshold.copyTo(bestVal);
- cvtColor(bestVal, bestVal, CV_GRAY2BGR);
-
- for (uint z = 0; z < charAnalysis->bestContours.size(); z++)
- {
- Scalar dcolor(255,0,0);
- if (charAnalysis->bestContours.goodIndices[z])
- dcolor = Scalar(0,255,0);
- drawContours(bestVal, charAnalysis->bestContours.contours, z, dcolor, 1);
- }
- tempDash.push_back(bestVal);
- displayImage(config, "Character Region Step 1 Thresholds", drawImageDashboard(tempDash, bestVal.type(), 3));
- }
-
-
- if (pipeline_data->textLines.size() > 0)
- {
- int confidenceDrainers = 0;
- int charSegmentCount = charAnalysis->bestContours.getGoodIndicesCount();
- if (charSegmentCount == 1)
- confidenceDrainers += 91;
- else if (charSegmentCount < 5)
- confidenceDrainers += (5 - charSegmentCount) * 10;
-
- // Use the angle for the first line -- assume they'll always be parallel for multi-line plates
- int absangle = abs(pipeline_data->textLines[0].topLine.angle);
- if (absangle > config->maxPlateAngleDegrees)
- confidenceDrainers += 91;
- else if (absangle > 1)
- confidenceDrainers += (config->maxPlateAngleDegrees - absangle) ;
-
- // If a multiline plate has only one line, disqualify
- if (pipeline_data->isMultiline && pipeline_data->textLines.size() < 2)
- confidenceDrainers += 95;
-
- if (confidenceDrainers >= 100)
- this->confidence=1;
- else
- this->confidence = 100 - confidenceDrainers;
- }
-
- if (config->debugTiming)
- {
- timespec endTime;
- getTime(&endTime);
- cout << "Character Region Time: " << diffclock(startTime, endTime) << "ms." << endl;
- }
-}
-
-CharacterRegion::~CharacterRegion()
-{
- delete(charAnalysis);
-}
-
-
diff --git a/src/openalpr/characterregion.h b/src/openalpr/characterregion.h
deleted file mode 100644
index ba55624..0000000
--- a/src/openalpr/characterregion.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014 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_CHARACTERREGION_H
-#define OPENALPR_CHARACTERREGION_H
-
-#include "opencv2/imgproc/imgproc.hpp"
-#include "constants.h"
-#include "utility.h"
-#include "textdetection/characteranalysis.h"
-#include "config.h"
-#include "pipeline_data.h"
-
-class CharacterRegion
-{
-
- public:
- CharacterRegion(PipelineData* pipeline_data);
- virtual ~CharacterRegion();
-
-
- int confidence;
-
-
-
- protected:
- Config* config;
- bool debug;
-
- CharacterAnalysis *charAnalysis;
- cv::Mat findOuterBoxMask(std::vector thresholds, std::vector > > allContours, std::vector > allHierarchy);
-
-
- bool isPlateInverted(cv::Mat threshold, std::vector > contours, std::vector hierarchy, std::vector goodIndices);
-
-};
-
-#endif // OPENALPR_CHARACTERREGION_H
diff --git a/src/openalpr/config.cpp b/src/openalpr/config.cpp
index 2f30a29..81a1fe4 100644
--- a/src/openalpr/config.cpp
+++ b/src/openalpr/config.cpp
@@ -188,7 +188,6 @@ void Config::loadValues(string country)
debugStateId = getBoolean("debug", "state_id", false);
debugPlateLines = getBoolean("debug", "plate_lines", false);
debugPlateCorners = getBoolean("debug", "plate_corners", false);
- debugCharRegions = getBoolean("debug", "char_regions", false);
debugCharSegmenter = getBoolean("debug", "char_segment", false);
debugCharAnalysis = getBoolean("debug", "char_analysis", false);
debugColorFiler = getBoolean("debug", "color_filter", false);
@@ -206,7 +205,6 @@ void Config::debugOff()
debugStateId = false;
debugPlateLines = false;
debugPlateCorners = false;
- debugCharRegions = false;
debugCharSegmenter = false;
debugCharAnalysis = false;
debugColorFiler = false;
diff --git a/src/openalpr/config.h b/src/openalpr/config.h
index 7477b79..a752441 100644
--- a/src/openalpr/config.h
+++ b/src/openalpr/config.h
@@ -103,7 +103,6 @@ class Config
bool debugStateId;
bool debugPlateLines;
bool debugPlateCorners;
- bool debugCharRegions;
bool debugCharSegmenter;
bool debugCharAnalysis;
bool debugColorFiler;
diff --git a/src/openalpr/licenseplatecandidate.cpp b/src/openalpr/licenseplatecandidate.cpp
index 9adc533..c7fda6b 100644
--- a/src/openalpr/licenseplatecandidate.cpp
+++ b/src/openalpr/licenseplatecandidate.cpp
@@ -51,9 +51,9 @@ void LicensePlateCandidate::recognize()
resize(pipeline_data->crop_gray, pipeline_data->crop_gray, Size(config->templateWidthPx, config->templateHeightPx));
- CharacterRegion charRegion(pipeline_data);
+ CharacterAnalysis textAnalysis(pipeline_data);
- if (charRegion.confidence > 10)
+ if (textAnalysis.confidence > 10)
{
PlateLines plateLines(pipeline_data);
@@ -119,7 +119,7 @@ void LicensePlateCandidate::recognize()
pipeline_data->plate_area_confidence = 100;
}
- charRegion.confidence = 0;
+
}
}
diff --git a/src/openalpr/licenseplatecandidate.h b/src/openalpr/licenseplatecandidate.h
index 63534f5..aeb76af 100644
--- a/src/openalpr/licenseplatecandidate.h
+++ b/src/openalpr/licenseplatecandidate.h
@@ -30,7 +30,7 @@
#include "utility.h"
#include "constants.h"
#include "platelines.h"
-#include "characterregion.h"
+#include "textdetection/characteranalysis.h"
#include "segmentation/charactersegmenter.h"
#include "platecorners.h"
#include "config.h"
@@ -57,7 +57,7 @@ class LicensePlateCandidate
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
+ std::vector findPlateCorners(cv::Mat inputImage, PlateLines plateLines, CharacterAnalysis textAnalysis); // top-left, top-right, bottom-right, bottom-left
cv::Size getOutputImageSize(std::vector corners);
std::vector transformPointsToOriginalImage(cv::Mat bigImage, cv::Mat smallImage, cv::Rect region, std::vector corners);
diff --git a/src/openalpr/platecorners.h b/src/openalpr/platecorners.h
index 5fc06df..c297513 100644
--- a/src/openalpr/platecorners.h
+++ b/src/openalpr/platecorners.h
@@ -21,7 +21,6 @@
#define OPENALPR_PLATECORNERS_H
#include "opencv2/imgproc/imgproc.hpp"
-#include "characterregion.h"
#include "platelines.h"
#include "utility.h"
#include "config.h"
diff --git a/src/openalpr/platelines.h b/src/openalpr/platelines.h
index 40a9016..f25be91 100644
--- a/src/openalpr/platelines.h
+++ b/src/openalpr/platelines.h
@@ -25,7 +25,7 @@
#include "utility.h"
#include "binarize_wolf.h"
#include "config.h"
-#include "characterregion.h"
+#include "pipeline_data.h"
struct PlateLine
{
diff --git a/src/openalpr/segmentation/charactersegmenter.h b/src/openalpr/segmentation/charactersegmenter.h
index b468e62..54b9c22 100644
--- a/src/openalpr/segmentation/charactersegmenter.h
+++ b/src/openalpr/segmentation/charactersegmenter.h
@@ -24,11 +24,10 @@
#include "constants.h"
#include "binarize_wolf.h"
#include "utility.h"
-#include "characterregion.h"
-#include "colorfilter.h"
#include "verticalhistogram.h"
#include "config.h"
#include "textdetection/textcontours.h"
+#include "pipeline_data.h"
//const float MIN_BOX_WIDTH_PX = 4; // 4 pixels
diff --git a/src/openalpr/textdetection/characteranalysis.cpp b/src/openalpr/textdetection/characteranalysis.cpp
index d959ff5..1b9f25b 100644
--- a/src/openalpr/textdetection/characteranalysis.cpp
+++ b/src/openalpr/textdetection/characteranalysis.cpp
@@ -32,10 +32,12 @@ CharacterAnalysis::CharacterAnalysis(PipelineData* pipeline_data)
this->pipeline_data = pipeline_data;
this->config = pipeline_data->config;
+ this->confidence = 0;
if (this->config->debugCharAnalysis)
cout << "Starting CharacterAnalysis identification" << endl;
+ this->analyze();
}
CharacterAnalysis::~CharacterAnalysis()
@@ -168,8 +170,70 @@ void CharacterAnalysis::analyze()
}
+ pipeline_data->plate_inverted = isPlateInverted();
- this->thresholdsInverted = isPlateInverted();
+
+ if (pipeline_data->textLines.size() > 0)
+ {
+ int confidenceDrainers = 0;
+ int charSegmentCount = this->bestContours.getGoodIndicesCount();
+ if (charSegmentCount == 1)
+ confidenceDrainers += 91;
+ else if (charSegmentCount < 5)
+ confidenceDrainers += (5 - charSegmentCount) * 10;
+
+ // Use the angle for the first line -- assume they'll always be parallel for multi-line plates
+ int absangle = abs(pipeline_data->textLines[0].topLine.angle);
+ if (absangle > config->maxPlateAngleDegrees)
+ confidenceDrainers += 91;
+ else if (absangle > 1)
+ confidenceDrainers += (config->maxPlateAngleDegrees - absangle) ;
+
+ // If a multiline plate has only one line, disqualify
+ if (pipeline_data->isMultiline && pipeline_data->textLines.size() < 2)
+ confidenceDrainers += 95;
+
+ if (confidenceDrainers >= 100)
+ this->confidence=1;
+ else
+ this->confidence = 100 - confidenceDrainers;
+ }
+
+
+ if (config->debugTiming)
+ {
+ timespec endTime;
+ getTime(&endTime);
+ cout << "Character Analysis Time: " << diffclock(startTime, endTime) << "ms." << endl;
+ }
+
+ // Draw debug dashboard
+ if (this->pipeline_data->config->debugCharAnalysis && pipeline_data->textLines.size() > 0)
+ {
+ vector tempDash;
+ for (uint z = 0; z < pipeline_data->thresholds.size(); z++)
+ {
+ 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);
+ }
+
+ Mat bestVal(this->bestThreshold.size(), this->bestThreshold.type());
+ this->bestThreshold.copyTo(bestVal);
+ cvtColor(bestVal, bestVal, CV_GRAY2BGR);
+
+ for (uint z = 0; z < this->bestContours.size(); z++)
+ {
+ Scalar dcolor(255,0,0);
+ if (this->bestContours.goodIndices[z])
+ dcolor = Scalar(0,255,0);
+ drawContours(bestVal, this->bestContours.contours, z, dcolor, 1);
+ }
+ tempDash.push_back(bestVal);
+ displayImage(config, "Character Region Step 1 Thresholds", drawImageDashboard(tempDash, bestVal.type(), 3));
+ }
}
diff --git a/src/openalpr/textdetection/characteranalysis.h b/src/openalpr/textdetection/characteranalysis.h
index 6223cd8..830ea32 100644
--- a/src/openalpr/textdetection/characteranalysis.h
+++ b/src/openalpr/textdetection/characteranalysis.h
@@ -36,12 +36,12 @@ class CharacterAnalysis
CharacterAnalysis(PipelineData* pipeline_data);
virtual ~CharacterAnalysis();
+ int confidence;
cv::Mat bestThreshold;
TextContours bestContours;
- bool thresholdsInverted;
std::vector allTextContours;