mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-06 06:46:53 +08:00
Removed characterregion class.
This was just serving as a pass-through after recent changes
This commit is contained in:
@@ -57,7 +57,6 @@ timing = 0
|
|||||||
state_id = 0
|
state_id = 0
|
||||||
plate_lines = 0
|
plate_lines = 0
|
||||||
plate_corners = 0
|
plate_corners = 0
|
||||||
char_regions = 0
|
|
||||||
char_segment = 0
|
char_segment = 0
|
||||||
char_analysis = 0
|
char_analysis = 0
|
||||||
color_filter = 0
|
color_filter = 0
|
||||||
|
@@ -114,7 +114,7 @@ int main( int argc, const char** argv )
|
|||||||
statecode[2] = '\0';
|
statecode[2] = '\0';
|
||||||
string statecodestr(statecode);
|
string statecodestr(statecode);
|
||||||
|
|
||||||
CharacterRegion charRegion(&pipeline_data);
|
CharacterAnalysis charRegion(&pipeline_data);
|
||||||
|
|
||||||
if (pipeline_data.textLines.size() > 0 &&
|
if (pipeline_data.textLines.size() > 0 &&
|
||||||
abs(pipeline_data.textLines[0].angle) > 4)
|
abs(pipeline_data.textLines[0].angle) > 4)
|
||||||
|
@@ -132,7 +132,7 @@ int main( int argc, const char** argv )
|
|||||||
statecode[2] = '\0';
|
statecode[2] = '\0';
|
||||||
string statecodestr(statecode);
|
string statecodestr(statecode);
|
||||||
|
|
||||||
CharacterRegion regionizer(&pipeline_data);
|
CharacterAnalysis regionizer(&pipeline_data);
|
||||||
|
|
||||||
if (abs(pipeline_data.textLines[0].angle) > 4)
|
if (abs(pipeline_data.textLines[0].angle) > 4)
|
||||||
{
|
{
|
||||||
|
@@ -16,7 +16,6 @@ set(lpr_source_files
|
|||||||
postprocess.cpp
|
postprocess.cpp
|
||||||
binarize_wolf.cpp
|
binarize_wolf.cpp
|
||||||
platelines.cpp
|
platelines.cpp
|
||||||
characterregion.cpp
|
|
||||||
segmentation/charactersegmenter.cpp
|
segmentation/charactersegmenter.cpp
|
||||||
segmentation/verticalhistogram.cpp
|
segmentation/verticalhistogram.cpp
|
||||||
platecorners.cpp
|
platecorners.cpp
|
||||||
|
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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<Mat> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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<cv::Mat> thresholds, std::vector<std::vector<std::vector<cv::Point> > > allContours, std::vector<std::vector<cv::Vec4i> > allHierarchy);
|
|
||||||
|
|
||||||
|
|
||||||
bool isPlateInverted(cv::Mat threshold, std::vector<std::vector<cv::Point> > contours, std::vector<cv::Vec4i> hierarchy, std::vector<bool> goodIndices);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // OPENALPR_CHARACTERREGION_H
|
|
@@ -188,7 +188,6 @@ void Config::loadValues(string country)
|
|||||||
debugStateId = getBoolean("debug", "state_id", false);
|
debugStateId = getBoolean("debug", "state_id", false);
|
||||||
debugPlateLines = getBoolean("debug", "plate_lines", false);
|
debugPlateLines = getBoolean("debug", "plate_lines", false);
|
||||||
debugPlateCorners = getBoolean("debug", "plate_corners", false);
|
debugPlateCorners = getBoolean("debug", "plate_corners", false);
|
||||||
debugCharRegions = getBoolean("debug", "char_regions", false);
|
|
||||||
debugCharSegmenter = getBoolean("debug", "char_segment", false);
|
debugCharSegmenter = getBoolean("debug", "char_segment", false);
|
||||||
debugCharAnalysis = getBoolean("debug", "char_analysis", false);
|
debugCharAnalysis = getBoolean("debug", "char_analysis", false);
|
||||||
debugColorFiler = getBoolean("debug", "color_filter", false);
|
debugColorFiler = getBoolean("debug", "color_filter", false);
|
||||||
@@ -206,7 +205,6 @@ void Config::debugOff()
|
|||||||
debugStateId = false;
|
debugStateId = false;
|
||||||
debugPlateLines = false;
|
debugPlateLines = false;
|
||||||
debugPlateCorners = false;
|
debugPlateCorners = false;
|
||||||
debugCharRegions = false;
|
|
||||||
debugCharSegmenter = false;
|
debugCharSegmenter = false;
|
||||||
debugCharAnalysis = false;
|
debugCharAnalysis = false;
|
||||||
debugColorFiler = false;
|
debugColorFiler = false;
|
||||||
|
@@ -103,7 +103,6 @@ class Config
|
|||||||
bool debugStateId;
|
bool debugStateId;
|
||||||
bool debugPlateLines;
|
bool debugPlateLines;
|
||||||
bool debugPlateCorners;
|
bool debugPlateCorners;
|
||||||
bool debugCharRegions;
|
|
||||||
bool debugCharSegmenter;
|
bool debugCharSegmenter;
|
||||||
bool debugCharAnalysis;
|
bool debugCharAnalysis;
|
||||||
bool debugColorFiler;
|
bool debugColorFiler;
|
||||||
|
@@ -51,9 +51,9 @@ 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);
|
CharacterAnalysis textAnalysis(pipeline_data);
|
||||||
|
|
||||||
if (charRegion.confidence > 10)
|
if (textAnalysis.confidence > 10)
|
||||||
{
|
{
|
||||||
PlateLines plateLines(pipeline_data);
|
PlateLines plateLines(pipeline_data);
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ void LicensePlateCandidate::recognize()
|
|||||||
|
|
||||||
pipeline_data->plate_area_confidence = 100;
|
pipeline_data->plate_area_confidence = 100;
|
||||||
}
|
}
|
||||||
charRegion.confidence = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "platelines.h"
|
#include "platelines.h"
|
||||||
#include "characterregion.h"
|
#include "textdetection/characteranalysis.h"
|
||||||
#include "segmentation/charactersegmenter.h"
|
#include "segmentation/charactersegmenter.h"
|
||||||
#include "platecorners.h"
|
#include "platecorners.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -57,7 +57,7 @@ class LicensePlateCandidate
|
|||||||
CharacterSegmenter* charSegmenter;
|
CharacterSegmenter* charSegmenter;
|
||||||
|
|
||||||
cv::Mat filterByCharacterHue(std::vector<std::vector<cv::Point> > charRegionContours);
|
cv::Mat filterByCharacterHue(std::vector<std::vector<cv::Point> > charRegionContours);
|
||||||
std::vector<cv::Point> findPlateCorners(cv::Mat inputImage, PlateLines plateLines, CharacterRegion charRegion); // top-left, top-right, bottom-right, bottom-left
|
std::vector<cv::Point> findPlateCorners(cv::Mat inputImage, PlateLines plateLines, CharacterAnalysis textAnalysis); // top-left, top-right, bottom-right, bottom-left
|
||||||
|
|
||||||
cv::Size getOutputImageSize(std::vector<cv::Point2f> corners);
|
cv::Size getOutputImageSize(std::vector<cv::Point2f> corners);
|
||||||
std::vector<cv::Point2f> transformPointsToOriginalImage(cv::Mat bigImage, cv::Mat smallImage, cv::Rect region, std::vector<cv::Point> corners);
|
std::vector<cv::Point2f> transformPointsToOriginalImage(cv::Mat bigImage, cv::Mat smallImage, cv::Rect region, std::vector<cv::Point> corners);
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
#define OPENALPR_PLATECORNERS_H
|
#define OPENALPR_PLATECORNERS_H
|
||||||
|
|
||||||
#include "opencv2/imgproc/imgproc.hpp"
|
#include "opencv2/imgproc/imgproc.hpp"
|
||||||
#include "characterregion.h"
|
|
||||||
#include "platelines.h"
|
#include "platelines.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "binarize_wolf.h"
|
#include "binarize_wolf.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "characterregion.h"
|
#include "pipeline_data.h"
|
||||||
|
|
||||||
struct PlateLine
|
struct PlateLine
|
||||||
{
|
{
|
||||||
|
@@ -24,11 +24,10 @@
|
|||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "binarize_wolf.h"
|
#include "binarize_wolf.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "characterregion.h"
|
|
||||||
#include "colorfilter.h"
|
|
||||||
#include "verticalhistogram.h"
|
#include "verticalhistogram.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "textdetection/textcontours.h"
|
#include "textdetection/textcontours.h"
|
||||||
|
#include "pipeline_data.h"
|
||||||
|
|
||||||
|
|
||||||
//const float MIN_BOX_WIDTH_PX = 4; // 4 pixels
|
//const float MIN_BOX_WIDTH_PX = 4; // 4 pixels
|
||||||
|
@@ -32,10 +32,12 @@ CharacterAnalysis::CharacterAnalysis(PipelineData* pipeline_data)
|
|||||||
this->pipeline_data = pipeline_data;
|
this->pipeline_data = pipeline_data;
|
||||||
this->config = pipeline_data->config;
|
this->config = pipeline_data->config;
|
||||||
|
|
||||||
|
this->confidence = 0;
|
||||||
|
|
||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
cout << "Starting CharacterAnalysis identification" << endl;
|
cout << "Starting CharacterAnalysis identification" << endl;
|
||||||
|
|
||||||
|
this->analyze();
|
||||||
}
|
}
|
||||||
|
|
||||||
CharacterAnalysis::~CharacterAnalysis()
|
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<Mat> 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -36,12 +36,12 @@ class CharacterAnalysis
|
|||||||
CharacterAnalysis(PipelineData* pipeline_data);
|
CharacterAnalysis(PipelineData* pipeline_data);
|
||||||
virtual ~CharacterAnalysis();
|
virtual ~CharacterAnalysis();
|
||||||
|
|
||||||
|
int confidence;
|
||||||
|
|
||||||
cv::Mat bestThreshold;
|
cv::Mat bestThreshold;
|
||||||
|
|
||||||
TextContours bestContours;
|
TextContours bestContours;
|
||||||
|
|
||||||
bool thresholdsInverted;
|
|
||||||
|
|
||||||
std::vector<TextContours> allTextContours;
|
std::vector<TextContours> allTextContours;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user