Merge pull request #13 from Silex/develop

Clean up files
This commit is contained in:
Matthew Hill
2014-03-17 20:19:44 -05:00
90 changed files with 4422 additions and 4479 deletions

View File

@@ -11,7 +11,7 @@ User Guide
OpenALPR includes a command line utility. Simply typing "alpr [image file path]" is enough to get started recognizing license plate images. OpenALPR includes a command line utility. Simply typing "alpr [image file path]" is enough to get started recognizing license plate images.
For example, the following output is created by analyzing this image: For example, the following output is created by analyzing this image:
![Plate Image](http://www.openalpr.com/images/demoscreenshots/plate3.png "Input image") ![Plate Image](http://www.openalpr.com/images/demoscreenshots/plate3.png "Input image")
@@ -39,7 +39,7 @@ Detailed command line usage:
``` ```
user@linux:~/openalpr$ alpr --help user@linux:~/openalpr$ alpr --help
USAGE: USAGE:
alpr [-t <region code>] [-r <runtime_dir>] [-n <topN>] alpr [-t <region code>] [-r <runtime_dir>] [-n <topN>]
[--seek <integer_ms>] [-c <country_code>] [--seek <integer_ms>] [-c <country_code>]
@@ -47,7 +47,7 @@ USAGE:
<image_file_path> <image_file_path>
Where: Where:
-t <region code>, --template_region <region code> -t <region code>, --template_region <region code>
Attempt to match the plate number against a region template (e.g., md Attempt to match the plate number against a region template (e.g., md
@@ -63,11 +63,11 @@ Where:
Seek to the specied millisecond in a video file. Default=0 Seek to the specied millisecond in a video file. Default=0
-c <country_code>, --country <country_code> -c <country_code>, --country <country_code>
Country code to identify (either us for USA or eu for Europe). Country code to identify (either us for USA or eu for Europe).
Default=us Default=us
--clock --clock
Measure/print the total time to process image and all plates. Measure/print the total time to process image and all plates.
Default=off Default=off
-d, --detect_region -d, --detect_region
@@ -100,7 +100,7 @@ OpenALPR compiles and runs on Linux, Mac OSX and Windows.
OpenALPR requires the following additional libraries: OpenALPR requires the following additional libraries:
- Tesseract OCR v3.x (https://code.google.com/p/tesseract-ocr/) - Tesseract OCR v3.x (https://code.google.com/p/tesseract-ocr/)
- OpenCV v2.4.x (http://opencv.org/) - OpenCV v2.4.x (http://opencv.org/)
After cloning this GitHub repository, you should download and extract Tesseract and OpenCV source code into their own directories. Compile both libraries. After cloning this GitHub repository, you should download and extract Tesseract and OpenCV source code into their own directories. Compile both libraries.
@@ -127,5 +127,3 @@ License
Affero GPLv3 Affero GPLv3
http://www.gnu.org/licenses/agpl-3.0.html http://www.gnu.org/licenses/agpl-3.0.html

View File

@@ -14,7 +14,7 @@ ocr_min_font_point = 6
; Minimum OCR confidence percent to consider. ; Minimum OCR confidence percent to consider.
postprocess_min_confidence = 60 postprocess_min_confidence = 60
; Any OCR character lower than this will also add an equally likely ; Any OCR character lower than this will also add an equally likely
; chance that the character is incorrect and will be skipped. Value is a confidence percent ; chance that the character is incorrect and will be skipped. Value is a confidence percent
postprocess_confidence_skip_level = 75 postprocess_confidence_skip_level = 75
@@ -110,7 +110,3 @@ min_plate_size_width_px = 100
min_plate_size_height_px = 20 min_plate_size_height_px = 20
ocr_language = leu ocr_language = leu

View File

@@ -1,8 +1,8 @@
base @@@#### base @@@####
base @@@### base @@@###
base ###@@@ base ###@@@
al #@##@## al #@##@##
al ##@##@# al ##@##@#
al @@##### al @@#####
al #####@@ al #####@@
al #@####@ al #@####@

View File

@@ -1,26 +1,26 @@
project(src) project(src)
cmake_minimum_required (VERSION 2.6) cmake_minimum_required (VERSION 2.6)
SET(OpenCV_DIR "${CMAKE_SOURCE_DIR}/../libraries/opencv/") SET(OpenCV_DIR "${CMAKE_SOURCE_DIR}/../libraries/opencv/")
SET(Tesseract_DIR "${CMAKE_SOURCE_DIR}/../libraries/tesseract-ocr") SET(Tesseract_DIR "${CMAKE_SOURCE_DIR}/../libraries/tesseract-ocr")
include_directories( include_directories(
${Tesseract_DIR}/api ${Tesseract_DIR}/api
${Tesseract_DIR}/ccutil/ ${Tesseract_DIR}/ccutil/
${Tesseract_DIR}/ccstruct/ ${Tesseract_DIR}/ccstruct/
${Tesseract_DIR}/ccmain/ ${Tesseract_DIR}/ccmain/
) )
IF (WIN32) IF (WIN32)
add_definitions( -DWINDOWS) add_definitions( -DWINDOWS)
add_definitions( -DNOMINMAX) add_definitions( -DNOMINMAX)
link_directories( ${Tesseract_DIR}/vs2008/LIB_Release/ ) link_directories( ${Tesseract_DIR}/vs2008/LIB_Release/ )
ELSE() ELSE()
link_directories( ${Tesseract_DIR}/api/.libs/ ) link_directories( ${Tesseract_DIR}/api/.libs/ )
ENDIF() ENDIF()
@@ -40,10 +40,10 @@ ADD_EXECUTABLE( alpr main.cpp )
IF (WIN32) IF (WIN32)
# Extra linker dependencies for Windows # Extra linker dependencies for Windows
TARGET_LINK_LIBRARIES(alpr TARGET_LINK_LIBRARIES(alpr
openalpr openalpr
support support
${OpenCV_LIBS} ${OpenCV_LIBS}
libtesseract302-static libtesseract302-static
liblept168 liblept168
liblept168-static-mtdll liblept168-static-mtdll
@@ -54,17 +54,16 @@ IF (WIN32)
zlib125-static-mtdll zlib125-static-mtdll
ws2_32.lib ws2_32.lib
) )
ELSE() ELSE()
TARGET_LINK_LIBRARIES(alpr TARGET_LINK_LIBRARIES(alpr
openalpr openalpr
support support
${OpenCV_LIBS} ${OpenCV_LIBS}
tesseract tesseract
) )
ENDIF() ENDIF()
add_subdirectory(openalpr) add_subdirectory(openalpr)
add_subdirectory(misc_utilities) add_subdirectory(misc_utilities)

View File

@@ -1,268 +1,264 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <iostream> #include <iostream>
#include <stdio.h> #include <stdio.h>
#include "opencv2/highgui/highgui.hpp" #include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgproc/imgproc.hpp"
#include "tclap/CmdLine.h" #include "tclap/CmdLine.h"
#include "support/filesystem.h" #include "support/filesystem.h"
#include "support/timing.h" #include "support/timing.h"
#include "alpr.h" #include "alpr.h"
const std::string MAIN_WINDOW_NAME = "ALPR main window"; const std::string MAIN_WINDOW_NAME = "ALPR main window";
const bool SAVE_LAST_VIDEO_STILL = false; const bool SAVE_LAST_VIDEO_STILL = false;
const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg"; const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg";
/** Function Headers */ /** Function Headers */
bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson); bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson);
bool measureProcessingTime = false; bool measureProcessingTime = false;
int main( int argc, const char** argv ) int main( int argc, const char** argv )
{ {
std::string filename; std::string filename;
std::string runtimePath = ""; std::string runtimePath = "";
bool outputJson = false; bool outputJson = false;
int seektoms = 0; int seektoms = 0;
bool detectRegion = false; bool detectRegion = false;
std::string templateRegion; std::string templateRegion;
std::string country; std::string country;
int topn; int topn;
try { try {
TCLAP::CmdLine cmd("OpenAlpr Command Line Utility", ' ', OPENALPR_VERSION); TCLAP::CmdLine cmd("OpenAlpr Command Line Utility", ' ', OPENALPR_VERSION);
TCLAP::UnlabeledValueArg<std::string> fileArg( "image_file", "Image containing license plates", true, "", "image_file_path" ); TCLAP::UnlabeledValueArg<std::string> fileArg( "image_file", "Image containing license plates", true, "", "image_file_path" );
TCLAP::ValueArg<std::string> countryCodeArg("c","country","Country code to identify (either us for USA or eu for Europe). Default=us",false, "us" ,"country_code"); TCLAP::ValueArg<std::string> countryCodeArg("c","country","Country code to identify (either us for USA or eu for Europe). Default=us",false, "us" ,"country_code");
TCLAP::ValueArg<int> seekToMsArg("","seek","Seek to the specied millisecond in a video file. Default=0",false, 0 ,"integer_ms"); TCLAP::ValueArg<int> seekToMsArg("","seek","Seek to the specied millisecond in a video file. Default=0",false, 0 ,"integer_ms");
TCLAP::ValueArg<std::string> runtimeDirArg("r","runtime_dir","Path to the OpenAlpr runtime data directory",false, "" ,"runtime_dir"); TCLAP::ValueArg<std::string> runtimeDirArg("r","runtime_dir","Path to the OpenAlpr runtime data directory",false, "" ,"runtime_dir");
TCLAP::ValueArg<std::string> templateRegionArg("t","template_region","Attempt to match the plate number against a region template (e.g., md for Maryland, ca for California)",false, "" ,"region code"); TCLAP::ValueArg<std::string> templateRegionArg("t","template_region","Attempt to match the plate number against a region template (e.g., md for Maryland, ca for California)",false, "" ,"region code");
TCLAP::ValueArg<int> topNArg("n","topn","Max number of possible plate numbers to return. Default=10",false, 10 ,"topN"); TCLAP::ValueArg<int> topNArg("n","topn","Max number of possible plate numbers to return. Default=10",false, 10 ,"topN");
TCLAP::SwitchArg jsonSwitch("j","json","Output recognition results in JSON format. Default=off", cmd, false); TCLAP::SwitchArg jsonSwitch("j","json","Output recognition results in JSON format. Default=off", cmd, false);
TCLAP::SwitchArg detectRegionSwitch("d","detect_region","Attempt to detect the region of the plate image. Default=off", cmd, false); TCLAP::SwitchArg detectRegionSwitch("d","detect_region","Attempt to detect the region of the plate image. Default=off", cmd, false);
TCLAP::SwitchArg clockSwitch("","clock","Measure/print the total time to process image and all plates. Default=off", cmd, false); TCLAP::SwitchArg clockSwitch("","clock","Measure/print the total time to process image and all plates. Default=off", cmd, false);
cmd.add( fileArg ); cmd.add( fileArg );
cmd.add( countryCodeArg ); cmd.add( countryCodeArg );
cmd.add( seekToMsArg ); cmd.add( seekToMsArg );
cmd.add( topNArg ); cmd.add( topNArg );
cmd.add( runtimeDirArg ); cmd.add( runtimeDirArg );
cmd.add( templateRegionArg ); cmd.add( templateRegionArg );
cmd.parse( argc, argv ); cmd.parse( argc, argv );
filename = fileArg.getValue(); filename = fileArg.getValue();
country = countryCodeArg.getValue(); country = countryCodeArg.getValue();
seektoms = seekToMsArg.getValue(); seektoms = seekToMsArg.getValue();
outputJson = jsonSwitch.getValue(); outputJson = jsonSwitch.getValue();
runtimePath = runtimeDirArg.getValue(); runtimePath = runtimeDirArg.getValue();
detectRegion = detectRegionSwitch.getValue(); detectRegion = detectRegionSwitch.getValue();
templateRegion = templateRegionArg.getValue(); templateRegion = templateRegionArg.getValue();
topn = topNArg.getValue(); topn = topNArg.getValue();
measureProcessingTime = clockSwitch.getValue(); measureProcessingTime = clockSwitch.getValue();
} catch (TCLAP::ArgException &e) // catch any exceptions } catch (TCLAP::ArgException &e) // catch any exceptions
{ {
std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
return 1; return 1;
} }
cv::Mat frame; cv::Mat frame;
Alpr alpr(country, runtimePath); Alpr alpr(country, runtimePath);
alpr.setTopN(topn); alpr.setTopN(topn);
if (detectRegion) if (detectRegion)
alpr.setDetectRegion(detectRegion); alpr.setDetectRegion(detectRegion);
if (strcmp(templateRegion.c_str(), "") != 0) if (strcmp(templateRegion.c_str(), "") != 0)
{ {
alpr.setDefaultRegion(templateRegion); alpr.setDefaultRegion(templateRegion);
} }
if (alpr.isLoaded() == false) if (alpr.isLoaded() == false)
{ {
std::cerr << "Error loading OpenAlpr" << std::endl; std::cerr << "Error loading OpenAlpr" << std::endl;
return 1; return 1;
} }
if (strcmp(filename.c_str(), "webcam") == 0) if (strcmp(filename.c_str(), "webcam") == 0)
{ {
int framenum = 0; int framenum = 0;
cv::VideoCapture cap(0); cv::VideoCapture cap(0);
if (!cap.isOpened()) if (!cap.isOpened())
{ {
std::cout << "Error opening webcam" << std::endl; std::cout << "Error opening webcam" << std::endl;
return 1; return 1;
} }
while (cap.read(frame) == true) while (cap.read(frame) == true)
{ {
detectandshow(&alpr, frame, "", outputJson); detectandshow(&alpr, frame, "", outputJson);
cv::waitKey(1); cv::waitKey(1);
framenum++; framenum++;
} }
} }
else if (hasEnding(filename, ".avi") || hasEnding(filename, ".mp4") || hasEnding(filename, ".webm") || hasEnding(filename, ".flv")) else if (hasEnding(filename, ".avi") || hasEnding(filename, ".mp4") || hasEnding(filename, ".webm") || hasEnding(filename, ".flv"))
{ {
if (fileExists(filename.c_str())) if (fileExists(filename.c_str()))
{ {
int framenum = 0; int framenum = 0;
cv::VideoCapture cap=cv::VideoCapture(); cv::VideoCapture cap=cv::VideoCapture();
cap.open(filename); cap.open(filename);
cap.set(CV_CAP_PROP_POS_MSEC, seektoms); cap.set(CV_CAP_PROP_POS_MSEC, seektoms);
while (cap.read(frame) == true) while (cap.read(frame) == true)
{ {
if (SAVE_LAST_VIDEO_STILL == true) if (SAVE_LAST_VIDEO_STILL == true)
{ {
cv::imwrite(LAST_VIDEO_STILL_LOCATION, frame); cv::imwrite(LAST_VIDEO_STILL_LOCATION, frame);
} }
std::cout << "Frame: " << framenum << std::endl; std::cout << "Frame: " << framenum << std::endl;
detectandshow( &alpr, frame, "", outputJson); detectandshow( &alpr, frame, "", outputJson);
//create a 1ms delay //create a 1ms delay
cv::waitKey(1); cv::waitKey(1);
framenum++; framenum++;
} }
} }
else else
{ {
std::cerr << "Video file not found: " << filename << std::endl; std::cerr << "Video file not found: " << filename << std::endl;
} }
} }
else if (hasEnding(filename, ".png") || hasEnding(filename, ".jpg") || hasEnding(filename, ".gif")) else if (hasEnding(filename, ".png") || hasEnding(filename, ".jpg") || hasEnding(filename, ".gif"))
{ {
if (fileExists(filename.c_str())) if (fileExists(filename.c_str()))
{ {
frame = cv::imread( filename ); frame = cv::imread( filename );
detectandshow( &alpr, frame, "", outputJson); detectandshow( &alpr, frame, "", outputJson);
} }
else else
{ {
std::cerr << "Image file not found: " << filename << std::endl; std::cerr << "Image file not found: " << filename << std::endl;
} }
} }
else if (DirectoryExists(filename.c_str())) else if (DirectoryExists(filename.c_str()))
{ {
std::vector<std::string> files = getFilesInDir(filename.c_str()); std::vector<std::string> files = getFilesInDir(filename.c_str());
std::sort( files.begin(), files.end(), stringCompare ); std::sort( files.begin(), files.end(), stringCompare );
for (int i = 0; i< files.size(); i++) for (int i = 0; i< files.size(); i++)
{ {
if (hasEnding(files[i], ".jpg") || hasEnding(files[i], ".png")) if (hasEnding(files[i], ".jpg") || hasEnding(files[i], ".png"))
{ {
std::string fullpath = filename + "/" + files[i]; std::string fullpath = filename + "/" + files[i];
std::cout << fullpath << std::endl; std::cout << fullpath << std::endl;
frame = cv::imread( fullpath.c_str() ); frame = cv::imread( fullpath.c_str() );
if (detectandshow( &alpr, frame, "", outputJson)) if (detectandshow( &alpr, frame, "", outputJson))
{ {
//while ((char) cv::waitKey(50) != 'c') { } //while ((char) cv::waitKey(50) != 'c') { }
} }
else else
{ {
//cv::waitKey(50); //cv::waitKey(50);
} }
} }
} }
} }
else else
{ {
std::cerr << "Unknown file type" << std::endl; std::cerr << "Unknown file type" << std::endl;
return 1; return 1;
} }
return 0; return 0;
} }
bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson) bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson)
{ {
std::vector<uchar> buffer; std::vector<uchar> buffer;
cv::imencode(".bmp", frame, buffer ); cv::imencode(".bmp", frame, buffer );
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
std::vector<AlprResult> results = alpr->recognize(buffer); std::vector<AlprResult> results = alpr->recognize(buffer);
if (writeJson) if (writeJson)
{ {
std::cout << alpr->toJson(results) << std::endl; std::cout << alpr->toJson(results) << std::endl;
} }
else else
{ {
for (int i = 0; i < results.size(); i++) for (int i = 0; i < results.size(); i++)
{ {
std::cout << "plate" << i << ": " << results[i].result_count << " results -- Processing Time = " << results[i].processing_time_ms << "ms." << std::endl; std::cout << "plate" << i << ": " << results[i].result_count << " results -- Processing Time = " << results[i].processing_time_ms << "ms." << std::endl;
for (int k = 0; k < results[i].topNPlates.size(); k++) for (int k = 0; k < results[i].topNPlates.size(); k++)
{ {
std::cout << " - " << results[i].topNPlates[k].characters << "\t confidence: " << results[i].topNPlates[k].overall_confidence << "\t template_match: " << results[i].topNPlates[k].matches_template << std::endl; std::cout << " - " << results[i].topNPlates[k].characters << "\t confidence: " << results[i].topNPlates[k].overall_confidence << "\t template_match: " << results[i].topNPlates[k].matches_template << std::endl;
} }
} }
} }
timespec endTime; timespec endTime;
getTime(&endTime); getTime(&endTime);
if (measureProcessingTime) if (measureProcessingTime)
std::cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << std::endl; std::cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << std::endl;
if (results.size() > 0) if (results.size() > 0)
return true; return true;
return false; return false;
} }

View File

@@ -4,35 +4,33 @@ target_link_libraries(openalpr)
ADD_EXECUTABLE( sortstate sortstate.cpp ) ADD_EXECUTABLE( sortstate sortstate.cpp )
TARGET_LINK_LIBRARIES(sortstate TARGET_LINK_LIBRARIES(sortstate
openalpr openalpr
support support
${OpenCV_LIBS} ${OpenCV_LIBS}
tesseract tesseract
) )
ADD_EXECUTABLE( classifychars classifychars.cpp ) ADD_EXECUTABLE( classifychars classifychars.cpp )
TARGET_LINK_LIBRARIES(classifychars TARGET_LINK_LIBRARIES(classifychars
openalpr openalpr
support support
${OpenCV_LIBS} ${OpenCV_LIBS}
tesseract tesseract
) )
ADD_EXECUTABLE( benchmark benchmark.cpp ) ADD_EXECUTABLE( benchmark benchmark.cpp )
TARGET_LINK_LIBRARIES(benchmark TARGET_LINK_LIBRARIES(benchmark
openalpr openalpr
support support
${OpenCV_LIBS} ${OpenCV_LIBS}
tesseract tesseract
) )
ADD_EXECUTABLE( prepcharsfortraining prepcharsfortraining.cpp ) ADD_EXECUTABLE( prepcharsfortraining prepcharsfortraining.cpp )
TARGET_LINK_LIBRARIES(prepcharsfortraining TARGET_LINK_LIBRARIES(prepcharsfortraining
support support
${OpenCV_LIBS} ${OpenCV_LIBS}
) )

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -39,9 +39,9 @@
// Given a directory full of lp images (named [statecode]#.png) crop out the alphanumeric characters. // Given a directory full of lp images (named [statecode]#.png) crop out the alphanumeric characters.
// These will be used to train the OCR // These will be used to train the OCR
void outputStats(vector<double> datapoints); void outputStats(vector<double> datapoints);
int main( int argc, const char** argv ) int main( int argc, const char** argv )
{ {
string country; string country;
@@ -49,8 +49,8 @@ int main( int argc, const char** argv )
string inDir; string inDir;
string outDir; string outDir;
Mat frame; Mat frame;
//Check if user specify image to process //Check if user specify image to process
if(argc == 5) if(argc == 5)
{ {
@@ -58,17 +58,17 @@ int main( int argc, const char** argv )
benchmarkName = argv[2]; benchmarkName = argv[2];
inDir = argv[3]; inDir = argv[3];
outDir = argv[4]; outDir = argv[4];
}else{ }else{
printf("Use:\n\t%s [country] [benchmark name] [img input dir] [results output dir]\n",argv[0]); printf("Use:\n\t%s [country] [benchmark name] [img input dir] [results output dir]\n",argv[0]);
printf("\tex: %s us speed ./speed/usimages ./speed\n",argv[0]); printf("\tex: %s us speed ./speed/usimages ./speed\n",argv[0]);
printf("\n"); printf("\n");
printf("\ttest names are: speed, segocr, detection\n\n" ); printf("\ttest names are: speed, segocr, detection\n\n" );
return 0; return 0;
} }
if (DirectoryExists(inDir.c_str()) == false) if (DirectoryExists(inDir.c_str()) == false)
{ {
printf("Input dir does not exist\n"); printf("Input dir does not exist\n");
@@ -79,20 +79,20 @@ int main( int argc, const char** argv )
printf("Output dir does not exist\n"); printf("Output dir does not exist\n");
return 0; return 0;
} }
vector<string> files = getFilesInDir(inDir.c_str()); vector<string> files = getFilesInDir(inDir.c_str());
sort( files.begin(), files.end(), stringCompare ); sort( files.begin(), files.end(), stringCompare );
if (benchmarkName.compare("segocr") == 0) if (benchmarkName.compare("segocr") == 0)
{ {
Config* config = new Config(country); Config* config = new Config(country);
config->debugOff(); config->debugOff();
OCR* ocr = new OCR(config); OCR* ocr = new OCR(config);
for (int i = 0; i< files.size(); i++) for (int i = 0; i< files.size(); i++)
{ {
if (hasEnding(files[i], ".png")) if (hasEnding(files[i], ".png"))
@@ -101,51 +101,51 @@ int main( int argc, const char** argv )
frame = imread( fullpath.c_str() ); frame = imread( fullpath.c_str() );
resize(frame, frame, Size(config->ocrImageWidthPx, config->ocrImageHeightPx)); resize(frame, frame, Size(config->ocrImageWidthPx, config->ocrImageHeightPx));
Rect plateCoords; Rect plateCoords;
plateCoords.x = 0; plateCoords.x = 0;
plateCoords.y = 0; plateCoords.y = 0;
plateCoords.width = frame.cols; plateCoords.width = frame.cols;
plateCoords.height = frame.rows; plateCoords.height = frame.rows;
char statecode[3]; char statecode[3];
statecode[0] = files[i][0]; statecode[0] = files[i][0];
statecode[1] = files[i][1]; statecode[1] = files[i][1];
statecode[2] = '\0'; statecode[2] = '\0';
string statecodestr(statecode); string statecodestr(statecode);
CharacterRegion charRegion(frame, config); CharacterRegion charRegion(frame, config);
if (abs(charRegion.getTopLine().angle) > 4) if (abs(charRegion.getTopLine().angle) > 4)
{ {
// Rotate image: // Rotate image:
Mat rotated(frame.size(), frame.type()); Mat rotated(frame.size(), frame.type());
Mat rot_mat( 2, 3, CV_32FC1 ); Mat rot_mat( 2, 3, CV_32FC1 );
Point center = Point( frame.cols/2, frame.rows/2 ); Point center = Point( frame.cols/2, frame.rows/2 );
rot_mat = getRotationMatrix2D( center, charRegion.getTopLine().angle, 1.0 ); rot_mat = getRotationMatrix2D( center, charRegion.getTopLine().angle, 1.0 );
warpAffine( frame, rotated, rot_mat, frame.size() ); warpAffine( frame, rotated, rot_mat, frame.size() );
rotated.copyTo(frame); rotated.copyTo(frame);
} }
CharacterSegmenter charSegmenter(frame, charRegion.thresholdsInverted(), config); CharacterSegmenter charSegmenter(frame, charRegion.thresholdsInverted(), config);
ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters); ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters);
ocr->postProcessor->analyze(statecode, 25); ocr->postProcessor->analyze(statecode, 25);
cout << files[i] << "," << statecode << "," << ocr->postProcessor->bestChars << endl; cout << files[i] << "," << statecode << "," << ocr->postProcessor->bestChars << endl;
imshow("Current LP", frame); imshow("Current LP", frame);
waitKey(5); waitKey(5);
} }
} }
delete config; delete config;
delete ocr; delete ocr;
} }
@@ -153,42 +153,42 @@ int main( int argc, const char** argv )
{ {
Config config(country); Config config(country);
RegionDetector plateDetector(&config); RegionDetector plateDetector(&config);
for (int i = 0; i< files.size(); i++) for (int i = 0; i< files.size(); i++)
{ {
if (hasEnding(files[i], ".png")) if (hasEnding(files[i], ".png"))
{ {
string fullpath = inDir + "/" + files[i]; string fullpath = inDir + "/" + files[i];
frame = imread( fullpath.c_str() ); frame = imread( fullpath.c_str() );
vector<Rect> regions = plateDetector.detect(frame); vector<Rect> regions = plateDetector.detect(frame);
imshow("Current LP", frame); imshow("Current LP", frame);
waitKey(5); waitKey(5);
} }
} }
} }
else if (benchmarkName.compare("speed") == 0) else if (benchmarkName.compare("speed") == 0)
{ {
// Benchmarks speed of region detection, plate analysis, and OCR // Benchmarks speed of region detection, plate analysis, and OCR
timespec startTime; timespec startTime;
timespec endTime; timespec endTime;
Config config(country); Config config(country);
config.debugOff(); config.debugOff();
AlprImpl alpr(country); AlprImpl alpr(country);
alpr.config->debugOff(); alpr.config->debugOff();
alpr.setDetectRegion(true); alpr.setDetectRegion(true);
RegionDetector plateDetector(&config); RegionDetector plateDetector(&config);
StateIdentifier stateIdentifier(&config); StateIdentifier stateIdentifier(&config);
OCR ocr(&config); OCR ocr(&config);
vector<double> endToEndTimes; vector<double> endToEndTimes;
vector<double> regionDetectionTimes; vector<double> regionDetectionTimes;
vector<double> stateIdTimes; vector<double> stateIdTimes;
@@ -196,33 +196,33 @@ int main( int argc, const char** argv )
vector<double> lpAnalysisNegativeTimes; vector<double> lpAnalysisNegativeTimes;
vector<double> ocrTimes; vector<double> ocrTimes;
vector<double> postProcessTimes; vector<double> postProcessTimes;
for (int i = 0; i< files.size(); i++) for (int i = 0; i< files.size(); i++)
{ {
if (hasEnding(files[i], ".png")) if (hasEnding(files[i], ".png"))
{ {
cout << "Image: " << files[i] << endl; cout << "Image: " << files[i] << endl;
string fullpath = inDir + "/" + files[i]; string fullpath = inDir + "/" + files[i];
frame = imread( fullpath.c_str() ); frame = imread( fullpath.c_str() );
getTime(&startTime); getTime(&startTime);
alpr.recognize(frame); alpr.recognize(frame);
getTime(&endTime); getTime(&endTime);
double endToEndTime = diffclock(startTime, endTime); double endToEndTime = diffclock(startTime, endTime);
cout << " -- End to End recognition time: " << endToEndTime << "ms." << endl; cout << " -- End to End recognition time: " << endToEndTime << "ms." << endl;
endToEndTimes.push_back(endToEndTime); endToEndTimes.push_back(endToEndTime);
getTime(&startTime); getTime(&startTime);
vector<Rect> regions = plateDetector.detect(frame); vector<Rect> regions = plateDetector.detect(frame);
getTime(&endTime); getTime(&endTime);
double regionDetectionTime = diffclock(startTime, endTime); double regionDetectionTime = diffclock(startTime, endTime);
cout << " -- Region detection time: " << regionDetectionTime << "ms." << endl; cout << " -- Region detection time: " << regionDetectionTime << "ms." << endl;
regionDetectionTimes.push_back(regionDetectionTime); regionDetectionTimes.push_back(regionDetectionTime);
for (int z = 0; z < regions.size(); z++) for (int z = 0; z < regions.size(); z++)
{ {
getTime(&startTime); getTime(&startTime);
@@ -232,26 +232,26 @@ int main( int argc, const char** argv )
double stateidTime = diffclock(startTime, endTime); double stateidTime = diffclock(startTime, endTime);
cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl; cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl;
stateIdTimes.push_back(stateidTime); stateIdTimes.push_back(stateidTime);
getTime(&startTime); getTime(&startTime);
LicensePlateCandidate lp(frame, regions[z], &config); LicensePlateCandidate lp(frame, regions[z], &config);
lp.recognize(); lp.recognize();
getTime(&endTime); getTime(&endTime);
double analysisTime = diffclock(startTime, endTime); double analysisTime = diffclock(startTime, endTime);
cout << "\tRegion " << z << ": Analysis time: " << analysisTime << "ms." << endl; cout << "\tRegion " << z << ": Analysis time: " << analysisTime << "ms." << endl;
if (lp.confidence > 10) if (lp.confidence > 10)
{ {
lpAnalysisPositiveTimes.push_back(analysisTime); lpAnalysisPositiveTimes.push_back(analysisTime);
getTime(&startTime); getTime(&startTime);
ocr.performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters); ocr.performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters);
getTime(&endTime); getTime(&endTime);
double ocrTime = diffclock(startTime, endTime); double ocrTime = diffclock(startTime, endTime);
cout << "\tRegion " << z << ": OCR time: " << ocrTime << "ms." << endl; cout << "\tRegion " << z << ": OCR time: " << ocrTime << "ms." << endl;
ocrTimes.push_back(ocrTime); ocrTimes.push_back(ocrTime);
getTime(&startTime); getTime(&startTime);
ocr.postProcessor->analyze("", 25); ocr.postProcessor->analyze("", 25);
getTime(&endTime); getTime(&endTime);
@@ -264,40 +264,40 @@ int main( int argc, const char** argv )
lpAnalysisNegativeTimes.push_back(analysisTime); lpAnalysisNegativeTimes.push_back(analysisTime);
} }
} }
waitKey(5); waitKey(5);
} }
} }
cout << endl << "---------------------" << endl; cout << endl << "---------------------" << endl;
cout << "End to End Time Statistics:" << endl; cout << "End to End Time Statistics:" << endl;
outputStats(endToEndTimes); outputStats(endToEndTimes);
cout << endl; cout << endl;
cout << "Region Detection Time Statistics:" << endl; cout << "Region Detection Time Statistics:" << endl;
outputStats(regionDetectionTimes); outputStats(regionDetectionTimes);
cout << endl; cout << endl;
cout << "State ID Time Statistics:" << endl; cout << "State ID Time Statistics:" << endl;
outputStats(stateIdTimes); outputStats(stateIdTimes);
cout << endl; cout << endl;
cout << "Positive Region Analysis Time Statistics:" << endl; cout << "Positive Region Analysis Time Statistics:" << endl;
outputStats(lpAnalysisPositiveTimes); outputStats(lpAnalysisPositiveTimes);
cout << endl; cout << endl;
cout << "Negative Region Analysis Time Statistics:" << endl; cout << "Negative Region Analysis Time Statistics:" << endl;
outputStats(lpAnalysisNegativeTimes); outputStats(lpAnalysisNegativeTimes);
cout << endl; cout << endl;
cout << "OCR Time Statistics:" << endl; cout << "OCR Time Statistics:" << endl;
outputStats(ocrTimes); outputStats(ocrTimes);
cout << endl; cout << endl;
cout << "Post Processing Time Statistics:" << endl; cout << "Post Processing Time Statistics:" << endl;
outputStats(postProcessTimes); outputStats(postProcessTimes);
cout << endl; cout << endl;
@@ -306,41 +306,41 @@ int main( int argc, const char** argv )
{ {
Alpr alpr(country); Alpr alpr(country);
alpr.setDetectRegion(true); alpr.setDetectRegion(true);
ofstream outputdatafile; ofstream outputdatafile;
outputdatafile.open("results.txt"); outputdatafile.open("results.txt");
for (int i = 0; i< files.size(); i++) for (int i = 0; i< files.size(); i++)
{ {
if (hasEnding(files[i], ".png")) if (hasEnding(files[i], ".png"))
{ {
string fullpath = inDir + "/" + files[i]; string fullpath = inDir + "/" + files[i];
frame = imread( fullpath.c_str() ); frame = imread( fullpath.c_str() );
vector<uchar> buffer; vector<uchar> buffer;
imencode(".bmp", frame, buffer ); imencode(".bmp", frame, buffer );
vector<AlprResult> results = alpr.recognize(buffer); vector<AlprResult> results = alpr.recognize(buffer);
outputdatafile << files[i] << ": "; outputdatafile << files[i] << ": ";
for (int z = 0; z < results.size(); z++) for (int z = 0; z < results.size(); z++)
{ {
outputdatafile << results[z].bestPlate.characters << ", "; outputdatafile << results[z].bestPlate.characters << ", ";
} }
outputdatafile << endl; outputdatafile << endl;
imshow("Current LP", frame); imshow("Current LP", frame);
waitKey(5); waitKey(5);
} }
} }
outputdatafile.close(); outputdatafile.close();
} }
} }
void outputStats(vector<double> datapoints) void outputStats(vector<double> datapoints)
@@ -357,5 +357,3 @@ void outputStats(vector<double> datapoints)
cout << "\t" << datapoints.size() << " samples, avg: " << mean << "ms, stdev: " << stdev << endl; cout << "\t" << datapoints.size() << " samples, avg: " << mean << "ms, stdev: " << stdev << endl;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -43,7 +43,7 @@ const int RIGHT_ARROW_KEY = 3;
const int SPACE_KEY = 32; const int SPACE_KEY = 32;
const int ENTER_KEY = 13; const int ENTER_KEY = 13;
const int ESCAPE_KEY = 27; const int ESCAPE_KEY = 27;
const int DOWN_ARROW_KEY = 1; const int DOWN_ARROW_KEY = 1;
const int UP_ARROW_KEY= 0; const int UP_ARROW_KEY= 0;
const int DASHBOARD_COLUMNS = 9; const int DASHBOARD_COLUMNS = 9;
@@ -54,7 +54,7 @@ const int RIGHT_ARROW_KEY = 83;
const int SPACE_KEY = 32; const int SPACE_KEY = 32;
const int ENTER_KEY = 10; const int ENTER_KEY = 10;
const int ESCAPE_KEY = 27; const int ESCAPE_KEY = 27;
const int DOWN_ARROW_KEY = 84; const int DOWN_ARROW_KEY = 84;
const int UP_ARROW_KEY= 82; const int UP_ARROW_KEY= 82;
const int DASHBOARD_COLUMNS = 3; const int DASHBOARD_COLUMNS = 3;
@@ -64,35 +64,35 @@ const int DASHBOARD_COLUMNS = 3;
void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex); void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex);
vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state); vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state);
int main( int argc, const char** argv ) int main( int argc, const char** argv )
{ {
string inDir; string inDir;
string outDir; string outDir;
Mat frame; Mat frame;
//Check if user specify image to process //Check if user specify image to process
if(argc == 3) if(argc == 3)
{ {
inDir = argv[1]; inDir = argv[1];
outDir = argv[2]; outDir = argv[2];
}else{ }else{
printf("Use:\n\t%s indirectory outdirectory\n",argv[0]); printf("Use:\n\t%s indirectory outdirectory\n",argv[0]);
printf("Ex: \n\t%s ./pics/ ./out \n",argv[0]); printf("Ex: \n\t%s ./pics/ ./out \n",argv[0]);
return 0; return 0;
} }
if (DirectoryExists(outDir.c_str()) == false) if (DirectoryExists(outDir.c_str()) == false)
{ {
printf("Output dir does not exist\n"); printf("Output dir does not exist\n");
return 0; return 0;
} }
cout << "Usage: " << endl; cout << "Usage: " << endl;
cout << "\tn -- Next plate" << endl; cout << "\tn -- Next plate" << endl;
cout << "\tp -- Previous plate" << endl; cout << "\tp -- Previous plate" << endl;
@@ -104,16 +104,16 @@ int main( int argc, const char** argv )
cout << "\t<- and -> -- Cycle between characters" << endl; cout << "\t<- and -> -- Cycle between characters" << endl;
cout << "\t[0-9A-Z] -- Identify a character (saves the image)" << endl; cout << "\t[0-9A-Z] -- Identify a character (saves the image)" << endl;
cout << "\tESC/Ent/Space -- Back to plate selection" << endl; cout << "\tESC/Ent/Space -- Back to plate selection" << endl;
Config* config = new Config("eu"); Config* config = new Config("eu");
OCR ocr(config); OCR ocr(config);
if (DirectoryExists(inDir.c_str())) if (DirectoryExists(inDir.c_str()))
{ {
vector<string> files = getFilesInDir(inDir.c_str()); vector<string> files = getFilesInDir(inDir.c_str());
sort( files.begin(), files.end(), stringCompare ); sort( files.begin(), files.end(), stringCompare );
for (int i = 0; i< files.size(); i++) for (int i = 0; i< files.size(); i++)
{ {
if (hasEnding(files[i], ".png") || hasEnding(files[i], ".jpg")) if (hasEnding(files[i], ".png") || hasEnding(files[i], ".jpg"))
@@ -122,57 +122,57 @@ int main( int argc, const char** argv )
cout << fullpath << endl; cout << fullpath << endl;
frame = imread( fullpath.c_str() ); frame = imread( fullpath.c_str() );
resize(frame, frame, Size(config->ocrImageWidthPx, config->ocrImageHeightPx)); resize(frame, frame, Size(config->ocrImageWidthPx, config->ocrImageHeightPx));
imshow ("Original", frame); imshow ("Original", frame);
char statecode[3]; char statecode[3];
statecode[0] = files[i][0]; statecode[0] = files[i][0];
statecode[1] = files[i][1]; statecode[1] = files[i][1];
statecode[2] = '\0'; statecode[2] = '\0';
string statecodestr(statecode); string statecodestr(statecode);
CharacterRegion regionizer(frame, config); CharacterRegion regionizer(frame, config);
if (abs(regionizer.getTopLine().angle) > 4) if (abs(regionizer.getTopLine().angle) > 4)
{ {
// Rotate image: // Rotate image:
Mat rotated(frame.size(), frame.type()); Mat rotated(frame.size(), frame.type());
Mat rot_mat( 2, 3, CV_32FC1 ); Mat rot_mat( 2, 3, CV_32FC1 );
Point center = Point( frame.cols/2, frame.rows/2 ); Point center = Point( frame.cols/2, frame.rows/2 );
rot_mat = getRotationMatrix2D( center, regionizer.getTopLine().angle, 1.0 ); rot_mat = getRotationMatrix2D( center, regionizer.getTopLine().angle, 1.0 );
warpAffine( frame, rotated, rot_mat, frame.size() ); warpAffine( frame, rotated, rot_mat, frame.size() );
rotated.copyTo(frame); rotated.copyTo(frame);
} }
CharacterSegmenter charSegmenter(frame, regionizer.thresholdsInverted(), config); CharacterSegmenter charSegmenter(frame, regionizer.thresholdsInverted(), config);
//ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters); //ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters);
ocr.performOCR(charSegmenter.getThresholds(), charSegmenter.characters); ocr.performOCR(charSegmenter.getThresholds(), charSegmenter.characters);
ocr.postProcessor->analyze(statecodestr, 25); ocr.postProcessor->analyze(statecodestr, 25);
cout << "OCR results: " << ocr.postProcessor->bestChars << endl; cout << "OCR results: " << ocr.postProcessor->bestChars << endl;
vector<bool> selectedBoxes(charSegmenter.getThresholds().size()); vector<bool> selectedBoxes(charSegmenter.getThresholds().size());
for (int z = 0; z < charSegmenter.getThresholds().size(); z++) for (int z = 0; z < charSegmenter.getThresholds().size(); z++)
selectedBoxes[z] = false; selectedBoxes[z] = false;
int curDashboardSelection = 0; int curDashboardSelection = 0;
vector<char> humanInputs(charSegmenter.characters.size()); vector<char> humanInputs(charSegmenter.characters.size());
for (int z = 0; z < charSegmenter.characters.size(); z++) for (int z = 0; z < charSegmenter.characters.size(); z++)
humanInputs[z] = ' '; humanInputs[z] = ' ';
showDashboard(charSegmenter.getThresholds(), selectedBoxes, 0); showDashboard(charSegmenter.getThresholds(), selectedBoxes, 0);
char waitkey = (char) waitKey(50); char waitkey = (char) waitKey(50);
while (waitkey != 'n' && waitkey != 'p') // Next image while (waitkey != 'n' && waitkey != 'p') // Next image
{ {
if (waitkey == LEFT_ARROW_KEY) // left arrow key if (waitkey == LEFT_ARROW_KEY) // left arrow key
@@ -233,17 +233,17 @@ int main( int argc, const char** argv )
// Save // Save
if (somethingSelected && chardataTagged) if (somethingSelected && chardataTagged)
{ {
for (int c = 0; c < charSegmenter.characters.size(); c++) for (int c = 0; c < charSegmenter.characters.size(); c++)
{ {
if (humanInputs[c] == ' ') if (humanInputs[c] == ' ')
continue; continue;
for (int t = 0; t < charSegmenter.getThresholds().size(); t++) for (int t = 0; t < charSegmenter.getThresholds().size(); t++)
{ {
if (selectedBoxes[t] == false) if (selectedBoxes[t] == false)
continue; continue;
stringstream filename; stringstream filename;
Mat cropped = charSegmenter.getThresholds()[t](charSegmenter.characters[c]); Mat cropped = charSegmenter.getThresholds()[t](charSegmenter.characters[c]);
filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i]; filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i];
@@ -257,34 +257,34 @@ int main( int argc, const char** argv )
else if (chardataTagged == false) else if (chardataTagged == false)
cout << "You have not tagged any characters" << endl; cout << "You have not tagged any characters" << endl;
} }
waitkey = (char) waitKey(50); waitkey = (char) waitKey(50);
} }
if (waitkey == 'p') if (waitkey == 'p')
i = i - 2; i = i - 2;
if (i < -1) if (i < -1)
i = -1; i = -1;
} }
} }
} }
} }
void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex) void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex)
{ {
vector<Mat> vecCopy; vector<Mat> vecCopy;
if (selectedIndex < 0) if (selectedIndex < 0)
selectedIndex = 0; selectedIndex = 0;
if (selectedIndex >= images.size()) if (selectedIndex >= images.size())
selectedIndex = images.size() -1; selectedIndex = images.size() -1;
for (int i = 0; i < images.size(); i++) for (int i = 0; i < images.size(); i++)
{ {
Mat imgCopy(images[i].size(), images[i].type()); Mat imgCopy(images[i].size(), images[i].type());
@@ -298,35 +298,35 @@ void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selected
{ {
rectangle(imgCopy, Point(2,2), Point(imgCopy.size().width - 2, imgCopy.size().height -2), Scalar(255, 0, 0), 1); rectangle(imgCopy, Point(2,2), Point(imgCopy.size().width - 2, imgCopy.size().height -2), Scalar(255, 0, 0), 1);
} }
vecCopy.push_back(imgCopy); vecCopy.push_back(imgCopy);
} }
Mat dashboard = drawImageDashboard(vecCopy, vecCopy[0].type(), DASHBOARD_COLUMNS); Mat dashboard = drawImageDashboard(vecCopy, vecCopy[0].type(), DASHBOARD_COLUMNS);
imshow("Selection dashboard", dashboard); imshow("Selection dashboard", dashboard);
} }
vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state) vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state)
{ {
int curCharIdx = 0; int curCharIdx = 0;
vector<char> humanInputs(charRegions.size()); vector<char> humanInputs(charRegions.size());
for (int i = 0; i < charRegions.size(); i++) for (int i = 0; i < charRegions.size(); i++)
humanInputs[i] = (char) SPACE_KEY; humanInputs[i] = (char) SPACE_KEY;
char waitkey = (char) waitKey(50); char waitkey = (char) waitKey(50);
while (waitkey != ENTER_KEY && waitkey != ESCAPE_KEY) while (waitkey != ENTER_KEY && waitkey != ESCAPE_KEY)
{ {
Mat imgCopy(image.size(), image.type()); Mat imgCopy(image.size(), image.type());
image.copyTo(imgCopy); image.copyTo(imgCopy);
cvtColor(imgCopy, imgCopy, CV_GRAY2BGR); cvtColor(imgCopy, imgCopy, CV_GRAY2BGR);
rectangle(imgCopy, charRegions[curCharIdx], Scalar(0, 255, 0), 1); rectangle(imgCopy, charRegions[curCharIdx], Scalar(0, 255, 0), 1);
imshow("Character selector", imgCopy); imshow("Character selector", imgCopy);
if (waitkey == LEFT_ARROW_KEY) if (waitkey == LEFT_ARROW_KEY)
curCharIdx--; curCharIdx--;
else if (waitkey == RIGHT_ARROW_KEY ) else if (waitkey == RIGHT_ARROW_KEY )
@@ -336,22 +336,22 @@ vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state
// Save the character to disk // Save the character to disk
humanInputs[curCharIdx] = toupper((char) waitkey); humanInputs[curCharIdx] = toupper((char) waitkey);
curCharIdx++; curCharIdx++;
if (curCharIdx >= charRegions.size()) if (curCharIdx >= charRegions.size())
{ {
waitkey = (char) ENTER_KEY; waitkey = (char) ENTER_KEY;
break; break;
} }
} }
if (curCharIdx < 0) if (curCharIdx < 0)
curCharIdx = 0; curCharIdx = 0;
if (curCharIdx >= charRegions.size()) if (curCharIdx >= charRegions.size())
curCharIdx = charRegions.size() -1; curCharIdx = charRegions.size() -1;
waitkey = (char) waitKey(50); waitkey = (char) waitKey(50);
} }
if (waitkey == ENTER_KEY) if (waitkey == ENTER_KEY)
{ {
// Save all the inputs // Save all the inputs
@@ -360,11 +360,11 @@ vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state
if (humanInputs[i] != (char) SPACE_KEY) if (humanInputs[i] != (char) SPACE_KEY)
cout << "Tagged " << state << " char code: '" << humanInputs[i] << "' at char position: " << i << endl; cout << "Tagged " << state << " char code: '" << humanInputs[i] << "' at char position: " << i << endl;
} }
} }
destroyWindow("Character selector"); destroyWindow("Character selector");
return humanInputs; return humanInputs;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -35,89 +35,89 @@
// Also creates a box file so Tesseract can recognize it // Also creates a box file so Tesseract can recognize it
int main( int argc, const char** argv ) int main( int argc, const char** argv )
{ {
string inDir; string inDir;
//Check if user specify image to process //Check if user specify image to process
if(argc == 2) if(argc == 2)
{ {
inDir = argv[1]; inDir = argv[1];
}else{ }else{
printf("Use:\n\t%s input dir \n",argv[0]); printf("Use:\n\t%s input dir \n",argv[0]);
return 0; return 0;
} }
if (DirectoryExists(inDir.c_str()) == false) if (DirectoryExists(inDir.c_str()) == false)
{ {
printf("Output dir does not exist\n"); printf("Output dir does not exist\n");
return 0; return 0;
} }
cout << "Usage: " << endl; cout << "Usage: " << endl;
cout << "\tinputdir -- input dir for benchmark data" << endl; cout << "\tinputdir -- input dir for benchmark data" << endl;
if (DirectoryExists(inDir.c_str())) if (DirectoryExists(inDir.c_str()))
{ {
const int X_OFFSET = 10; const int X_OFFSET = 10;
const int Y_OFFSET = 10; const int Y_OFFSET = 10;
const int PAGE_MARGIN_X = 70; const int PAGE_MARGIN_X = 70;
const int PAGE_MARGIN_Y = 70; const int PAGE_MARGIN_Y = 70;
const int HORIZONTAL_RESOLUTION = 3500; const int HORIZONTAL_RESOLUTION = 3500;
const int TILE_WIDTH = 55; const int TILE_WIDTH = 55;
const int CHAR_HORIZ_OFFSET = 40; const int CHAR_HORIZ_OFFSET = 40;
const int TILE_HEIGHT = 70; const int TILE_HEIGHT = 70;
const int CHAR_VERT_OFFSET = 48; const int CHAR_VERT_OFFSET = 48;
vector<string> files = getFilesInDir(inDir.c_str()); vector<string> files = getFilesInDir(inDir.c_str());
sort( files.begin(), files.end(), stringCompare ); sort( files.begin(), files.end(), stringCompare );
int tiles_per_row = ((float) (HORIZONTAL_RESOLUTION - (PAGE_MARGIN_X * 2))) / ((float) TILE_WIDTH); int tiles_per_row = ((float) (HORIZONTAL_RESOLUTION - (PAGE_MARGIN_X * 2))) / ((float) TILE_WIDTH);
int lines = files.size() / (tiles_per_row); int lines = files.size() / (tiles_per_row);
int vertical_resolution = (lines * TILE_HEIGHT) + (PAGE_MARGIN_Y * 2) ; int vertical_resolution = (lines * TILE_HEIGHT) + (PAGE_MARGIN_Y * 2) ;
cout << tiles_per_row << " : " << vertical_resolution << endl; cout << tiles_per_row << " : " << vertical_resolution << endl;
Mat bigTif = Mat::zeros(Size(HORIZONTAL_RESOLUTION, vertical_resolution), CV_8U); Mat bigTif = Mat::zeros(Size(HORIZONTAL_RESOLUTION, vertical_resolution), CV_8U);
bitwise_not(bigTif, bigTif); bitwise_not(bigTif, bigTif);
stringstream boxFileOut; stringstream boxFileOut;
for (int i = 0; i< files.size(); i++) for (int i = 0; i< files.size(); i++)
{ {
int col = i % tiles_per_row; int col = i % tiles_per_row;
int line = i / tiles_per_row; int line = i / tiles_per_row;
int xPos = (col * TILE_WIDTH) + PAGE_MARGIN_X; int xPos = (col * TILE_WIDTH) + PAGE_MARGIN_X;
int yPos = (line * TILE_HEIGHT) + PAGE_MARGIN_Y; int yPos = (line * TILE_HEIGHT) + PAGE_MARGIN_Y;
if (hasEnding(files[i], ".png") || hasEnding(files[i], ".jpg")) if (hasEnding(files[i], ".png") || hasEnding(files[i], ".jpg"))
{ {
string fullpath = inDir + "/" + files[i]; string fullpath = inDir + "/" + files[i];
cout << "Processing file: " << (i + 1) << " of " << files.size() << endl; cout << "Processing file: " << (i + 1) << " of " << files.size() << endl;
char charcode = files[i][0]; char charcode = files[i][0];
Mat characterImg = imread(fullpath); Mat characterImg = imread(fullpath);
Mat charImgCopy = Mat::zeros(Size(150, 150), characterImg.type()); Mat charImgCopy = Mat::zeros(Size(150, 150), characterImg.type());
bitwise_not(charImgCopy, charImgCopy); bitwise_not(charImgCopy, charImgCopy);
characterImg.copyTo(charImgCopy(Rect(X_OFFSET, Y_OFFSET, characterImg.cols, characterImg.rows))); characterImg.copyTo(charImgCopy(Rect(X_OFFSET, Y_OFFSET, characterImg.cols, characterImg.rows)));
cvtColor(charImgCopy, charImgCopy, CV_BGR2GRAY); cvtColor(charImgCopy, charImgCopy, CV_BGR2GRAY);
bitwise_not(charImgCopy, charImgCopy); bitwise_not(charImgCopy, charImgCopy);
vector<vector<Point> > contours; vector<vector<Point> > contours;
//imshow("copy", charImgCopy); //imshow("copy", charImgCopy);
findContours(charImgCopy, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); findContours(charImgCopy, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
Rect tallestRect(0, 0, 0, 0); Rect tallestRect(0, 0, 0, 0);
for (int c = 0; c < contours.size(); c++) for (int c = 0; c < contours.size(); c++)
{ {
@@ -125,23 +125,23 @@ int main( int argc, const char** argv )
if (tmpRect.height > tallestRect.height) if (tmpRect.height > tallestRect.height)
tallestRect = tmpRect; tallestRect = tmpRect;
} }
//cout << tallestRect.x << ":" << tallestRect.y << " -- " << tallestRect.width << ":" << tallestRect.height << endl; //cout << tallestRect.x << ":" << tallestRect.y << " -- " << tallestRect.width << ":" << tallestRect.height << endl;
Rect cropRect(0, tallestRect.y - Y_OFFSET, tallestRect.width, tallestRect.height); Rect cropRect(0, tallestRect.y - Y_OFFSET, tallestRect.width, tallestRect.height);
//cout << "Cropped: " << cropRect.x << ":" << cropRect.y << " -- " << cropRect.width << ":" << cropRect.height << endl; //cout << "Cropped: " << cropRect.x << ":" << cropRect.y << " -- " << cropRect.width << ":" << cropRect.height << endl;
Mat cropped(characterImg, cropRect); Mat cropped(characterImg, cropRect);
cvtColor(cropped, cropped, CV_BGR2GRAY); cvtColor(cropped, cropped, CV_BGR2GRAY);
Rect destinationRect(xPos + (CHAR_HORIZ_OFFSET - tallestRect.width), yPos + (CHAR_VERT_OFFSET - tallestRect.height), tallestRect.width, tallestRect.height); Rect destinationRect(xPos + (CHAR_HORIZ_OFFSET - tallestRect.width), yPos + (CHAR_VERT_OFFSET - tallestRect.height), tallestRect.width, tallestRect.height);
//cout << "1" << endl; //cout << "1" << endl;
cropped.copyTo(bigTif(destinationRect)); cropped.copyTo(bigTif(destinationRect));
int x1= destinationRect.x - 2; int x1= destinationRect.x - 2;
int y1 = (vertical_resolution - destinationRect.y - destinationRect.height) - 2; int y1 = (vertical_resolution - destinationRect.y - destinationRect.height) - 2;
int x2 = (destinationRect.x + destinationRect.width) + 2; int x2 = (destinationRect.x + destinationRect.width) + 2;
@@ -150,24 +150,22 @@ int main( int argc, const char** argv )
boxFileOut << charcode << " " << x1 << " " << y1 << " "; boxFileOut << charcode << " " << x1 << " " << y1 << " ";
boxFileOut << x2 << " " << y2 ; boxFileOut << x2 << " " << y2 ;
boxFileOut << " 0" << endl; boxFileOut << " 0" << endl;
//rectangle(characterImg, tallestRect, Scalar(0, 255, 0)); //rectangle(characterImg, tallestRect, Scalar(0, 255, 0));
//imshow("characterImg", cropped); //imshow("characterImg", cropped);
waitKey(2); waitKey(2);
} }
} }
imwrite("combined.tif", bigTif); imwrite("combined.tif", bigTif);
ofstream boxFile("combined.box", std::ios::out); ofstream boxFile("combined.box", std::ios::out);
boxFile << boxFileOut.str(); boxFile << boxFileOut.str();
} }
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -37,42 +37,42 @@
// This is used to sort our own positive image database as a first step before grabbing characters to use to train the OCR. // This is used to sort our own positive image database as a first step before grabbing characters to use to train the OCR.
bool detectPlate( StateIdentifier* identifier, Mat frame); bool detectPlate( StateIdentifier* identifier, Mat frame);
int main( int argc, const char** argv ) int main( int argc, const char** argv )
{ {
string inDir; string inDir;
string outDir; string outDir;
Mat frame; Mat frame;
//Check if user specify image to process //Check if user specify image to process
if(argc == 3 ) if(argc == 3 )
{ {
inDir = argv[1]; inDir = argv[1];
outDir = argv[2]; outDir = argv[2];
outDir = outDir + "/"; outDir = outDir + "/";
}else{ }else{
printf("Use:\n\t%s directory \n",argv[0]); printf("Use:\n\t%s directory \n",argv[0]);
printf("Ex: \n\t%s ./pics/ \n",argv[0]); printf("Ex: \n\t%s ./pics/ \n",argv[0]);
return 0; return 0;
} }
Config config("us"); Config config("us");
StateIdentifier identifier(&config); StateIdentifier identifier(&config);
if (DirectoryExists(outDir.c_str()) == false) if (DirectoryExists(outDir.c_str()) == false)
{ {
printf("Output dir does not exist\n"); printf("Output dir does not exist\n");
return 0; return 0;
} }
if (DirectoryExists(inDir.c_str())) if (DirectoryExists(inDir.c_str()))
{ {
vector<string> files = getFilesInDir(inDir.c_str()); vector<string> files = getFilesInDir(inDir.c_str());
for (int i = 0; i< files.size(); i++) for (int i = 0; i< files.size(); i++)
{ {
if (hasEnding(files[i], ".png")) if (hasEnding(files[i], ".png"))
@@ -80,26 +80,26 @@ int main( int argc, const char** argv )
string fullpath = inDir + "/" + files[i]; string fullpath = inDir + "/" + files[i];
cout << fullpath << endl; cout << fullpath << endl;
frame = imread( fullpath.c_str() ); frame = imread( fullpath.c_str() );
char code[4]; char code[4];
int confidence = identifier.recognize(frame, code); int confidence = identifier.recognize(frame, code);
if (confidence <= 20) if (confidence <= 20)
{ {
code[0] = 'z'; code[0] = 'z';
code[1] = 'z'; code[1] = 'z';
confidence = 100; confidence = 100;
} }
//imshow("Plate", frame); //imshow("Plate", frame);
if (confidence > 20) if (confidence > 20)
{ {
cout << confidence << " : " << code; cout << confidence << " : " << code;
ostringstream convert; // stream used for the conversion ostringstream convert; // stream used for the conversion
convert << i; // insert the textual representation of 'Number' in the characters in the stream 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 + code + convert.str() + ".png";
system( copyCommand.c_str() ); system( copyCommand.c_str() );
waitKey(50); waitKey(50);
@@ -108,10 +108,10 @@ int main( int argc, const char** argv )
else else
waitKey(50); waitKey(50);
} }
} }
} }
} }
bool detectPlate( StateIdentifier* identifier, Mat frame); bool detectPlate( StateIdentifier* identifier, Mat frame);

View File

@@ -25,7 +25,7 @@ set(lpr_source_files
cjson.c cjson.c
) )
add_subdirectory(simpleini) add_subdirectory(simpleini)
add_subdirectory(support) add_subdirectory(support)
@@ -35,4 +35,4 @@ add_library(openalpr ${lpr_source_files})
# Add definition for default runtime dir # Add definition for default runtime dir
add_definitions(-DDEFAULT_RUNTIME_DIR="${CMAKE_SOURCE_DIR}/../runtime_data/") add_definitions(-DDEFAULT_RUNTIME_DIR="${CMAKE_SOURCE_DIR}/../runtime_data/")

View File

@@ -1,75 +1,75 @@
#ifndef _TREXPP_H_ #ifndef _TREXPP_H_
#define _TREXPP_H_ #define _TREXPP_H_
/*************************************************************** /***************************************************************
T-Rex a tiny regular expression library T-Rex a tiny regular expression library
Copyright (C) 2003-2004 Alberto Demichelis Copyright (C) 2003-2004 Alberto Demichelis
This software is provided 'as-is', without any express This software is provided 'as-is', without any express
or implied warranty. In no event will the authors be held or implied warranty. In no event will the authors be held
liable for any damages arising from the use of this software. liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for Permission is granted to anyone to use this software for
any purpose, including commercial applications, and to alter any purpose, including commercial applications, and to alter
it and redistribute it freely, subject to the following restrictions: it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; 1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software. you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but in the product documentation would be appreciated but
is not required. is not required.
2. Altered source versions must be plainly marked as such, 2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software. and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any 3. This notice may not be removed or altered from any
source distribution. source distribution.
****************************************************************/ ****************************************************************/
extern "C" { extern "C" {
#include "trex.h" #include "trex.h"
} }
struct TRexParseException{TRexParseException(const TRexChar *c):desc(c){}const TRexChar *desc;}; struct TRexParseException{TRexParseException(const TRexChar *c):desc(c){}const TRexChar *desc;};
class TRexpp { class TRexpp {
public: public:
TRexpp() { _exp = (TRex *)0; } TRexpp() { _exp = (TRex *)0; }
~TRexpp() { CleanUp(); } ~TRexpp() { CleanUp(); }
// compiles a regular expression // compiles a regular expression
void Compile(const TRexChar *pattern) { void Compile(const TRexChar *pattern) {
const TRexChar *error; const TRexChar *error;
CleanUp(); CleanUp();
if(!(_exp = trex_compile(pattern,&error))) if(!(_exp = trex_compile(pattern,&error)))
throw TRexParseException(error); throw TRexParseException(error);
} }
// return true if the given text match the expression // return true if the given text match the expression
bool Match(const TRexChar* text) { bool Match(const TRexChar* text) {
return _exp?(trex_match(_exp,text) != 0):false; return _exp?(trex_match(_exp,text) != 0):false;
} }
// Searches for the first match of the expression in a zero terminated string // Searches for the first match of the expression in a zero terminated string
bool Search(const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) { bool Search(const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) {
return _exp?(trex_search(_exp,text,out_begin,out_end) != 0):false; return _exp?(trex_search(_exp,text,out_begin,out_end) != 0):false;
} }
// Searches for the first match of the expression in a string sarting at text_begin and ending at text_end // Searches for the first match of the expression in a string sarting at text_begin and ending at text_end
bool SearchRange(const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) { bool SearchRange(const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) {
return _exp?(trex_searchrange(_exp,text_begin,text_end,out_begin,out_end) != 0):false; return _exp?(trex_searchrange(_exp,text_begin,text_end,out_begin,out_end) != 0):false;
} }
bool GetSubExp(int n, const TRexChar** out_begin, int *out_len) bool GetSubExp(int n, const TRexChar** out_begin, int *out_len)
{ {
TRexMatch match; TRexMatch match;
TRexBool res = _exp?(trex_getsubexp(_exp,n,&match)):TRex_False; TRexBool res = _exp?(trex_getsubexp(_exp,n,&match)):TRex_False;
if(res) { if(res) {
*out_begin = match.begin; *out_begin = match.begin;
*out_len = match.len; *out_len = match.len;
return true; return true;
} }
return false; return false;
} }
int GetSubExpCount() { return _exp?trex_getsubexpcount(_exp):0; } int GetSubExpCount() { return _exp?trex_getsubexpcount(_exp):0; }
private: private:
void CleanUp() { if(_exp) trex_free(_exp); _exp = (TRex *)0; } void CleanUp() { if(_exp) trex_free(_exp); _exp = (TRex *)0; }
TRex *_exp; TRex *_exp;
}; };
#endif //_TREXPP_H_ #endif //_TREXPP_H_

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -24,7 +24,7 @@
// ALPR code // ALPR code
Alpr::Alpr(const std::string country, const std::string runtimeDir) Alpr::Alpr(const std::string country, const std::string runtimeDir)
{ {
impl = new AlprImpl(country, runtimeDir); impl = new AlprImpl(country, runtimeDir);
@@ -37,7 +37,7 @@ std::vector<AlprResult> Alpr::recognize(std::string filepath)
{ {
cv::Mat img = cv::imread(filepath, CV_LOAD_IMAGE_COLOR); cv::Mat img = cv::imread(filepath, CV_LOAD_IMAGE_COLOR);
return impl->recognize(img); return impl->recognize(img);
} }
@@ -45,7 +45,7 @@ std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer)
{ {
// Not sure if this actually works // Not sure if this actually works
cv::Mat img = cv::imdecode(Mat(imageBuffer), 1); cv::Mat img = cv::imdecode(Mat(imageBuffer), 1);
return impl->recognize(img); return impl->recognize(img);
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -30,7 +30,7 @@ struct AlprPlate
{ {
std::string characters; std::string characters;
float overall_confidence; float overall_confidence;
bool matches_template; bool matches_template;
//int char_confidence[]; //int char_confidence[];
}; };
@@ -46,16 +46,16 @@ class AlprResult
public: public:
AlprResult(); AlprResult();
virtual ~AlprResult(); virtual ~AlprResult();
int requested_topn; int requested_topn;
int result_count; int result_count;
AlprPlate bestPlate; AlprPlate bestPlate;
std::vector<AlprPlate> topNPlates; std::vector<AlprPlate> topNPlates;
float processing_time_ms; float processing_time_ms;
AlprCoordinate plate_points[4]; AlprCoordinate plate_points[4];
int regionConfidence; int regionConfidence;
std::string region; std::string region;
}; };
@@ -73,16 +73,16 @@ class Alpr
void setDetectRegion(bool detectRegion); void setDetectRegion(bool detectRegion);
void setTopN(int topN); void setTopN(int topN);
void setDefaultRegion(std::string region); void setDefaultRegion(std::string region);
std::vector<AlprResult> recognize(std::string filepath); std::vector<AlprResult> recognize(std::string filepath);
std::vector<AlprResult> recognize(std::vector<unsigned char> imageBuffer); std::vector<AlprResult> recognize(std::vector<unsigned char> imageBuffer);
std::string toJson(const std::vector<AlprResult> results); std::string toJson(const std::vector<AlprResult> results);
bool isLoaded(); bool isLoaded();
private: private:
AlprImpl* impl; AlprImpl* impl;
}; };
#endif // APLR_H #endif // APLR_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -26,32 +26,32 @@ AlprImpl::AlprImpl(const std::string country, const std::string runtimeDir)
plateDetector = new RegionDetector(config); plateDetector = new RegionDetector(config);
stateIdentifier = new StateIdentifier(config); stateIdentifier = new StateIdentifier(config);
ocr = new OCR(config); ocr = new OCR(config);
this->detectRegion = DEFAULT_DETECT_REGION; this->detectRegion = DEFAULT_DETECT_REGION;
this->topN = DEFAULT_TOPN; this->topN = DEFAULT_TOPN;
this->defaultRegion = ""; this->defaultRegion = "";
if (config->opencl_enabled) if (config->opencl_enabled)
{ {
cv::ocl::PlatformsInfo platinfo; cv::ocl::PlatformsInfo platinfo;
cv::ocl::getOpenCLPlatforms(platinfo); cv::ocl::getOpenCLPlatforms(platinfo);
for (int i = 0; i < platinfo.size(); i++) for (int i = 0; i < platinfo.size(); i++)
{ {
std::cout << platinfo[i]->platformName << std::endl; std::cout << platinfo[i]->platformName << std::endl;
} }
cv::ocl::DevicesInfo devices; cv::ocl::DevicesInfo devices;
cv::ocl::getOpenCLDevices(devices, cv::ocl::CVCL_DEVICE_TYPE_CPU); cv::ocl::getOpenCLDevices(devices, cv::ocl::CVCL_DEVICE_TYPE_CPU);
for (int i = 0; i < devices.size(); i++) for (int i = 0; i < devices.size(); i++)
std:: cout << devices[i]->deviceName << std::endl; std:: cout << devices[i]->deviceName << std::endl;
if (devices.size() > 0) if (devices.size() > 0)
{ {
cv::ocl::setDevice(devices[0]); cv::ocl::setDevice(devices[0]);
cout << "Using OpenCL Device: " << devices[0]->deviceName << endl; cout << "Using OpenCL Device: " << devices[0]->deviceName << endl;
} }
else else
@@ -73,9 +73,9 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
{ {
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
vector<AlprResult> response; vector<AlprResult> response;
vector<Rect> plateRegions = plateDetector->detect(img); vector<Rect> plateRegions = plateDetector->detect(img);
@@ -86,24 +86,24 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
{ {
timespec platestarttime; timespec platestarttime;
getTime(&platestarttime); getTime(&platestarttime);
LicensePlateCandidate lp(img, plateRegions[i], config); LicensePlateCandidate lp(img, plateRegions[i], config);
lp.recognize(); lp.recognize();
if (lp.confidence > 10) if (lp.confidence > 10)
{ {
AlprResult plateResult; AlprResult plateResult;
plateResult.region = defaultRegion; plateResult.region = defaultRegion;
plateResult.regionConfidence = 0; plateResult.regionConfidence = 0;
for (int pointidx = 0; pointidx < 4; pointidx++) for (int pointidx = 0; pointidx < 4; pointidx++)
{ {
plateResult.plate_points[pointidx].x = (int) lp.plateCorners[pointidx].x; plateResult.plate_points[pointidx].x = (int) lp.plateCorners[pointidx].x;
plateResult.plate_points[pointidx].y = (int) lp.plateCorners[pointidx].y; plateResult.plate_points[pointidx].y = (int) lp.plateCorners[pointidx].y;
} }
if (detectRegion) if (detectRegion)
{ {
char statecode[4]; char statecode[4];
@@ -113,26 +113,26 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
plateResult.region = statecode; plateResult.region = statecode;
} }
} }
ocr->performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters); ocr->performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters);
ocr->postProcessor->analyze(plateResult.region, topN); ocr->postProcessor->analyze(plateResult.region, topN);
//plateResult.characters = ocr->postProcessor->bestChars; //plateResult.characters = ocr->postProcessor->bestChars;
const vector<PPResult> ppResults = ocr->postProcessor->getResults(); const vector<PPResult> ppResults = ocr->postProcessor->getResults();
int bestPlateIndex = 0; int bestPlateIndex = 0;
for (int pp = 0; pp < ppResults.size(); pp++) for (int pp = 0; pp < ppResults.size(); pp++)
{ {
if (pp >= topN) if (pp >= topN)
break; break;
// Set our "best plate" match to either the first entry, or the first entry with a postprocessor template match // Set our "best plate" match to either the first entry, or the first entry with a postprocessor template match
if (bestPlateIndex == 0 && ppResults[pp].matchesTemplate) if (bestPlateIndex == 0 && ppResults[pp].matchesTemplate)
bestPlateIndex = pp; bestPlateIndex = pp;
if (ppResults[pp].letters.size() >= config->postProcessMinCharacters && if (ppResults[pp].letters.size() >= config->postProcessMinCharacters &&
ppResults[pp].letters.size() <= config->postProcessMaxCharacters) ppResults[pp].letters.size() <= config->postProcessMaxCharacters)
{ {
@@ -144,32 +144,32 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
} }
} }
plateResult.result_count = plateResult.topNPlates.size(); plateResult.result_count = plateResult.topNPlates.size();
if (plateResult.topNPlates.size() > 0) if (plateResult.topNPlates.size() > 0)
plateResult.bestPlate = plateResult.topNPlates[bestPlateIndex]; plateResult.bestPlate = plateResult.topNPlates[bestPlateIndex];
timespec plateEndTime; timespec plateEndTime;
getTime(&plateEndTime); getTime(&plateEndTime);
plateResult.processing_time_ms = diffclock(platestarttime, plateEndTime); plateResult.processing_time_ms = diffclock(platestarttime, plateEndTime);
if (plateResult.result_count > 0) if (plateResult.result_count > 0)
response.push_back(plateResult); response.push_back(plateResult);
if (config->debugGeneral) if (config->debugGeneral)
{ {
rectangle(img, plateRegions[i], Scalar(0, 255, 0), 2); rectangle(img, plateRegions[i], Scalar(0, 255, 0), 2);
for (int z = 0; z < 4; z++) for (int z = 0; z < 4; z++)
line(img, lp.plateCorners[z], lp.plateCorners[(z + 1) % 4], Scalar(255,0,255), 2); line(img, lp.plateCorners[z], lp.plateCorners[(z + 1) % 4], Scalar(255,0,255), 2);
} }
} }
else else
{ {
if (config->debugGeneral) if (config->debugGeneral)
rectangle(img, plateRegions[i], Scalar(0, 0, 255), 2); rectangle(img, plateRegions[i], Scalar(0, 0, 255), 2);
} }
} }
if (config->debugTiming) if (config->debugTiming)
@@ -178,7 +178,7 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
getTime(&endTime); getTime(&endTime);
cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << endl; cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << endl;
} }
if (config->debugGeneral && config->debugShowImages) if (config->debugGeneral && config->debugShowImages)
{ {
displayImage(config, "Main Image", img); displayImage(config, "Main Image", img);
@@ -191,21 +191,21 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
string AlprImpl::toJson(const vector< AlprResult > results) string AlprImpl::toJson(const vector< AlprResult > results)
{ {
cJSON *root = cJSON_CreateArray(); cJSON *root = cJSON_CreateArray();
for (int i = 0; i < results.size(); i++) for (int i = 0; i < results.size(); i++)
{ {
cJSON *resultObj = createJsonObj( &results[i] ); cJSON *resultObj = createJsonObj( &results[i] );
cJSON_AddItemToArray(root, resultObj); cJSON_AddItemToArray(root, resultObj);
} }
// Print the JSON object to a string and return // Print the JSON object to a string and return
char *out; char *out;
out=cJSON_PrintUnformatted(root); out=cJSON_PrintUnformatted(root);
cJSON_Delete(root); cJSON_Delete(root);
string response(out); string response(out);
free(out); free(out);
return response; return response;
} }
@@ -215,18 +215,18 @@ string AlprImpl::toJson(const vector< AlprResult > results)
cJSON* AlprImpl::createJsonObj(const AlprResult* result) cJSON* AlprImpl::createJsonObj(const AlprResult* result)
{ {
cJSON *root, *coords, *candidates; cJSON *root, *coords, *candidates;
root=cJSON_CreateObject(); root=cJSON_CreateObject();
cJSON_AddStringToObject(root,"plate", result->bestPlate.characters.c_str()); cJSON_AddStringToObject(root,"plate", result->bestPlate.characters.c_str());
cJSON_AddNumberToObject(root,"confidence", result->bestPlate.overall_confidence); cJSON_AddNumberToObject(root,"confidence", result->bestPlate.overall_confidence);
cJSON_AddNumberToObject(root,"matches_template", result->bestPlate.matches_template); cJSON_AddNumberToObject(root,"matches_template", result->bestPlate.matches_template);
cJSON_AddStringToObject(root,"region", result->region.c_str()); cJSON_AddStringToObject(root,"region", result->region.c_str());
cJSON_AddNumberToObject(root,"region_confidence", result->regionConfidence); cJSON_AddNumberToObject(root,"region_confidence", result->regionConfidence);
cJSON_AddNumberToObject(root,"processing_time_ms", result->processing_time_ms); cJSON_AddNumberToObject(root,"processing_time_ms", result->processing_time_ms);
cJSON_AddItemToObject(root, "coordinates", coords=cJSON_CreateArray()); cJSON_AddItemToObject(root, "coordinates", coords=cJSON_CreateArray());
for (int i=0;i<4;i++) for (int i=0;i<4;i++)
{ {
@@ -237,8 +237,8 @@ cJSON* AlprImpl::createJsonObj(const AlprResult* result)
cJSON_AddItemToArray(coords, coords_object); cJSON_AddItemToArray(coords, coords_object);
} }
cJSON_AddItemToObject(root, "candidates", candidates=cJSON_CreateArray()); cJSON_AddItemToObject(root, "candidates", candidates=cJSON_CreateArray());
for (int i = 0; i < result->topNPlates.size(); i++) for (int i = 0; i < result->topNPlates.size(); i++)
{ {
@@ -250,7 +250,7 @@ cJSON* AlprImpl::createJsonObj(const AlprResult* result)
cJSON_AddItemToArray(candidates, candidate_object); cJSON_AddItemToArray(candidates, candidate_object);
} }
return root; return root;
} }
@@ -267,4 +267,3 @@ void AlprImpl::setDefaultRegion(string region)
{ {
this->defaultRegion = region; this->defaultRegion = region;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -34,7 +34,7 @@
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include "opencv2/ocl/ocl.hpp" #include "opencv2/ocl/ocl.hpp"
#define DEFAULT_TOPN 25 #define DEFAULT_TOPN 25
@@ -48,28 +48,28 @@ class AlprImpl
virtual ~AlprImpl(); virtual ~AlprImpl();
std::vector<AlprResult> recognize(cv::Mat img); std::vector<AlprResult> recognize(cv::Mat img);
void applyRegionTemplate(AlprResult* result, std::string region); void applyRegionTemplate(AlprResult* result, std::string region);
void setDetectRegion(bool detectRegion); void setDetectRegion(bool detectRegion);
void setTopN(int topn); void setTopN(int topn);
void setDefaultRegion(string region); void setDefaultRegion(string region);
std::string toJson(const vector<AlprResult> results); std::string toJson(const vector<AlprResult> results);
Config* config; Config* config;
private: private:
RegionDetector* plateDetector; RegionDetector* plateDetector;
StateIdentifier* stateIdentifier; StateIdentifier* stateIdentifier;
OCR* ocr; OCR* ocr;
int topN; int topN;
bool detectRegion; bool detectRegion;
std::string defaultRegion; std::string defaultRegion;
cJSON* createJsonObj(const AlprResult* result); cJSON* createJsonObj(const AlprResult* result);
}; };
#endif // ALPRIMPL_H #endif // ALPRIMPL_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -54,7 +54,7 @@ float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy) {
max_s = 0; max_s = 0;
for (int j = y_firstth ; j<=y_lastth; j++) for (int j = y_firstth ; j<=y_lastth; j++)
{ {
// Calculate the initial window at the beginning of the line // Calculate the initial window at the beginning of the line
sum = sum_sq = 0; sum = sum_sq = 0;
@@ -91,7 +91,7 @@ float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy) {
map_s.fset(i+wxh, j, s); map_s.fset(i+wxh, j, s);
} }
} }
return max_s; return max_s;
} }
@@ -103,9 +103,9 @@ float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy) {
void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version, void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
int winx, int winy, float k) { int winx, int winy, float k) {
float dR = BINARIZEWOLF_DEFAULTDR; float dR = BINARIZEWOLF_DEFAULTDR;
float m, s, max_s; float m, s, max_s;
float th=0; float th=0;
double min_I, max_I; double min_I, max_I;
@@ -121,11 +121,11 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
Mat map_m = Mat::zeros (im.rows, im.cols, CV_32F); Mat map_m = Mat::zeros (im.rows, im.cols, CV_32F);
Mat map_s = Mat::zeros (im.rows, im.cols, CV_32F); Mat map_s = Mat::zeros (im.rows, im.cols, CV_32F);
max_s = calcLocalStats (im, map_m, map_s, winx, winy); max_s = calcLocalStats (im, map_m, map_s, winx, winy);
minMaxLoc(im, &min_I, &max_I); minMaxLoc(im, &min_I, &max_I);
Mat thsurf (im.rows, im.cols, CV_32F); Mat thsurf (im.rows, im.cols, CV_32F);
// Create the threshold surface, including border processing // Create the threshold surface, including border processing
// ---------------------------------------------------- // ----------------------------------------------------
@@ -151,12 +151,12 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
case WOLFJOLION: case WOLFJOLION:
th = m + k * (s/max_s-1) * (m-min_I); th = m + k * (s/max_s-1) * (m-min_I);
break; break;
default: default:
cerr << "Unknown threshold type in ImageThresholder::surfaceNiblackImproved()\n"; cerr << "Unknown threshold type in ImageThresholder::surfaceNiblackImproved()\n";
exit (1); exit (1);
} }
thsurf.fset(i+wxh,j,th); thsurf.fset(i+wxh,j,th);
if (i==0) { if (i==0) {
@@ -205,10 +205,10 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
thsurf.fset(i,u,th); thsurf.fset(i,u,th);
} }
for (int y=0; y<im.rows; ++y) for (int y=0; y<im.rows; ++y)
for (int x=0; x<im.cols; ++x) for (int x=0; x<im.cols; ++x)
{ {
if (im.uget(x,y) >= thsurf.fget(x,y)) if (im.uget(x,y) >= thsurf.fget(x,y))
{ {

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -30,7 +30,7 @@
using namespace std; using namespace std;
using namespace cv; using namespace cv;
enum NiblackVersion enum NiblackVersion
{ {
NIBLACK=0, NIBLACK=0,
SAUVOLA, SAUVOLA,
@@ -53,4 +53,4 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
#endif // BINARIZEWOLF_H #endif // BINARIZEWOLF_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -40,64 +40,62 @@ class CharacterAnalysis
bool hasPlateMask; bool hasPlateMask;
Mat plateMask; Mat plateMask;
Mat bestThreshold; Mat bestThreshold;
vector<vector<Point> > bestContours; vector<vector<Point> > bestContours;
vector<Vec4i> bestHierarchy; vector<Vec4i> bestHierarchy;
vector<bool> bestCharSegments; vector<bool> bestCharSegments;
int bestCharSegmentsCount; int bestCharSegmentsCount;
LineSegment topLine; LineSegment topLine;
LineSegment bottomLine; LineSegment bottomLine;
vector<Point> linePolygon; vector<Point> linePolygon;
vector<Point> charArea; vector<Point> charArea;
LineSegment charBoxTop; LineSegment charBoxTop;
LineSegment charBoxBottom; LineSegment charBoxBottom;
LineSegment charBoxLeft; LineSegment charBoxLeft;
LineSegment charBoxRight; LineSegment charBoxRight;
bool thresholdsInverted; bool thresholdsInverted;
vector<Mat> thresholds; vector<Mat> thresholds;
vector<vector<vector<Point> > > allContours; vector<vector<vector<Point> > > allContours;
vector<vector<Vec4i> > allHierarchy; vector<vector<Vec4i> > allHierarchy;
vector<vector<bool> > charSegments; vector<vector<bool> > charSegments;
void analyze(); void analyze();
Mat getCharacterMask(); Mat getCharacterMask();
private: private:
Config* config; Config* config;
Mat img_gray; Mat img_gray;
Mat findOuterBoxMask( ); Mat findOuterBoxMask( );
bool isPlateInverted(); bool isPlateInverted();
vector<bool> filter(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy); vector<bool> filter(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy);
vector<bool> filterByBoxSize(vector<vector<Point> > contours, vector<bool> goodIndices, int minHeightPx, int maxHeightPx); vector<bool> filterByBoxSize(vector<vector<Point> > contours, vector<bool> goodIndices, int minHeightPx, int maxHeightPx);
vector<bool> filterByParentContour( vector< vector< Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); vector<bool> filterByParentContour( vector< vector< Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
vector<bool> filterContourHoles(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); vector<bool> filterContourHoles(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
vector<bool> filterByOuterMask(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); vector<bool> filterByOuterMask(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
vector<Point> getCharArea(); vector<Point> getCharArea();
vector<Point> getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices); vector<Point> getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices);
//vector<Point> getCharSegmentsBetweenLines(Mat img, vector<vector<Point> > contours, vector<Point> outerPolygon); //vector<Point> getCharSegmentsBetweenLines(Mat img, vector<vector<Point> > contours, vector<Point> outerPolygon);
vector<bool> filterBetweenLines(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<Point> outerPolygon, vector<bool> goodIndices); vector<bool> filterBetweenLines(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<Point> outerPolygon, vector<bool> goodIndices);
bool verifySize(Mat r, float minHeightPx, float maxHeightPx); bool verifySize(Mat r, float minHeightPx, float maxHeightPx);
int getGoodIndicesCount(vector<bool> goodIndices); int getGoodIndicesCount(vector<bool> goodIndices);
}; };
#endif // CHARACTERANALYSIS_H #endif // CHARACTERANALYSIS_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -25,22 +25,22 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
{ {
this->config = config; this->config = config;
this->debug = config->debugCharRegions; this->debug = config->debugCharRegions;
this->confidence = 0; this->confidence = 0;
if (this->debug) if (this->debug)
cout << "Starting CharacterRegion identification" << endl; cout << "Starting CharacterRegion identification" << endl;
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
charAnalysis = new CharacterAnalysis(img, config); charAnalysis = new CharacterAnalysis(img, config);
charAnalysis->analyze(); charAnalysis->analyze();
if (this->debug) if (this->debug)
{ {
vector<Mat> tempDash; vector<Mat> tempDash;
@@ -49,15 +49,15 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
Mat tmp(charAnalysis->thresholds[z].size(), charAnalysis->thresholds[z].type()); Mat tmp(charAnalysis->thresholds[z].size(), charAnalysis->thresholds[z].type());
charAnalysis->thresholds[z].copyTo(tmp); charAnalysis->thresholds[z].copyTo(tmp);
cvtColor(tmp, tmp, CV_GRAY2BGR); cvtColor(tmp, tmp, CV_GRAY2BGR);
tempDash.push_back(tmp); tempDash.push_back(tmp);
} }
Mat bestVal(charAnalysis->bestThreshold.size(), charAnalysis->bestThreshold.type()); Mat bestVal(charAnalysis->bestThreshold.size(), charAnalysis->bestThreshold.type());
charAnalysis->bestThreshold.copyTo(bestVal); charAnalysis->bestThreshold.copyTo(bestVal);
cvtColor(bestVal, bestVal, CV_GRAY2BGR); cvtColor(bestVal, bestVal, CV_GRAY2BGR);
for (int z = 0; z < charAnalysis->bestContours.size(); z++) for (int z = 0; z < charAnalysis->bestContours.size(); z++)
{ {
Scalar dcolor(255,0,0); Scalar dcolor(255,0,0);
@@ -70,73 +70,73 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
} }
if (this->debug) if (this->debug)
{ {
/* /*
Mat img_contours(img_threshold.size(), CV_8U); Mat img_contours(img_threshold.size(), CV_8U);
img_threshold.copyTo(img_contours); img_threshold.copyTo(img_contours);
cvtColor(img_contours, img_contours, CV_GRAY2RGB); cvtColor(img_contours, img_contours, CV_GRAY2RGB);
vector<vector<Point> > allowedContours; vector<vector<Point> > allowedContours;
for (int i = 0; i < contours.size(); i++) for (int i = 0; i < contours.size(); i++)
{ {
if (charSegments[i]) if (charSegments[i])
allowedContours.push_back(contours[i]); allowedContours.push_back(contours[i]);
} }
drawContours(img_contours, contours, drawContours(img_contours, contours,
-1, // draw all contours -1, // draw all contours
cv::Scalar(255,0,0), // in blue cv::Scalar(255,0,0), // in blue
1); // with a thickness of 1 1); // with a thickness of 1
drawContours(img_contours, allowedContours, drawContours(img_contours, allowedContours,
-1, // draw all contours -1, // draw all contours
cv::Scalar(0,255,0), // in green cv::Scalar(0,255,0), // in green
1); // with a thickness of 1 1); // with a thickness of 1
displayImage(config, "Matching Contours", img_contours); displayImage(config, "Matching Contours", img_contours);
*/ */
} }
//charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP)); //charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP));
if (charAnalysis->linePolygon.size() > 0) if (charAnalysis->linePolygon.size() > 0)
{ {
int confidenceDrainers = 0; int confidenceDrainers = 0;
int charSegmentCount = charAnalysis->bestCharSegmentsCount; int charSegmentCount = charAnalysis->bestCharSegmentsCount;
if (charSegmentCount == 1) if (charSegmentCount == 1)
confidenceDrainers += 91; confidenceDrainers += 91;
else if (charSegmentCount < 5) else if (charSegmentCount < 5)
confidenceDrainers += (5 - charSegmentCount) * 10; confidenceDrainers += (5 - charSegmentCount) * 10;
int absangle = abs(charAnalysis->topLine.angle); int absangle = abs(charAnalysis->topLine.angle);
if (absangle > 10) if (absangle > 10)
confidenceDrainers += 91; confidenceDrainers += 91;
else if (absangle > 1) else if (absangle > 1)
confidenceDrainers += (10 - absangle) * 5; confidenceDrainers += (10 - absangle) * 5;
if (confidenceDrainers >= 100) if (confidenceDrainers >= 100)
this->confidence=1; this->confidence=1;
else else
this->confidence = 100 - confidenceDrainers; this->confidence = 100 - confidenceDrainers;
} }
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
getTime(&endTime); getTime(&endTime);
cout << "Character Region Time: " << diffclock(startTime, endTime) << "ms." << endl; cout << "Character Region Time: " << diffclock(startTime, endTime) << "ms." << endl;
} }
} }
CharacterRegion::~CharacterRegion() CharacterRegion::~CharacterRegion()
@@ -150,45 +150,43 @@ Mat CharacterRegion::getPlateMask()
{ {
return charAnalysis->plateMask; return charAnalysis->plateMask;
} }
LineSegment CharacterRegion::getTopLine() LineSegment CharacterRegion::getTopLine()
{ {
return charAnalysis->topLine; return charAnalysis->topLine;
} }
LineSegment CharacterRegion::getBottomLine() LineSegment CharacterRegion::getBottomLine()
{ {
return charAnalysis->bottomLine; return charAnalysis->bottomLine;
} }
vector<Point> CharacterRegion::getCharArea() vector<Point> CharacterRegion::getCharArea()
{ {
return charAnalysis->charArea; return charAnalysis->charArea;
} }
LineSegment CharacterRegion::getCharBoxTop() LineSegment CharacterRegion::getCharBoxTop()
{ {
return charAnalysis->charBoxTop; return charAnalysis->charBoxTop;
} }
LineSegment CharacterRegion::getCharBoxBottom() LineSegment CharacterRegion::getCharBoxBottom()
{ {
return charAnalysis->charBoxBottom; return charAnalysis->charBoxBottom;
} }
LineSegment CharacterRegion::getCharBoxLeft() LineSegment CharacterRegion::getCharBoxLeft()
{ {
return charAnalysis->charBoxLeft; return charAnalysis->charBoxLeft;
} }
LineSegment CharacterRegion::getCharBoxRight() LineSegment CharacterRegion::getCharBoxRight()
{ {
return charAnalysis->charBoxRight; return charAnalysis->charBoxRight;
} }
bool CharacterRegion::thresholdsInverted() bool CharacterRegion::thresholdsInverted()
{ {
return charAnalysis->thresholdsInverted; return charAnalysis->thresholdsInverted;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -40,47 +40,45 @@ class CharacterRegion
virtual ~CharacterRegion(); virtual ~CharacterRegion();
CharacterAnalysis *charAnalysis; CharacterAnalysis *charAnalysis;
int confidence; int confidence;
Mat getPlateMask(); Mat getPlateMask();
LineSegment getTopLine(); LineSegment getTopLine();
LineSegment getBottomLine(); LineSegment getBottomLine();
//vector<Point> getLinePolygon(); //vector<Point> getLinePolygon();
vector<Point> getCharArea(); vector<Point> getCharArea();
LineSegment getCharBoxTop(); LineSegment getCharBoxTop();
LineSegment getCharBoxBottom(); LineSegment getCharBoxBottom();
LineSegment getCharBoxLeft(); LineSegment getCharBoxLeft();
LineSegment getCharBoxRight(); LineSegment getCharBoxRight();
bool thresholdsInverted(); bool thresholdsInverted();
protected: protected:
Config* config; Config* config;
bool debug; bool debug;
Mat findOuterBoxMask(vector<Mat> thresholds, vector<vector<vector<Point> > > allContours, vector<vector<Vec4i> > allHierarchy); Mat findOuterBoxMask(vector<Mat> thresholds, vector<vector<vector<Point> > > allContours, vector<vector<Vec4i> > allHierarchy);
vector<bool> filter(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy); vector<bool> filter(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy);
vector<bool> filterByBoxSize(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices, float minHeightPx, float maxHeightPx); vector<bool> filterByBoxSize(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices, float minHeightPx, float maxHeightPx);
vector<bool> filterByParentContour( vector< vector< Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); vector<bool> filterByParentContour( vector< vector< Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
vector<bool> filterContourHoles(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); vector<bool> filterContourHoles(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
vector<Point> getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices); vector<Point> getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices);
//vector<Point> getCharSegmentsBetweenLines(Mat img, vector<vector<Point> > contours, vector<Point> outerPolygon); //vector<Point> getCharSegmentsBetweenLines(Mat img, vector<vector<Point> > contours, vector<Point> outerPolygon);
vector<bool> filterBetweenLines(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<Point> outerPolygon, vector<bool> goodIndices); vector<bool> filterBetweenLines(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<Point> outerPolygon, vector<bool> goodIndices);
Mat getCharacterMask(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); Mat getCharacterMask(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
vector<Rect> wrapContours(vector<vector<Point> > contours); vector<Rect> wrapContours(vector<vector<Point> > contours);
bool verifySize(Mat r, float minHeightPx, float maxHeightPx); bool verifySize(Mat r, float minHeightPx, float maxHeightPx);
int getGoodIndicesCount(vector<bool> goodIndices); int getGoodIndicesCount(vector<bool> goodIndices);
bool isPlateInverted(Mat threshold, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); bool isPlateInverted(Mat threshold, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
}; };
#endif // CHARACTERREGION_H #endif // CHARACTERREGION_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -53,53 +53,51 @@ class CharacterSegmenter
vector<Rect> characters; vector<Rect> characters;
int confidence; int confidence;
vector<Mat> getThresholds(); vector<Mat> getThresholds();
private: private:
Config* config; Config* config;
CharacterAnalysis* charAnalysis; CharacterAnalysis* charAnalysis;
LineSegment top; LineSegment top;
LineSegment bottom; LineSegment bottom;
vector<Mat> imgDbgGeneral; vector<Mat> imgDbgGeneral;
vector<Mat> imgDbgCleanStages; vector<Mat> imgDbgCleanStages;
vector<bool> filter(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy); vector<bool> filter(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy);
vector<bool> filterByBoxSize(vector< vector< Point> > contours, vector<bool> goodIndices, float minHeightPx, float maxHeightPx); vector<bool> filterByBoxSize(vector< vector< Point> > contours, vector<bool> goodIndices, float minHeightPx, float maxHeightPx);
vector<bool> filterBetweenLines(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<Point> outerPolygon, vector<bool> goodIndices); vector<bool> filterBetweenLines(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<Point> outerPolygon, vector<bool> goodIndices);
vector<bool> filterContourHoles(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); vector<bool> filterContourHoles(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
vector<Point> getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices); vector<Point> getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices);
int getGoodIndicesCount(vector<bool> goodIndices); int getGoodIndicesCount(vector<bool> goodIndices);
Mat getCharacterMask(Mat img_threshold, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices); Mat getCharacterMask(Mat img_threshold, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
Mat getCharBoxMask(Mat img_threshold, vector<Rect> charBoxes); Mat getCharBoxMask(Mat img_threshold, vector<Rect> charBoxes);
void removeSmallContours(vector<Mat> thresholds, vector<vector<vector<Point > > > allContours, float avgCharWidth, float avgCharHeight); void removeSmallContours(vector<Mat> thresholds, vector<vector<vector<Point > > > allContours, float avgCharWidth, float avgCharHeight);
Mat getVerticalHistogram(Mat img, Mat mask); Mat getVerticalHistogram(Mat img, Mat mask);
vector<Rect> getHistogramBoxes(VerticalHistogram histogram, float avgCharWidth, float avgCharHeight, float* score); vector<Rect> getHistogramBoxes(VerticalHistogram histogram, float avgCharWidth, float avgCharHeight, float* score);
vector<Rect> getBestCharBoxes(Mat img, vector<Rect> charBoxes, float avgCharWidth); vector<Rect> getBestCharBoxes(Mat img, vector<Rect> charBoxes, float avgCharWidth);
vector<Rect> combineCloseBoxes( vector<Rect> charBoxes, float avgCharWidth); vector<Rect> combineCloseBoxes( vector<Rect> charBoxes, float avgCharWidth);
vector<Rect> get1DHits(Mat img, int yOffset); vector<Rect> get1DHits(Mat img, int yOffset);
void cleanCharRegions(vector<Mat> thresholds, vector<Rect> charRegions); void cleanCharRegions(vector<Mat> thresholds, vector<Rect> charRegions);
void cleanBasedOnColor(vector<Mat> thresholds, Mat colorMask, vector<Rect> charRegions); void cleanBasedOnColor(vector<Mat> thresholds, Mat colorMask, vector<Rect> charRegions);
void cleanMostlyFullBoxes(vector<Mat> thresholds, const vector<Rect> charRegions); void cleanMostlyFullBoxes(vector<Mat> thresholds, const vector<Rect> charRegions);
vector<Rect> filterMostlyEmptyBoxes(vector<Mat> thresholds, const vector<Rect> charRegions); vector<Rect> filterMostlyEmptyBoxes(vector<Mat> thresholds, const vector<Rect> charRegions);
void filterEdgeBoxes(vector<Mat> thresholds, const vector<Rect> charRegions, float avgCharWidth, float avgCharHeight); void filterEdgeBoxes(vector<Mat> thresholds, const vector<Rect> charRegions, float avgCharWidth, float avgCharHeight);
int getLongestBlobLengthBetweenLines(Mat img, int col); int getLongestBlobLengthBetweenLines(Mat img, int col);
int isSkinnyLineInsideBox(Mat threshold, Rect box, vector<vector<Point> > contours, vector<Vec4i> hierarchy, float avgCharWidth, float avgCharHeight); int isSkinnyLineInsideBox(Mat threshold, Rect box, vector<vector<Point> > contours, vector<Vec4i> hierarchy, float avgCharWidth, float avgCharHeight);
vector<Point> getEncapsulatingLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices); vector<Point> getEncapsulatingLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices);
}; };
#endif // CHARACTERSEGMENTER_H #endif // CHARACTERSEGMENTER_H

View File

@@ -107,7 +107,7 @@ static const char *parse_number(cJSON *item,const char *num)
} }
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
item->valuedouble=n; item->valuedouble=n;
item->valueint=(int)n; item->valueint=(int)n;
item->type=cJSON_Number; item->type=cJSON_Number;
@@ -156,12 +156,12 @@ static const char *parse_string(cJSON *item,const char *str)
{ {
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') {ep=str;return 0;} /* not a string! */ if (*str!='\"') {ep=str;return 0;} /* not a string! */
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
if (!out) return 0; if (!out) return 0;
ptr=str+1;ptr2=out; ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr) while (*ptr!='\"' && *ptr)
{ {
@@ -190,7 +190,7 @@ static const char *parse_string(cJSON *item,const char *str)
} }
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
switch (len) { switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
@@ -215,10 +215,10 @@ static const char *parse_string(cJSON *item,const char *str)
static char *print_string_ptr(const char *str) static char *print_string_ptr(const char *str)
{ {
const char *ptr;char *ptr2,*out;int len=0;unsigned char token; const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
if (!str) return cJSON_strdup(""); if (!str) return cJSON_strdup("");
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
out=(char*)cJSON_malloc(len+3); out=(char*)cJSON_malloc(len+3);
if (!out) return 0; if (!out) return 0;
@@ -351,7 +351,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
char *out=0,*ptr,*ret;int len=5; char *out=0,*ptr,*ret;int len=5;
cJSON *child=item->child; cJSON *child=item->child;
int numentries=0,i=0,fail=0; int numentries=0,i=0,fail=0;
/* How many entries in the array? */ /* How many entries in the array? */
while (child) numentries++,child=child->next; while (child) numentries++,child=child->next;
/* Explicitly handle numentries==0 */ /* Explicitly handle numentries==0 */
@@ -374,7 +374,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
child=child->next; child=child->next;
} }
/* If we didn't fail, try to malloc the output string */ /* If we didn't fail, try to malloc the output string */
if (!fail) out=(char*)cJSON_malloc(len); if (!fail) out=(char*)cJSON_malloc(len);
/* If that fails, we fail. */ /* If that fails, we fail. */
@@ -387,7 +387,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
cJSON_free(entries); cJSON_free(entries);
return 0; return 0;
} }
/* Compose the output array. */ /* Compose the output array. */
*out='['; *out='[';
ptr=out+1;*ptr=0; ptr=out+1;*ptr=0;
@@ -399,7 +399,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
} }
cJSON_free(entries); cJSON_free(entries);
*ptr++=']';*ptr++=0; *ptr++=']';*ptr++=0;
return out; return out;
} }
/* Build an object from the text. */ /* Build an object from the text. */
@@ -407,11 +407,11 @@ static const char *parse_object(cJSON *item,const char *value)
{ {
cJSON *child; cJSON *child;
if (*value!='{') {ep=value;return 0;} /* not an object! */ if (*value!='{') {ep=value;return 0;} /* not an object! */
item->type=cJSON_Object; item->type=cJSON_Object;
value=skip(value+1); value=skip(value+1);
if (*value=='}') return value+1; /* empty array. */ if (*value=='}') return value+1; /* empty array. */
item->child=child=cJSON_New_Item(); item->child=child=cJSON_New_Item();
if (!item->child) return 0; if (!item->child) return 0;
value=skip(parse_string(child,skip(value))); value=skip(parse_string(child,skip(value)));
@@ -420,7 +420,7 @@ static const char *parse_object(cJSON *item,const char *value)
if (*value!=':') {ep=value;return 0;} /* fail! */ if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0; if (!value) return 0;
while (*value==',') while (*value==',')
{ {
cJSON *new_item; cJSON *new_item;
@@ -433,7 +433,7 @@ static const char *parse_object(cJSON *item,const char *value)
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0; if (!value) return 0;
} }
if (*value=='}') return value+1; /* end of array */ if (*value=='}') return value+1; /* end of array */
ep=value;return 0; /* malformed. */ ep=value;return 0; /* malformed. */
} }
@@ -474,7 +474,7 @@ static char *print_object(cJSON *item,int depth,int fmt)
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
child=child->next; child=child->next;
} }
/* Try to allocate the output string */ /* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len); if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1; if (!out) fail=1;
@@ -486,7 +486,7 @@ static char *print_object(cJSON *item,int depth,int fmt)
cJSON_free(names);cJSON_free(entries); cJSON_free(names);cJSON_free(entries);
return 0; return 0;
} }
/* Compose the output: */ /* Compose the output: */
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++) for (i=0;i<numentries;i++)
@@ -499,11 +499,11 @@ static char *print_object(cJSON *item,int depth,int fmt)
if (fmt) *ptr++='\n';*ptr=0; if (fmt) *ptr++='\n';*ptr=0;
cJSON_free(names[i]);cJSON_free(entries[i]); cJSON_free(names[i]);cJSON_free(entries[i]);
} }
cJSON_free(names);cJSON_free(entries); cJSON_free(names);cJSON_free(entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr++=0; *ptr++='}';*ptr++=0;
return out; return out;
} }
/* Get Array size/item / object item. */ /* Get Array size/item / object item. */
@@ -593,4 +593,4 @@ void cJSON_Minify(char *json)
else *into++=*json++; // All other characters. else *into++=*json++; // All other characters.
} }
*into=0; // and null-terminate. *into=0; // and null-terminate.
} }

View File

@@ -1,16 +1,16 @@
/* /*
Copyright (c) 2009 Dave Gamble Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -36,7 +36,7 @@ extern "C"
#define cJSON_String 4 #define cJSON_String 4
#define cJSON_Array 5 #define cJSON_Array 5
#define cJSON_Object 6 #define cJSON_Object 6
#define cJSON_IsReference 256 #define cJSON_IsReference 256
/* The cJSON structure: */ /* The cJSON structure: */
@@ -80,7 +80,7 @@ extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr(void); extern const char *cJSON_GetErrorPtr(void);
/* These calls create a cJSON item of the appropriate type. */ /* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void); extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void); extern cJSON *cJSON_CreateTrue(void);
@@ -109,7 +109,7 @@ extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which); extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
/* Update array items. */ /* Update array items. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -24,31 +24,31 @@
ColorFilter::ColorFilter(Mat image, Mat characterMask, Config* config) ColorFilter::ColorFilter(Mat image, Mat characterMask, Config* config)
{ {
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
this->config = config; this->config = config;
this->debug = config->debugColorFiler; this->debug = config->debugColorFiler;
this->grayscale = imageIsGrayscale(image); this->grayscale = imageIsGrayscale(image);
if (this->debug) if (this->debug)
cout << "ColorFilter: isGrayscale = " << grayscale << endl; cout << "ColorFilter: isGrayscale = " << grayscale << endl;
this->hsv = Mat(image.size(), image.type()); this->hsv = Mat(image.size(), image.type());
cvtColor( image, this->hsv, CV_BGR2HSV ); cvtColor( image, this->hsv, CV_BGR2HSV );
preprocessImage(); preprocessImage();
this->charMask = characterMask; this->charMask = characterMask;
this->colorMask = Mat(image.size(), CV_8U); this->colorMask = Mat(image.size(), CV_8U);
findCharColors(); findCharColors();
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
@@ -72,7 +72,7 @@ bool ColorFilter::imageIsGrayscale(Mat image)
int r = (int) image.at<Vec3b>(row, col)[0]; int r = (int) image.at<Vec3b>(row, col)[0];
int g = (int) image.at<Vec3b>(row, col)[1]; int g = (int) image.at<Vec3b>(row, col)[1];
int b = (int) image.at<Vec3b>(row, col)[2]; int b = (int) image.at<Vec3b>(row, col)[2];
if (r == g == b) if (r == g == b)
{ {
// So far so good // So far so good
@@ -84,7 +84,7 @@ bool ColorFilter::imageIsGrayscale(Mat image)
} }
} }
} }
return true; return true;
} }
@@ -94,7 +94,7 @@ void ColorFilter::preprocessImage()
vector<Mat> channels; vector<Mat> channels;
split(this->hsv,channels); split(this->hsv,channels);
Mat img_equalized = equalizeBrightness(channels[2]); Mat img_equalized = equalizeBrightness(channels[2]);
merge(channels,this->hsv); merge(channels,this->hsv);
} }
// Gets the hue/sat/val for areas that we believe are license plate characters // Gets the hue/sat/val for areas that we believe are license plate characters
@@ -102,14 +102,14 @@ void ColorFilter::preprocessImage()
void ColorFilter::findCharColors() void ColorFilter::findCharColors()
{ {
int MINIMUM_SATURATION = 45; int MINIMUM_SATURATION = 45;
if (this->debug) if (this->debug)
cout << "ColorFilter::findCharColors" << endl; cout << "ColorFilter::findCharColors" << endl;
//charMask.copyTo(this->colorMask); //charMask.copyTo(this->colorMask);
this->colorMask = Mat::zeros(charMask.size(), CV_8U); this->colorMask = Mat::zeros(charMask.size(), CV_8U);
bitwise_not(this->colorMask, this->colorMask); bitwise_not(this->colorMask, this->colorMask);
Mat erodedCharMask(charMask.size(), CV_8U); Mat erodedCharMask(charMask.size(), CV_8U);
Mat element = getStructuringElement( 1, Mat element = getStructuringElement( 1,
Size( 2 + 1, 2+1 ), Size( 2 + 1, 2+1 ),
@@ -120,80 +120,80 @@ void ColorFilter::findCharColors()
vector<Vec4i> hierarchy; vector<Vec4i> hierarchy;
findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
vector<float> hMeans, sMeans, vMeans; vector<float> hMeans, sMeans, vMeans;
vector<float> hStdDevs, sStdDevs, vStdDevs; vector<float> hStdDevs, sStdDevs, vStdDevs;
for (int i = 0; i < contours.size(); i++) for (int i = 0; i < contours.size(); i++)
{ {
if (hierarchy[i][3] != -1) if (hierarchy[i][3] != -1)
continue; continue;
Mat singleCharMask = Mat::zeros(hsv.size(), CV_8U); Mat singleCharMask = Mat::zeros(hsv.size(), CV_8U);
drawContours(singleCharMask, contours, drawContours(singleCharMask, contours,
i, // draw this contour i, // draw this contour
cv::Scalar(255,255,255), // in cv::Scalar(255,255,255), // in
CV_FILLED, CV_FILLED,
8, 8,
hierarchy hierarchy
); );
// get rid of the outline by drawing a 1 pixel width black line // get rid of the outline by drawing a 1 pixel width black line
drawContours(singleCharMask, contours, drawContours(singleCharMask, contours,
i, // draw this contour i, // draw this contour
cv::Scalar(0,0,0), // in cv::Scalar(0,0,0), // in
1, 1,
8, 8,
hierarchy hierarchy
); );
//drawAndWait(&singleCharMask); //drawAndWait(&singleCharMask);
Scalar mean; Scalar mean;
Scalar stddev; Scalar stddev;
meanStdDev(hsv, mean, stddev, singleCharMask); meanStdDev(hsv, mean, stddev, singleCharMask);
if (this->debug) if (this->debug)
{ {
cout << "ColorFilter " << setw(3) << i << ". Mean: h: " << setw(7) << mean[0] << " s: " << setw(7) <<mean[1] << " v: " << setw(7) << mean[2] cout << "ColorFilter " << setw(3) << i << ". Mean: h: " << setw(7) << mean[0] << " s: " << setw(7) <<mean[1] << " v: " << setw(7) << mean[2]
<< " | Std: h: " << setw(7) <<stddev[0] << " s: " << setw(7) <<stddev[1] << " v: " << stddev[2] << endl; << " | Std: h: " << setw(7) <<stddev[0] << " s: " << setw(7) <<stddev[1] << " v: " << stddev[2] << endl;
} }
if (mean[0] == 0 && mean[1] == 0 && mean[2] == 0) if (mean[0] == 0 && mean[1] == 0 && mean[2] == 0)
continue; continue;
hMeans.push_back(mean[0]); hMeans.push_back(mean[0]);
sMeans.push_back(mean[1]); sMeans.push_back(mean[1]);
vMeans.push_back(mean[2]); vMeans.push_back(mean[2]);
hStdDevs.push_back(stddev[0]); hStdDevs.push_back(stddev[0]);
sStdDevs.push_back(stddev[1]); sStdDevs.push_back(stddev[1]);
vStdDevs.push_back(stddev[2]); vStdDevs.push_back(stddev[2]);
} }
if (hMeans.size() == 0) if (hMeans.size() == 0)
return; return;
int bestHueIndex = this->getMajorityOpinion(hMeans, .65, 30); int bestHueIndex = this->getMajorityOpinion(hMeans, .65, 30);
int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35); int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35);
int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30); int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30);
if (sMeans[bestSatIndex] < MINIMUM_SATURATION) if (sMeans[bestSatIndex] < MINIMUM_SATURATION)
return; return;
bool doHueFilter = false, doSatFilter = false, doValFilter = false; bool doHueFilter = false, doSatFilter = false, doValFilter = false;
float hueMin, hueMax; float hueMin, hueMax;
float satMin, satMax; float satMin, satMax;
float valMin, valMax; float valMin, valMax;
if (this->debug) if (this->debug)
cout << "ColorFilter Winning indices:" << endl; cout << "ColorFilter Winning indices:" << endl;
if (bestHueIndex != -1) if (bestHueIndex != -1)
@@ -201,64 +201,64 @@ void ColorFilter::findCharColors()
doHueFilter = true; doHueFilter = true;
hueMin = hMeans[bestHueIndex] - (2 * hStdDevs[bestHueIndex]); hueMin = hMeans[bestHueIndex] - (2 * hStdDevs[bestHueIndex]);
hueMax = hMeans[bestHueIndex] + (2 * hStdDevs[bestHueIndex]); hueMax = hMeans[bestHueIndex] + (2 * hStdDevs[bestHueIndex]);
if (abs(hueMin - hueMax) < 20) if (abs(hueMin - hueMax) < 20)
{ {
hueMin = hMeans[bestHueIndex] - 20; hueMin = hMeans[bestHueIndex] - 20;
hueMax = hMeans[bestHueIndex] + 20; hueMax = hMeans[bestHueIndex] + 20;
} }
if (hueMin < 0) if (hueMin < 0)
hueMin = 0; hueMin = 0;
if (hueMax > 180) if (hueMax > 180)
hueMax = 180; hueMax = 180;
if (this->debug) if (this->debug)
cout << "ColorFilter Hue: " << bestHueIndex << " : " << setw(7) << hMeans[bestHueIndex] << " -- " << hueMin << "-" << hueMax << endl; cout << "ColorFilter Hue: " << bestHueIndex << " : " << setw(7) << hMeans[bestHueIndex] << " -- " << hueMin << "-" << hueMax << endl;
} }
if (bestSatIndex != -1) if (bestSatIndex != -1)
{ {
doSatFilter = true; doSatFilter = true;
satMin = sMeans[bestSatIndex] - (2 * sStdDevs[bestSatIndex]); satMin = sMeans[bestSatIndex] - (2 * sStdDevs[bestSatIndex]);
satMax = sMeans[bestSatIndex] + (2 * sStdDevs[bestSatIndex]); satMax = sMeans[bestSatIndex] + (2 * sStdDevs[bestSatIndex]);
if (abs(satMin - satMax) < 20) if (abs(satMin - satMax) < 20)
{ {
satMin = sMeans[bestSatIndex] - 20; satMin = sMeans[bestSatIndex] - 20;
satMax = sMeans[bestSatIndex] + 20; satMax = sMeans[bestSatIndex] + 20;
} }
if (satMin < 0) if (satMin < 0)
satMin = 0; satMin = 0;
if (satMax > 255) if (satMax > 255)
satMax = 255; satMax = 255;
if (this->debug) if (this->debug)
cout << "ColorFilter Sat: " << bestSatIndex << " : " << setw(7) << sMeans[bestSatIndex] << " -- " << satMin << "-" << satMax << endl; cout << "ColorFilter Sat: " << bestSatIndex << " : " << setw(7) << sMeans[bestSatIndex] << " -- " << satMin << "-" << satMax << endl;
} }
if (bestValIndex != -1) if (bestValIndex != -1)
{ {
doValFilter = true; doValFilter = true;
valMin = vMeans[bestValIndex] - (1.5 * vStdDevs[bestValIndex]); valMin = vMeans[bestValIndex] - (1.5 * vStdDevs[bestValIndex]);
valMax = vMeans[bestValIndex] + (1.5 * vStdDevs[bestValIndex]); valMax = vMeans[bestValIndex] + (1.5 * vStdDevs[bestValIndex]);
if (abs(valMin - valMax) < 20) if (abs(valMin - valMax) < 20)
{ {
valMin = vMeans[bestValIndex] - 20; valMin = vMeans[bestValIndex] - 20;
valMax = vMeans[bestValIndex] + 20; valMax = vMeans[bestValIndex] + 20;
} }
if (valMin < 0) if (valMin < 0)
valMin = 0; valMin = 0;
if (valMax > 255) if (valMax > 255)
valMax = 255; valMax = 255;
if (this->debug) if (this->debug)
cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax << endl; cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax << endl;
} }
Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type()); Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type());
@@ -266,7 +266,7 @@ void ColorFilter::findCharColors()
Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U); Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U);
Mat debugMask = Mat::zeros(hsv.size(), CV_8U); Mat debugMask = Mat::zeros(hsv.size(), CV_8U);
bitwise_not(debugMask, debugMask); bitwise_not(debugMask, debugMask);
for (int row = 0; row < charMask.rows; row++) for (int row = 0; row < charMask.rows; row++)
{ {
for (int col = 0; col < charMask.cols; col++) for (int col = 0; col < charMask.cols; col++)
@@ -274,21 +274,21 @@ void ColorFilter::findCharColors()
int h = (int) hsv.at<Vec3b>(row, col)[0]; int h = (int) hsv.at<Vec3b>(row, col)[0];
int s = (int) hsv.at<Vec3b>(row, col)[1]; int s = (int) hsv.at<Vec3b>(row, col)[1];
int v = (int) hsv.at<Vec3b>(row, col)[2]; int v = (int) hsv.at<Vec3b>(row, col)[2];
bool hPasses = true; bool hPasses = true;
bool sPasses = true; bool sPasses = true;
bool vPasses = true; bool vPasses = true;
int vDistance = abs(v - vMeans[bestValIndex]); int vDistance = abs(v - vMeans[bestValIndex]);
imgDebugHueOnly.at<Vec3b>(row, col)[0] = h; imgDebugHueOnly.at<Vec3b>(row, col)[0] = h;
imgDebugHueOnly.at<Vec3b>(row, col)[1] = 255; imgDebugHueOnly.at<Vec3b>(row, col)[1] = 255;
imgDebugHueOnly.at<Vec3b>(row, col)[2] = 255; imgDebugHueOnly.at<Vec3b>(row, col)[2] = 255;
imgDebug.at<Vec3b>(row, col)[0] = 255; imgDebug.at<Vec3b>(row, col)[0] = 255;
imgDebug.at<Vec3b>(row, col)[1] = 255; imgDebug.at<Vec3b>(row, col)[1] = 255;
imgDebug.at<Vec3b>(row, col)[2] = 255; imgDebug.at<Vec3b>(row, col)[2] = 255;
if (doHueFilter && (h < hueMin || h > hueMax)) if (doHueFilter && (h < hueMin || h > hueMax))
{ {
hPasses = false; hPasses = false;
@@ -305,20 +305,20 @@ void ColorFilter::findCharColors()
vPasses = false; vPasses = false;
imgDebug.at<Vec3b>(row, col)[2] = 0; imgDebug.at<Vec3b>(row, col)[2] = 0;
} }
//if (pixelPasses) //if (pixelPasses)
// colorMask.at<uchar>(row, col) = 255; // colorMask.at<uchar>(row, col) = 255;
//else //else
//imgDebug.at<Vec3b>(row, col)[0] = hPasses & 255; //imgDebug.at<Vec3b>(row, col)[0] = hPasses & 255;
//imgDebug.at<Vec3b>(row, col)[1] = sPasses & 255; //imgDebug.at<Vec3b>(row, col)[1] = sPasses & 255;
//imgDebug.at<Vec3b>(row, col)[2] = vPasses & 255; //imgDebug.at<Vec3b>(row, col)[2] = vPasses & 255;
if ((hPasses) || (hPasses && sPasses))//(hPasses && vPasses) || (sPasses && vPasses) || if ((hPasses) || (hPasses && sPasses))//(hPasses && vPasses) || (sPasses && vPasses) ||
this->colorMask.at<uchar>(row, col) = 255; this->colorMask.at<uchar>(row, col) = 255;
else else
this->colorMask.at<uchar>(row, col) = 0; this->colorMask.at<uchar>(row, col) = 0;
if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses)) if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses))
{ {
vDistance = pow(vDistance, 0.9); vDistance = pow(vDistance, 0.9);
@@ -332,11 +332,11 @@ void ColorFilter::findCharColors()
imgDistanceFromCenter.at<uchar>(row, col) = vDistance; imgDistanceFromCenter.at<uchar>(row, col) = vDistance;
} }
} }
vector<Mat> debugImagesSet; vector<Mat> debugImagesSet;
if (this->debug) if (this->debug)
{ {
debugImagesSet.push_back(addLabel(charMask, "Charecter mask")); debugImagesSet.push_back(addLabel(charMask, "Charecter mask"));
@@ -345,40 +345,40 @@ void ColorFilter::findCharColors()
colorMask.copyTo(maskCopy); colorMask.copyTo(maskCopy);
debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before")); debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before"));
} }
Mat bigElement = getStructuringElement( 1, Mat bigElement = getStructuringElement( 1,
Size( 3 + 1, 3+1 ), Size( 3 + 1, 3+1 ),
Point( 1, 1 ) ); Point( 1, 1 ) );
Mat smallElement = getStructuringElement( 1, Mat smallElement = getStructuringElement( 1,
Size( 1 + 1, 1+1 ), Size( 1 + 1, 1+1 ),
Point( 1, 1 ) ); Point( 1, 1 ) );
morphologyEx(this->colorMask, this->colorMask, MORPH_CLOSE, bigElement); morphologyEx(this->colorMask, this->colorMask, MORPH_CLOSE, bigElement);
//dilate(this->colorMask, this->colorMask, bigElement); //dilate(this->colorMask, this->colorMask, bigElement);
Mat combined(charMask.size(), charMask.type()); Mat combined(charMask.size(), charMask.type());
bitwise_and(charMask, colorMask, combined); bitwise_and(charMask, colorMask, combined);
if (this->debug) if (this->debug)
{ {
debugImagesSet.push_back(addLabel(colorMask, "Color Mask After")); debugImagesSet.push_back(addLabel(colorMask, "Color Mask After"));
debugImagesSet.push_back(addLabel(combined, "Combined")); debugImagesSet.push_back(addLabel(combined, "Combined"));
//displayImage(config, "COLOR filter Mask", colorMask); //displayImage(config, "COLOR filter Mask", colorMask);
debugImagesSet.push_back(addLabel(imgDebug, "Color filter Debug")); debugImagesSet.push_back(addLabel(imgDebug, "Color filter Debug"));
cvtColor(imgDebugHueOnly, imgDebugHueOnly, CV_HSV2BGR); cvtColor(imgDebugHueOnly, imgDebugHueOnly, CV_HSV2BGR);
debugImagesSet.push_back(addLabel(imgDebugHueOnly, "Color Filter Hue")); debugImagesSet.push_back(addLabel(imgDebugHueOnly, "Color Filter Hue"));
equalizeHist(imgDistanceFromCenter, imgDistanceFromCenter); equalizeHist(imgDistanceFromCenter, imgDistanceFromCenter);
debugImagesSet.push_back(addLabel(imgDistanceFromCenter, "COLOR filter Distance")); debugImagesSet.push_back(addLabel(imgDistanceFromCenter, "COLOR filter Distance"));
debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off")); debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off"));
Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3); Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3);
displayImage(config, "Color Filter Images", dashboard); displayImage(config, "Color Filter Images", dashboard);
} }
@@ -394,7 +394,7 @@ int ColorFilter::getMajorityOpinion(vector<float> values, float minPercentAgreem
float bestPercentAgreement = 0; float bestPercentAgreement = 0;
float lowestOverallDiff = 1000000000; float lowestOverallDiff = 1000000000;
int bestPercentAgreementIndex = -1; int bestPercentAgreementIndex = -1;
for (int i = 0; i < values.size(); i++) for (int i = 0; i < values.size(); i++)
{ {
int valuesInRange = 0; int valuesInRange = 0;
@@ -404,10 +404,10 @@ int ColorFilter::getMajorityOpinion(vector<float> values, float minPercentAgreem
float diff = abs(values[i] - values[j]); float diff = abs(values[i] - values[j]);
if (diff < maxValDifference) if (diff < maxValDifference)
valuesInRange++; valuesInRange++;
overallDiff += diff; overallDiff += diff;
} }
float percentAgreement = ((float) valuesInRange) / ((float) values.size()); float percentAgreement = ((float) valuesInRange) / ((float) values.size());
if (overallDiff < lowestOverallDiff && percentAgreement >= bestPercentAgreement && percentAgreement >= minPercentAgreement) if (overallDiff < lowestOverallDiff && percentAgreement >= bestPercentAgreement && percentAgreement >= minPercentAgreement)
{ {
@@ -416,6 +416,6 @@ int ColorFilter::getMajorityOpinion(vector<float> values, float minPercentAgreem
lowestOverallDiff = overallDiff; lowestOverallDiff = overallDiff;
} }
} }
return bestPercentAgreementIndex; return bestPercentAgreementIndex;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -43,23 +43,23 @@ class ColorFilter
Mat colorMask; Mat colorMask;
private: private:
Config* config; Config* config;
bool debug; bool debug;
Mat hsv; Mat hsv;
Mat charMask; Mat charMask;
bool grayscale; bool grayscale;
void preprocessImage(); void preprocessImage();
void findCharColors(); void findCharColors();
bool imageIsGrayscale(Mat image); bool imageIsGrayscale(Mat image);
int getMajorityOpinion(vector<float> values, float minPercentAgreement, float maxValDifference); int getMajorityOpinion(vector<float> values, float minPercentAgreement, float maxValDifference);
}; };
#endif // COLORFILTER_H #endif // COLORFILTER_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -23,15 +23,15 @@
Config::Config(const std::string country, const std::string runtimeBaseDir) Config::Config(const std::string country, const std::string runtimeBaseDir)
{ {
this->runtimeBaseDir = runtimeBaseDir; this->runtimeBaseDir = runtimeBaseDir;
ini = new CSimpleIniA(); ini = new CSimpleIniA();
char* envRuntimeDir; char* envRuntimeDir;
envRuntimeDir = getenv (ENV_VARIABLE_RUNTIME_DIR); envRuntimeDir = getenv (ENV_VARIABLE_RUNTIME_DIR);
if (runtimeBaseDir.compare("") != 0) if (runtimeBaseDir.compare("") != 0)
{ {
// User has supplied a runtime directory. Use that. // User has supplied a runtime directory. Use that.
} }
else if (envRuntimeDir!=NULL) else if (envRuntimeDir!=NULL)
{ {
@@ -43,9 +43,9 @@ Config::Config(const std::string country, const std::string runtimeBaseDir)
// Use the default // Use the default
this->runtimeBaseDir = DEFAULT_RUNTIME_DIR; this->runtimeBaseDir = DEFAULT_RUNTIME_DIR;
} }
string configFile = (this->runtimeBaseDir + CONFIG_FILE); string configFile = (this->runtimeBaseDir + CONFIG_FILE);
if (DirectoryExists(this->runtimeBaseDir.c_str()) == false) if (DirectoryExists(this->runtimeBaseDir.c_str()) == false)
{ {
std::cerr << "--(!)Runtime directory '" << this->runtimeBaseDir << "' does not exist!" << endl; std::cerr << "--(!)Runtime directory '" << this->runtimeBaseDir << "' does not exist!" << endl;
@@ -56,11 +56,11 @@ Config::Config(const std::string country, const std::string runtimeBaseDir)
std::cerr << "--(!)Runtime directory '" << this->runtimeBaseDir << "' does not contain a config file '" << CONFIG_FILE << "'!" << endl; std::cerr << "--(!)Runtime directory '" << this->runtimeBaseDir << "' does not contain a config file '" << CONFIG_FILE << "'!" << endl;
return; return;
} }
ini->LoadFile(configFile.c_str()); ini->LoadFile(configFile.c_str());
this->country = country; this->country = country;
loadValues(country); loadValues(country);
} }
Config::~Config() Config::~Config()
@@ -70,56 +70,56 @@ Config::~Config()
void Config::loadValues(string country) void Config::loadValues(string country)
{ {
opencl_enabled = getBoolean("common", "opencl_enabled", false); opencl_enabled = getBoolean("common", "opencl_enabled", false);
maxPlateWidthPercent = getFloat("common", "max_plate_width_percent", 100); maxPlateWidthPercent = getFloat("common", "max_plate_width_percent", 100);
maxPlateHeightPercent = getFloat("common", "max_plate_height_percent", 100); maxPlateHeightPercent = getFloat("common", "max_plate_height_percent", 100);
minPlateSizeWidthPx = getInt(country, "min_plate_size_width_px", 100); minPlateSizeWidthPx = getInt(country, "min_plate_size_width_px", 100);
minPlateSizeHeightPx = getInt(country, "min_plate_size_height_px", 100); minPlateSizeHeightPx = getInt(country, "min_plate_size_height_px", 100);
plateWidthMM = getFloat(country, "plate_width_mm", 100); plateWidthMM = getFloat(country, "plate_width_mm", 100);
plateHeightMM = getFloat(country, "plate_height_mm", 100); plateHeightMM = getFloat(country, "plate_height_mm", 100);
charHeightMM = getFloat(country, "char_height_mm", 100); charHeightMM = getFloat(country, "char_height_mm", 100);
charWidthMM = getFloat(country, "char_width_mm", 100); charWidthMM = getFloat(country, "char_width_mm", 100);
charWhitespaceTopMM = getFloat(country, "char_whitespace_top_mm", 100); charWhitespaceTopMM = getFloat(country, "char_whitespace_top_mm", 100);
charWhitespaceBotMM = getFloat(country, "char_whitespace_bot_mm", 100); charWhitespaceBotMM = getFloat(country, "char_whitespace_bot_mm", 100);
templateWidthPx = getInt(country, "template_max_width_px", 100); templateWidthPx = getInt(country, "template_max_width_px", 100);
templateHeightPx = getInt(country, "template_max_height_px", 100); templateHeightPx = getInt(country, "template_max_height_px", 100);
float ocrImagePercent = getFloat("common", "ocr_img_size_percent", 100); float ocrImagePercent = getFloat("common", "ocr_img_size_percent", 100);
ocrImageWidthPx = round(((float) templateWidthPx) * ocrImagePercent); ocrImageWidthPx = round(((float) templateWidthPx) * ocrImagePercent);
ocrImageHeightPx = round(((float)templateHeightPx) * ocrImagePercent); ocrImageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
float stateIdImagePercent = getFloat("common", "state_id_img_size_percent", 100); float stateIdImagePercent = getFloat("common", "state_id_img_size_percent", 100);
stateIdImageWidthPx = round(((float)templateWidthPx) * ocrImagePercent); stateIdImageWidthPx = round(((float)templateWidthPx) * ocrImagePercent);
stateIdimageHeightPx = round(((float)templateHeightPx) * ocrImagePercent); stateIdimageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
charAnalysisMinPercent = getFloat(country, "char_analysis_min_pct", 0); charAnalysisMinPercent = getFloat(country, "char_analysis_min_pct", 0);
charAnalysisHeightRange = getFloat(country, "char_analysis_height_range", 0); charAnalysisHeightRange = getFloat(country, "char_analysis_height_range", 0);
charAnalysisHeightStepSize = getFloat(country, "char_analysis_height_step_size", 0); charAnalysisHeightStepSize = getFloat(country, "char_analysis_height_step_size", 0);
charAnalysisNumSteps = getInt(country, "char_analysis_height_num_steps", 0); charAnalysisNumSteps = getInt(country, "char_analysis_height_num_steps", 0);
segmentationMinBoxWidthPx = getInt(country, "segmentation_min_box_width_px", 0); segmentationMinBoxWidthPx = getInt(country, "segmentation_min_box_width_px", 0);
segmentationMinCharHeightPercent = getFloat(country, "segmentation_min_charheight_percent", 0); segmentationMinCharHeightPercent = getFloat(country, "segmentation_min_charheight_percent", 0);
segmentationMaxCharWidthvsAverage = getFloat(country, "segmentation_max_segment_width_percent_vs_average", 0); segmentationMaxCharWidthvsAverage = getFloat(country, "segmentation_max_segment_width_percent_vs_average", 0);
plateLinesSensitivityVertical = getFloat(country, "plateline_sensitivity_vertical", 0); plateLinesSensitivityVertical = getFloat(country, "plateline_sensitivity_vertical", 0);
plateLinesSensitivityHorizontal = getFloat(country, "plateline_sensitivity_horizontal", 0); plateLinesSensitivityHorizontal = getFloat(country, "plateline_sensitivity_horizontal", 0);
ocrLanguage = getString(country, "ocr_language", "none"); ocrLanguage = getString(country, "ocr_language", "none");
ocrMinFontSize = getInt("common", "ocr_min_font_point", 100); ocrMinFontSize = getInt("common", "ocr_min_font_point", 100);
postProcessMinConfidence = getFloat("common", "postprocess_min_confidence", 100); postProcessMinConfidence = getFloat("common", "postprocess_min_confidence", 100);
postProcessConfidenceSkipLevel = getFloat("common", "postprocess_confidence_skip_level", 100); postProcessConfidenceSkipLevel = getFloat("common", "postprocess_confidence_skip_level", 100);
postProcessMaxSubstitutions = getInt("common", "postprocess_max_substitutions", 100); postProcessMaxSubstitutions = getInt("common", "postprocess_max_substitutions", 100);
postProcessMinCharacters = getInt("common", "postprocess_min_characers", 100); postProcessMinCharacters = getInt("common", "postprocess_min_characers", 100);
postProcessMaxCharacters = getInt("common", "postprocess_max_characers", 100); postProcessMaxCharacters = getInt("common", "postprocess_max_characers", 100);
debugGeneral = getBoolean("debug", "general", false); debugGeneral = getBoolean("debug", "general", false);
debugTiming = getBoolean("debug", "timing", false); debugTiming = getBoolean("debug", "timing", false);
debugStateId = getBoolean("debug", "state_id", false); debugStateId = getBoolean("debug", "state_id", false);
@@ -132,7 +132,7 @@ void Config::loadValues(string country)
debugOcr = getBoolean("debug", "ocr", false); debugOcr = getBoolean("debug", "ocr", false);
debugPostProcess = getBoolean("debug", "postprocess", false); debugPostProcess = getBoolean("debug", "postprocess", false);
debugShowImages = getBoolean("debug", "show_images", false); debugShowImages = getBoolean("debug", "show_images", false);
} }
void Config::debugOff() void Config::debugOff()
@@ -179,7 +179,7 @@ float Config::getFloat(string section, string key, float defaultValue)
std::cout << "Error: missing configuration entry for: " << section << "->" << key << endl; std::cout << "Error: missing configuration entry for: " << section << "->" << key << endl;
return defaultValue; return defaultValue;
} }
float val = atof(pszValue); float val = atof(pszValue);
return val; return val;
} }
@@ -191,7 +191,7 @@ int Config::getInt(string section, string key, int defaultValue)
std::cout << "Error: missing configuration entry for: " << section << "->" << key << endl; std::cout << "Error: missing configuration entry for: " << section << "->" << key << endl;
return defaultValue; return defaultValue;
} }
int val = atoi(pszValue); int val = atoi(pszValue);
return val; return val;
} }
@@ -203,7 +203,7 @@ bool Config::getBoolean(string section, string key, bool defaultValue)
std::cout << "Error: missing configuration entry for: " << section << "->" << key << endl; std::cout << "Error: missing configuration entry for: " << section << "->" << key << endl;
return defaultValue; return defaultValue;
} }
int val = atoi(pszValue); int val = atoi(pszValue);
return val != 0; return val != 0;
} }
@@ -215,7 +215,7 @@ string Config::getString(string section, string key, string defaultValue)
std::cout << "Error: missing configuration entry for: " << section << "->" << key << endl; std::cout << "Error: missing configuration entry for: " << section << "->" << key << endl;
return defaultValue; return defaultValue;
} }
string val = string(pszValue); string val = string(pszValue);
return val; return val;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -42,54 +42,54 @@ class Config
virtual ~Config(); virtual ~Config();
string country; string country;
bool opencl_enabled; bool opencl_enabled;
float maxPlateWidthPercent; float maxPlateWidthPercent;
float maxPlateHeightPercent; float maxPlateHeightPercent;
float minPlateSizeWidthPx; float minPlateSizeWidthPx;
float minPlateSizeHeightPx; float minPlateSizeHeightPx;
float plateWidthMM; float plateWidthMM;
float plateHeightMM; float plateHeightMM;
float charHeightMM; float charHeightMM;
float charWidthMM; float charWidthMM;
float charWhitespaceTopMM; float charWhitespaceTopMM;
float charWhitespaceBotMM; float charWhitespaceBotMM;
int templateWidthPx; int templateWidthPx;
int templateHeightPx; int templateHeightPx;
int ocrImageWidthPx; int ocrImageWidthPx;
int ocrImageHeightPx; int ocrImageHeightPx;
int stateIdImageWidthPx; int stateIdImageWidthPx;
int stateIdimageHeightPx; int stateIdimageHeightPx;
float charAnalysisMinPercent; float charAnalysisMinPercent;
float charAnalysisHeightRange; float charAnalysisHeightRange;
float charAnalysisHeightStepSize; float charAnalysisHeightStepSize;
int charAnalysisNumSteps; int charAnalysisNumSteps;
float plateLinesSensitivityVertical; float plateLinesSensitivityVertical;
float plateLinesSensitivityHorizontal; float plateLinesSensitivityHorizontal;
int segmentationMinBoxWidthPx; int segmentationMinBoxWidthPx;
float segmentationMinCharHeightPercent; float segmentationMinCharHeightPercent;
float segmentationMaxCharWidthvsAverage; float segmentationMaxCharWidthvsAverage;
string ocrLanguage; string ocrLanguage;
int ocrMinFontSize; int ocrMinFontSize;
float postProcessMinConfidence; float postProcessMinConfidence;
float postProcessConfidenceSkipLevel; float postProcessConfidenceSkipLevel;
int postProcessMaxSubstitutions; int postProcessMaxSubstitutions;
int postProcessMinCharacters; int postProcessMinCharacters;
int postProcessMaxCharacters; int postProcessMaxCharacters;
bool debugGeneral; bool debugGeneral;
bool debugTiming; bool debugTiming;
bool debugStateId; bool debugStateId;
@@ -102,9 +102,9 @@ class Config
bool debugOcr; bool debugOcr;
bool debugPostProcess; bool debugPostProcess;
bool debugShowImages; bool debugShowImages;
void debugOff(); void debugOff();
string getKeypointsRuntimeDir(); string getKeypointsRuntimeDir();
string getCascadeRuntimeDir(); string getCascadeRuntimeDir();
string getPostProcessRuntimeDir(); string getPostProcessRuntimeDir();
@@ -114,9 +114,9 @@ private:
CSimpleIniA* ini; CSimpleIniA* ini;
string runtimeBaseDir; string runtimeBaseDir;
void loadValues(string country); void loadValues(string country);
int getInt(string section, string key, int defaultValue); int getInt(string section, string key, int defaultValue);
float getFloat(string section, string key, float defaultValue); float getFloat(string section, string key, float defaultValue);
string getString(string section, string key, string defaultValue); string getString(string section, string key, string defaultValue);
@@ -124,4 +124,4 @@ private:
}; };
#endif // CONFIG_H #endif // CONFIG_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -26,4 +26,4 @@
#define DEFAULT_RUNTIME_DIR "/default_runtime_data_dir/" #define DEFAULT_RUNTIME_DIR "/default_runtime_data_dir/"
#endif #endif
#define ENV_VARIABLE_RUNTIME_DIR "OPENALPR_RUNTIME_DIR" #define ENV_VARIABLE_RUNTIME_DIR "OPENALPR_RUNTIME_DIR"

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -29,13 +29,13 @@ const float MAX_DISTANCE_TO_MATCH = 100.0f;
FeatureMatcher::FeatureMatcher(Config* config) FeatureMatcher::FeatureMatcher(Config* config)
{ {
this->config = config; this->config = config;
//this->descriptorMatcher = DescriptorMatcher::create( "BruteForce-HammingLUT" ); //this->descriptorMatcher = DescriptorMatcher::create( "BruteForce-HammingLUT" );
this->descriptorMatcher = new BFMatcher(NORM_HAMMING, false); this->descriptorMatcher = new BFMatcher(NORM_HAMMING, false);
//this->descriptorMatcher = DescriptorMatcher::create( "FlannBased" ); //this->descriptorMatcher = DescriptorMatcher::create( "FlannBased" );
this->detector = new FastFeatureDetector(10, true); this->detector = new FastFeatureDetector(10, true);
this->extractor = new BRISK(10, 1, 0.9); this->extractor = new BRISK(10, 1, 0.9);
} }
@@ -45,11 +45,11 @@ FeatureMatcher::~FeatureMatcher()
for (int i = 0; i < trainingImgKeypoints.size(); i++) for (int i = 0; i < trainingImgKeypoints.size(); i++)
trainingImgKeypoints[i].clear(); trainingImgKeypoints[i].clear();
trainingImgKeypoints.clear(); trainingImgKeypoints.clear();
descriptorMatcher.release(); descriptorMatcher.release();
detector.release(); detector.release();
extractor.release(); extractor.release();
} }
@@ -59,7 +59,7 @@ bool FeatureMatcher::isLoaded()
{ {
return false; return false;
} }
return true; return true;
} }
@@ -75,13 +75,13 @@ void FeatureMatcher::surfStyleMatching( const Mat& queryDescriptors, vector<KeyP
vector<DMatch>& matches12 ) vector<DMatch>& matches12 )
{ {
vector<vector<DMatch> > matchesKnn; vector<vector<DMatch> > matchesKnn;
this->descriptorMatcher->radiusMatch(queryDescriptors, matchesKnn, MAX_DISTANCE_TO_MATCH); this->descriptorMatcher->radiusMatch(queryDescriptors, matchesKnn, MAX_DISTANCE_TO_MATCH);
vector<DMatch> tempMatches; vector<DMatch> tempMatches;
_surfStyleMatching(queryDescriptors, matchesKnn, tempMatches); _surfStyleMatching(queryDescriptors, matchesKnn, tempMatches);
crisscrossFiltering(queryKeypoints, tempMatches, matches12); crisscrossFiltering(queryKeypoints, tempMatches, matches12);
} }
@@ -101,13 +101,13 @@ void FeatureMatcher::_surfStyleMatching(const Mat& queryDescriptors, vector<vect
// Check to make sure we have 2 matches. I think this is always the case, but it doesn't hurt to be sure // Check to make sure we have 2 matches. I think this is always the case, but it doesn't hurt to be sure
if (matchesKnn[descInd].size() > 1) if (matchesKnn[descInd].size() > 1)
{ {
// Next throw out matches with a crappy score // Next throw out matches with a crappy score
// Ignore... already handled by the radiusMatch // Ignore... already handled by the radiusMatch
//if (matchesKnn[descInd][0].distance < MAX_DISTANCE_TO_MATCH) //if (matchesKnn[descInd][0].distance < MAX_DISTANCE_TO_MATCH)
//{ //{
float ratioThreshold = 0.75; float ratioThreshold = 0.75;
// Check if both matches came from the same image. If they both came from the same image, score them slightly less harshly // Check if both matches came from the same image. If they both came from the same image, score them slightly less harshly
if (matchesKnn[descInd][0].imgIdx == matchesKnn[descInd][1].imgIdx) if (matchesKnn[descInd][0].imgIdx == matchesKnn[descInd][1].imgIdx)
{ {
@@ -125,20 +125,20 @@ void FeatureMatcher::_surfStyleMatching(const Mat& queryDescriptors, vector<vect
already_exists = true; already_exists = true;
break; break;
} }
else if ((matchesKnn[descInd][0].trainIdx == matches12[q].trainIdx) && else if ((matchesKnn[descInd][0].trainIdx == matches12[q].trainIdx) &&
(matchesKnn[descInd][0].imgIdx == matches12[q].imgIdx)) (matchesKnn[descInd][0].imgIdx == matches12[q].imgIdx))
{ {
already_exists = true; already_exists = true;
break; break;
} }
} }
// Good match. // Good match.
if (already_exists == false) if (already_exists == false)
matches12.push_back(matchesKnn[descInd][0]); matches12.push_back(matchesKnn[descInd][0]);
} }
//} //}
} }
else if (matchesKnn[descInd].size() == 1) else if (matchesKnn[descInd].size() == 1)
@@ -149,28 +149,28 @@ void FeatureMatcher::_surfStyleMatching(const Mat& queryDescriptors, vector<vect
// In the ratio test, we will compare the quality of a match with the next match that is not from the same object: // In the ratio test, we will compare the quality of a match with the next match that is not from the same object:
// we can accept several matches with similar scores as long as they are for the same object. Those should not be // we can accept several matches with similar scores as long as they are for the same object. Those should not be
// part of the model anyway as they are not discriminative enough // part of the model anyway as they are not discriminative enough
//for (unsigned int first_index = 0; first_index < matches.size(); ++first_index) //for (unsigned int first_index = 0; first_index < matches.size(); ++first_index)
//{ //{
//matches12.push_back(match); //matches12.push_back(match);
//} //}
} }
} }
// Compares the matches keypoints for parallel lines. Removes matches that are criss-crossing too much // Compares the matches keypoints for parallel lines. Removes matches that are criss-crossing too much
// We assume that license plates won't be upside-down or backwards. So expect lines to be closely parallel // We assume that license plates won't be upside-down or backwards. So expect lines to be closely parallel
void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints, const vector<DMatch> inputMatches, vector<DMatch> &outputMatches) void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints, const vector<DMatch> inputMatches, vector<DMatch> &outputMatches)
{ {
Rect crissCrossAreaVertical(0, 0, config->stateIdImageWidthPx, config->stateIdimageHeightPx * 2); Rect crissCrossAreaVertical(0, 0, config->stateIdImageWidthPx, config->stateIdimageHeightPx * 2);
Rect crissCrossAreaHorizontal(0, 0, config->stateIdImageWidthPx * 2, config->stateIdimageHeightPx); Rect crissCrossAreaHorizontal(0, 0, config->stateIdImageWidthPx * 2, config->stateIdimageHeightPx);
for (int i = 0; i < billMapping.size(); i++) for (int i = 0; i < billMapping.size(); i++)
{ {
vector<DMatch> matchesForOnePlate; vector<DMatch> matchesForOnePlate;
@@ -179,32 +179,32 @@ void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints,
if (inputMatches[j].imgIdx == i) if (inputMatches[j].imgIdx == i)
matchesForOnePlate.push_back(inputMatches[j]); matchesForOnePlate.push_back(inputMatches[j]);
} }
// For each plate, compare the lines for the keypoints (training image and query image) // For each plate, compare the lines for the keypoints (training image and query image)
// go through each line between keypoints and filter out matches that are criss-crossing // go through each line between keypoints and filter out matches that are criss-crossing
vector<LineSegment> vlines; vector<LineSegment> vlines;
vector<LineSegment> hlines; vector<LineSegment> hlines;
vector<int> matchIdx; vector<int> matchIdx;
for (int j = 0; j < matchesForOnePlate.size(); j++) for (int j = 0; j < matchesForOnePlate.size(); j++)
{ {
KeyPoint tkp = trainingImgKeypoints[i][matchesForOnePlate[j].trainIdx]; KeyPoint tkp = trainingImgKeypoints[i][matchesForOnePlate[j].trainIdx];
KeyPoint qkp = queryKeypoints[matchesForOnePlate[j].queryIdx]; KeyPoint qkp = queryKeypoints[matchesForOnePlate[j].queryIdx];
vlines.push_back(LineSegment(tkp.pt.x, tkp.pt.y + config->stateIdimageHeightPx, qkp.pt.x, qkp.pt.y)); vlines.push_back(LineSegment(tkp.pt.x, tkp.pt.y + config->stateIdimageHeightPx, qkp.pt.x, qkp.pt.y));
hlines.push_back(LineSegment(tkp.pt.x, tkp.pt.y, qkp.pt.x + config->stateIdImageWidthPx, qkp.pt.y)); hlines.push_back(LineSegment(tkp.pt.x, tkp.pt.y, qkp.pt.x + config->stateIdImageWidthPx, qkp.pt.y));
matchIdx.push_back(j); matchIdx.push_back(j);
} }
// Iterate through each line (n^2) removing the one with the most criss-crosses until there are none left. // Iterate through each line (n^2) removing the one with the most criss-crosses until there are none left.
int mostIntersections = 1; int mostIntersections = 1;
while (mostIntersections > 0 && vlines.size() > 0) while (mostIntersections > 0 && vlines.size() > 0)
{ {
int mostIntersectionsIndex = -1; int mostIntersectionsIndex = -1;
mostIntersections = 0; mostIntersections = 0;
for (int j = 0; j < vlines.size(); j++) for (int j = 0; j < vlines.size(); j++)
{ {
int intrCount = 0; int intrCount = 0;
@@ -223,14 +223,14 @@ void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints,
intrCount++; intrCount++;
} }
} }
if (intrCount > mostIntersections) if (intrCount > mostIntersections)
{ {
mostIntersections = intrCount; mostIntersections = intrCount;
mostIntersectionsIndex = j; mostIntersectionsIndex = j;
} }
} }
if (mostIntersectionsIndex >= 0) if (mostIntersectionsIndex >= 0)
{ {
if (this->config->debugStateId) if (this->config->debugStateId)
@@ -239,75 +239,75 @@ void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints,
hlines.erase(hlines.begin() + mostIntersectionsIndex); hlines.erase(hlines.begin() + mostIntersectionsIndex);
matchIdx.erase(matchIdx.begin() + mostIntersectionsIndex); matchIdx.erase(matchIdx.begin() + mostIntersectionsIndex);
} }
} }
// Push the non-crisscrosses back on the list // Push the non-crisscrosses back on the list
for (int j = 0; j < matchIdx.size(); j++) for (int j = 0; j < matchIdx.size(); j++)
{ {
outputMatches.push_back(matchesForOnePlate[matchIdx[j]]); outputMatches.push_back(matchesForOnePlate[matchIdx[j]]);
} }
} }
} }
// Returns true if successful, false otherwise // Returns true if successful, false otherwise
bool FeatureMatcher::loadRecognitionSet(string country) bool FeatureMatcher::loadRecognitionSet(string country)
{ {
std::ostringstream out; std::ostringstream out;
out << config->getKeypointsRuntimeDir() << "/" << country << "/"; out << config->getKeypointsRuntimeDir() << "/" << country << "/";
string country_dir = out.str(); string country_dir = out.str();
if (DirectoryExists(country_dir.c_str())) if (DirectoryExists(country_dir.c_str()))
{ {
vector<Mat> trainImages; vector<Mat> trainImages;
vector<string> plateFiles = getFilesInDir(country_dir.c_str()); vector<string> plateFiles = getFilesInDir(country_dir.c_str());
for (int i = 0; i < plateFiles.size(); i++) for (int i = 0; i < plateFiles.size(); i++)
{ {
if (hasEnding(plateFiles[i], ".jpg") == false) if (hasEnding(plateFiles[i], ".jpg") == false)
continue; continue;
string fullpath = country_dir + plateFiles[i]; string fullpath = country_dir + plateFiles[i];
Mat img = imread( fullpath ); Mat img = imread( fullpath );
// convert to gray and resize to the size of the templates // convert to gray and resize to the size of the templates
cvtColor(img, img, CV_BGR2GRAY); cvtColor(img, img, CV_BGR2GRAY);
resize(img, img, getSizeMaintainingAspect(img, config->stateIdImageWidthPx, config->stateIdimageHeightPx)); resize(img, img, getSizeMaintainingAspect(img, config->stateIdImageWidthPx, config->stateIdimageHeightPx));
if( img.empty() ) if( img.empty() )
{ {
cout << "Can not read images" << endl; cout << "Can not read images" << endl;
return -1; return -1;
} }
Mat descriptors; Mat descriptors;
vector<KeyPoint> keypoints; vector<KeyPoint> keypoints;
detector->detect( img, keypoints ); detector->detect( img, keypoints );
extractor->compute(img, keypoints, descriptors); extractor->compute(img, keypoints, descriptors);
if (descriptors.cols > 0) if (descriptors.cols > 0)
{ {
billMapping.push_back(plateFiles[i].substr(0, 2)); billMapping.push_back(plateFiles[i].substr(0, 2));
trainImages.push_back(descriptors); trainImages.push_back(descriptors);
trainingImgKeypoints.push_back(keypoints); trainingImgKeypoints.push_back(keypoints);
} }
} }
this->descriptorMatcher->add(trainImages); this->descriptorMatcher->add(trainImages);
this->descriptorMatcher->train(); this->descriptorMatcher->train();
return true; return true;
} }
return false; return false;
} }
@@ -317,16 +317,16 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
) )
{ {
RecognitionResult result; RecognitionResult result;
result.haswinner = false; result.haswinner = false;
Mat queryDescriptors; Mat queryDescriptors;
vector<KeyPoint> queryKeypoints; vector<KeyPoint> queryKeypoints;
detector->detect( queryImg, queryKeypoints ); detector->detect( queryImg, queryKeypoints );
extractor->compute(queryImg, queryKeypoints, queryDescriptors); extractor->compute(queryImg, queryKeypoints, queryDescriptors);
if (queryKeypoints.size() <= 5) if (queryKeypoints.size() <= 5)
{ {
@@ -337,27 +337,27 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
} }
return result; return result;
} }
vector<DMatch> filteredMatches; vector<DMatch> filteredMatches;
surfStyleMatching( queryDescriptors, queryKeypoints, filteredMatches ); surfStyleMatching( queryDescriptors, queryKeypoints, filteredMatches );
// Create and initialize the counts to 0 // Create and initialize the counts to 0
std::vector<int> bill_match_counts( billMapping.size() ); std::vector<int> bill_match_counts( billMapping.size() );
for (int i = 0; i < billMapping.size(); i++) { bill_match_counts[i] = 0; } for (int i = 0; i < billMapping.size(); i++) { bill_match_counts[i] = 0; }
for (int i = 0; i < filteredMatches.size(); i++) for (int i = 0; i < filteredMatches.size(); i++)
{ {
bill_match_counts[filteredMatches[i].imgIdx]++; bill_match_counts[filteredMatches[i].imgIdx]++;
//if (filteredMatches[i].imgIdx //if (filteredMatches[i].imgIdx
} }
float max_count = 0; // represented as a percent (0 to 100) float max_count = 0; // represented as a percent (0 to 100)
int secondmost_count = 0; int secondmost_count = 0;
int maxcount_index = -1; int maxcount_index = -1;
@@ -368,25 +368,25 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
secondmost_count = max_count; secondmost_count = max_count;
if (secondmost_count <= 2) // A value of 1 or 2 is effectively 0 if (secondmost_count <= 2) // A value of 1 or 2 is effectively 0
secondmost_count = 0; secondmost_count = 0;
max_count = bill_match_counts[i]; max_count = bill_match_counts[i];
maxcount_index = i; maxcount_index = i;
} }
} }
float score = ((max_count - secondmost_count - 3) / 10) * 100; float score = ((max_count - secondmost_count - 3) / 10) * 100;
if (score < 0) if (score < 0)
score = 0; score = 0;
else if (score > 100) else if (score > 100)
score = 100; score = 100;
if (score > 0) if (score > 0)
{ {
result.haswinner = true; result.haswinner = true;
result.winner = billMapping[maxcount_index]; result.winner = billMapping[maxcount_index];
result.confidence = score; result.confidence = score;
if (drawOnImage) if (drawOnImage)
{ {
vector<KeyPoint> positiveMatches; vector<KeyPoint> positiveMatches;
@@ -397,36 +397,35 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
positiveMatches.push_back( queryKeypoints[filteredMatches[i].queryIdx] ); positiveMatches.push_back( queryKeypoints[filteredMatches[i].queryIdx] );
} }
} }
Mat tmpImg; Mat tmpImg;
drawKeypoints( queryImg, queryKeypoints, tmpImg, CV_RGB(185, 0, 0), DrawMatchesFlags::DEFAULT ); drawKeypoints( queryImg, queryKeypoints, tmpImg, CV_RGB(185, 0, 0), DrawMatchesFlags::DEFAULT );
drawKeypoints( tmpImg, positiveMatches, *outputImage, CV_RGB(0, 255, 0), DrawMatchesFlags::DEFAULT ); drawKeypoints( tmpImg, positiveMatches, *outputImage, CV_RGB(0, 255, 0), DrawMatchesFlags::DEFAULT );
if (result.haswinner == true) if (result.haswinner == true)
{ {
std::ostringstream out; std::ostringstream out;
out << result.winner << " (" << result.confidence << "%)"; out << result.winner << " (" << result.confidence << "%)";
// we detected a bill, let the people know! // we detected a bill, let the people know!
//putText(*outputImage, out.str(), Point(15, 27), FONT_HERSHEY_DUPLEX, 1.1, CV_RGB(0, 0, 0), 2); //putText(*outputImage, out.str(), Point(15, 27), FONT_HERSHEY_DUPLEX, 1.1, CV_RGB(0, 0, 0), 2);
} }
} }
} }
if (this->config->debugStateId) if (this->config->debugStateId)
{ {
for (int i = 0; i < billMapping.size(); i++) for (int i = 0; i < billMapping.size(); i++)
{ {
cout << billMapping[i] << " : " << bill_match_counts[i] << endl; cout << billMapping[i] << " : " << bill_match_counts[i] << endl;
} }
} }
return result; return result;
}
}

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -55,31 +55,31 @@ class FeatureMatcher
RecognitionResult recognize( const Mat& queryImg, bool drawOnImage, Mat* outputImage, RecognitionResult recognize( const Mat& queryImg, bool drawOnImage, Mat* outputImage,
bool debug_on, vector<int> debug_matches_array ); bool debug_on, vector<int> debug_matches_array );
bool loadRecognitionSet(string country); bool loadRecognitionSet(string country);
bool isLoaded(); bool isLoaded();
int numTrainingElements(); int numTrainingElements();
private: private:
Config* config; Config* config;
Ptr<DescriptorMatcher> descriptorMatcher; Ptr<DescriptorMatcher> descriptorMatcher;
Ptr<FastFeatureDetector> detector; Ptr<FastFeatureDetector> detector;
Ptr<BRISK> extractor; Ptr<BRISK> extractor;
vector<vector<KeyPoint> > trainingImgKeypoints; vector<vector<KeyPoint> > trainingImgKeypoints;
void _surfStyleMatching(const Mat& queryDescriptors, vector<vector<DMatch> > matchesKnn, vector<DMatch>& matches12); void _surfStyleMatching(const Mat& queryDescriptors, vector<vector<DMatch> > matchesKnn, vector<DMatch>& matches12);
void crisscrossFiltering(const vector<KeyPoint> queryKeypoints, const vector<DMatch> inputMatches, vector<DMatch> &outputMatches); void crisscrossFiltering(const vector<KeyPoint> queryKeypoints, const vector<DMatch> inputMatches, vector<DMatch> &outputMatches);
vector<string> billMapping; vector<string> billMapping;
void surfStyleMatching( const Mat& queryDescriptors, vector<KeyPoint> queryKeypoints, void surfStyleMatching( const Mat& queryDescriptors, vector<KeyPoint> queryKeypoints,
@@ -88,5 +88,3 @@ class FeatureMatcher
}; };
#endif // FEATUREMATCHER_H #endif // FEATUREMATCHER_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -23,7 +23,7 @@
LicensePlateCandidate::LicensePlateCandidate(Mat frame, Rect regionOfInterest, Config* config) LicensePlateCandidate::LicensePlateCandidate(Mat frame, Rect regionOfInterest, Config* config)
{ {
this->config = config; this->config = config;
this->frame = frame; this->frame = frame;
this->plateRegion = regionOfInterest; this->plateRegion = regionOfInterest;
} }
@@ -37,61 +37,61 @@ LicensePlateCandidate::~LicensePlateCandidate()
void LicensePlateCandidate::recognize() void LicensePlateCandidate::recognize()
{ {
charSegmenter = NULL; charSegmenter = NULL;
this->confidence = 0; this->confidence = 0;
int expandX = round(this->plateRegion.width * 0.15); int expandX = round(this->plateRegion.width * 0.15);
int expandY = round(this->plateRegion.height * 0.10); int expandY = round(this->plateRegion.height * 0.10);
// expand box by 15% in all directions // expand box by 15% in all directions
Rect expandedRegion = expandRect( this->plateRegion, expandX, expandY, frame.cols, frame.rows) ; Rect expandedRegion = expandRect( this->plateRegion, expandX, expandY, frame.cols, frame.rows) ;
Mat plate_bgr = Mat(frame, expandedRegion); Mat plate_bgr = Mat(frame, expandedRegion);
resize(plate_bgr, plate_bgr, Size(config->templateWidthPx, config->templateHeightPx)); resize(plate_bgr, plate_bgr, Size(config->templateWidthPx, config->templateHeightPx));
Mat plate_bgr_cleaned = Mat(plate_bgr.size(), plate_bgr.type()); Mat plate_bgr_cleaned = Mat(plate_bgr.size(), plate_bgr.type());
this->cleanupColors(plate_bgr, plate_bgr_cleaned); this->cleanupColors(plate_bgr, plate_bgr_cleaned);
CharacterRegion charRegion(plate_bgr, config); CharacterRegion charRegion(plate_bgr, config);
if (charRegion.confidence > 10) if (charRegion.confidence > 10)
{ {
PlateLines plateLines(config); PlateLines plateLines(config);
//Mat boogedy = charRegion.getPlateMask(); //Mat boogedy = charRegion.getPlateMask();
plateLines.processImage(charRegion.getPlateMask(), 1.15); plateLines.processImage(charRegion.getPlateMask(), 1.15);
plateLines.processImage(plate_bgr_cleaned, 0.9); plateLines.processImage(plate_bgr_cleaned, 0.9);
PlateCorners cornerFinder(plate_bgr, &plateLines, &charRegion, config); PlateCorners cornerFinder(plate_bgr, &plateLines, &charRegion, config);
vector<Point> smallPlateCorners = cornerFinder.findPlateCorners(); vector<Point> smallPlateCorners = cornerFinder.findPlateCorners();
if (cornerFinder.confidence > 0) if (cornerFinder.confidence > 0)
{ {
this->plateCorners = transformPointsToOriginalImage(frame, plate_bgr, expandedRegion, smallPlateCorners); this->plateCorners = transformPointsToOriginalImage(frame, plate_bgr, expandedRegion, smallPlateCorners);
this->deskewed = deSkewPlate(frame, this->plateCorners); this->deskewed = deSkewPlate(frame, this->plateCorners);
charSegmenter = new CharacterSegmenter(deskewed, charRegion.thresholdsInverted(), config); charSegmenter = new CharacterSegmenter(deskewed, charRegion.thresholdsInverted(), config);
//this->recognizedText = ocr->recognizedText; //this->recognizedText = ocr->recognizedText;
//strcpy(this->recognizedText, ocr.recognizedText); //strcpy(this->recognizedText, ocr.recognizedText);
this->confidence = 100; this->confidence = 100;
} }
charRegion.confidence = 0; charRegion.confidence = 0;
} }
} }
@@ -106,30 +106,30 @@ vector<Point2f> LicensePlateCandidate::transformPointsToOriginalImage(Mat bigIma
{ {
float bigX = (corners[i].x * ((float) region.width / smallImage.cols)); float bigX = (corners[i].x * ((float) region.width / smallImage.cols));
float bigY = (corners[i].y * ((float) region.height / smallImage.rows)); float bigY = (corners[i].y * ((float) region.height / smallImage.rows));
bigX = bigX + region.x; bigX = bigX + region.x;
bigY = bigY + region.y; bigY = bigY + region.y;
cornerPoints.push_back(Point2f(bigX, bigY)); cornerPoints.push_back(Point2f(bigX, bigY));
} }
return cornerPoints; return cornerPoints;
} }
Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners) Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners)
{ {
// Figure out the appoximate width/height of the license plate region, so we can maintain the aspect ratio. // Figure out the appoximate width/height of the license plate region, so we can maintain the aspect ratio.
LineSegment leftEdge(round(corners[3].x), round(corners[3].y), round(corners[0].x), round(corners[0].y)); LineSegment leftEdge(round(corners[3].x), round(corners[3].y), round(corners[0].x), round(corners[0].y));
LineSegment rightEdge(round(corners[2].x), round(corners[2].y), round(corners[1].x), round(corners[1].y)); LineSegment rightEdge(round(corners[2].x), round(corners[2].y), round(corners[1].x), round(corners[1].y));
LineSegment topEdge(round(corners[0].x), round(corners[0].y), round(corners[1].x), round(corners[1].y)); LineSegment topEdge(round(corners[0].x), round(corners[0].y), round(corners[1].x), round(corners[1].y));
LineSegment bottomEdge(round(corners[3].x), round(corners[3].y), round(corners[2].x), round(corners[2].y)); LineSegment bottomEdge(round(corners[3].x), round(corners[3].y), round(corners[2].x), round(corners[2].y));
float w = distanceBetweenPoints(leftEdge.midpoint(), rightEdge.midpoint()); float w = distanceBetweenPoints(leftEdge.midpoint(), rightEdge.midpoint());
float h = distanceBetweenPoints(bottomEdge.midpoint(), topEdge.midpoint()); float h = distanceBetweenPoints(bottomEdge.midpoint(), topEdge.midpoint());
float aspect = w/h; float aspect = w/h;
int width = config->ocrImageWidthPx; int width = config->ocrImageWidthPx;
int height = round(((float) width) / aspect); int height = round(((float) width) / aspect);
if (height > config->ocrImageHeightPx) if (height > config->ocrImageHeightPx)
@@ -137,9 +137,9 @@ Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners)
height = config->ocrImageHeightPx; height = config->ocrImageHeightPx;
width = round(((float) height) * aspect); width = round(((float) height) * aspect);
} }
Mat deskewed(height, width, frame.type()); Mat deskewed(height, width, frame.type());
// Corners of the destination image // Corners of the destination image
vector<Point2f> quad_pts; vector<Point2f> quad_pts;
quad_pts.push_back(Point2f(0, 0)); quad_pts.push_back(Point2f(0, 0));
@@ -152,10 +152,10 @@ Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners)
// Apply perspective transformation // Apply perspective transformation
warpPerspective(inputImage, deskewed, transmtx, deskewed.size()); warpPerspective(inputImage, deskewed, transmtx, deskewed.size());
if (this->config->debugGeneral) if (this->config->debugGeneral)
displayImage(config, "quadrilateral", deskewed); displayImage(config, "quadrilateral", deskewed);
return deskewed; return deskewed;
} }
@@ -164,13 +164,13 @@ void LicensePlateCandidate::cleanupColors(Mat inputImage, Mat outputImage)
{ {
if (this->config->debugGeneral) if (this->config->debugGeneral)
cout << "LicensePlate::cleanupColors" << endl; cout << "LicensePlate::cleanupColors" << endl;
//Mat normalized(inputImage.size(), inputImage.type()); //Mat normalized(inputImage.size(), inputImage.type());
Mat intermediate(inputImage.size(), inputImage.type()); Mat intermediate(inputImage.size(), inputImage.type());
normalize(inputImage, intermediate, 0, 255, CV_MINMAX ); normalize(inputImage, intermediate, 0, 255, CV_MINMAX );
// Equalize intensity: // Equalize intensity:
if(intermediate.channels() >= 3) if(intermediate.channels() >= 3)
{ {
@@ -189,14 +189,14 @@ void LicensePlateCandidate::cleanupColors(Mat inputImage, Mat outputImage)
//ycrcb.release(); //ycrcb.release();
} }
bilateralFilter(intermediate, outputImage, 3, 25, 35); bilateralFilter(intermediate, outputImage, 3, 25, 35);
if (this->config->debugGeneral) if (this->config->debugGeneral)
{ {
displayImage(config, "After cleanup", outputImage); displayImage(config, "After cleanup", outputImage);
} }
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -54,28 +54,28 @@ class LicensePlateCandidate
float confidence; // 0-100 float confidence; // 0-100
//vector<Point> points; // top-left, top-right, bottom-right, bottom-left //vector<Point> points; // top-left, top-right, bottom-right, bottom-left
vector<Point2f> plateCorners; vector<Point2f> plateCorners;
void recognize(); void recognize();
Mat deskewed; Mat deskewed;
CharacterSegmenter* charSegmenter; CharacterSegmenter* charSegmenter;
private: private:
Config* config; Config* config;
Mat frame; Mat frame;
Rect plateRegion; Rect plateRegion;
void cleanupColors(Mat inputImage, Mat outputImage); void cleanupColors(Mat inputImage, Mat outputImage);
Mat filterByCharacterHue(vector<vector<Point> > charRegionContours); Mat filterByCharacterHue(vector<vector<Point> > charRegionContours);
vector<Point> findPlateCorners(Mat inputImage, PlateLines plateLines, CharacterRegion charRegion); // top-left, top-right, bottom-right, bottom-left vector<Point> findPlateCorners(Mat inputImage, PlateLines plateLines, CharacterRegion charRegion); // top-left, top-right, bottom-right, bottom-left
vector<Point2f> transformPointsToOriginalImage(Mat bigImage, Mat smallImage, Rect region, vector<Point> corners); vector<Point2f> transformPointsToOriginalImage(Mat bigImage, Mat smallImage, Rect region, vector<Point> corners);
Mat deSkewPlate(Mat inputImage, vector<Point2f> corners); Mat deSkewPlate(Mat inputImage, vector<Point2f> corners);
}; };
#endif // STAGE2_H #endif // STAGE2_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -25,9 +25,9 @@
OCR::OCR(Config* config) OCR::OCR(Config* config)
{ {
this->config = config; this->config = config;
this->postProcessor = new PostProcess(config); this->postProcessor = new PostProcess(config);
tesseract=new TessBaseAPI(); tesseract=new TessBaseAPI();
// Tesseract requires the prefix directory to be set as an env variable // Tesseract requires the prefix directory to be set as an env variable
@@ -35,11 +35,11 @@ OCR::OCR(Config* config)
strcpy(tessdataPrefix.data(), config->getTessdataPrefix().c_str()); strcpy(tessdataPrefix.data(), config->getTessdataPrefix().c_str());
putenv(tessdataPrefix.data()); putenv(tessdataPrefix.data());
tesseract->Init("", config->ocrLanguage.c_str() ); tesseract->Init("", config->ocrLanguage.c_str() );
tesseract->SetVariable("save_blob_choices", "T"); tesseract->SetVariable("save_blob_choices", "T");
//tesseract->SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNPQRSTUVWXYZ1234567890"); //tesseract->SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNPQRSTUVWXYZ1234567890");
tesseract->SetPageSegMode(PSM_SINGLE_CHAR); tesseract->SetPageSegMode(PSM_SINGLE_CHAR);
} }
@@ -53,56 +53,56 @@ OCR::~OCR()
void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions) void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
{ {
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
postProcessor->clear(); postProcessor->clear();
for (int i = 0; i < thresholds.size(); i++) for (int i = 0; i < thresholds.size(); i++)
{ {
// Make it black text on white background // Make it black text on white background
bitwise_not(thresholds[i], thresholds[i]); 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()); tesseract->SetImage((uchar*) thresholds[i].data, thresholds[i].size().width, thresholds[i].size().height, thresholds[i].channels(), thresholds[i].step1());
for (int j = 0; j < charRegions.size(); j++) for (int j = 0; j < charRegions.size(); j++)
{ {
Rect expandedRegion = expandRect( charRegions[j], 2, 2, thresholds[i].cols, thresholds[i].rows) ; Rect expandedRegion = expandRect( charRegions[j], 2, 2, thresholds[i].cols, thresholds[i].rows) ;
tesseract->SetRectangle(expandedRegion.x, expandedRegion.y, expandedRegion.width, expandedRegion.height); tesseract->SetRectangle(expandedRegion.x, expandedRegion.y, expandedRegion.width, expandedRegion.height);
tesseract->Recognize(NULL); tesseract->Recognize(NULL);
tesseract::ResultIterator* ri = tesseract->GetIterator(); tesseract::ResultIterator* ri = tesseract->GetIterator();
tesseract::PageIteratorLevel level = tesseract::RIL_SYMBOL; tesseract::PageIteratorLevel level = tesseract::RIL_SYMBOL;
do { do {
const char* symbol = ri->GetUTF8Text(level); const char* symbol = ri->GetUTF8Text(level);
float conf = ri->Confidence(level); float conf = ri->Confidence(level);
bool dontcare; bool dontcare;
int fontindex = 0; int fontindex = 0;
int pointsize = 0; int pointsize = 0;
const char* fontName = ri->WordFontAttributes(&dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &pointsize, &fontindex); const char* fontName = ri->WordFontAttributes(&dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &pointsize, &fontindex);
if(symbol != 0 && pointsize >= config->ocrMinFontSize) { if(symbol != 0 && pointsize >= config->ocrMinFontSize) {
postProcessor->addLetter(*symbol, j, conf); postProcessor->addLetter(*symbol, j, conf);
if (this->config->debugOcr) if (this->config->debugOcr)
printf("charpos%d: threshold %d: symbol %s, conf: %f font: %s (index %d) size %dpx", j, i, symbol, conf, fontName, fontindex, pointsize); printf("charpos%d: threshold %d: symbol %s, conf: %f font: %s (index %d) size %dpx", j, i, symbol, conf, fontName, fontindex, pointsize);
bool indent = false; bool indent = false;
tesseract::ChoiceIterator ci(*ri); tesseract::ChoiceIterator ci(*ri);
do { do {
const char* choice = ci.GetUTF8Text(); const char* choice = ci.GetUTF8Text();
postProcessor->addLetter(*choice, j, ci.Confidence()); postProcessor->addLetter(*choice, j, ci.Confidence());
//letterScores.addScore(*choice, j, ci.Confidence() - MIN_CONFIDENCE); //letterScores.addScore(*choice, j, ci.Confidence() - MIN_CONFIDENCE);
if (this->config->debugOcr) if (this->config->debugOcr)
{ {
@@ -110,36 +110,31 @@ void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
printf("\t- "); printf("\t- ");
printf("%s conf: %f\n", choice, ci.Confidence()); printf("%s conf: %f\n", choice, ci.Confidence());
} }
indent = true; indent = true;
} while(ci.Next()); } while(ci.Next());
} }
if (this->config->debugOcr) if (this->config->debugOcr)
printf("---------------------------------------------\n"); printf("---------------------------------------------\n");
delete[] symbol; delete[] symbol;
} while((ri->Next(level))); } while((ri->Next(level)));
delete ri; delete ri;
} }
} }
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
getTime(&endTime); getTime(&endTime);
cout << "OCR Time: " << diffclock(startTime, endTime) << "ms." << endl; cout << "OCR Time: " << diffclock(startTime, endTime) << "ms." << endl;
} }
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -25,7 +25,7 @@
#include <iostream> #include <iostream>
#include <stdio.h> #include <stdio.h>
#include "utility.h" #include "utility.h"
#include "postprocess.h" #include "postprocess.h"
#include "config.h" #include "config.h"
@@ -45,22 +45,22 @@ class OCR
public: public:
OCR(Config* config); OCR(Config* config);
virtual ~OCR(); virtual ~OCR();
void performOCR(vector<Mat> thresholds, vector<Rect> charRegions); void performOCR(vector<Mat> thresholds, vector<Rect> charRegions);
PostProcess* postProcessor; PostProcess* postProcessor;
//string recognizedText; //string recognizedText;
//float confidence; //float confidence;
//float overallConfidence; //float overallConfidence;
private: private:
Config* config; Config* config;
TessBaseAPI *tesseract; TessBaseAPI *tesseract;
}; };

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -23,20 +23,20 @@
PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegion* charRegion, Config* config) PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegion* charRegion, Config* config)
{ {
this->config = config; this->config = config;
if (this->config->debugPlateCorners) if (this->config->debugPlateCorners)
cout << "PlateCorners constructor" << endl; cout << "PlateCorners constructor" << endl;
this->inputImage = inputImage; this->inputImage = inputImage;
this->plateLines = plateLines; this->plateLines = plateLines;
this->charRegion = charRegion; this->charRegion = charRegion;
this->bestHorizontalScore = 9999999999999; this->bestHorizontalScore = 9999999999999;
this->bestVerticalScore = 9999999999999; this->bestVerticalScore = 9999999999999;
Point topPoint = charRegion->getTopLine().midpoint(); Point topPoint = charRegion->getTopLine().midpoint();
Point bottomPoint = charRegion->getBottomLine().closestPointOnSegmentTo(topPoint); Point bottomPoint = charRegion->getBottomLine().closestPointOnSegmentTo(topPoint);
this->charHeight = distanceBetweenPoints(topPoint, bottomPoint); this->charHeight = distanceBetweenPoints(topPoint, bottomPoint);
@@ -45,7 +45,7 @@ PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegi
//this->charHeight = this->charHeight - 2; // Adjust since this height is a box around our char. //this->charHeight = this->charHeight - 2; // Adjust since this height is a box around our char.
// Adjust the char height for the difference in size... // Adjust the char height for the difference in size...
//this->charHeight = ((float) inputImage.size().height / (float) TEMPLATE_PLATE_HEIGHT) * this->charHeight; //this->charHeight = ((float) inputImage.size().height / (float) TEMPLATE_PLATE_HEIGHT) * this->charHeight;
this->charAngle = angleBetweenPoints(charRegion->getCharArea()[0], charRegion->getCharArea()[1]); this->charAngle = angleBetweenPoints(charRegion->getCharArea()[0], charRegion->getCharArea()[1]);
} }
@@ -58,61 +58,61 @@ vector<Point> PlateCorners::findPlateCorners()
{ {
if (this->config->debugPlateCorners) if (this->config->debugPlateCorners)
cout << "PlateCorners::findPlateCorners" << endl; cout << "PlateCorners::findPlateCorners" << endl;
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
int horizontalLines = this->plateLines->horizontalLines.size(); int horizontalLines = this->plateLines->horizontalLines.size();
int verticalLines = this->plateLines->verticalLines.size(); int verticalLines = this->plateLines->verticalLines.size();
// layout horizontal lines // layout horizontal lines
for (int h1 = NO_LINE; h1 < horizontalLines; h1++) for (int h1 = NO_LINE; h1 < horizontalLines; h1++)
{ {
for (int h2 = NO_LINE; h2 < horizontalLines; h2++) for (int h2 = NO_LINE; h2 < horizontalLines; h2++)
{ {
if (h1 == h2 && h1 != NO_LINE) continue; if (h1 == h2 && h1 != NO_LINE) continue;
this->scoreHorizontals(h1, h2); this->scoreHorizontals(h1, h2);
} }
} }
// layout vertical lines // layout vertical lines
for (int v1 = NO_LINE; v1 < verticalLines; v1++) for (int v1 = NO_LINE; v1 < verticalLines; v1++)
{ {
for (int v2 = NO_LINE; v2 < verticalLines; v2++) for (int v2 = NO_LINE; v2 < verticalLines; v2++)
{ {
if (v1 == v2 && v1 != NO_LINE) continue; if (v1 == v2 && v1 != NO_LINE) continue;
this->scoreVerticals(v1, v2); this->scoreVerticals(v1, v2);
} }
} }
if (this->config->debugPlateCorners) if (this->config->debugPlateCorners)
{ {
cout << "Drawing debug stuff..." << endl; cout << "Drawing debug stuff..." << endl;
Mat imgCorners = Mat(inputImage.size(), inputImage.type()); Mat imgCorners = Mat(inputImage.size(), inputImage.type());
inputImage.copyTo(imgCorners); inputImage.copyTo(imgCorners);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
circle(imgCorners, charRegion->getCharArea()[i], 2, Scalar(0, 0, 0)); circle(imgCorners, charRegion->getCharArea()[i], 2, Scalar(0, 0, 0));
line(imgCorners, this->bestTop.p1, this->bestTop.p2, Scalar(255, 0, 0), 1, CV_AA); line(imgCorners, this->bestTop.p1, this->bestTop.p2, Scalar(255, 0, 0), 1, CV_AA);
line(imgCorners, this->bestRight.p1, this->bestRight.p2, Scalar(0, 0, 255), 1, CV_AA); line(imgCorners, this->bestRight.p1, this->bestRight.p2, Scalar(0, 0, 255), 1, CV_AA);
line(imgCorners, this->bestBottom.p1, this->bestBottom.p2, Scalar(0, 0, 255), 1, CV_AA); line(imgCorners, this->bestBottom.p1, this->bestBottom.p2, Scalar(0, 0, 255), 1, CV_AA);
line(imgCorners, this->bestLeft.p1, this->bestLeft.p2, Scalar(255, 0, 0), 1, CV_AA); line(imgCorners, this->bestLeft.p1, this->bestLeft.p2, Scalar(255, 0, 0), 1, CV_AA);
displayImage(config, "Winning top/bottom Boundaries", imgCorners);
displayImage(config, "Winning top/bottom Boundaries", imgCorners);
} }
// Check if a left/right edge has been established. // Check if a left/right edge has been established.
if (bestLeft.p1.x == 0 && bestLeft.p1.y == 0 && bestLeft.p2.x == 0 && bestLeft.p2.y == 0) if (bestLeft.p1.x == 0 && bestLeft.p1.y == 0 && bestLeft.p2.x == 0 && bestLeft.p2.y == 0)
confidence = 0; confidence = 0;
@@ -120,49 +120,49 @@ vector<Point> PlateCorners::findPlateCorners()
confidence = 0; confidence = 0;
else else
confidence = 100; confidence = 100;
vector<Point> corners; vector<Point> corners;
corners.push_back(bestTop.intersection(bestLeft)); corners.push_back(bestTop.intersection(bestLeft));
corners.push_back(bestTop.intersection(bestRight)); corners.push_back(bestTop.intersection(bestRight));
corners.push_back(bestBottom.intersection(bestRight)); corners.push_back(bestBottom.intersection(bestRight));
corners.push_back(bestBottom.intersection(bestLeft)); corners.push_back(bestBottom.intersection(bestLeft));
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
getTime(&endTime); getTime(&endTime);
cout << "Plate Corners Time: " << diffclock(startTime, endTime) << "ms." << endl; cout << "Plate Corners Time: " << diffclock(startTime, endTime) << "ms." << endl;
} }
return corners; return corners;
} }
void PlateCorners::scoreVerticals(int v1, int v2) void PlateCorners::scoreVerticals(int v1, int v2)
{ {
float score = 0; // Lower is better float score = 0; // Lower is better
LineSegment left; LineSegment left;
LineSegment right; LineSegment right;
float charHeightToPlateWidthRatio = config->plateWidthMM / config->charHeightMM; float charHeightToPlateWidthRatio = config->plateWidthMM / config->charHeightMM;
float idealPixelWidth = this->charHeight * (charHeightToPlateWidthRatio * 1.05); // Add 10% so we don't clip any characters float idealPixelWidth = this->charHeight * (charHeightToPlateWidthRatio * 1.05); // Add 10% so we don't clip any characters
if (v1 == NO_LINE && v2 == NO_LINE) if (v1 == NO_LINE && v2 == NO_LINE)
{ {
//return; //return;
Point centerTop = charRegion->getCharBoxTop().midpoint(); Point centerTop = charRegion->getCharBoxTop().midpoint();
Point centerBottom = charRegion->getCharBoxBottom().midpoint(); Point centerBottom = charRegion->getCharBoxBottom().midpoint();
LineSegment centerLine = LineSegment(centerBottom.x, centerBottom.y, centerTop.x, centerTop.y); LineSegment centerLine = LineSegment(centerBottom.x, centerBottom.y, centerTop.x, centerTop.y);
left = centerLine.getParallelLine(idealPixelWidth / 2); left = centerLine.getParallelLine(idealPixelWidth / 2);
right = centerLine.getParallelLine(-1 * idealPixelWidth / 2 ); right = centerLine.getParallelLine(-1 * idealPixelWidth / 2 );
score += SCORING_MISSING_SEGMENT_PENALTY_VERTICAL * 2; score += SCORING_MISSING_SEGMENT_PENALTY_VERTICAL * 2;
} }
else if (v1 != NO_LINE && v2 != NO_LINE) else if (v1 != NO_LINE && v2 != NO_LINE)
@@ -182,109 +182,109 @@ void PlateCorners::scoreVerticals(int v1, int v2)
right = left.getParallelLine(-1 * idealPixelWidth); right = left.getParallelLine(-1 * idealPixelWidth);
score += SCORING_MISSING_SEGMENT_PENALTY_VERTICAL; score += SCORING_MISSING_SEGMENT_PENALTY_VERTICAL;
} }
// Make sure this line is to the left of our license plate letters // Make sure this line is to the left of our license plate letters
if (left.isPointBelowLine(charRegion->getCharBoxLeft().midpoint()) == false) if (left.isPointBelowLine(charRegion->getCharBoxLeft().midpoint()) == false)
return; return;
// Make sure this line is to the right of our license plate letters // Make sure this line is to the right of our license plate letters
if (right.isPointBelowLine(charRegion->getCharBoxRight().midpoint())) if (right.isPointBelowLine(charRegion->getCharBoxRight().midpoint()))
return; return;
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// Score "Distance from the edge... // Score "Distance from the edge...
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
float leftDistanceFromEdge = abs((float) (left.p1.x + left.p2.x) / 2); float leftDistanceFromEdge = abs((float) (left.p1.x + left.p2.x) / 2);
float rightDistanceFromEdge = abs(this->inputImage.cols - ((float) (right.p1.x + right.p2.x) / 2)); float rightDistanceFromEdge = abs(this->inputImage.cols - ((float) (right.p1.x + right.p2.x) / 2));
float distanceFromEdge = leftDistanceFromEdge + rightDistanceFromEdge; float distanceFromEdge = leftDistanceFromEdge + rightDistanceFromEdge;
score += distanceFromEdge * SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT; score += distanceFromEdge * SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT;
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// Score "Boxiness" of the 4 lines. How close is it to a parallelogram? // Score "Boxiness" of the 4 lines. How close is it to a parallelogram?
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
float verticalAngleDiff = abs(left.angle - right.angle); float verticalAngleDiff = abs(left.angle - right.angle);
score += (verticalAngleDiff) * SCORING_BOXINESS_WEIGHT; score += (verticalAngleDiff) * SCORING_BOXINESS_WEIGHT;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// SCORE the shape wrt character position and height relative to position // SCORE the shape wrt character position and height relative to position
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
Point leftMidLinePoint = left.closestPointOnSegmentTo(charRegion->getCharBoxLeft().midpoint()); Point leftMidLinePoint = left.closestPointOnSegmentTo(charRegion->getCharBoxLeft().midpoint());
Point rightMidLinePoint = right.closestPointOnSegmentTo(charRegion->getCharBoxRight().midpoint()); Point rightMidLinePoint = right.closestPointOnSegmentTo(charRegion->getCharBoxRight().midpoint());
float plateDistance = abs(idealPixelWidth - distanceBetweenPoints(leftMidLinePoint, rightMidLinePoint)); float plateDistance = abs(idealPixelWidth - distanceBetweenPoints(leftMidLinePoint, rightMidLinePoint));
score += plateDistance * SCORING_VERTICALDISTANCE_WEIGHT; score += plateDistance * SCORING_VERTICALDISTANCE_WEIGHT;
if (score < this->bestVerticalScore) if (score < this->bestVerticalScore)
{ {
float scorecomponent; float scorecomponent;
if (this->config->debugPlateCorners) if (this->config->debugPlateCorners)
{ {
cout << "xx xx Score: charHeight " << this->charHeight << endl; cout << "xx xx Score: charHeight " << this->charHeight << endl;
cout << "xx xx Score: idealwidth " << idealPixelWidth << endl; cout << "xx xx Score: idealwidth " << idealPixelWidth << endl;
cout << "xx xx Score: v1,v2= " << v1 << "," << v2 << endl; cout << "xx xx Score: v1,v2= " << v1 << "," << v2 << endl;
cout << "xx xx Score: Left= " << left.str() << endl; cout << "xx xx Score: Left= " << left.str() << endl;
cout << "xx xx Score: Right= " << right.str() << endl; cout << "xx xx Score: Right= " << right.str() << endl;
cout << "Vertical breakdown Score:" << endl; cout << "Vertical breakdown Score:" << endl;
cout << " -- Boxiness Score: " << verticalAngleDiff << " -- Weight (" << SCORING_BOXINESS_WEIGHT << ")" << endl; cout << " -- Boxiness Score: " << verticalAngleDiff << " -- Weight (" << SCORING_BOXINESS_WEIGHT << ")" << endl;
scorecomponent = verticalAngleDiff * SCORING_BOXINESS_WEIGHT; scorecomponent = verticalAngleDiff * SCORING_BOXINESS_WEIGHT;
cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl; cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl;
cout << " -- Distance From Edge Score: " << distanceFromEdge << " -- Weight (" << SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT << ")" << endl; cout << " -- Distance From Edge Score: " << distanceFromEdge << " -- Weight (" << SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT << ")" << endl;
scorecomponent = distanceFromEdge * SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT; scorecomponent = distanceFromEdge * SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT;
cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl; cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl;
cout << " -- Distance Score: " << plateDistance << " -- Weight (" << SCORING_VERTICALDISTANCE_WEIGHT << ")" << endl; cout << " -- Distance Score: " << plateDistance << " -- Weight (" << SCORING_VERTICALDISTANCE_WEIGHT << ")" << endl;
scorecomponent = plateDistance * SCORING_VERTICALDISTANCE_WEIGHT; scorecomponent = plateDistance * SCORING_VERTICALDISTANCE_WEIGHT;
cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl; cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl;
cout << " -- Score: " << score << endl; cout << " -- Score: " << score << endl;
} }
this->bestVerticalScore = score; this->bestVerticalScore = score;
bestLeft = LineSegment(left.p1.x, left.p1.y, left.p2.x, left.p2.y); bestLeft = LineSegment(left.p1.x, left.p1.y, left.p2.x, left.p2.y);
bestRight = LineSegment(right.p1.x, right.p1.y, right.p2.x, right.p2.y); bestRight = LineSegment(right.p1.x, right.p1.y, right.p2.x, right.p2.y);
} }
} }
// Score a collection of lines as a possible license plate region. // Score a collection of lines as a possible license plate region.
// If any segments are missing, extrapolate the missing pieces // If any segments are missing, extrapolate the missing pieces
void PlateCorners::scoreHorizontals(int h1, int h2) void PlateCorners::scoreHorizontals(int h1, int h2)
{ {
//if (this->debug) //if (this->debug)
// cout << "PlateCorners::scorePlate" << endl; // cout << "PlateCorners::scorePlate" << endl;
float score = 0; // Lower is better float score = 0; // Lower is better
LineSegment top; LineSegment top;
LineSegment bottom; LineSegment bottom;
float charHeightToPlateHeightRatio = config->plateHeightMM / config->charHeightMM; float charHeightToPlateHeightRatio = config->plateHeightMM / config->charHeightMM;
float idealPixelHeight = this->charHeight * charHeightToPlateHeightRatio; float idealPixelHeight = this->charHeight * charHeightToPlateHeightRatio;
if (h1 == NO_LINE && h2 == NO_LINE) if (h1 == NO_LINE && h2 == NO_LINE)
{ {
// return; // return;
Point centerLeft = charRegion->getCharBoxLeft().midpoint(); Point centerLeft = charRegion->getCharBoxLeft().midpoint();
Point centerRight = charRegion->getCharBoxRight().midpoint(); Point centerRight = charRegion->getCharBoxRight().midpoint();
LineSegment centerLine = LineSegment(centerLeft.x, centerLeft.y, centerRight.x, centerRight.y); LineSegment centerLine = LineSegment(centerLeft.x, centerLeft.y, centerRight.x, centerRight.y);
top = centerLine.getParallelLine(idealPixelHeight / 2); top = centerLine.getParallelLine(idealPixelHeight / 2);
bottom = centerLine.getParallelLine(-1 * idealPixelHeight / 2 ); bottom = centerLine.getParallelLine(-1 * idealPixelHeight / 2 );
@@ -307,141 +307,141 @@ void PlateCorners::scoreHorizontals(int h1, int h2)
bottom = top.getParallelLine(-1 * idealPixelHeight); bottom = top.getParallelLine(-1 * idealPixelHeight);
score += SCORING_MISSING_SEGMENT_PENALTY_HORIZONTAL; score += SCORING_MISSING_SEGMENT_PENALTY_HORIZONTAL;
} }
// Make sure this line is above our license plate letters // Make sure this line is above our license plate letters
if (top.isPointBelowLine(charRegion->getCharBoxTop().midpoint()) == false) if (top.isPointBelowLine(charRegion->getCharBoxTop().midpoint()) == false)
return; return;
// Make sure this line is below our license plate letters // Make sure this line is below our license plate letters
if (bottom.isPointBelowLine(charRegion->getCharBoxBottom().midpoint())) if (bottom.isPointBelowLine(charRegion->getCharBoxBottom().midpoint()))
return; return;
// We now have 4 possible lines. Let's put them to the test and score them... // We now have 4 possible lines. Let's put them to the test and score them...
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// Score "Boxiness" of the 4 lines. How close is it to a parallelogram? // Score "Boxiness" of the 4 lines. How close is it to a parallelogram?
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
float horizontalAngleDiff = abs(top.angle - bottom.angle); float horizontalAngleDiff = abs(top.angle - bottom.angle);
score += (horizontalAngleDiff) * SCORING_BOXINESS_WEIGHT; score += (horizontalAngleDiff) * SCORING_BOXINESS_WEIGHT;
// if (this->debug) // if (this->debug)
// cout << "PlateCorners boxiness score: " << (horizontalAngleDiff + verticalAngleDiff) * SCORING_BOXINESS_WEIGHT << endl; // cout << "PlateCorners boxiness score: " << (horizontalAngleDiff + verticalAngleDiff) * SCORING_BOXINESS_WEIGHT << endl;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// SCORE the shape wrt character position and height relative to position // SCORE the shape wrt character position and height relative to position
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
Point topPoint = top.midpoint(); Point topPoint = top.midpoint();
Point botPoint = bottom.closestPointOnSegmentTo(topPoint); Point botPoint = bottom.closestPointOnSegmentTo(topPoint);
float plateHeightPx = distanceBetweenPoints(topPoint, botPoint); float plateHeightPx = distanceBetweenPoints(topPoint, botPoint);
// Get the height difference // Get the height difference
float heightRatio = charHeight / plateHeightPx; float heightRatio = charHeight / plateHeightPx;
float idealHeightRatio = (config->charHeightMM / config->plateHeightMM); float idealHeightRatio = (config->charHeightMM / config->plateHeightMM);
//if (leftRatio < MIN_CHAR_HEIGHT_RATIO || leftRatio > MAX_CHAR_HEIGHT_RATIO || rightRatio < MIN_CHAR_HEIGHT_RATIO || rightRatio > MAX_CHAR_HEIGHT_RATIO) //if (leftRatio < MIN_CHAR_HEIGHT_RATIO || leftRatio > MAX_CHAR_HEIGHT_RATIO || rightRatio < MIN_CHAR_HEIGHT_RATIO || rightRatio > MAX_CHAR_HEIGHT_RATIO)
float heightRatioDiff = abs(heightRatio - idealHeightRatio); float heightRatioDiff = abs(heightRatio - idealHeightRatio);
// Ideal ratio == ~.45 // Ideal ratio == ~.45
// Get the distance from the top and the distance from the bottom // Get the distance from the top and the distance from the bottom
// Take the average distances from the corners of the character region to the top/bottom lines // Take the average distances from the corners of the character region to the top/bottom lines
// float topDistance = distanceBetweenPoints(topMidLinePoint, charRegion->getCharBoxTop().midpoint()); // float topDistance = distanceBetweenPoints(topMidLinePoint, charRegion->getCharBoxTop().midpoint());
// float bottomDistance = distanceBetweenPoints(bottomMidLinePoint, charRegion->getCharBoxBottom().midpoint()); // float bottomDistance = distanceBetweenPoints(bottomMidLinePoint, charRegion->getCharBoxBottom().midpoint());
// float idealTopDistance = charHeight * (TOP_WHITESPACE_HEIGHT_MM / CHARACTER_HEIGHT_MM); // float idealTopDistance = charHeight * (TOP_WHITESPACE_HEIGHT_MM / CHARACTER_HEIGHT_MM);
// float idealBottomDistance = charHeight * (BOTTOM_WHITESPACE_HEIGHT_MM / CHARACTER_HEIGHT_MM); // float idealBottomDistance = charHeight * (BOTTOM_WHITESPACE_HEIGHT_MM / CHARACTER_HEIGHT_MM);
// float distScore = abs(topDistance - idealTopDistance) + abs(bottomDistance - idealBottomDistance); // float distScore = abs(topDistance - idealTopDistance) + abs(bottomDistance - idealBottomDistance);
score += heightRatioDiff * SCORING_PLATEHEIGHT_WEIGHT; score += heightRatioDiff * SCORING_PLATEHEIGHT_WEIGHT;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// SCORE the middliness of the stuff. We want our top and bottom line to have the characters right towards the middle // SCORE the middliness of the stuff. We want our top and bottom line to have the characters right towards the middle
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
Point charAreaMidPoint = charRegion->getCharBoxLeft().midpoint(); Point charAreaMidPoint = charRegion->getCharBoxLeft().midpoint();
Point topLineSpot = top.closestPointOnSegmentTo(charAreaMidPoint); Point topLineSpot = top.closestPointOnSegmentTo(charAreaMidPoint);
Point botLineSpot = bottom.closestPointOnSegmentTo(charAreaMidPoint); Point botLineSpot = bottom.closestPointOnSegmentTo(charAreaMidPoint);
float topDistanceFromMiddle = distanceBetweenPoints(topLineSpot, charAreaMidPoint); float topDistanceFromMiddle = distanceBetweenPoints(topLineSpot, charAreaMidPoint);
float bottomDistanceFromMiddle = distanceBetweenPoints(topLineSpot, charAreaMidPoint); float bottomDistanceFromMiddle = distanceBetweenPoints(topLineSpot, charAreaMidPoint);
float idealDistanceFromMiddle = idealPixelHeight / 2; float idealDistanceFromMiddle = idealPixelHeight / 2;
float middleScore = abs(topDistanceFromMiddle - idealDistanceFromMiddle) + abs(bottomDistanceFromMiddle - idealDistanceFromMiddle); float middleScore = abs(topDistanceFromMiddle - idealDistanceFromMiddle) + abs(bottomDistanceFromMiddle - idealDistanceFromMiddle);
score += middleScore * SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT; score += middleScore * SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT;
// if (this->debug) // if (this->debug)
// { // {
// cout << "PlateCorners boxiness score: " << avgRatio * SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT << endl; // cout << "PlateCorners boxiness score: " << avgRatio * SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT << endl;
// cout << "PlateCorners boxiness score: " << distScore * SCORING_PLATEHEIGHT_WEIGHT << endl; // cout << "PlateCorners boxiness score: " << distScore * SCORING_PLATEHEIGHT_WEIGHT << endl;
// } // }
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// SCORE: the shape for angles matching the character region // SCORE: the shape for angles matching the character region
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
float charanglediff = abs(charAngle - top.angle) + abs(charAngle - bottom.angle); float charanglediff = abs(charAngle - top.angle) + abs(charAngle - bottom.angle);
score += charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT; score += charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT;
// if (this->debug) // if (this->debug)
// cout << "PlateCorners boxiness score: " << charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT << endl; // cout << "PlateCorners boxiness score: " << charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT << endl;
if (score < this->bestHorizontalScore) if (score < this->bestHorizontalScore)
{ {
float scorecomponent; float scorecomponent;
if (this->config->debugPlateCorners) if (this->config->debugPlateCorners)
{ {
cout << "xx xx Score: charHeight " << this->charHeight << endl; cout << "xx xx Score: charHeight " << this->charHeight << endl;
cout << "xx xx Score: idealHeight " << idealPixelHeight << endl; cout << "xx xx Score: idealHeight " << idealPixelHeight << endl;
cout << "xx xx Score: h1,h2= " << h1 << "," << h2 << endl; cout << "xx xx Score: h1,h2= " << h1 << "," << h2 << endl;
cout << "xx xx Score: Top= " << top.str() << endl; cout << "xx xx Score: Top= " << top.str() << endl;
cout << "xx xx Score: Bottom= " << bottom.str() << endl; cout << "xx xx Score: Bottom= " << bottom.str() << endl;
cout << "Horizontal breakdown Score:" << endl; cout << "Horizontal breakdown Score:" << endl;
cout << " -- Boxiness Score: " << horizontalAngleDiff << " -- Weight (" << SCORING_BOXINESS_WEIGHT << ")" << endl; cout << " -- Boxiness Score: " << horizontalAngleDiff << " -- Weight (" << SCORING_BOXINESS_WEIGHT << ")" << endl;
scorecomponent = horizontalAngleDiff * SCORING_BOXINESS_WEIGHT; scorecomponent = horizontalAngleDiff * SCORING_BOXINESS_WEIGHT;
cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl; cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl;
cout << " -- Height Ratio Diff Score: " << heightRatioDiff << " -- Weight (" << SCORING_PLATEHEIGHT_WEIGHT << ")" << endl; cout << " -- Height Ratio Diff Score: " << heightRatioDiff << " -- Weight (" << SCORING_PLATEHEIGHT_WEIGHT << ")" << endl;
scorecomponent = heightRatioDiff * SCORING_PLATEHEIGHT_WEIGHT; scorecomponent = heightRatioDiff * SCORING_PLATEHEIGHT_WEIGHT;
cout << " -- -- " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl; cout << " -- -- " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl;
cout << " -- Distance Score: " << middleScore << " -- Weight (" << SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT << ")" << endl; cout << " -- Distance Score: " << middleScore << " -- Weight (" << SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT << ")" << endl;
scorecomponent = middleScore * SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT; scorecomponent = middleScore * SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT;
cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl; cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl;
cout << " -- Char angle Score: " << charanglediff << " -- Weight (" << SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT << ")" << endl; cout << " -- Char angle Score: " << charanglediff << " -- Weight (" << SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT << ")" << endl;
scorecomponent = charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT; scorecomponent = charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT;
cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl; cout << " -- -- Score: " << scorecomponent << " = " << scorecomponent / score * 100 << "% of score" << endl;
cout << " -- Score: " << score << endl; cout << " -- Score: " << score << endl;
} }
this->bestHorizontalScore = score; this->bestHorizontalScore = score;
bestTop = LineSegment(top.p1.x, top.p1.y, top.p2.x, top.p2.y); bestTop = LineSegment(top.p1.x, top.p1.y, top.p2.x, top.p2.y);
bestBottom = LineSegment(bottom.p1.x, bottom.p1.y, bottom.p2.x, bottom.p2.y); bestBottom = LineSegment(bottom.p1.x, bottom.p1.y, bottom.p2.x, bottom.p2.y);
} }
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -36,13 +36,13 @@ using namespace std;
#define SCORING_MISSING_SEGMENT_PENALTY_VERTICAL 10 #define SCORING_MISSING_SEGMENT_PENALTY_VERTICAL 10
#define SCORING_MISSING_SEGMENT_PENALTY_HORIZONTAL 15 #define SCORING_MISSING_SEGMENT_PENALTY_HORIZONTAL 15
#define SCORING_BOXINESS_WEIGHT 0.8 #define SCORING_BOXINESS_WEIGHT 0.8
#define SCORING_PLATEHEIGHT_WEIGHT 2.2 #define SCORING_PLATEHEIGHT_WEIGHT 2.2
#define SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT 0.05 #define SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT 0.05
#define SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT 1.1 #define SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT 1.1
#define SCORING_VERTICALDISTANCE_WEIGHT 0.1 #define SCORING_VERTICALDISTANCE_WEIGHT 0.1
#define SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT 0.05 #define SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT 0.05
class PlateCorners class PlateCorners
{ {
@@ -50,33 +50,31 @@ class PlateCorners
public: public:
PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegion* charRegion, Config* config); PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegion* charRegion, Config* config);
virtual ~PlateCorners(); virtual ~PlateCorners();
vector<Point> findPlateCorners(); vector<Point> findPlateCorners();
float confidence; float confidence;
private: private:
Config* config; Config* config;
Mat inputImage; Mat inputImage;
float charHeight; float charHeight;
float charAngle; float charAngle;
float bestHorizontalScore; float bestHorizontalScore;
float bestVerticalScore; float bestVerticalScore;
LineSegment bestTop; LineSegment bestTop;
LineSegment bestBottom; LineSegment bestBottom;
LineSegment bestLeft; LineSegment bestLeft;
LineSegment bestRight; LineSegment bestRight;
PlateLines* plateLines; PlateLines* plateLines;
CharacterRegion* charRegion; CharacterRegion* charRegion;
void scoreHorizontals( int h1, int h2 ); void scoreHorizontals( int h1, int h2 );
void scoreVerticals( int v1, int v2 ); void scoreVerticals( int v1, int v2 );
}; };
#endif // PLATELINES_H #endif // PLATELINES_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -24,10 +24,10 @@ PlateLines::PlateLines(Config* config)
{ {
this->config = config; this->config = config;
this->debug = config->debugPlateLines; this->debug = config->debugPlateLines;
if (debug) if (debug)
cout << "PlateLines constructor" << endl; cout << "PlateLines constructor" << endl;
} }
@@ -36,18 +36,18 @@ PlateLines::~PlateLines()
} }
void PlateLines::processImage(Mat inputImage, float sensitivity) void PlateLines::processImage(Mat inputImage, float sensitivity)
{ {
if (this->debug) if (this->debug)
cout << "PlateLines findLines" << endl; cout << "PlateLines findLines" << endl;
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
Mat smoothed(inputImage.size(), inputImage.type()); Mat smoothed(inputImage.size(), inputImage.type());
inputImage.copyTo(smoothed); inputImage.copyTo(smoothed);
int morph_elem = 2; int morph_elem = 2;
@@ -55,31 +55,31 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
morphologyEx( smoothed, smoothed, MORPH_CLOSE, element ); morphologyEx( smoothed, smoothed, MORPH_CLOSE, element );
morph_size = 1; morph_size = 1;
element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
//morphologyEx( thresholded, thresholded, MORPH_GRADIENT, element ); //morphologyEx( thresholded, thresholded, MORPH_GRADIENT, element );
morph_size = 1; morph_size = 1;
element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
morphologyEx( smoothed, smoothed, MORPH_OPEN, element ); morphologyEx( smoothed, smoothed, MORPH_OPEN, element );
Mat edges(inputImage.size(), inputImage.type()); Mat edges(inputImage.size(), inputImage.type());
Canny(smoothed, edges, 66, 133); Canny(smoothed, edges, 66, 133);
vector<LineSegment> hlines = this->getLines(edges, sensitivity, false); vector<LineSegment> hlines = this->getLines(edges, sensitivity, false);
vector<LineSegment> vlines = this->getLines(edges, sensitivity, true); vector<LineSegment> vlines = this->getLines(edges, sensitivity, true);
for (int i = 0; i < hlines.size(); i++) for (int i = 0; i < hlines.size(); i++)
this->horizontalLines.push_back(hlines[i]); this->horizontalLines.push_back(hlines[i]);
for (int i = 0; i < vlines.size(); i++) for (int i = 0; i < vlines.size(); i++)
this->verticalLines.push_back(vlines[i]); this->verticalLines.push_back(vlines[i]);
// if debug is enabled, draw the image // if debug is enabled, draw the image
if (this->debug) if (this->debug)
@@ -90,27 +90,27 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
edges.copyTo(debugImgVert); edges.copyTo(debugImgVert);
cvtColor(debugImgHoriz,debugImgHoriz,CV_GRAY2BGR); cvtColor(debugImgHoriz,debugImgHoriz,CV_GRAY2BGR);
cvtColor(debugImgVert,debugImgVert,CV_GRAY2BGR); cvtColor(debugImgVert,debugImgVert,CV_GRAY2BGR);
for( size_t i = 0; i < this->horizontalLines.size(); i++ ) for( size_t i = 0; i < this->horizontalLines.size(); i++ )
{ {
line( debugImgHoriz, this->horizontalLines[i].p1, this->horizontalLines[i].p2, Scalar(0,0,255), 1, CV_AA); line( debugImgHoriz, this->horizontalLines[i].p1, this->horizontalLines[i].p2, Scalar(0,0,255), 1, CV_AA);
} }
for( size_t i = 0; i < this->verticalLines.size(); i++ ) for( size_t i = 0; i < this->verticalLines.size(); i++ )
{ {
line( debugImgVert, this->verticalLines[i].p1, this->verticalLines[i].p2, Scalar(0,0,255), 1, CV_AA); line( debugImgVert, this->verticalLines[i].p1, this->verticalLines[i].p2, Scalar(0,0,255), 1, CV_AA);
} }
vector<Mat> images; vector<Mat> images;
images.push_back(debugImgHoriz); images.push_back(debugImgHoriz);
images.push_back(debugImgVert); images.push_back(debugImgVert);
Mat dashboard = drawImageDashboard(images, debugImgVert.type(), 1); Mat dashboard = drawImageDashboard(images, debugImgVert.type(), 1);
displayImage(config, "Hough Lines", dashboard); displayImage(config, "Hough Lines", dashboard);
} }
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
@@ -118,27 +118,27 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
cout << "Plate Lines Time: " << diffclock(startTime, endTime) << "ms." << endl; cout << "Plate Lines Time: " << diffclock(startTime, endTime) << "ms." << endl;
} }
//smoothed.release(); //smoothed.release();
//////////////// METHOD2!!!!!!!//////////////////// //////////////// METHOD2!!!!!!!////////////////////
/* /*
Mat imgBlur; Mat imgBlur;
Mat imgCanny; Mat imgCanny;
GaussianBlur(inputImage, imgBlur, Size(9, 9), 1, 1); GaussianBlur(inputImage, imgBlur, Size(9, 9), 1, 1);
Canny(imgBlur, imgCanny, 10, 30, 3);
Canny(imgBlur, imgCanny, 10, 30, 3);
//int morph_elem = 2; //int morph_elem = 2;
//int morph_size = 1; //int morph_size = 1;
//Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); //Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
morphologyEx( imgCanny, imgCanny, MORPH_CLOSE, element ); morphologyEx( imgCanny, imgCanny, MORPH_CLOSE, element );
Mat imgShaped; Mat imgShaped;
imgCanny.copyTo(imgShaped); imgCanny.copyTo(imgShaped);
//Find contours of possibles characters //Find contours of possibles characters
@@ -147,26 +147,26 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
biggestShapes, // a vector of contours biggestShapes, // a vector of contours
CV_RETR_EXTERNAL, // retrieve the external contours CV_RETR_EXTERNAL, // retrieve the external contours
CV_CHAIN_APPROX_SIMPLE ); // all pixels of each contours CV_CHAIN_APPROX_SIMPLE ); // all pixels of each contours
// Draw blue contours on a white image // Draw blue contours on a white image
//cvtColor(imgShaped, imgShaped, CV_GRAY2RGB); //cvtColor(imgShaped, imgShaped, CV_GRAY2RGB);
cv::drawContours(imgShaped,biggestShapes, cv::drawContours(imgShaped,biggestShapes,
-1, // draw all contours -1, // draw all contours
cv::Scalar(255,255,255), // in blue cv::Scalar(255,255,255), // in blue
1); // with a thickness of 1 1); // with a thickness of 1
displayImage(config, "Blurred", imgCanny); displayImage(config, "Blurred", imgCanny);
displayImage(config, "Blurred Contours", imgShaped); displayImage(config, "Blurred Contours", imgShaped);
vector<Rect> shapeRects( biggestShapes.size() ); vector<Rect> shapeRects( biggestShapes.size() );
vector<vector<Point> >hull( biggestShapes.size() ); vector<vector<Point> >hull( biggestShapes.size() );
for( int i = 0; i < biggestShapes.size(); i++ ) for( int i = 0; i < biggestShapes.size(); i++ )
{ {
//approxPolyDP( Mat(biggestShapes[i]), shapeRects[i], 3, true ); //approxPolyDP( Mat(biggestShapes[i]), shapeRects[i], 3, true );
convexHull( biggestShapes[i], hull[i], false ); convexHull( biggestShapes[i], hull[i], false );
//approxPolyDP( biggestShapes[i], hull[i], 10, true ); //approxPolyDP( biggestShapes[i], hull[i], 10, true );
//minEnclosingCircle( (Mat)contours_poly[i], center[i], radius[i] ); //minEnclosingCircle( (Mat)contours_poly[i], center[i], radius[i] );
} }
*/ */
@@ -176,21 +176,21 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
/* /*
vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical) vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical)
{ {
vector<LineSegment> filteredLines; vector<LineSegment> filteredLines;
int sensitivity; int sensitivity;
LSWMS lswms(Size(edges.cols, edges.rows), 3, 155, false); LSWMS lswms(Size(edges.cols, edges.rows), 3, 155, false);
vector<LSEG> lsegs; vector<LSEG> lsegs;
vector<double> errors; vector<double> errors;
lswms.run(edges, lsegs, errors); lswms.run(edges, lsegs, errors);
for( size_t i = 0; i < lsegs.size(); i++ ) for( size_t i = 0; i < lsegs.size(); i++ )
{ {
if (vertical) if (vertical)
{ {
LineSegment candidate; LineSegment candidate;
@@ -198,13 +198,13 @@ vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical)
candidate = LineSegment(lsegs[i][0].x, lsegs[i][0].y, lsegs[i][1].x, lsegs[i][1].y); candidate = LineSegment(lsegs[i][0].x, lsegs[i][0].y, lsegs[i][1].x, lsegs[i][1].y);
else else
candidate = LineSegment(lsegs[i][1].x, lsegs[i][1].y, lsegs[i][0].x, lsegs[i][0].y); candidate = LineSegment(lsegs[i][1].x, lsegs[i][1].y, lsegs[i][0].x, lsegs[i][0].y);
cout << "VERT Angle: " << candidate.angle << endl; cout << "VERT Angle: " << candidate.angle << endl;
//if ((candidate.angle > 70 && candidate.angle < 110) || (candidate.angle > 250 && candidate.angle < 290)) //if ((candidate.angle > 70 && candidate.angle < 110) || (candidate.angle > 250 && candidate.angle < 290))
//{ //{
// good vertical // good vertical
filteredLines.push_back(candidate); filteredLines.push_back(candidate);
//} //}
} }
else else
@@ -215,26 +215,26 @@ vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical)
else else
candidate = LineSegment(lsegs[i][1].x, lsegs[i][1].y, lsegs[i][0].x, lsegs[i][0].y); candidate = LineSegment(lsegs[i][1].x, lsegs[i][1].y, lsegs[i][0].x, lsegs[i][0].y);
cout << "HORIZAngle: " << candidate.angle << endl; cout << "HORIZAngle: " << candidate.angle << endl;
//if ( (candidate.angle > -20 && candidate.angle < 20) || (candidate.angle > 160 && candidate.angle < 200)) //if ( (candidate.angle > -20 && candidate.angle < 20) || (candidate.angle > 160 && candidate.angle < 200))
//{ //{
// good horizontal // good horizontal
filteredLines.push_back(candidate); filteredLines.push_back(candidate);
//} //}
} }
} }
// if debug is enabled, draw the image // if debug is enabled, draw the image
if (this->debug) if (this->debug)
{ {
Mat debugImg(edges.size(), edges.type()); Mat debugImg(edges.size(), edges.type());
edges.copyTo(debugImg); edges.copyTo(debugImg);
cvtColor(debugImg,debugImg,CV_GRAY2BGR); cvtColor(debugImg,debugImg,CV_GRAY2BGR);
for( size_t i = 0; i < filteredLines.size(); i++ ) for( size_t i = 0; i < filteredLines.size(); i++ )
{ {
line( debugImg, filteredLines[i].p1, filteredLines[i].p2, Scalar(0,0,255), 1, CV_AA); line( debugImg, filteredLines[i].p1, filteredLines[i].p2, Scalar(0,0,255), 1, CV_AA);
} }
if (vertical) if (vertical)
@@ -242,7 +242,7 @@ vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical)
else else
displayImage(config, "Lines Horizontal", debugImg); displayImage(config, "Lines Horizontal", debugImg);
} }
return filteredLines; return filteredLines;
} }
*/ */
@@ -252,47 +252,47 @@ vector<LineSegment> PlateLines::getLines(Mat edges, float sensitivityMultiplier,
{ {
if (this->debug) if (this->debug)
cout << "PlateLines::getLines" << endl; cout << "PlateLines::getLines" << endl;
static int HORIZONTAL_SENSITIVITY = config->plateLinesSensitivityHorizontal; static int HORIZONTAL_SENSITIVITY = config->plateLinesSensitivityHorizontal;
static int VERTICAL_SENSITIVITY = config->plateLinesSensitivityVertical; static int VERTICAL_SENSITIVITY = config->plateLinesSensitivityVertical;
vector<Vec2f> allLines; vector<Vec2f> allLines;
vector<LineSegment> filteredLines; vector<LineSegment> filteredLines;
int sensitivity; int sensitivity;
if (vertical) if (vertical)
sensitivity = VERTICAL_SENSITIVITY * (1.0 / sensitivityMultiplier); sensitivity = VERTICAL_SENSITIVITY * (1.0 / sensitivityMultiplier);
else else
sensitivity = HORIZONTAL_SENSITIVITY * (1.0 / sensitivityMultiplier); sensitivity = HORIZONTAL_SENSITIVITY * (1.0 / sensitivityMultiplier);
HoughLines( edges, allLines, 1, CV_PI/180, sensitivity, 0, 0 ); HoughLines( edges, allLines, 1, CV_PI/180, sensitivity, 0, 0 );
for( size_t i = 0; i < allLines.size(); i++ ) for( size_t i = 0; i < allLines.size(); i++ )
{ {
float rho = allLines[i][0], theta = allLines[i][1]; float rho = allLines[i][0], theta = allLines[i][1];
Point pt1, pt2; Point pt1, pt2;
double a = cos(theta), b = sin(theta); double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho; double x0 = a*rho, y0 = b*rho;
double angle = theta * (180 / CV_PI); double angle = theta * (180 / CV_PI);
pt1.x = cvRound(x0 + 1000*(-b)); pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a)); pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b)); pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a)); pt2.y = cvRound(y0 - 1000*(a));
if (vertical) if (vertical)
{ {
if (angle < 20 || angle > 340 || (angle > 160 && angle < 210)) if (angle < 20 || angle > 340 || (angle > 160 && angle < 210))
{ {
// good vertical // good vertical
LineSegment line; LineSegment line;
if (pt1.y <= pt2.y) if (pt1.y <= pt2.y)
line = LineSegment(pt2.x, pt2.y, pt1.x, pt1.y); line = LineSegment(pt2.x, pt2.y, pt1.x, pt1.y);
else else
line = LineSegment(pt1.x, pt1.y, pt2.x, pt2.y); line = LineSegment(pt1.x, pt1.y, pt2.x, pt2.y);
// Get rid of the -1000, 1000 stuff. Terminate at the edges of the image // Get rid of the -1000, 1000 stuff. Terminate at the edges of the image
// Helps with debugging/rounding issues later // Helps with debugging/rounding issues later
LineSegment top(0, 0, edges.cols, 0); LineSegment top(0, 0, edges.cols, 0);
@@ -304,28 +304,28 @@ vector<LineSegment> PlateLines::getLines(Mat edges, float sensitivityMultiplier,
} }
else else
{ {
if ( (angle > 70 && angle < 110) || (angle > 250 && angle < 290)) if ( (angle > 70 && angle < 110) || (angle > 250 && angle < 290))
{ {
// good horizontal // good horizontal
LineSegment line; LineSegment line;
if (pt1.x <= pt2.x) if (pt1.x <= pt2.x)
line = LineSegment(pt1.x, pt1.y, pt2.x, pt2.y); line = LineSegment(pt1.x, pt1.y, pt2.x, pt2.y);
else else
line =LineSegment(pt2.x, pt2.y, pt1.x, pt1.y); line =LineSegment(pt2.x, pt2.y, pt1.x, pt1.y);
// Get rid of the -1000, 1000 stuff. Terminate at the edges of the image // Get rid of the -1000, 1000 stuff. Terminate at the edges of the image
// Helps with debugging/ rounding issues later // Helps with debugging/ rounding issues later
int newY1 = line.getPointAt(0); int newY1 = line.getPointAt(0);
int newY2 = line.getPointAt(edges.cols); int newY2 = line.getPointAt(edges.cols);
filteredLines.push_back(LineSegment(0, newY1, edges.cols, newY2)); filteredLines.push_back(LineSegment(0, newY1, edges.cols, newY2));
} }
} }
} }
return filteredLines; return filteredLines;
} }
@@ -337,11 +337,11 @@ Mat PlateLines::customGrayscaleConversion(Mat src)
{ {
Mat img_hsv; Mat img_hsv;
cvtColor(src,img_hsv,CV_BGR2HSV); cvtColor(src,img_hsv,CV_BGR2HSV);
Mat grayscale = Mat(img_hsv.size(), CV_8U ); Mat grayscale = Mat(img_hsv.size(), CV_8U );
Mat hue(img_hsv.size(), CV_8U ); Mat hue(img_hsv.size(), CV_8U );
for (int row = 0; row < img_hsv.rows; row++) for (int row = 0; row < img_hsv.rows; row++)
{ {
for (int col = 0; col < img_hsv.cols; col++) for (int col = 0; col < img_hsv.cols; col++)
@@ -349,18 +349,18 @@ Mat PlateLines::customGrayscaleConversion(Mat src)
int h = (int) img_hsv.at<Vec3b>(row, col)[0]; int h = (int) img_hsv.at<Vec3b>(row, col)[0];
int s = (int) img_hsv.at<Vec3b>(row, col)[1]; int s = (int) img_hsv.at<Vec3b>(row, col)[1];
int v = (int) img_hsv.at<Vec3b>(row, col)[2]; int v = (int) img_hsv.at<Vec3b>(row, col)[2];
int pixval = pow(v, 1.05); int pixval = pow(v, 1.05);
if (pixval > 255) if (pixval > 255)
pixval = 255; pixval = 255;
grayscale.at<uchar>(row, col) = pixval; grayscale.at<uchar>(row, col) = pixval;
hue.at<uchar>(row, col) = h * (255.0 / 180.0); hue.at<uchar>(row, col) = h * (255.0 / 180.0);
} }
} }
//displayImage(config, "Hue", hue); //displayImage(config, "Hue", hue);
return grayscale; return grayscale;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -38,24 +38,22 @@ class PlateLines
public: public:
PlateLines(Config* config); PlateLines(Config* config);
virtual ~PlateLines(); virtual ~PlateLines();
void processImage(Mat img, float sensitivity=1.0); void processImage(Mat img, float sensitivity=1.0);
vector<LineSegment> horizontalLines; vector<LineSegment> horizontalLines;
vector<LineSegment> verticalLines; vector<LineSegment> verticalLines;
vector<Point> winningCorners; vector<Point> winningCorners;
private: private:
Config* config; Config* config;
bool debug; bool debug;
Mat customGrayscaleConversion(Mat src); Mat customGrayscaleConversion(Mat src);
void findLines(Mat inputImage); void findLines(Mat inputImage);
vector<LineSegment> getLines(Mat edges, float sensitivityMultiplier, bool vertical); vector<LineSegment> getLines(Mat edges, float sensitivityMultiplier, bool vertical);
}; };
#endif // PLATELINES_H #endif // PLATELINES_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -23,19 +23,19 @@
PostProcess::PostProcess(Config* config) PostProcess::PostProcess(Config* config)
{ {
this->config = config; this->config = config;
stringstream filename; stringstream filename;
filename << config->getPostProcessRuntimeDir() << "/" << config->country << ".patterns"; filename << config->getPostProcessRuntimeDir() << "/" << config->country << ".patterns";
std::ifstream infile(filename.str().c_str()); std::ifstream infile(filename.str().c_str());
string region, pattern; string region, pattern;
while (infile >> region >> pattern) while (infile >> region >> pattern)
{ {
RegexRule* rule = new RegexRule(region, pattern); RegexRule* rule = new RegexRule(region, pattern);
//cout << "REGION: " << region << " PATTERN: " << pattern << endl; //cout << "REGION: " << region << " PATTERN: " << pattern << endl;
if (rules.find(region) == rules.end()) if (rules.find(region) == rules.end())
{ {
vector<RegexRule*> newRule; vector<RegexRule*> newRule;
@@ -49,7 +49,7 @@ PostProcess::PostProcess(Config* config)
rules[region] = oldRule; rules[region] = oldRule;
} }
} }
//vector<RegexRule> test = rules["base"]; //vector<RegexRule> test = rules["base"];
//for (int i = 0; i < test.size(); i++) //for (int i = 0; i < test.size(); i++)
// cout << "Rule: " << test[i].regex << endl; // cout << "Rule: " << test[i].regex << endl;
@@ -66,7 +66,7 @@ PostProcess::~PostProcess()
{ {
delete iter->second[i]; delete iter->second[i];
} }
} }
} }
@@ -75,28 +75,28 @@ void PostProcess::addLetter(char letter, int charposition, float score)
{ {
if (score < config->postProcessMinConfidence) if (score < config->postProcessMinConfidence)
return; return;
insertLetter(letter, charposition, score); insertLetter(letter, charposition, score);
if (score < config->postProcessConfidenceSkipLevel) if (score < config->postProcessConfidenceSkipLevel)
{ {
float adjustedScore = abs(config->postProcessConfidenceSkipLevel - score) + config->postProcessMinConfidence; float adjustedScore = abs(config->postProcessConfidenceSkipLevel - score) + config->postProcessMinConfidence;
insertLetter(SKIP_CHAR, charposition, adjustedScore ); insertLetter(SKIP_CHAR, charposition, adjustedScore );
} }
//if (letter == '0') //if (letter == '0')
//{ //{
// insertLetter('O', charposition, score - 0.5); // insertLetter('O', charposition, score - 0.5);
//} //}
} }
void PostProcess::insertLetter(char letter, int charposition, float score) void PostProcess::insertLetter(char letter, int charposition, float score)
{ {
score = score - config->postProcessMinConfidence; score = score - config->postProcessMinConfidence;
int existingIndex = -1; int existingIndex = -1;
if (letters.size() < charposition + 1) if (letters.size() < charposition + 1)
{ {
@@ -106,7 +106,7 @@ void PostProcess::insertLetter(char letter, int charposition, float score)
letters.push_back(tmp); letters.push_back(tmp);
} }
} }
for (int i = 0; i < letters[charposition].size(); i++) for (int i = 0; i < letters[charposition].size(); i++)
{ {
if (letters[charposition][i].letter == letter && if (letters[charposition][i].letter == letter &&
@@ -116,7 +116,7 @@ void PostProcess::insertLetter(char letter, int charposition, float score)
break; break;
} }
} }
if (existingIndex == -1) if (existingIndex == -1)
{ {
Letter newLetter; Letter newLetter;
@@ -131,7 +131,7 @@ void PostProcess::insertLetter(char letter, int charposition, float score)
letters[charposition][existingIndex].occurences = letters[charposition][existingIndex].occurences + 1; letters[charposition][existingIndex].occurences = letters[charposition][existingIndex].occurences + 1;
letters[charposition][existingIndex].totalscore = letters[charposition][existingIndex].totalscore + score; letters[charposition][existingIndex].totalscore = letters[charposition][existingIndex].totalscore + score;
} }
} }
@@ -142,23 +142,23 @@ void PostProcess::clear()
letters[i].clear(); letters[i].clear();
} }
letters.resize(0); letters.resize(0);
unknownCharPositions.clear(); unknownCharPositions.clear();
unknownCharPositions.resize(0); unknownCharPositions.resize(0);
allPossibilities.clear(); allPossibilities.clear();
//allPossibilities.resize(0); //allPossibilities.resize(0);
bestChars = ""; bestChars = "";
matchesTemplate = false; matchesTemplate = false;
} }
void PostProcess::analyze(string templateregion, int topn) void PostProcess::analyze(string templateregion, int topn)
{ {
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
// Get a list of missing positions // Get a list of missing positions
for (int i = letters.size() -1; i >= 0; i--) for (int i = letters.size() -1; i >= 0; i--)
{ {
@@ -167,38 +167,38 @@ void PostProcess::analyze(string templateregion, int topn)
unknownCharPositions.push_back(i); unknownCharPositions.push_back(i);
} }
} }
if (letters.size() == 0) if (letters.size() == 0)
return; return;
// Sort the letters as they are // Sort the letters as they are
for (int i = 0; i < letters.size(); i++) for (int i = 0; i < letters.size(); i++)
{ {
if (letters[i].size() > 0) if (letters[i].size() > 0)
sort(letters[i].begin(), letters[i].end(), letterCompare); sort(letters[i].begin(), letters[i].end(), letterCompare);
} }
if (this->config->debugPostProcess) if (this->config->debugPostProcess)
{ {
// Print all letters // Print all letters
for (int i = 0; i < letters.size(); i++) for (int i = 0; i < letters.size(); i++)
{ {
for (int j = 0; j < letters[i].size(); j++) for (int j = 0; j < letters[i].size(); j++)
cout << "PostProcess Letter: " << letters[i][j].charposition << " " << letters[i][j].letter << " -- score: " << letters[i][j].totalscore << " -- occurences: " << letters[i][j].occurences << endl; cout << "PostProcess Letter: " << letters[i][j].charposition << " " << letters[i][j].letter << " -- score: " << letters[i][j].totalscore << " -- occurences: " << letters[i][j].occurences << endl;
} }
} }
// Prune the letters based on the topN value. // Prune the letters based on the topN value.
// If our topN value is 3, for example, we can get rid of a lot of low scoring letters // If our topN value is 3, for example, we can get rid of a lot of low scoring letters
// because it would be impossible for them to be a part of our topN results. // because it would be impossible for them to be a part of our topN results.
vector<int> maxDepth = getMaxDepth(topn); vector<int> maxDepth = getMaxDepth(topn);
for (int i = 0; i < letters.size(); i++) for (int i = 0; i < letters.size(); i++)
{ {
for (int k = letters[i].size() - 1; k > maxDepth[i]; k--) for (int k = letters[i].size() - 1; k > maxDepth[i]; k--)
@@ -206,37 +206,37 @@ void PostProcess::analyze(string templateregion, int topn)
letters[i].erase(letters[i].begin() + k); letters[i].erase(letters[i].begin() + k);
} }
} }
//getTopN(); //getTopN();
vector<Letter> tmp; vector<Letter> tmp;
findAllPermutations(tmp, 0, config->postProcessMaxSubstitutions); findAllPermutations(tmp, 0, config->postProcessMaxSubstitutions);
timespec sortStartTime; timespec sortStartTime;
getTime(&sortStartTime); getTime(&sortStartTime);
int numelements = topn; int numelements = topn;
if (allPossibilities.size() < topn) if (allPossibilities.size() < topn)
numelements = allPossibilities.size() - 1; numelements = allPossibilities.size() - 1;
partial_sort( allPossibilities.begin(), allPossibilities.begin() + numelements, allPossibilities.end(), wordCompare ); partial_sort( allPossibilities.begin(), allPossibilities.begin() + numelements, allPossibilities.end(), wordCompare );
if (config->debugTiming) if (config->debugTiming)
{ {
timespec sortEndTime; timespec sortEndTime;
getTime(&sortEndTime); getTime(&sortEndTime);
cout << " -- PostProcess Sort Time: " << diffclock(sortStartTime, sortEndTime) << "ms." << endl; cout << " -- PostProcess Sort Time: " << diffclock(sortStartTime, sortEndTime) << "ms." << endl;
} }
matchesTemplate = false; matchesTemplate = false;
if (templateregion != "") if (templateregion != "")
{ {
vector<RegexRule*> regionRules = rules[templateregion]; vector<RegexRule*> regionRules = rules[templateregion];
for (int i = 0; i < allPossibilities.size(); i++) for (int i = 0; i < allPossibilities.size(); i++)
{ {
for (int j = 0; j < regionRules.size(); j++) for (int j = 0; j < regionRules.size(); j++)
@@ -250,16 +250,16 @@ void PostProcess::analyze(string templateregion, int topn)
break; break;
} }
} }
if (i >= topn - 1) if (i >= topn - 1)
break; break;
//if (matchesTemplate || i >= TOP_N - 1) //if (matchesTemplate || i >= TOP_N - 1)
//break; //break;
} }
} }
if (matchesTemplate) if (matchesTemplate)
{ {
for (int z = 0; z < allPossibilities.size(); z++) for (int z = 0; z < allPossibilities.size(); z++)
@@ -275,26 +275,26 @@ void PostProcess::analyze(string templateregion, int topn)
{ {
bestChars = allPossibilities[0].letters; bestChars = allPossibilities[0].letters;
} }
// Now adjust the confidence scores to a percentage value // Now adjust the confidence scores to a percentage value
if (allPossibilities.size() > 0) if (allPossibilities.size() > 0)
{ {
float maxPercentScore = calculateMaxConfidenceScore(); float maxPercentScore = calculateMaxConfidenceScore();
float highestRelativeScore = (float) allPossibilities[0].totalscore; float highestRelativeScore = (float) allPossibilities[0].totalscore;
for (int i = 0; i < allPossibilities.size(); i++) for (int i = 0; i < allPossibilities.size(); i++)
{ {
allPossibilities[i].totalscore = maxPercentScore * (allPossibilities[i].totalscore / highestRelativeScore); allPossibilities[i].totalscore = maxPercentScore * (allPossibilities[i].totalscore / highestRelativeScore);
} }
} }
if (this->config->debugPostProcess) if (this->config->debugPostProcess)
{ {
// Print top words // Print top words
for (int i = 0; i < allPossibilities.size(); i++) for (int i = 0; i < allPossibilities.size(); i++)
{ {
@@ -302,22 +302,22 @@ void PostProcess::analyze(string templateregion, int topn)
if (allPossibilities[i].letters == bestChars) if (allPossibilities[i].letters == bestChars)
cout << " <--- "; cout << " <--- ";
cout << endl; cout << endl;
if (i >= topn - 1) if (i >= topn - 1)
break; break;
} }
cout << allPossibilities.size() << " total permutations" << endl; cout << allPossibilities.size() << " total permutations" << endl;
} }
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
getTime(&endTime); getTime(&endTime);
cout << "PostProcess Time: " << diffclock(startTime, endTime) << "ms." << endl; cout << "PostProcess Time: " << diffclock(startTime, endTime) << "ms." << endl;
} }
if (this->config->debugPostProcess) if (this->config->debugPostProcess)
cout << "PostProcess Analysis Complete: " << bestChars << " -- MATCH: " << matchesTemplate << endl; cout << "PostProcess Analysis Complete: " << bestChars << " -- MATCH: " << matchesTemplate << endl;
} }
@@ -325,7 +325,7 @@ void PostProcess::analyze(string templateregion, int topn)
float PostProcess::calculateMaxConfidenceScore() float PostProcess::calculateMaxConfidenceScore()
{ {
// Take the best score for each char position and average it. // Take the best score for each char position and average it.
float totalScore = 0; float totalScore = 0;
int numScores = 0; int numScores = 0;
// Get a list of missing positions // Get a list of missing positions
@@ -337,15 +337,15 @@ float PostProcess::calculateMaxConfidenceScore()
numScores++; numScores++;
} }
} }
if (numScores == 0) if (numScores == 0)
return 0; return 0;
return totalScore / ((float) numScores); return totalScore / ((float) numScores);
} }
// Finds the minimum number of letters to include in the recursive sorting algorithm. // Finds the minimum number of letters to include in the recursive sorting algorithm.
// For example, if I have letters // For example, if I have letters
// A-200 B-100 C-100 // A-200 B-100 C-100
// X-99 Y-95 Z-90 // X-99 Y-95 Z-90
// Q-55 R-80 // Q-55 R-80
@@ -356,23 +356,23 @@ float PostProcess::calculateMaxConfidenceScore()
// Y-95 Z-90 // Y-95 Z-90
vector<int> PostProcess::getMaxDepth(int topn) vector<int> PostProcess::getMaxDepth(int topn)
{ {
vector<int> depth; vector<int> depth;
for (int i = 0; i < letters.size(); i++) for (int i = 0; i < letters.size(); i++)
depth.push_back(0); depth.push_back(0);
int nextLeastDropCharPos = getNextLeastDrop(depth); int nextLeastDropCharPos = getNextLeastDrop(depth);
while (nextLeastDropCharPos != -1) while (nextLeastDropCharPos != -1)
{ {
if (getPermutationCount(depth) >= topn) if (getPermutationCount(depth) >= topn)
break; break;
depth[nextLeastDropCharPos] = depth[nextLeastDropCharPos] + 1; depth[nextLeastDropCharPos] = depth[nextLeastDropCharPos] + 1;
nextLeastDropCharPos = getNextLeastDrop(depth); nextLeastDropCharPos = getNextLeastDrop(depth);
} }
return depth; return depth;
} }
@@ -383,7 +383,7 @@ int PostProcess::getPermutationCount(vector<int> depth)
{ {
permutationCount *= (depth[i] + 1); permutationCount *= (depth[i] + 1);
} }
return permutationCount; return permutationCount;
} }
@@ -391,21 +391,21 @@ int PostProcess::getNextLeastDrop(vector<int> depth)
{ {
int nextLeastDropCharPos = -1; int nextLeastDropCharPos = -1;
float leastNextDrop = 99999999999; float leastNextDrop = 99999999999;
for (int i = 0; i < letters.size(); i++) for (int i = 0; i < letters.size(); i++)
{ {
if (depth[i] + 1 >= letters[i].size()) if (depth[i] + 1 >= letters[i].size())
continue; continue;
float drop = letters[i][depth[i]].totalscore - letters[i][depth[i]+1].totalscore; float drop = letters[i][depth[i]].totalscore - letters[i][depth[i]+1].totalscore;
if (drop < leastNextDrop) if (drop < leastNextDrop)
{ {
nextLeastDropCharPos = i; nextLeastDropCharPos = i;
leastNextDrop = drop; leastNextDrop = drop;
} }
} }
return nextLeastDropCharPos; return nextLeastDropCharPos;
} }
@@ -416,14 +416,14 @@ const vector<PPResult> PostProcess::getResults()
void PostProcess::findAllPermutations(vector<Letter> prevletters, int charPos, int substitutionsLeft) void PostProcess::findAllPermutations(vector<Letter> prevletters, int charPos, int substitutionsLeft)
{ {
if (substitutionsLeft < 0) if (substitutionsLeft < 0)
return; return;
// Add my letter to the chain and recurse // Add my letter to the chain and recurse
for (int i = 0; i < letters[charPos].size(); i++) for (int i = 0; i < letters[charPos].size(); i++)
{ {
if (charPos == letters.size() - 1) if (charPos == letters.size() - 1)
{ {
// Last letter, add the word // Last letter, add the word
@@ -437,27 +437,27 @@ void PostProcess::findAllPermutations(vector<Letter> prevletters, int charPos, i
possibility.letters = possibility.letters + prevletters[z].letter; possibility.letters = possibility.letters + prevletters[z].letter;
possibility.totalscore = possibility.totalscore + prevletters[z].totalscore; possibility.totalscore = possibility.totalscore + prevletters[z].totalscore;
} }
if (letters[charPos][i].letter != SKIP_CHAR) if (letters[charPos][i].letter != SKIP_CHAR)
possibility.letters = possibility.letters + letters[charPos][i].letter; possibility.letters = possibility.letters + letters[charPos][i].letter;
possibility.totalscore = possibility.totalscore +letters[charPos][i].totalscore; possibility.totalscore = possibility.totalscore +letters[charPos][i].totalscore;
allPossibilities.push_back(possibility); allPossibilities.push_back(possibility);
} }
else else
{ {
prevletters.push_back(letters[charPos][i]); prevletters.push_back(letters[charPos][i]);
float scorePercentDiff = abs( letters[charPos][0].totalscore - letters[charPos][i].totalscore ) / letters[charPos][0].totalscore; float scorePercentDiff = abs( letters[charPos][0].totalscore - letters[charPos][i].totalscore ) / letters[charPos][0].totalscore;
if (i != 0 && letters[charPos][i].letter != SKIP_CHAR && scorePercentDiff > 0.10f ) if (i != 0 && letters[charPos][i].letter != SKIP_CHAR && scorePercentDiff > 0.10f )
findAllPermutations(prevletters, charPos + 1, substitutionsLeft - 1); findAllPermutations(prevletters, charPos + 1, substitutionsLeft - 1);
else else
findAllPermutations(prevletters, charPos + 1, substitutionsLeft); findAllPermutations(prevletters, charPos + 1, substitutionsLeft);
prevletters.pop_back(); prevletters.pop_back();
} }
} }
if (letters[charPos].size() == 0) if (letters[charPos].size() == 0)
{ {
// No letters for this char position... // No letters for this char position...
@@ -465,8 +465,8 @@ void PostProcess::findAllPermutations(vector<Letter> prevletters, int charPos, i
findAllPermutations(prevletters, charPos + 1, substitutionsLeft); findAllPermutations(prevletters, charPos + 1, substitutionsLeft);
} }
} }
@@ -491,7 +491,7 @@ RegexRule::RegexRule(string region, string pattern)
{ {
this->original = pattern; this->original = pattern;
this->region = region; this->region = region;
numchars = 0; numchars = 0;
for (int i = 0; i < pattern.size(); i++) for (int i = 0; i < pattern.size(); i++)
{ {
@@ -503,7 +503,7 @@ RegexRule::RegexRule(string region, string pattern)
i++; i++;
} }
this->regex = this->regex + ']'; this->regex = this->regex + ']';
} }
else if (pattern.at(i) == '?') else if (pattern.at(i) == '?')
{ {
@@ -518,12 +518,12 @@ RegexRule::RegexRule(string region, string pattern)
{ {
this->regex = this->regex + "\\d"; this->regex = this->regex + "\\d";
} }
numchars++; numchars++;
} }
trexp.Compile(this->regex.c_str()); trexp.Compile(this->regex.c_str());
//cout << "AA " << this->region << ": " << original << " regex: " << regex << endl; //cout << "AA " << this->region << ": " << original << " regex: " << regex << endl;
//for (int z = 0; z < this->skipPositions.size(); z++) //for (int z = 0; z < this->skipPositions.size(); z++)
// cout << "AA Skip position: " << skipPositions[z] << endl; // cout << "AA Skip position: " << skipPositions[z] << endl;
@@ -534,7 +534,7 @@ bool RegexRule::match(string text)
{ {
if (text.length() != numchars) if (text.length() != numchars)
return false; return false;
return trexp.Match(text.c_str()); return trexp.Match(text.c_str());
} }
@@ -552,10 +552,10 @@ string RegexRule::filterSkips(string text)
break; break;
} }
} }
if (skip == false) if (skip == false)
response = response + text[i]; response = response + text[i];
} }
return response; return response;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -35,7 +35,7 @@ using namespace std;
#define SKIP_CHAR '~' #define SKIP_CHAR '~'
struct Letter struct Letter
{ {
char letter; char letter;
int charposition; int charposition;
@@ -60,10 +60,10 @@ class RegexRule
public: public:
RegexRule(string region, string pattern); RegexRule(string region, string pattern);
bool match(string text); bool match(string text);
string filterSkips(string text); string filterSkips(string text);
private: private:
int numchars; int numchars;
TRexpp trexp; TRexpp trexp;
@@ -79,34 +79,34 @@ class PostProcess
public: public:
PostProcess(Config* config); PostProcess(Config* config);
~PostProcess(); ~PostProcess();
void addLetter(char letter, int charposition, float score); void addLetter(char letter, int charposition, float score);
void clear(); void clear();
void analyze(string templateregion, int topn); void analyze(string templateregion, int topn);
string bestChars; string bestChars;
bool matchesTemplate; bool matchesTemplate;
const vector<PPResult> getResults(); const vector<PPResult> getResults();
private: private:
Config* config; Config* config;
//void getTopN(); //void getTopN();
void findAllPermutations(vector<Letter> prevletters, int charPos, int substitutionsLeft); void findAllPermutations(vector<Letter> prevletters, int charPos, int substitutionsLeft);
void insertLetter(char letter, int charPosition, float score); void insertLetter(char letter, int charPosition, float score);
map<string, vector<RegexRule*> > rules; map<string, vector<RegexRule*> > rules;
float calculateMaxConfidenceScore(); float calculateMaxConfidenceScore();
vector<vector<Letter> > letters; vector<vector<Letter> > letters;
vector<int> unknownCharPositions; vector<int> unknownCharPositions;
vector<PPResult> allPossibilities; vector<PPResult> allPossibilities;
// Functions used to prune the list of letters (based on topn) to improve performance // Functions used to prune the list of letters (based on topn) to improve performance
vector<int> getMaxDepth(int topn); vector<int> getMaxDepth(int topn);
int getPermutationCount(vector<int> depth); int getPermutationCount(vector<int> depth);
@@ -118,18 +118,18 @@ class LetterScores
{ {
public: public:
LetterScores(int numCharPositions); LetterScores(int numCharPositions);
void addScore(char letter, int charposition, float score); void addScore(char letter, int charposition, float score);
vector<char> getBestScore(); vector<char> getBestScore();
float getConfidence(); float getConfidence();
private: private:
int numCharPositions; int numCharPositions;
vector<char> letters; vector<char> letters;
vector<int> charpositions; vector<int> charpositions;
vector<float> scores; vector<float> scores;
}; };
*/ */
#endif // POSTPROCESS_H #endif // POSTPROCESS_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -27,18 +27,18 @@ RegionDetector::RegionDetector(Config* config)
this->config = config; this->config = config;
// Don't scale. Can change this in the future (i.e., maximum resolution preference, or some such). // Don't scale. Can change this in the future (i.e., maximum resolution preference, or some such).
this->scale_factor = 1.0f; this->scale_factor = 1.0f;
// Load either the regular or OpenCL version of the cascade classifier // Load either the regular or OpenCL version of the cascade classifier
if (config->opencl_enabled) if (config->opencl_enabled)
{ {
this->plate_cascade = new ocl::OclCascadeClassifier(); this->plate_cascade = new ocl::OclCascadeClassifier();
} }
else else
{ {
this->plate_cascade = new CascadeClassifier(); this->plate_cascade = new CascadeClassifier();
} }
if( this->plate_cascade->load( config->getCascadeRuntimeDir() + config->country + ".xml" ) ) if( this->plate_cascade->load( config->getCascadeRuntimeDir() + config->country + ".xml" ) )
{ {
this->loaded = true; this->loaded = true;
@@ -46,11 +46,11 @@ RegionDetector::RegionDetector(Config* config)
else else
{ {
this->loaded = false; this->loaded = false;
printf("--(!)Error loading classifier\n"); printf("--(!)Error loading classifier\n");
} }
} }
RegionDetector::~RegionDetector() RegionDetector::~RegionDetector()
@@ -68,10 +68,10 @@ bool RegionDetector::isLoaded()
vector<Rect> RegionDetector::detect(Mat frame) vector<Rect> RegionDetector::detect(Mat frame)
{ {
Mat frame_gray; Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY ); cvtColor( frame, frame_gray, CV_BGR2GRAY );
vector<Rect> regionsOfInterest = doCascade(frame_gray); vector<Rect> regionsOfInterest = doCascade(frame_gray);
return regionsOfInterest; return regionsOfInterest;
@@ -84,19 +84,19 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
//float scale_factor = 1; //float scale_factor = 1;
int w = frame.size().width; int w = frame.size().width;
int h = frame.size().height; int h = frame.size().height;
vector<Rect> plates; vector<Rect> plates;
equalizeHist( frame, frame ); equalizeHist( frame, frame );
resize(frame, frame, Size(w * this->scale_factor, h * this->scale_factor)); resize(frame, frame, Size(w * this->scale_factor, h * this->scale_factor));
//-- Detect plates //-- Detect plates
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
Size minSize(config->minPlateSizeWidthPx * this->scale_factor, config->minPlateSizeHeightPx * this->scale_factor); Size minSize(config->minPlateSizeWidthPx * this->scale_factor, config->minPlateSizeHeightPx * this->scale_factor);
Size maxSize(w * config->maxPlateWidthPercent * this->scale_factor, h * config->maxPlateHeightPercent * this->scale_factor); Size maxSize(w * config->maxPlateWidthPercent * this->scale_factor, h * config->maxPlateHeightPercent * this->scale_factor);
if (config->opencl_enabled) if (config->opencl_enabled)
{ {
ocl::oclMat openclFrame(frame); ocl::oclMat openclFrame(frame);
@@ -104,14 +104,14 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
} }
else else
{ {
plate_cascade->detectMultiScale( frame, plates, 1.1, 3, plate_cascade->detectMultiScale( frame, plates, 1.1, 3,
0, 0,
//0|CV_HAAR_SCALE_IMAGE, //0|CV_HAAR_SCALE_IMAGE,
minSize, maxSize ); minSize, maxSize );
} }
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
@@ -120,15 +120,15 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
} }
for( int i = 0; i < plates.size(); i++ ) for( int i = 0; i < plates.size(); i++ )
{ {
plates[i].x = plates[i].x / scale_factor; plates[i].x = plates[i].x / scale_factor;
plates[i].y = plates[i].y / scale_factor; plates[i].y = plates[i].y / scale_factor;
plates[i].width = plates[i].width / scale_factor; plates[i].width = plates[i].width / scale_factor;
plates[i].height = plates[i].height / scale_factor; plates[i].height = plates[i].height / scale_factor;
} }
return plates; return plates;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -25,7 +25,7 @@
#include <iostream> #include <iostream>
#include <stdio.h> #include <stdio.h>
#include "opencv2/objdetect/objdetect.hpp" #include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp" #include "opencv2/core/core.hpp"
@@ -36,10 +36,10 @@
#include "support/timing.h" #include "support/timing.h"
#include "constants.h" #include "constants.h"
class RegionDetector class RegionDetector
{ {
@@ -52,17 +52,17 @@ class RegionDetector
private: private:
Config* config; Config* config;
float scale_factor; float scale_factor;
CascadeClassifier* plate_cascade; CascadeClassifier* plate_cascade;
bool loaded; bool loaded;
vector<Rect> doCascade(Mat frame); vector<Rect> doCascade(Mat frame);
}; };
#endif // REGIONDETECTOR_H #endif // REGIONDETECTOR_H

View File

@@ -4,5 +4,5 @@ set(simpleini_source_files
ConvertUTF.c ConvertUTF.c
) )
add_library(simpleini ${simpleini_source_files}) add_library(simpleini ${simpleini_source_files})

View File

@@ -1,8 +1,8 @@
/* /*
* Copyright 2001-2004 Unicode, Inc. * Copyright 2001-2004 Unicode, Inc.
* *
* Disclaimer * Disclaimer
* *
* This source code is provided as is by Unicode, Inc. No claims are * This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any * made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine * kind are expressed or implied. The recipient agrees to determine
@@ -10,9 +10,9 @@
* purchased on magnetic or optical media from Unicode, Inc., the * purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media * sole remedy for any claim will be exchange of defective media
* within 90 days of receipt. * within 90 days of receipt.
* *
* Limitations on Rights to Redistribute This Code * Limitations on Rights to Redistribute This Code
* *
* Unicode, Inc. hereby grants the right to freely use the information * Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the * supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form * Unicode Standard, and to make copies of this file in any form
@@ -59,7 +59,7 @@ static const UTF32 halfMask = 0x3FFUL;
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF16 ( ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd, const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK; ConversionResult result = conversionOK;
const UTF32* source = *sourceStart; const UTF32* source = *sourceStart;
@@ -108,7 +108,7 @@ ConversionResult ConvertUTF32toUTF16 (
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF32 ( ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd, const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK; ConversionResult result = conversionOK;
const UTF16* source = *sourceStart; const UTF16* source = *sourceStart;
@@ -187,7 +187,7 @@ static const char trailingBytesForUTF8[256] = {
* This table contains as many values as there might be trailing bytes * This table contains as many values as there might be trailing bytes
* in a UTF-8 sequence. * in a UTF-8 sequence.
*/ */
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL }; 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
/* /*
@@ -212,7 +212,7 @@ static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF8 ( ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd, const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK; ConversionResult result = conversionOK;
const UTF16* source = *sourceStart; const UTF16* source = *sourceStart;
@@ -221,7 +221,7 @@ ConversionResult ConvertUTF16toUTF8 (
UTF32 ch; UTF32 ch;
unsigned short bytesToWrite = 0; unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF; const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80; const UTF32 byteMark = 0x80;
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++; ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */ /* If we have a surrogate pair, convert to UTF32 first. */
@@ -334,7 +334,7 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF16 ( ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd, const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK; ConversionResult result = conversionOK;
const UTF8* source = *sourceStart; const UTF8* source = *sourceStart;
@@ -407,7 +407,7 @@ ConversionResult ConvertUTF8toUTF16 (
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF8 ( ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd, const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK; ConversionResult result = conversionOK;
const UTF32* source = *sourceStart; const UTF32* source = *sourceStart;
@@ -416,7 +416,7 @@ ConversionResult ConvertUTF32toUTF8 (
UTF32 ch; UTF32 ch;
unsigned short bytesToWrite = 0; unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF; const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80; const UTF32 byteMark = 0x80;
ch = *source++; ch = *source++;
if (flags == strictConversion ) { if (flags == strictConversion ) {
/* UTF-16 surrogate values are illegal in UTF-32 */ /* UTF-16 surrogate values are illegal in UTF-32 */
@@ -438,7 +438,7 @@ ConversionResult ConvertUTF32toUTF8 (
ch = UNI_REPLACEMENT_CHAR; ch = UNI_REPLACEMENT_CHAR;
result = sourceIllegal; result = sourceIllegal;
} }
target += bytesToWrite; target += bytesToWrite;
if (target > targetEnd) { if (target > targetEnd) {
--source; /* Back up source pointer! */ --source; /* Back up source pointer! */
@@ -460,7 +460,7 @@ ConversionResult ConvertUTF32toUTF8 (
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF32 ( ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd, const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK; ConversionResult result = conversionOK;
const UTF8* source = *sourceStart; const UTF8* source = *sourceStart;

View File

@@ -1,8 +1,8 @@
/* /*
* Copyright 2001-2004 Unicode, Inc. * Copyright 2001-2004 Unicode, Inc.
* *
* Disclaimer * Disclaimer
* *
* This source code is provided as is by Unicode, Inc. No claims are * This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any * made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine * kind are expressed or implied. The recipient agrees to determine
@@ -10,9 +10,9 @@
* purchased on magnetic or optical media from Unicode, Inc., the * purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media * sole remedy for any claim will be exchange of defective media
* within 90 days of receipt. * within 90 days of receipt.
* *
* Limitations on Rights to Redistribute This Code * Limitations on Rights to Redistribute This Code
* *
* Unicode, Inc. hereby grants the right to freely use the information * Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the * supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form * Unicode Standard, and to make copies of this file in any form
@@ -33,7 +33,7 @@
Each routine converts the text between *sourceStart and sourceEnd, Each routine converts the text between *sourceStart and sourceEnd,
putting the result into the buffer between *targetStart and putting the result into the buffer between *targetStart and
targetEnd. Note: the end pointers are *after* the last item: e.g. targetEnd. Note: the end pointers are *after* the last item: e.g.
*(sourceEnd - 1) is the last item. *(sourceEnd - 1) is the last item.
The return result indicates whether the conversion was successful, The return result indicates whether the conversion was successful,
@@ -71,7 +71,7 @@
sequence is malformed. When "sourceIllegal" is returned, the source sequence is malformed. When "sourceIllegal" is returned, the source
value will point to the illegal value that caused the problem. E.g., value will point to the illegal value that caused the problem. E.g.,
in UTF-8 when a sequence is malformed, it points to the start of the in UTF-8 when a sequence is malformed, it points to the start of the
malformed sequence. malformed sequence.
Author: Mark E. Davis, 1994. Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001. Rev History: Rick McGowan, fixes & updates May 2001.
@@ -117,27 +117,27 @@ extern "C" {
#endif #endif
ConversionResult ConvertUTF8toUTF16 ( ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd, const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF8 ( ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd, const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF8toUTF32 ( ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd, const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF8 ( ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd, const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF32 ( ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd, const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF16 ( ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd, const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);

View File

@@ -78,14 +78,14 @@ ini.GetAllKeys("section-name", keys);
```c++ ```c++
// get the value of a key // get the value of a key
const char * pszValue = ini.GetValue("section-name", const char * pszValue = ini.GetValue("section-name",
"key-name", NULL /*default*/); "key-name", NULL /*default*/);
// get the value of a key which may have multiple // get the value of a key which may have multiple
// values. If bHasMultipleValues is true, then just // values. If bHasMultipleValues is true, then just
// one value has been returned // one value has been returned
bool bHasMultipleValues; bool bHasMultipleValues;
pszValue = ini.GetValue("section-name", "key-name", pszValue = ini.GetValue("section-name", "key-name",
NULL /*default*/, &amp;bHasMultipleValues); NULL /*default*/, &amp;bHasMultipleValues);
// get all values of a key with multiple values // get all values of a key with multiple values
@@ -97,7 +97,7 @@ values.sort(CSimpleIniA::Entry::LoadOrder());
// output all of the items // output all of the items
CSimpleIniA::TNamesDepend::const_iterator i; CSimpleIniA::TNamesDepend::const_iterator i;
for (i = values.begin(); i != values.end(); ++i) { for (i = values.begin(); i != values.end(); ++i) {
printf("key-name = '%s'\n", i->pItem); printf("key-name = '%s'\n", i->pItem);
} }
``` ```
@@ -108,20 +108,20 @@ for (i = values.begin(); i != values.end(); ++i) {
// adding a new section // adding a new section
rc = ini.SetValue("new-section", NULL, NULL); rc = ini.SetValue("new-section", NULL, NULL);
if (rc < 0) return false; if (rc < 0) return false;
printf("section: %s\n", rc == SI_INSERTED ? printf("section: %s\n", rc == SI_INSERTED ?
"inserted" : "updated"); "inserted" : "updated");
// adding a new key ("new-section" will be added // adding a new key ("new-section" will be added
// automatically if it doesn't already exist) // automatically if it doesn't already exist)
rc = ini.SetValue("new-section", "new-key", "value"); rc = ini.SetValue("new-section", "new-key", "value");
if (rc < 0) return false; if (rc < 0) return false;
printf("key: %s\n", rc == SI_INSERTED ? printf("key: %s\n", rc == SI_INSERTED ?
"inserted" : "updated"); "inserted" : "updated");
// changing the value of a key // changing the value of a key
rc = ini.SetValue("section", "key", "updated-value"); rc = ini.SetValue("section", "key", "updated-value");
if (rc < 0) return false; if (rc < 0) return false;
printf("key: %s\n", rc == SI_INSERTED ? printf("key: %s\n", rc == SI_INSERTED ?
"inserted" : "updated"); "inserted" : "updated");
``` ```
@@ -130,7 +130,7 @@ printf("key: %s\n", rc == SI_INSERTED ?
```c++ ```c++
// deleting a key from a section. Optionally the entire // deleting a key from a section. Optionally the entire
// section may be deleted if it is now empty. // section may be deleted if it is now empty.
ini.Delete("section-name", "key-name", ini.Delete("section-name", "key-name",
true /*delete the section if empty*/); true /*delete the section if empty*/);
// deleting an entire section and all keys in it // deleting an entire section and all keys in it

View File

@@ -1,5 +1,5 @@
; Syntax file for ini files - contributed by Brodie Thiesfield ; Syntax file for ini files - contributed by Brodie Thiesfield
; ;
; Suggested Colors: ; Suggested Colors:
; Comments (;#) Comments, Comments 2 Green ; Comments (;#) Comments, Comments 2 Green
; Sections Characters Red ; Sections Characters Red
@@ -13,24 +13,24 @@ IgnoreCase = Yes
KeyWordLength = 1 KeyWordLength = 1
BracketChars = BracketChars =
OperatorChars = OperatorChars =
PreprocStart = PreprocStart =
SyntaxStart = SyntaxStart =
SyntaxEnd = SyntaxEnd =
HexPrefix = HexPrefix =
CommentStart = CommentStart =
CommentEnd = CommentEnd =
CommentStartAlt = CommentStartAlt =
CommentEndAlt = CommentEndAlt =
SingleComment = # SingleComment = #
SingleCommentCol = SingleCommentCol =
SingleCommentAlt = ; SingleCommentAlt = ;
SingleCommentColAlt = SingleCommentColAlt =
SingleCommentEsc = SingleCommentEsc =
StringsSpanLines = No StringsSpanLines = No
StringStart = StringStart =
StringEnd = StringEnd =
StringAlt = = StringAlt = =
StringEsc = StringEsc =
CharStart = [ CharStart = [
CharEnd = ] CharEnd = ]
CharEsc = CharEsc =

File diff suppressed because it is too large Load Diff

View File

@@ -163,7 +163,7 @@
SI_NO_MBCS. This is defined automatically on Windows CE platforms. SI_NO_MBCS. This is defined automatically on Windows CE platforms.
@section contrib CONTRIBUTIONS @section contrib CONTRIBUTIONS
- 2010/05/03: Tobias Gehrig: added GetDoubleValue() - 2010/05/03: Tobias Gehrig: added GetDoubleValue()
@section licence MIT LICENCE @section licence MIT LICENCE
@@ -530,7 +530,7 @@ public:
bool IsMultiLine() const { return m_bAllowMultiLine; } bool IsMultiLine() const { return m_bAllowMultiLine; }
/** Should spaces be added around the equals sign when writing key/value /** Should spaces be added around the equals sign when writing key/value
pairs out. When true, the result will be "key = value". When false, pairs out. When true, the result will be "key = value". When false,
the result will be "key=value". This value may be changed at any time. the result will be "key=value". This value may be changed at any time.
\param a_bSpaces Add spaces around the equals sign? \param a_bSpaces Add spaces around the equals sign?
@@ -541,7 +541,7 @@ public:
/** Query the status of spaces output */ /** Query the status of spaces output */
bool UsingSpaces() const { return m_bSpaces; } bool UsingSpaces() const { return m_bSpaces; }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/** @} /** @}
@{ @name Loading INI Data */ @{ @name Loading INI Data */
@@ -771,8 +771,8 @@ public:
) const; ) const;
/** Retrieve all unique key names in a section. The sort order of the /** Retrieve all unique key names in a section. The sort order of the
returned strings is NOT DEFINED. You can sort the names into the load returned strings is NOT DEFINED. You can sort the names into the load
order if desired. Search this file for ".sort" for an example. Only order if desired. Search this file for ".sort" for an example. Only
unique key names are returned. unique key names are returned.
NOTE! This structure contains only pointers to strings. The actual NOTE! This structure contains only pointers to strings. The actual
@@ -793,8 +793,8 @@ public:
) const; ) const;
/** Retrieve all values for a specific key. This method can be used when /** Retrieve all values for a specific key. This method can be used when
multiple keys are both enabled and disabled. Note that the sort order multiple keys are both enabled and disabled. Note that the sort order
of the returned strings is NOT DEFINED. You can sort the names into of the returned strings is NOT DEFINED. You can sort the names into
the load order if desired. Search this file for ".sort" for an example. the load order if desired. Search this file for ".sort" for an example.
NOTE! The returned values are pointers to string data stored in memory NOTE! The returned values are pointers to string data stored in memory
@@ -915,7 +915,7 @@ public:
Strings starting with "t", "y", "on" or "1" are returned as logically true. Strings starting with "t", "y", "on" or "1" are returned as logically true.
Strings starting with "f", "n", "of" or "0" are returned as logically false. Strings starting with "f", "n", "of" or "0" are returned as logically false.
For all other values the default is returned. Character comparisons are For all other values the default is returned. Character comparisons are
case-insensitive. case-insensitive.
@param a_pSection Section to search @param a_pSection Section to search
@@ -954,9 +954,9 @@ public:
character starting every line). character starting every line).
@param a_bForceReplace Should all existing values in a multi-key INI @param a_bForceReplace Should all existing values in a multi-key INI
file be replaced with this entry. This option has file be replaced with this entry. This option has
no effect if not using multi-key files. The no effect if not using multi-key files. The
difference between Delete/SetValue and SetValue difference between Delete/SetValue and SetValue
with a_bForceReplace = true, is that the load with a_bForceReplace = true, is that the load
order and comment will be preserved this way. order and comment will be preserved this way.
@return SI_Error See error definitions @return SI_Error See error definitions
@@ -978,19 +978,19 @@ public:
when multiple keys are enabled. when multiple keys are enabled.
@param a_pSection Section to add or update @param a_pSection Section to add or update
@param a_pKey Key to add or update. @param a_pKey Key to add or update.
@param a_nValue Value to set. @param a_nValue Value to set.
@param a_pComment Comment to be associated with the key. See the @param a_pComment Comment to be associated with the key. See the
notes on SetValue() for comments. notes on SetValue() for comments.
@param a_bUseHex By default the value will be written to the file @param a_bUseHex By default the value will be written to the file
in decimal format. Set this to true to write it in decimal format. Set this to true to write it
as hexadecimal. as hexadecimal.
@param a_bForceReplace Should all existing values in a multi-key INI @param a_bForceReplace Should all existing values in a multi-key INI
file be replaced with this entry. This option has file be replaced with this entry. This option has
no effect if not using multi-key files. The no effect if not using multi-key files. The
difference between Delete/SetLongValue and difference between Delete/SetLongValue and
SetLongValue with a_bForceReplace = true, is that SetLongValue with a_bForceReplace = true, is that
the load order and comment will be preserved this the load order and comment will be preserved this
way. way.
@return SI_Error See error definitions @return SI_Error See error definitions
@@ -1010,16 +1010,16 @@ public:
when multiple keys are enabled. when multiple keys are enabled.
@param a_pSection Section to add or update @param a_pSection Section to add or update
@param a_pKey Key to add or update. @param a_pKey Key to add or update.
@param a_nValue Value to set. @param a_nValue Value to set.
@param a_pComment Comment to be associated with the key. See the @param a_pComment Comment to be associated with the key. See the
notes on SetValue() for comments. notes on SetValue() for comments.
@param a_bForceReplace Should all existing values in a multi-key INI @param a_bForceReplace Should all existing values in a multi-key INI
file be replaced with this entry. This option has file be replaced with this entry. This option has
no effect if not using multi-key files. The no effect if not using multi-key files. The
difference between Delete/SetDoubleValue and difference between Delete/SetDoubleValue and
SetDoubleValue with a_bForceReplace = true, is that SetDoubleValue with a_bForceReplace = true, is that
the load order and comment will be preserved this the load order and comment will be preserved this
way. way.
@return SI_Error See error definitions @return SI_Error See error definitions
@@ -1038,16 +1038,16 @@ public:
when multiple keys are enabled. when multiple keys are enabled.
@param a_pSection Section to add or update @param a_pSection Section to add or update
@param a_pKey Key to add or update. @param a_pKey Key to add or update.
@param a_bValue Value to set. @param a_bValue Value to set.
@param a_pComment Comment to be associated with the key. See the @param a_pComment Comment to be associated with the key. See the
notes on SetValue() for comments. notes on SetValue() for comments.
@param a_bForceReplace Should all existing values in a multi-key INI @param a_bForceReplace Should all existing values in a multi-key INI
file be replaced with this entry. This option has file be replaced with this entry. This option has
no effect if not using multi-key files. The no effect if not using multi-key files. The
difference between Delete/SetBoolValue and difference between Delete/SetBoolValue and
SetBoolValue with a_bForceReplace = true, is that SetBoolValue with a_bForceReplace = true, is that
the load order and comment will be preserved this the load order and comment will be preserved this
way. way.
@return SI_Error See error definitions @return SI_Error See error definitions
@@ -1141,9 +1141,9 @@ private:
comment character starting every line). comment character starting every line).
@param a_bForceReplace Should all existing values in a multi-key INI @param a_bForceReplace Should all existing values in a multi-key INI
file be replaced with this entry. This option has file be replaced with this entry. This option has
no effect if not using multi-key files. The no effect if not using multi-key files. The
difference between Delete/AddEntry and AddEntry difference between Delete/AddEntry and AddEntry
with a_bForceReplace = true, is that the load with a_bForceReplace = true, is that the load
order and comment will be preserved this way. order and comment will be preserved this way.
@param a_bCopyStrings Should copies of the strings be made or not. @param a_bCopyStrings Should copies of the strings be made or not.
If false then the pointers will be used as is. If false then the pointers will be used as is.
@@ -1238,7 +1238,7 @@ private:
/** Should spaces be written out surrounding the equals sign? */ /** Should spaces be written out surrounding the equals sign? */
bool m_bSpaces; bool m_bSpaces;
/** Next order value, used to ensure sections and keys are output in the /** Next order value, used to ensure sections and keys are output in the
same order that they are loaded/added. same order that they are loaded/added.
*/ */
@@ -1358,14 +1358,14 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadFile(
if (lSize == 0) { if (lSize == 0) {
return SI_OK; return SI_OK;
} }
// allocate and ensure NULL terminated // allocate and ensure NULL terminated
char * pData = new char[lSize+1]; char * pData = new char[lSize+1];
if (!pData) { if (!pData) {
return SI_NOMEM; return SI_NOMEM;
} }
pData[lSize] = 0; pData[lSize] = 0;
// load data into buffer // load data into buffer
fseek(a_fpFile, 0, SEEK_SET); fseek(a_fpFile, 0, SEEK_SET);
size_t uRead = fread(pData, sizeof(char), lSize, a_fpFile); size_t uRead = fread(pData, sizeof(char), lSize, a_fpFile);
@@ -2018,15 +2018,15 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetLongValue(
} }
// any invalid strings will return the default value // any invalid strings will return the default value
if (*pszSuffix) { if (*pszSuffix) {
return a_nDefault; return a_nDefault;
} }
return nValue; return nValue;
} }
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER> template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
SI_Error SI_Error
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetLongValue( CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetLongValue(
const SI_CHAR * a_pSection, const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey, const SI_CHAR * a_pKey,
@@ -2050,7 +2050,7 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetLongValue(
// convert to output text // convert to output text
SI_CHAR szOutput[64]; SI_CHAR szOutput[64];
SI_CONVERTER c(m_bStoreIsUtf8); SI_CONVERTER c(m_bStoreIsUtf8);
c.ConvertFromStore(szInput, strlen(szInput) + 1, c.ConvertFromStore(szInput, strlen(szInput) + 1,
szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
// actually add it // actually add it
@@ -2081,15 +2081,15 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetDoubleValue(
double nValue = strtod(szValue, &pszSuffix); double nValue = strtod(szValue, &pszSuffix);
// any invalid strings will return the default value // any invalid strings will return the default value
if (!pszSuffix || *pszSuffix) { if (!pszSuffix || *pszSuffix) {
return a_nDefault; return a_nDefault;
} }
return nValue; return nValue;
} }
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER> template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
SI_Error SI_Error
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetDoubleValue( CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetDoubleValue(
const SI_CHAR * a_pSection, const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey, const SI_CHAR * a_pKey,
@@ -2112,7 +2112,7 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetDoubleValue(
// convert to output text // convert to output text
SI_CHAR szOutput[64]; SI_CHAR szOutput[64];
SI_CONVERTER c(m_bStoreIsUtf8); SI_CONVERTER c(m_bStoreIsUtf8);
c.ConvertFromStore(szInput, strlen(szInput) + 1, c.ConvertFromStore(szInput, strlen(szInput) + 1,
szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
// actually add it // actually add it
@@ -2155,7 +2155,7 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetBoolValue(
} }
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER> template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
SI_Error SI_Error
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetBoolValue( CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetBoolValue(
const SI_CHAR * a_pSection, const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey, const SI_CHAR * a_pKey,
@@ -2173,13 +2173,13 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetBoolValue(
// convert to output text // convert to output text
SI_CHAR szOutput[64]; SI_CHAR szOutput[64];
SI_CONVERTER c(m_bStoreIsUtf8); SI_CONVERTER c(m_bStoreIsUtf8);
c.ConvertFromStore(pszInput, strlen(pszInput) + 1, c.ConvertFromStore(pszInput, strlen(pszInput) + 1,
szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
// actually add it // actually add it
return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true);
} }
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER> template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
bool bool
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetAllValues( CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetAllValues(
@@ -3383,4 +3383,3 @@ typedef CSimpleIniTempl<wchar_t,
#endif #endif
#endif // INCLUDED_SimpleIni_h #endif // INCLUDED_SimpleIni_h

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -23,15 +23,15 @@
StateIdentifier::StateIdentifier(Config* config) StateIdentifier::StateIdentifier(Config* config)
{ {
this->config = config; this->config = config;
featureMatcher = new FeatureMatcher(config); featureMatcher = new FeatureMatcher(config);
if (featureMatcher->isLoaded() == false) if (featureMatcher->isLoaded() == false)
{ {
cout << "Can not create detector or descriptor extractor or descriptor matcher of given types" << endl; cout << "Can not create detector or descriptor extractor or descriptor matcher of given types" << endl;
return; return;
} }
featureMatcher->loadRecognitionSet(config->country); featureMatcher->loadRecognitionSet(config->country);
} }
@@ -43,56 +43,55 @@ StateIdentifier::~StateIdentifier()
int StateIdentifier::recognize(Mat img, Rect frame, char* stateCode) int StateIdentifier::recognize(Mat img, Rect frame, char* stateCode)
{ {
Mat croppedImage = Mat(img, frame); Mat croppedImage = Mat(img, frame);
return this->recognize(croppedImage, stateCode); return this->recognize(croppedImage, stateCode);
} }
// Attempts to recognize the plate. Returns a confidence level. Updates teh "stateCode" variable // Attempts to recognize the plate. Returns a confidence level. Updates teh "stateCode" variable
// with the value of the country/state // with the value of the country/state
int StateIdentifier::recognize(Mat img, char* stateCode) int StateIdentifier::recognize(Mat img, char* stateCode)
{ {
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
cvtColor(img, img, CV_BGR2GRAY); cvtColor(img, img, CV_BGR2GRAY);
resize(img, img, getSizeMaintainingAspect(img, config->stateIdImageWidthPx, config->stateIdimageHeightPx)); resize(img, img, getSizeMaintainingAspect(img, config->stateIdImageWidthPx, config->stateIdimageHeightPx));
Mat plateImg(img.size(), img.type()); Mat plateImg(img.size(), img.type());
//plateImg = equalizeBrightness(img); //plateImg = equalizeBrightness(img);
img.copyTo(plateImg); img.copyTo(plateImg);
Mat debugImg(plateImg.size(), plateImg.type()); Mat debugImg(plateImg.size(), plateImg.type());
plateImg.copyTo(debugImg); plateImg.copyTo(debugImg);
vector<int> matchesArray(featureMatcher->numTrainingElements()); vector<int> matchesArray(featureMatcher->numTrainingElements());
RecognitionResult result = featureMatcher->recognize(plateImg, true, &debugImg, true, matchesArray ); RecognitionResult result = featureMatcher->recognize(plateImg, true, &debugImg, true, matchesArray );
if (this->config->debugStateId) if (this->config->debugStateId)
{ {
displayImage(config, "State Identifier1", plateImg); displayImage(config, "State Identifier1", plateImg);
displayImage(config, "State Identifier", debugImg); displayImage(config, "State Identifier", debugImg);
cout << result.haswinner << " : " << result.confidence << " : " << result.winner << endl; cout << result.haswinner << " : " << result.confidence << " : " << result.winner << endl;
} }
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
getTime(&endTime); getTime(&endTime);
cout << "State Identification Time: " << diffclock(startTime, endTime) << "ms." << endl; cout << "State Identification Time: " << diffclock(startTime, endTime) << "ms." << endl;
} }
if (result.haswinner == false) if (result.haswinner == false)
return 0; return 0;
strcpy(stateCode, result.winner.c_str()); strcpy(stateCode, result.winner.c_str());
return result.confidence; return result.confidence;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -39,20 +39,18 @@ class StateIdentifier
int recognize(Mat img, Rect frame, char* stateCode); int recognize(Mat img, Rect frame, char* stateCode);
int recognize(Mat img, char* stateCode); int recognize(Mat img, char* stateCode);
//int confidence; //int confidence;
protected: protected:
Config* config; Config* config;
private: private:
FeatureMatcher* featureMatcher; FeatureMatcher* featureMatcher;
}; };
#endif // STATEIDENTIFIER_H #endif // STATEIDENTIFIER_H

View File

@@ -5,5 +5,5 @@ set(support_source_files
timing.cpp timing.cpp
) )
add_library(support ${support_source_files}) add_library(support ${support_source_files})

View File

@@ -22,7 +22,7 @@ bool DirectoryExists( const char* pzPath )
if (pDir != NULL) if (pDir != NULL)
{ {
bExists = true; bExists = true;
(void) closedir (pDir); (void) closedir (pDir);
} }
@@ -34,7 +34,7 @@ bool fileExists( const char* pzPath )
if (pzPath == NULL) return false; if (pzPath == NULL) return false;
bool fExists = false; bool fExists = false;
std::ifstream f(pzPath); std::ifstream f(pzPath);
fExists = f.is_open(); fExists = f.is_open();
f.close(); f.close();
return fExists; return fExists;
@@ -43,9 +43,9 @@ bool fileExists( const char* pzPath )
std::vector<std::string> getFilesInDir(const char* dirPath) std::vector<std::string> getFilesInDir(const char* dirPath)
{ {
DIR *dir; DIR *dir;
std::vector<std::string> files; std::vector<std::string> files;
struct dirent *ent; struct dirent *ent;
if ((dir = opendir (dirPath)) != NULL) { if ((dir = opendir (dirPath)) != NULL) {
/* print all the files and directories within directory */ /* print all the files and directories within directory */
@@ -59,7 +59,7 @@ std::vector<std::string> getFilesInDir(const char* dirPath)
perror (""); perror ("");
return files; return files;
} }
return files; return files;
} }
@@ -73,4 +73,4 @@ bool stringCompare( const std::string &left, const std::string &right ){
if( left.size() < right.size() ) if( left.size() < right.size() )
return true; return true;
return false; return false;
} }

View File

@@ -23,8 +23,8 @@
bool DirectoryExists( const char* pzPath ); bool DirectoryExists( const char* pzPath );
bool fileExists( const char* pzPath ); bool fileExists( const char* pzPath );
std::vector<std::string> getFilesInDir(const char* dirPath); std::vector<std::string> getFilesInDir(const char* dirPath);
bool stringCompare( const std::string &left, const std::string &right ); bool stringCompare( const std::string &left, const std::string &right );
#endif // FILESYSTEM_H #endif // FILESYSTEM_H

View File

@@ -76,8 +76,8 @@ double diffclock(timespec time1,timespec time2)
{ {
timespec delta = diff(time1,time2); timespec delta = diff(time1,time2);
double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_usec) / 1000.0); double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_usec) / 1000.0);
return milliseconds; return milliseconds;
} }
@@ -116,13 +116,13 @@ void getTime(timespec* time)
} }
double diffclock(timespec time1,timespec time2) double diffclock(timespec time1,timespec time2)
{ {
timespec delta = diff(time1,time2); timespec delta = diff(time1,time2);
double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_nsec) / 1000000.0); double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_nsec) / 1000000.0);
return milliseconds; return milliseconds;
} }

View File

@@ -18,6 +18,6 @@
void getTime(timespec* time); void getTime(timespec* time);
double diffclock(timespec time1,timespec time2); double diffclock(timespec time1,timespec time2);
#endif #endif

View File

@@ -33,7 +33,7 @@
* capital W) in order to maintain compatibility with MingW. * capital W) in order to maintain compatibility with MingW.
* *
* Version 1.12, Sep 30 2012, Toni Ronkko * Version 1.12, Sep 30 2012, Toni Ronkko
* Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR, * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR,
* _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir(). * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir().
* Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code. * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
* *
@@ -410,11 +410,11 @@ _wreaddir(
if (datap) { if (datap) {
size_t n; size_t n;
DWORD attr; DWORD attr;
/* Pointer to directory entry to return */ /* Pointer to directory entry to return */
entp = &dirp->ent; entp = &dirp->ent;
/* /*
* Copy file name as wide-character string. If the file name is too * Copy file name as wide-character string. If the file name is too
* long to fit in to the destination buffer, then truncate file name * long to fit in to the destination buffer, then truncate file name
* to PATH_MAX characters and zero-terminate the buffer. * to PATH_MAX characters and zero-terminate the buffer.
@@ -570,12 +570,12 @@ dirent_next(
return p; return p;
} }
/* /*
* Open directory stream using plain old C-string. * Open directory stream using plain old C-string.
*/ */
static DIR* static DIR*
opendir( opendir(
const char *dirname) const char *dirname)
{ {
struct DIR *dirp; struct DIR *dirp;
int error; int error;
@@ -608,7 +608,7 @@ opendir(
} }
} else { } else {
/* /*
* Cannot convert file name to wide-character string. This * Cannot convert file name to wide-character string. This
* occurs if the string contains invalid multi-byte sequences or * occurs if the string contains invalid multi-byte sequences or
* the output buffer is too small to contain the resulting * the output buffer is too small to contain the resulting
@@ -646,7 +646,7 @@ opendir(
*/ */
static struct dirent* static struct dirent*
readdir( readdir(
DIR *dirp) DIR *dirp)
{ {
WIN32_FIND_DATAW *datap; WIN32_FIND_DATAW *datap;
struct dirent *entp; struct dirent *entp;
@@ -661,7 +661,7 @@ readdir(
error = dirent_wcstombs_s( error = dirent_wcstombs_s(
&n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH); &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
/* /*
* If the file name cannot be represented by a multi-byte string, * If the file name cannot be represented by a multi-byte string,
* then attempt to use old 8+3 file name. This allows traditional * then attempt to use old 8+3 file name. This allows traditional
* Unix-code to access some file names despite of unicode * Unix-code to access some file names despite of unicode
@@ -674,7 +674,7 @@ readdir(
if (error && datap->cAlternateFileName[0] != '\0') { if (error && datap->cAlternateFileName[0] != '\0') {
error = dirent_wcstombs_s( error = dirent_wcstombs_s(
&n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName, &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
sizeof (datap->cAlternateFileName) / sizeof (datap->cAlternateFileName) /
sizeof (datap->cAlternateFileName[0])); sizeof (datap->cAlternateFileName[0]));
} }
@@ -702,7 +702,7 @@ readdir(
entp->d_reclen = sizeof (struct dirent); entp->d_reclen = sizeof (struct dirent);
} else { } else {
/* /*
* Cannot convert file name to multi-byte string so construct * Cannot convert file name to multi-byte string so construct
* an errornous directory entry and return that. Note that * an errornous directory entry and return that. Note that
* we cannot return NULL as that would stop the processing * we cannot return NULL as that would stop the processing
@@ -730,7 +730,7 @@ readdir(
*/ */
static int static int
closedir( closedir(
DIR *dirp) DIR *dirp)
{ {
int ok; int ok;
if (dirp) { if (dirp) {
@@ -757,7 +757,7 @@ closedir(
*/ */
static void static void
rewinddir( rewinddir(
DIR* dirp) DIR* dirp)
{ {
/* Rewind wide-character string directory stream */ /* Rewind wide-character string directory stream */
_wrewinddir (dirp->wdirp); _wrewinddir (dirp->wdirp);
@@ -886,4 +886,3 @@ dirent_set_errno(
} }
#endif #endif
#endif /*DIRENT_H*/ #endif /*DIRENT_H*/

View File

@@ -1,9 +1,9 @@
#ifndef _UNISTD_H #ifndef _UNISTD_H
#define _UNISTD_H 1 #define _UNISTD_H 1
/* This file intended to serve as a drop-in replacement for /* This file intended to serve as a drop-in replacement for
* unistd.h on Windows * unistd.h on Windows
* Please add functionality as neeeded * Please add functionality as neeeded
*/ */
#include <stdlib.h> #include <stdlib.h>
@@ -31,7 +31,7 @@
#define STDERR_FILENO 2 #define STDERR_FILENO 2
/* should be in some equivalent to <sys/types.h> */ /* should be in some equivalent to <sys/types.h> */
typedef __int8 int8_t; typedef __int8 int8_t;
typedef __int16 int16_t; typedef __int16 int16_t;
typedef __int32 int32_t; typedef __int32 int32_t;
typedef __int64 int64_t; typedef __int64 int64_t;
typedef unsigned __int8 uint8_t; typedef unsigned __int8 uint8_t;
@@ -39,4 +39,4 @@ typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t; typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t; typedef unsigned __int64 uint64_t;
#endif /* unistd.h */ #endif /* unistd.h */

View File

@@ -2,6 +2,6 @@
#include <math.h> #include <math.h>
static inline double round(double val) static inline double round(double val)
{ {
return floor(val + 0.5); return floor(val + 0.5);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,67 +1,67 @@
#ifndef _TREX_H_ #ifndef _TREX_H_
#define _TREX_H_ #define _TREX_H_
/*************************************************************** /***************************************************************
T-Rex a tiny regular expression library T-Rex a tiny regular expression library
Copyright (C) 2003-2006 Alberto Demichelis Copyright (C) 2003-2006 Alberto Demichelis
This software is provided 'as-is', without any express This software is provided 'as-is', without any express
or implied warranty. In no event will the authors be held or implied warranty. In no event will the authors be held
liable for any damages arising from the use of this software. liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for Permission is granted to anyone to use this software for
any purpose, including commercial applications, and to alter any purpose, including commercial applications, and to alter
it and redistribute it freely, subject to the following restrictions: it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; 1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software. you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but in the product documentation would be appreciated but
is not required. is not required.
2. Altered source versions must be plainly marked as such, 2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software. and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any 3. This notice may not be removed or altered from any
source distribution. source distribution.
****************************************************************/ ****************************************************************/
#ifdef _UNICODE #ifdef _UNICODE
#define TRexChar unsigned short #define TRexChar unsigned short
#define MAX_CHAR 0xFFFF #define MAX_CHAR 0xFFFF
#define _TREXC(c) L##c #define _TREXC(c) L##c
#define trex_strlen wcslen #define trex_strlen wcslen
#define trex_printf wprintf #define trex_printf wprintf
#else #else
#define TRexChar char #define TRexChar char
#define MAX_CHAR 0xFF #define MAX_CHAR 0xFF
#define _TREXC(c) (c) #define _TREXC(c) (c)
#define trex_strlen strlen #define trex_strlen strlen
#define trex_printf printf #define trex_printf printf
#endif #endif
#ifndef TREX_API #ifndef TREX_API
#define TREX_API extern #define TREX_API extern
#endif #endif
#define TRex_True 1 #define TRex_True 1
#define TRex_False 0 #define TRex_False 0
typedef unsigned int TRexBool; typedef unsigned int TRexBool;
typedef struct TRex TRex; typedef struct TRex TRex;
typedef struct { typedef struct {
const TRexChar *begin; const TRexChar *begin;
int len; int len;
} TRexMatch; } TRexMatch;
TREX_API TRex *trex_compile(const TRexChar *pattern,const TRexChar **error); TREX_API TRex *trex_compile(const TRexChar *pattern,const TRexChar **error);
TREX_API void trex_free(TRex *exp); TREX_API void trex_free(TRex *exp);
TREX_API TRexBool trex_match(TRex* exp,const TRexChar* text); TREX_API TRexBool trex_match(TRex* exp,const TRexChar* text);
TREX_API TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end); TREX_API TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end);
TREX_API TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end); TREX_API TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end);
TREX_API int trex_getsubexpcount(TRex* exp); TREX_API int trex_getsubexpcount(TRex* exp);
TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp); TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp);
#endif #endif

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -26,14 +26,14 @@
Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, int maxY) Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, int maxY)
{ {
Rect expandedRegion = Rect(original); Rect expandedRegion = Rect(original);
float halfX = round((float) expandXPixels / 2.0); float halfX = round((float) expandXPixels / 2.0);
float halfY = round((float) expandYPixels / 2.0); float halfY = round((float) expandYPixels / 2.0);
expandedRegion.x = expandedRegion.x - halfX; expandedRegion.x = expandedRegion.x - halfX;
expandedRegion.width = expandedRegion.width + expandXPixels; expandedRegion.width = expandedRegion.width + expandXPixels;
expandedRegion.y = expandedRegion.y - halfY; expandedRegion.y = expandedRegion.y - halfY;
expandedRegion.height = expandedRegion.height + expandYPixels; expandedRegion.height = expandedRegion.height + expandYPixels;
if (expandedRegion.x < 0) if (expandedRegion.x < 0)
expandedRegion.x = 0; expandedRegion.x = 0;
if (expandedRegion.y < 0) if (expandedRegion.y < 0)
@@ -42,16 +42,16 @@ Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, i
expandedRegion.width = maxX - expandedRegion.x; expandedRegion.width = maxX - expandedRegion.x;
if (expandedRegion.y + expandedRegion.height > maxY) if (expandedRegion.y + expandedRegion.height > maxY)
expandedRegion.height = maxY - expandedRegion.y; expandedRegion.height = maxY - expandedRegion.y;
return expandedRegion; return expandedRegion;
} }
Mat drawImageDashboard(vector<Mat> images, int imageType, int numColumns) Mat drawImageDashboard(vector<Mat> images, int imageType, int numColumns)
{ {
int numRows = ceil((float) images.size() / (float) numColumns); int numRows = ceil((float) images.size() / (float) numColumns);
Mat dashboard(Size(images[0].cols * numColumns, images[0].rows * numRows), imageType); Mat dashboard(Size(images[0].cols * numColumns, images[0].rows * numRows), imageType);
for (int i = 0; i < numColumns * numRows; i++) for (int i = 0; i < numColumns * numRows; i++)
{ {
if (i < images.size()) if (i < images.size())
@@ -62,7 +62,7 @@ Mat drawImageDashboard(vector<Mat> images, int imageType, int numColumns)
black.copyTo(dashboard(Rect((i%numColumns) * images[0].cols, floor((float) i/numColumns) * images[0].rows, images[0].cols, images[0].rows))); black.copyTo(dashboard(Rect((i%numColumns) * images[0].cols, floor((float) i/numColumns) * images[0].rows, images[0].cols, images[0].rows)));
} }
} }
return dashboard; return dashboard;
} }
@@ -73,20 +73,20 @@ Mat addLabel(Mat input, string label)
const int extraHeight = 20; const int extraHeight = 20;
const Scalar bg(222,222,222); const Scalar bg(222,222,222);
const Scalar fg(0,0,0); const Scalar fg(0,0,0);
Rect destinationRect(border_size, extraHeight, input.cols, input.rows); Rect destinationRect(border_size, extraHeight, input.cols, input.rows);
Mat newImage(Size(input.cols + (border_size), input.rows + extraHeight + (border_size )), input.type()); Mat newImage(Size(input.cols + (border_size), input.rows + extraHeight + (border_size )), input.type());
input.copyTo(newImage(destinationRect)); input.copyTo(newImage(destinationRect));
cout << " Adding label " << label << endl; cout << " Adding label " << label << endl;
if (input.type() == CV_8U) if (input.type() == CV_8U)
cvtColor(newImage, newImage, CV_GRAY2BGR); cvtColor(newImage, newImage, CV_GRAY2BGR);
rectangle(newImage, Point(0,0), Point(input.cols, extraHeight), bg, CV_FILLED); rectangle(newImage, Point(0,0), Point(input.cols, extraHeight), bg, CV_FILLED);
putText(newImage, label, Point(5, extraHeight - 5), CV_FONT_HERSHEY_PLAIN , 0.7, fg); putText(newImage, label, Point(5, extraHeight - 5), CV_FONT_HERSHEY_PLAIN , 0.7, fg);
rectangle(newImage, Point(0,0), Point(newImage.cols - 1, newImage.rows -1), border_color, border_size); rectangle(newImage, Point(0,0), Point(newImage.cols - 1, newImage.rows -1), border_color, border_size);
return newImage; return newImage;
} }
@@ -95,12 +95,12 @@ Mat addLabel(Mat input, string label)
void drawAndWait(cv::Mat* frame) void drawAndWait(cv::Mat* frame)
{ {
cv::imshow("Temp Window", *frame); cv::imshow("Temp Window", *frame);
while (cv::waitKey(50) == -1) while (cv::waitKey(50) == -1)
{ {
// loop // loop
} }
cv::destroyWindow("Temp Window"); cv::destroyWindow("Temp Window");
} }
@@ -114,35 +114,35 @@ vector<Mat> produceThresholds(const Mat img_gray, Config* config)
{ {
const int THRESHOLD_COUNT = 4; const int THRESHOLD_COUNT = 4;
//Mat img_equalized = equalizeBrightness(img_gray); //Mat img_equalized = equalizeBrightness(img_gray);
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
vector<Mat> thresholds; vector<Mat> thresholds;
for (int i = 0; i < THRESHOLD_COUNT; i++) for (int i = 0; i < THRESHOLD_COUNT; i++)
thresholds.push_back(Mat(img_gray.size(), CV_8U)); thresholds.push_back(Mat(img_gray.size(), CV_8U));
int i = 0; int i = 0;
// Adaptive // Adaptive
//adaptiveThreshold(img_gray, thresholds[i++], 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV , 7, 3); //adaptiveThreshold(img_gray, thresholds[i++], 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV , 7, 3);
//adaptiveThreshold(img_gray, thresholds[i++], 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV , 13, 3); //adaptiveThreshold(img_gray, thresholds[i++], 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV , 13, 3);
//adaptiveThreshold(img_gray, thresholds[i++], 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV , 17, 3); //adaptiveThreshold(img_gray, thresholds[i++], 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV , 17, 3);
// Wolf // Wolf
int k = 0, win=18; int k = 0, win=18;
//NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35)); //NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
//bitwise_not(thresholds[i-1], thresholds[i-1]); //bitwise_not(thresholds[i-1], thresholds[i-1]);
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35)); NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
bitwise_not(thresholds[i-1], thresholds[i-1]); bitwise_not(thresholds[i-1], thresholds[i-1]);
k = 1; win = 22; k = 1; win = 22;
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35)); NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
bitwise_not(thresholds[i-1], thresholds[i-1]); bitwise_not(thresholds[i-1], thresholds[i-1]);
//NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35)); //NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
//bitwise_not(thresholds[i-1], thresholds[i-1]); //bitwise_not(thresholds[i-1], thresholds[i-1]);
// Sauvola // Sauvola
k = 1; k = 1;
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], SAUVOLA, 12, 12, 0.18 * k); NiblackSauvolaWolfJolion (img_gray, thresholds[i++], SAUVOLA, 12, 12, 0.18 * k);
@@ -150,22 +150,22 @@ vector<Mat> produceThresholds(const Mat img_gray, Config* config)
k=2; k=2;
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], SAUVOLA, 12, 12, 0.18 * k); NiblackSauvolaWolfJolion (img_gray, thresholds[i++], SAUVOLA, 12, 12, 0.18 * k);
bitwise_not(thresholds[i-1], thresholds[i-1]); bitwise_not(thresholds[i-1], thresholds[i-1]);
if (config->debugTiming) if (config->debugTiming)
{ {
timespec endTime; timespec endTime;
getTime(&endTime); getTime(&endTime);
cout << " -- Produce Threshold Time: " << diffclock(startTime, endTime) << "ms." << endl; cout << " -- Produce Threshold Time: " << diffclock(startTime, endTime) << "ms." << endl;
} }
return thresholds; return thresholds;
//threshold(img_equalized, img_threshold, 100, 255, THRESH_BINARY); //threshold(img_equalized, img_threshold, 100, 255, THRESH_BINARY);
} }
double median(int array[], int arraySize) double median(int array[], int arraySize)
@@ -175,7 +175,7 @@ double median(int array[], int arraySize)
//std::cerr << "Median calculation requested on empty array" << endl; //std::cerr << "Median calculation requested on empty array" << endl;
return 0; return 0;
} }
std::sort(&array[0], &array[arraySize]); std::sort(&array[0], &array[arraySize]);
return arraySize % 2 ? array[arraySize / 2] : (array[arraySize / 2 - 1] + array[arraySize / 2]) / 2; return arraySize % 2 ? array[arraySize / 2] : (array[arraySize / 2 - 1] + array[arraySize / 2]) / 2;
} }
@@ -183,7 +183,7 @@ double median(int array[], int arraySize)
Mat equalizeBrightness(Mat img) Mat equalizeBrightness(Mat img)
{ {
// Divide the image by its morphologically closed counterpart // Divide the image by its morphologically closed counterpart
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(19,19)); Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(19,19));
Mat closed; Mat closed;
@@ -193,7 +193,7 @@ Mat equalizeBrightness(Mat img)
divide(img, closed, img, 1, CV_32FC1); divide(img, closed, img, 1, CV_32FC1);
normalize(img, img, 0, 255, NORM_MINMAX); normalize(img, img, 0, 255, NORM_MINMAX);
img.convertTo(img, CV_8U); // convert back to unsigned int img.convertTo(img, CV_8U); // convert back to unsigned int
return img; return img;
} }
@@ -201,7 +201,7 @@ Mat equalizeBrightness(Mat img)
void drawRotatedRect(Mat* img, RotatedRect rect, Scalar color, int thickness) void drawRotatedRect(Mat* img, RotatedRect rect, Scalar color, int thickness)
{ {
Point2f rect_points[4]; Point2f rect_points[4];
rect.points( rect_points ); rect.points( rect_points );
for( int j = 0; j < 4; j++ ) for( int j = 0; j < 4; j++ )
line( *img, rect_points[j], rect_points[(j+1)%4], color, thickness, 8 ); line( *img, rect_points[j], rect_points[(j+1)%4], color, thickness, 8 );
@@ -215,7 +215,7 @@ void fillMask(Mat img, const Mat mask, Scalar color)
for (int col = 0; col < img.cols; col++) for (int col = 0; col < img.cols; col++)
{ {
int m = (int) mask.at<uchar>(row, col); int m = (int) mask.at<uchar>(row, col);
if (m) if (m)
{ {
for (int z = 0; z < 3; z++) for (int z = 0; z < 3; z++)
@@ -236,7 +236,7 @@ void drawX(Mat img, Rect rect, Scalar color, int thickness)
Point tr(rect.x + rect.width, rect.y); Point tr(rect.x + rect.width, rect.y);
Point bl(rect.x, rect.y + rect.height); Point bl(rect.x, rect.y + rect.height);
Point br(rect.x + rect.width, rect.y + rect.height); Point br(rect.x + rect.width, rect.y + rect.height);
line(img, tl, br, color, thickness); line(img, tl, br, color, thickness);
line(img, bl, tr, color, thickness); line(img, bl, tr, color, thickness);
} }
@@ -245,7 +245,7 @@ double distanceBetweenPoints(Point p1, Point p2)
{ {
float asquared = (p2.x - p1.x)*(p2.x - p1.x); float asquared = (p2.x - p1.x)*(p2.x - p1.x);
float bsquared = (p2.y - p1.y)*(p2.y - p1.y); float bsquared = (p2.y - p1.y)*(p2.y - p1.y);
return sqrt(asquared + bsquared); return sqrt(asquared + bsquared);
} }
@@ -253,7 +253,7 @@ float angleBetweenPoints(Point p1, Point p2)
{ {
int deltaY = p2.y - p1.y; int deltaY = p2.y - p1.y;
int deltaX = p2.x - p1.x; int deltaX = p2.x - p1.x;
return atan2((float) deltaY, (float) deltaX) * (180 / CV_PI); return atan2((float) deltaY, (float) deltaX) * (180 / CV_PI);
} }
@@ -261,7 +261,7 @@ float angleBetweenPoints(Point p1, Point p2)
Size getSizeMaintainingAspect(Mat inputImg, int maxWidth, int maxHeight) Size getSizeMaintainingAspect(Mat inputImg, int maxWidth, int maxHeight)
{ {
float aspect = ((float) inputImg.cols) / ((float) inputImg.rows); float aspect = ((float) inputImg.cols) / ((float) inputImg.rows);
if (maxWidth / aspect > maxHeight) if (maxWidth / aspect > maxHeight)
{ {
return Size(maxHeight * aspect, maxHeight); return Size(maxHeight * aspect, maxHeight);
@@ -296,9 +296,9 @@ void LineSegment::init(int x1, int y1, int x2, int y2)
this->slope = 0.00000000001; this->slope = 0.00000000001;
else else
this->slope = (float) (p2.y - p1.y) / (float) (p2.x - p1.x); this->slope = (float) (p2.y - p1.y) / (float) (p2.x - p1.x);
this->length = distanceBetweenPoints(p1, p2); this->length = distanceBetweenPoints(p1, p2);
this->angle = angleBetweenPoints(p1, p2); this->angle = angleBetweenPoints(p1, p2);
} }
@@ -314,15 +314,15 @@ float LineSegment::getPointAt(float x)
Point LineSegment::closestPointOnSegmentTo(Point p) Point LineSegment::closestPointOnSegmentTo(Point p)
{ {
float top = (p.x - p1.x) * (p2.x - p1.x) + (p.y - p1.y)*(p2.y - p1.y); float top = (p.x - p1.x) * (p2.x - p1.x) + (p.y - p1.y)*(p2.y - p1.y);
float bottom = distanceBetweenPoints(p2, p1); float bottom = distanceBetweenPoints(p2, p1);
bottom = bottom * bottom; bottom = bottom * bottom;
float u = top / bottom; float u = top / bottom;
float x = p1.x + u * (p2.x - p1.x); float x = p1.x + u * (p2.x - p1.x);
float y = p1.y + u * (p2.y - p1.y); float y = p1.y + u * (p2.y - p1.y);
return Point(x, y); return Point(x, y);
} }
@@ -330,12 +330,12 @@ Point LineSegment::intersection(LineSegment line)
{ {
float c1, c2; float c1, c2;
float intersection_X = -1, intersection_Y= -1; float intersection_X = -1, intersection_Y= -1;
c1 = p1.y - slope * p1.x; // which is same as y2 - slope * x2 c1 = p1.y - slope * p1.x; // which is same as y2 - slope * x2
c2 = line.p2.y - line.slope * line.p2.x; // which is same as y2 - slope * x2 c2 = line.p2.y - line.slope * line.p2.x; // which is same as y2 - slope * x2
if( (slope - line.slope) == 0) if( (slope - line.slope) == 0)
{ {
//std::cout << "No Intersection between the lines" << endl; //std::cout << "No Intersection between the lines" << endl;
@@ -344,7 +344,7 @@ Point LineSegment::intersection(LineSegment line)
{ {
// Line1 is vertical // Line1 is vertical
return Point(p1.x, line.getPointAt(p1.x)); return Point(p1.x, line.getPointAt(p1.x));
} }
else if (line.p1.x == line.p2.x) else if (line.p1.x == line.p2.x)
{ {
// Line2 is vertical // Line2 is vertical
@@ -354,11 +354,11 @@ Point LineSegment::intersection(LineSegment line)
{ {
intersection_X = (c2 - c1) / (slope - line.slope); intersection_X = (c2 - c1) / (slope - line.slope);
intersection_Y = slope * intersection_X + c1; intersection_Y = slope * intersection_X + c1;
} }
return Point(intersection_X, intersection_Y); return Point(intersection_X, intersection_Y);
} }
@@ -375,7 +375,7 @@ Point LineSegment::midpoint()
float diff = p2.x - p1.x; float diff = p2.x - p1.x;
float midX = ((float) p1.x) + (diff / 2); float midX = ((float) p1.x) + (diff / 2);
int midY = getPointAt(midX); int midY = getPointAt(midX);
return Point(midX, midY); return Point(midX, midY);
} }
@@ -386,17 +386,12 @@ LineSegment LineSegment::getParallelLine(float distance)
float angle = atan2( diff_x, diff_y); float angle = atan2( diff_x, diff_y);
float dist_x = distance * cos(angle); float dist_x = distance * cos(angle);
float dist_y = -distance * sin(angle); float dist_y = -distance * sin(angle);
int offsetX = (int)round(dist_x); int offsetX = (int)round(dist_x);
int offsetY = (int)round(dist_y); int offsetY = (int)round(dist_y);
LineSegment result(p1.x + offsetX, p1.y + offsetY, LineSegment result(p1.x + offsetX, p1.y + offsetY,
p2.x + offsetX, p2.y + offsetY); p2.x + offsetX, p2.y + offsetY);
return result; return result;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -38,9 +38,9 @@
#include "binarize_wolf.h" #include "binarize_wolf.h"
#include <vector> #include <vector>
#include "config.h" #include "config.h"
/* /*
struct LineSegment struct LineSegment
{ {
@@ -50,70 +50,70 @@ struct LineSegment
float y2; float y2;
}; };
*/ */
class LineSegment class LineSegment
{ {
public: public:
Point p1, p2; Point p1, p2;
float slope; float slope;
float length; float length;
float angle; float angle;
// LineSegment(Point point1, Point point2); // LineSegment(Point point1, Point point2);
LineSegment(); LineSegment();
LineSegment(int x1, int y1, int x2, int y2); LineSegment(int x1, int y1, int x2, int y2);
LineSegment(Point p1, Point p2); LineSegment(Point p1, Point p2);
void init(int x1, int y1, int x2, int y2); void init(int x1, int y1, int x2, int y2);
bool isPointBelowLine(Point tp); bool isPointBelowLine(Point tp);
float getPointAt(float x); float getPointAt(float x);
Point closestPointOnSegmentTo(Point p); Point closestPointOnSegmentTo(Point p);
Point intersection(LineSegment line); Point intersection(LineSegment line);
LineSegment getParallelLine(float distance); LineSegment getParallelLine(float distance);
Point midpoint(); Point midpoint();
inline std::string str() inline std::string str()
{ {
std::stringstream ss; std::stringstream ss;
ss << "(" << p1.x << ", " << p1.y << ") : (" << p2.x << ", " << p2.y << ")"; ss << "(" << p1.x << ", " << p1.y << ") : (" << p2.x << ", " << p2.y << ")";
return ss.str() ; return ss.str() ;
} }
}; };
double median(int array[], int arraySize); double median(int array[], int arraySize);
vector<Mat> produceThresholds(const Mat img_gray, Config* config); vector<Mat> produceThresholds(const Mat img_gray, Config* config);
Mat drawImageDashboard(vector<Mat> images, int imageType, int numColumns); Mat drawImageDashboard(vector<Mat> images, int imageType, int numColumns);
void displayImage(Config* config, string windowName, cv::Mat frame); void displayImage(Config* config, string windowName, cv::Mat frame);
void drawAndWait(cv::Mat* frame); void drawAndWait(cv::Mat* frame);
double distanceBetweenPoints(Point p1, Point p2); double distanceBetweenPoints(Point p1, Point p2);
void drawRotatedRect(Mat* img, RotatedRect rect, Scalar color, int thickness); void drawRotatedRect(Mat* img, RotatedRect rect, Scalar color, int thickness);
void drawX(Mat img, Rect rect, Scalar color, int thickness); void drawX(Mat img, Rect rect, Scalar color, int thickness);
void fillMask(Mat img, const Mat mask, Scalar color); void fillMask(Mat img, const Mat mask, Scalar color);
float angleBetweenPoints(Point p1, Point p2); float angleBetweenPoints(Point p1, Point p2);
Size getSizeMaintainingAspect(Mat inputImg, int maxWidth, int maxHeight); Size getSizeMaintainingAspect(Mat inputImg, int maxWidth, int maxHeight);
Mat equalizeBrightness(Mat img); Mat equalizeBrightness(Mat img);
Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, int maxY); Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, int maxY);
Mat addLabel(Mat input, string label); Mat addLabel(Mat input, string label);
#endif // UTILITY_H #endif // UTILITY_H

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -22,9 +22,9 @@
VerticalHistogram::VerticalHistogram(Mat inputImage, Mat mask) VerticalHistogram::VerticalHistogram(Mat inputImage, Mat mask)
{ {
analyzeImage(inputImage, mask); analyzeImage(inputImage, mask);
} }
VerticalHistogram::~VerticalHistogram() VerticalHistogram::~VerticalHistogram()
@@ -38,44 +38,44 @@ void VerticalHistogram::analyzeImage(Mat inputImage, Mat mask)
{ {
highestPeak = 0; highestPeak = 0;
lowestValley = inputImage.rows; lowestValley = inputImage.rows;
histoImg = Mat::zeros(inputImage.size(), CV_8U); histoImg = Mat::zeros(inputImage.size(), CV_8U);
int columnCount; int columnCount;
for (int col = 0; col < inputImage.cols; col++) for (int col = 0; col < inputImage.cols; col++)
{ {
columnCount = 0; columnCount = 0;
for (int row = 0; row < inputImage.rows; row++) for (int row = 0; row < inputImage.rows; row++)
{ {
if (inputImage.at<uchar>(row, col) > 0 && mask.at<uchar>(row, col) > 0) if (inputImage.at<uchar>(row, col) > 0 && mask.at<uchar>(row, col) > 0)
columnCount++; columnCount++;
} }
this->colHeights.push_back(columnCount); this->colHeights.push_back(columnCount);
if (columnCount < lowestValley) if (columnCount < lowestValley)
lowestValley = columnCount; lowestValley = columnCount;
if (columnCount > highestPeak) if (columnCount > highestPeak)
highestPeak = columnCount; highestPeak = columnCount;
for (; columnCount > 0; columnCount--) for (; columnCount > 0; columnCount--)
histoImg.at<uchar>(inputImage.rows - columnCount, col) = 255; histoImg.at<uchar>(inputImage.rows - columnCount, col) = 255;
} }
} }
int VerticalHistogram::getLocalMinimum(int leftX, int rightX) int VerticalHistogram::getLocalMinimum(int leftX, int rightX)
{ {
int minimum = histoImg.rows + 1; int minimum = histoImg.rows + 1;
int lowestX = leftX; int lowestX = leftX;
for (int i = leftX; i <= rightX; i++) for (int i = leftX; i <= rightX; i++)
{ {
if (colHeights[i] < minimum) if (colHeights[i] < minimum)
@@ -84,7 +84,7 @@ int VerticalHistogram::getLocalMinimum(int leftX, int rightX)
minimum = colHeights[i]; minimum = colHeights[i];
} }
} }
return lowestX; return lowestX;
} }
@@ -92,7 +92,7 @@ int VerticalHistogram::getLocalMaximum(int leftX, int rightX)
{ {
int maximum = -1; int maximum = -1;
int highestX = leftX; int highestX = leftX;
for (int i = leftX; i <= rightX; i++) for (int i = leftX; i <= rightX; i++)
{ {
if (colHeights[i] > maximum) if (colHeights[i] > maximum)
@@ -101,8 +101,8 @@ int VerticalHistogram::getLocalMaximum(int leftX, int rightX)
maximum = colHeights[i]; maximum = colHeights[i];
} }
} }
return highestX; return highestX;
} }
int VerticalHistogram::getHeightAt(int x) int VerticalHistogram::getHeightAt(int x)
@@ -113,78 +113,78 @@ int VerticalHistogram::getHeightAt(int x)
void VerticalHistogram::findValleys() void VerticalHistogram::findValleys()
{ {
int MINIMUM_PEAK_HEIGHT = (int) (((float) highestPeak) * 0.75); int MINIMUM_PEAK_HEIGHT = (int) (((float) highestPeak) * 0.75);
int totalWidth = colHeights.size(); int totalWidth = colHeights.size();
int midpoint = ((highestPeak - lowestValley) / 2) + lowestValley; int midpoint = ((highestPeak - lowestValley) / 2) + lowestValley;
HistogramDirection prevDirection = FALLING; HistogramDirection prevDirection = FALLING;
int relativePeakHeight = 0; int relativePeakHeight = 0;
int valleyStart = 0; int valleyStart = 0;
for (int i = 0; i < totalWidth; i++) for (int i = 0; i < totalWidth; i++)
{ {
bool aboveMidpoint = (colHeights[i] >= midpoint); bool aboveMidpoint = (colHeights[i] >= midpoint);
if (aboveMidpoint) if (aboveMidpoint)
{ {
if (colHeights[i] > relativePeakHeight) if (colHeights[i] > relativePeakHeight)
relativePeakHeight = colHeights[i]; relativePeakHeight = colHeights[i];
prevDirection = FLAT; prevDirection = FLAT;
} }
else else
{ {
relativePeakHeight = 0; relativePeakHeight = 0;
HistogramDirection direction = getHistogramDirection(i); HistogramDirection direction = getHistogramDirection(i);
if ((prevDirection == FALLING || prevDirection == FLAT) && direction == RISING) if ((prevDirection == FALLING || prevDirection == FLAT) && direction == RISING)
{ {
} }
else if ((prevDirection == FALLING || prevDirection == FLAT) && direction == RISING) else if ((prevDirection == FALLING || prevDirection == FLAT) && direction == RISING)
{ {
} }
} }
} }
} }
HistogramDirection VerticalHistogram::getHistogramDirection(int index) HistogramDirection VerticalHistogram::getHistogramDirection(int index)
{ {
int EXTRA_WIDTH_TO_AVERAGE = 2; int EXTRA_WIDTH_TO_AVERAGE = 2;
float trailingAverage = 0; float trailingAverage = 0;
float forwardAverage = 0; float forwardAverage = 0;
int trailStartIndex = index - EXTRA_WIDTH_TO_AVERAGE; int trailStartIndex = index - EXTRA_WIDTH_TO_AVERAGE;
if (trailStartIndex < 0) if (trailStartIndex < 0)
trailStartIndex = 0; trailStartIndex = 0;
int forwardEndIndex = index + EXTRA_WIDTH_TO_AVERAGE; int forwardEndIndex = index + EXTRA_WIDTH_TO_AVERAGE;
if (forwardEndIndex >= colHeights.size()) if (forwardEndIndex >= colHeights.size())
forwardEndIndex = colHeights.size() - 1; forwardEndIndex = colHeights.size() - 1;
for (int i = index; i >= trailStartIndex; i--) for (int i = index; i >= trailStartIndex; i--)
{ {
trailingAverage += colHeights[i]; trailingAverage += colHeights[i];
} }
trailingAverage = trailingAverage / ((float) (1 + index - trailStartIndex)); trailingAverage = trailingAverage / ((float) (1 + index - trailStartIndex));
for (int i = index; i <= forwardEndIndex; i++) for (int i = index; i <= forwardEndIndex; i++)
{ {
forwardAverage += colHeights[i]; forwardAverage += colHeights[i];
} }
forwardAverage = forwardAverage / ((float) (1 + forwardEndIndex - index)); forwardAverage = forwardAverage / ((float) (1 + forwardEndIndex - index));
float diff = forwardAverage - trailingAverage; float diff = forwardAverage - trailingAverage;
float minDiff = ((float) (highestPeak - lowestValley)) * 0.10; float minDiff = ((float) (highestPeak - lowestValley)) * 0.10;
if (diff > minDiff) if (diff > minDiff)
return RISING; return RISING;
else if (diff < minDiff) else if (diff < minDiff)
@@ -192,5 +192,3 @@ HistogramDirection VerticalHistogram::getHistogramDirection(int index)
else else
return FLAT; return FLAT;
} }

View File

@@ -1,18 +1,18 @@
/* /*
* Copyright (c) 2013 New Designs Unlimited, LLC * Copyright (c) 2013 New Designs Unlimited, LLC
* Opensource Automated License Plate Recognition [http://www.openalpr.com] * Opensource Automated License Plate Recognition [http://www.openalpr.com]
* *
* This file is part of OpenAlpr. * This file is part of OpenAlpr.
* *
* OpenAlpr is free software: you can redistribute it and/or modify * OpenAlpr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License * it under the terms of the GNU Affero General Public License
* version 3 as published by the Free Software Foundation * version 3 as published by the Free Software Foundation
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -45,24 +45,24 @@ class VerticalHistogram
virtual ~VerticalHistogram(); virtual ~VerticalHistogram();
Mat histoImg; Mat histoImg;
// Returns the lowest X position between two points. // Returns the lowest X position between two points.
int getLocalMinimum(int leftX, int rightX); int getLocalMinimum(int leftX, int rightX);
// Returns the highest X position between two points. // Returns the highest X position between two points.
int getLocalMaximum(int leftX, int rightX); int getLocalMaximum(int leftX, int rightX);
int getHeightAt(int x); int getHeightAt(int x);
private: private:
vector<int> colHeights; vector<int> colHeights;
int highestPeak; int highestPeak;
int lowestValley; int lowestValley;
vector<Valley> valleys; vector<Valley> valleys;
void analyzeImage(Mat inputImage, Mat mask); void analyzeImage(Mat inputImage, Mat mask);
void findValleys(); void findValleys();
HistogramDirection getHistogramDirection(int index); HistogramDirection getHistogramDirection(int index);
}; };
#endif // VERTICALHISTOGRAM_H #endif // VERTICALHISTOGRAM_H

View File

@@ -689,4 +689,3 @@ inline void Arg::reset()
} //namespace TCLAP } //namespace TCLAP
#endif #endif

View File

@@ -1,24 +1,24 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
/****************************************************************************** /******************************************************************************
* *
* file: ArgException.h * file: ArgException.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_ARG_EXCEPTION_H #ifndef TCLAP_ARG_EXCEPTION_H
@@ -36,7 +36,7 @@ namespace TCLAP {
class ArgException : public std::exception class ArgException : public std::exception
{ {
public: public:
/** /**
* Constructor. * Constructor.
* \param text - The text of the exception. * \param text - The text of the exception.
@@ -44,15 +44,15 @@ class ArgException : public std::exception
* \param td - Text describing the type of ArgException it is. * \param td - Text describing the type of ArgException it is.
* of the exception. * of the exception.
*/ */
ArgException( const std::string& text = "undefined exception", ArgException( const std::string& text = "undefined exception",
const std::string& id = "undefined", const std::string& id = "undefined",
const std::string& td = "Generic ArgException") const std::string& td = "Generic ArgException")
: std::exception(), : std::exception(),
_errorText(text), _errorText(text),
_argId( id ), _argId( id ),
_typeDescription(td) _typeDescription(td)
{ } { }
/** /**
* Destructor. * Destructor.
*/ */
@@ -66,20 +66,20 @@ class ArgException : public std::exception
/** /**
* Returns the argument id. * Returns the argument id.
*/ */
std::string argId() const std::string argId() const
{ {
if ( _argId == "undefined" ) if ( _argId == "undefined" )
return " "; return " ";
else else
return ( "Argument: " + _argId ); return ( "Argument: " + _argId );
} }
/** /**
* Returns the arg id and error text. * Returns the arg id and error text.
*/ */
const char* what() const throw() const char* what() const throw()
{ {
static std::string ex; static std::string ex;
ex = _argId + " -- " + _errorText; ex = _argId + " -- " + _errorText;
return ex.c_str(); return ex.c_str();
} }
@@ -90,7 +90,7 @@ class ArgException : public std::exception
*/ */
std::string typeDescription() const std::string typeDescription() const
{ {
return _typeDescription; return _typeDescription;
} }
@@ -119,19 +119,19 @@ class ArgException : public std::exception
* parse the argument it has been passed. * parse the argument it has been passed.
*/ */
class ArgParseException : public ArgException class ArgParseException : public ArgException
{ {
public: public:
/** /**
* Constructor. * Constructor.
* \param text - The text of the exception. * \param text - The text of the exception.
* \param id - The text identifying the argument source * \param id - The text identifying the argument source
* of the exception. * of the exception.
*/ */
ArgParseException( const std::string& text = "undefined exception", ArgParseException( const std::string& text = "undefined exception",
const std::string& id = "undefined" ) const std::string& id = "undefined" )
: ArgException( text, : ArgException( text,
id, id,
std::string( "Exception found while parsing " ) + std::string( "Exception found while parsing " ) +
std::string( "the value the Arg has been passed." )) std::string( "the value the Arg has been passed." ))
{ } { }
}; };
@@ -146,12 +146,12 @@ class CmdLineParseException : public ArgException
/** /**
* Constructor. * Constructor.
* \param text - The text of the exception. * \param text - The text of the exception.
* \param id - The text identifying the argument source * \param id - The text identifying the argument source
* of the exception. * of the exception.
*/ */
CmdLineParseException( const std::string& text = "undefined exception", CmdLineParseException( const std::string& text = "undefined exception",
const std::string& id = "undefined" ) const std::string& id = "undefined" )
: ArgException( text, : ArgException( text,
id, id,
std::string( "Exception found when the values ") + std::string( "Exception found when the values ") +
std::string( "on the command line do not meet ") + std::string( "on the command line do not meet ") +
@@ -161,7 +161,7 @@ class CmdLineParseException : public ArgException
}; };
/** /**
* Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g.
* same flag as another Arg, same name, etc. * same flag as another Arg, same name, etc.
*/ */
class SpecificationException : public ArgException class SpecificationException : public ArgException
@@ -170,16 +170,16 @@ class SpecificationException : public ArgException
/** /**
* Constructor. * Constructor.
* \param text - The text of the exception. * \param text - The text of the exception.
* \param id - The text identifying the argument source * \param id - The text identifying the argument source
* of the exception. * of the exception.
*/ */
SpecificationException( const std::string& text = "undefined exception", SpecificationException( const std::string& text = "undefined exception",
const std::string& id = "undefined" ) const std::string& id = "undefined" )
: ArgException( text, : ArgException( text,
id, id,
std::string("Exception found when an Arg object ")+ std::string("Exception found when an Arg object ")+
std::string("is improperly defined by the ") + std::string("is improperly defined by the ") +
std::string("developer." )) std::string("developer." ))
{ } { }
}; };
@@ -197,4 +197,3 @@ private:
} // namespace TCLAP } // namespace TCLAP
#endif #endif

View File

@@ -452,7 +452,7 @@ inline void CmdLine::parse(std::vector<std::string>& args)
int requiredCount = 0; int requiredCount = 0;
for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
{ {
bool matched = false; bool matched = false;
for (ArgListIterator it = _argList.begin(); for (ArgListIterator it = _argList.begin();
@@ -619,7 +619,7 @@ inline void CmdLine::reset()
{ {
for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
(*it)->reset(); (*it)->reset();
_progName.clear(); _progName.clear();
} }

View File

@@ -1,24 +1,24 @@
/****************************************************************************** /******************************************************************************
* *
* file: CmdLineInterface.h * file: CmdLineInterface.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_COMMANDLINE_INTERFACE_H #ifndef TCLAP_COMMANDLINE_INTERFACE_H
#define TCLAP_COMMANDLINE_INTERFACE_H #define TCLAP_COMMANDLINE_INTERFACE_H
@@ -31,7 +31,7 @@
namespace TCLAP { namespace TCLAP {
class Arg; class Arg;
class CmdLineOutput; class CmdLineOutput;
class XorHandler; class XorHandler;
@@ -51,29 +51,29 @@ class CmdLineInterface
/** /**
* Adds an argument to the list of arguments to be parsed. * Adds an argument to the list of arguments to be parsed.
* \param a - Argument to be added. * \param a - Argument to be added.
*/ */
virtual void add( Arg& a )=0; virtual void add( Arg& a )=0;
/** /**
* An alternative add. Functionally identical. * An alternative add. Functionally identical.
* \param a - Argument to be added. * \param a - Argument to be added.
*/ */
virtual void add( Arg* a )=0; virtual void add( Arg* a )=0;
/** /**
* Add two Args that will be xor'd. * Add two Args that will be xor'd.
* If this method is used, add does * If this method is used, add does
* not need to be called. * not need to be called.
* \param a - Argument to be added and xor'd. * \param a - Argument to be added and xor'd.
* \param b - Argument to be added and xor'd. * \param b - Argument to be added and xor'd.
*/ */
virtual void xorAdd( Arg& a, Arg& b )=0; virtual void xorAdd( Arg& a, Arg& b )=0;
/** /**
* Add a list of Args that will be xor'd. If this method is used, * Add a list of Args that will be xor'd. If this method is used,
* add does not need to be called. * add does not need to be called.
* \param xors - List of Args to be added and xor'd. * \param xors - List of Args to be added and xor'd.
*/ */
virtual void xorAdd( std::vector<Arg*>& xors )=0; virtual void xorAdd( std::vector<Arg*>& xors )=0;
@@ -86,7 +86,7 @@ class CmdLineInterface
/** /**
* Parses the command line. * Parses the command line.
* \param args - A vector of strings representing the args. * \param args - A vector of strings representing the args.
* args[0] is still the program name. * args[0] is still the program name.
*/ */
void parse(std::vector<std::string>& args); void parse(std::vector<std::string>& args);
@@ -97,7 +97,7 @@ class CmdLineInterface
virtual CmdLineOutput* getOutput()=0; virtual CmdLineOutput* getOutput()=0;
/** /**
* \param co - CmdLineOutput object that we want to use instead. * \param co - CmdLineOutput object that we want to use instead.
*/ */
virtual void setOutput(CmdLineOutput* co)=0; virtual void setOutput(CmdLineOutput* co)=0;
@@ -112,12 +112,12 @@ class CmdLineInterface
virtual std::string& getProgramName()=0; virtual std::string& getProgramName()=0;
/** /**
* Returns the argList. * Returns the argList.
*/ */
virtual std::list<Arg*>& getArgList()=0; virtual std::list<Arg*>& getArgList()=0;
/** /**
* Returns the XorHandler. * Returns the XorHandler.
*/ */
virtual XorHandler& getXorHandler()=0; virtual XorHandler& getXorHandler()=0;
@@ -137,9 +137,9 @@ class CmdLineInterface
*/ */
virtual bool hasHelpAndVersion()=0; virtual bool hasHelpAndVersion()=0;
/** /**
* Resets the instance as if it had just been constructed so that the * Resets the instance as if it had just been constructed so that the
* instance can be reused. * instance can be reused.
*/ */
virtual void reset()=0; virtual void reset()=0;
}; };
@@ -147,4 +147,4 @@ class CmdLineInterface
} //namespace } //namespace
#endif #endif

View File

@@ -1,24 +1,24 @@
/****************************************************************************** /******************************************************************************
* *
* file: CmdLineOutput.h * file: CmdLineOutput.h
* *
* Copyright (c) 2004, Michael E. Smoot * Copyright (c) 2004, Michael E. Smoot
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_CMDLINEOUTPUT_H #ifndef TCLAP_CMDLINEOUTPUT_H
#define TCLAP_CMDLINEOUTPUT_H #define TCLAP_CMDLINEOUTPUT_H
@@ -38,7 +38,7 @@ class ArgException;
/** /**
* The interface that any output object must implement. * The interface that any output object must implement.
*/ */
class CmdLineOutput class CmdLineOutput
{ {
public: public:
@@ -49,26 +49,26 @@ class CmdLineOutput
virtual ~CmdLineOutput() {} virtual ~CmdLineOutput() {}
/** /**
* Generates some sort of output for the USAGE. * Generates some sort of output for the USAGE.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
*/ */
virtual void usage(CmdLineInterface& c)=0; virtual void usage(CmdLineInterface& c)=0;
/** /**
* Generates some sort of output for the version. * Generates some sort of output for the version.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
*/ */
virtual void version(CmdLineInterface& c)=0; virtual void version(CmdLineInterface& c)=0;
/** /**
* Generates some sort of output for a failure. * Generates some sort of output for a failure.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
* \param e - The ArgException that caused the failure. * \param e - The ArgException that caused the failure.
*/ */
virtual void failure( CmdLineInterface& c, virtual void failure( CmdLineInterface& c,
ArgException& e )=0; ArgException& e )=0;
}; };
} //namespace TCLAP } //namespace TCLAP
#endif #endif

View File

@@ -1,24 +1,24 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
/****************************************************************************** /******************************************************************************
* *
* file: DocBookOutput.h * file: DocBookOutput.h
* *
* Copyright (c) 2004, Michael E. Smoot * Copyright (c) 2004, Michael E. Smoot
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_DOCBOOKOUTPUT_H #ifndef TCLAP_DOCBOOKOUTPUT_H
#define TCLAP_DOCBOOKOUTPUT_H #define TCLAP_DOCBOOKOUTPUT_H
@@ -37,7 +37,7 @@
namespace TCLAP { namespace TCLAP {
/** /**
* A class that generates DocBook output for usage() method for the * A class that generates DocBook output for usage() method for the
* given CmdLine and its Args. * given CmdLine and its Args.
*/ */
class DocBookOutput : public CmdLineOutput class DocBookOutput : public CmdLineOutput
@@ -46,35 +46,35 @@ class DocBookOutput : public CmdLineOutput
public: public:
/** /**
* Prints the usage to stdout. Can be overridden to * Prints the usage to stdout. Can be overridden to
* produce alternative behavior. * produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
*/ */
virtual void usage(CmdLineInterface& c); virtual void usage(CmdLineInterface& c);
/** /**
* Prints the version to stdout. Can be overridden * Prints the version to stdout. Can be overridden
* to produce alternative behavior. * to produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
*/ */
virtual void version(CmdLineInterface& c); virtual void version(CmdLineInterface& c);
/** /**
* Prints (to stderr) an error message, short usage * Prints (to stderr) an error message, short usage
* Can be overridden to produce alternative behavior. * Can be overridden to produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
* \param e - The ArgException that caused the failure. * \param e - The ArgException that caused the failure.
*/ */
virtual void failure(CmdLineInterface& c, virtual void failure(CmdLineInterface& c,
ArgException& e ); ArgException& e );
protected: protected:
/** /**
* Substitutes the char r for string x in string s. * Substitutes the char r for string x in string s.
* \param s - The string to operate on. * \param s - The string to operate on.
* \param r - The char to replace. * \param r - The char to replace.
* \param x - What to replace r with. * \param x - What to replace r with.
*/ */
void substituteSpecialChars( std::string& s, char r, std::string& x ); void substituteSpecialChars( std::string& s, char r, std::string& x );
void removeChar( std::string& s, char r); void removeChar( std::string& s, char r);
@@ -87,12 +87,12 @@ class DocBookOutput : public CmdLineOutput
}; };
inline void DocBookOutput::version(CmdLineInterface& _cmd) inline void DocBookOutput::version(CmdLineInterface& _cmd)
{ {
std::cout << _cmd.getVersion() << std::endl; std::cout << _cmd.getVersion() << std::endl;
} }
inline void DocBookOutput::usage(CmdLineInterface& _cmd ) inline void DocBookOutput::usage(CmdLineInterface& _cmd )
{ {
std::list<Arg*> argList = _cmd.getArgList(); std::list<Arg*> argList = _cmd.getArgList();
std::string progName = _cmd.getProgramName(); std::string progName = _cmd.getProgramName();
@@ -127,13 +127,13 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) for ( int i = 0; (unsigned int)i < xorList.size(); i++ )
{ {
std::cout << "<group choice='req'>" << std::endl; std::cout << "<group choice='req'>" << std::endl;
for ( ArgVectorIterator it = xorList[i].begin(); for ( ArgVectorIterator it = xorList[i].begin();
it != xorList[i].end(); it++ ) it != xorList[i].end(); it++ )
printShortArg((*it)); printShortArg((*it));
std::cout << "</group>" << std::endl; std::cout << "</group>" << std::endl;
} }
// rest of args // rest of args
for (ArgListIterator it = argList.begin(); it != argList.end(); it++) for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
if ( !xorHandler.contains( (*it) ) ) if ( !xorHandler.contains( (*it) ) )
@@ -145,7 +145,7 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
std::cout << "<refsect1>" << std::endl; std::cout << "<refsect1>" << std::endl;
std::cout << "<title>Description</title>" << std::endl; std::cout << "<title>Description</title>" << std::endl;
std::cout << "<para>" << std::endl; std::cout << "<para>" << std::endl;
std::cout << _cmd.getMessage() << std::endl; std::cout << _cmd.getMessage() << std::endl;
std::cout << "</para>" << std::endl; std::cout << "</para>" << std::endl;
std::cout << "</refsect1>" << std::endl; std::cout << "</refsect1>" << std::endl;
@@ -153,7 +153,7 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
std::cout << "<title>Options</title>" << std::endl; std::cout << "<title>Options</title>" << std::endl;
std::cout << "<variablelist>" << std::endl; std::cout << "<variablelist>" << std::endl;
for (ArgListIterator it = argList.begin(); it != argList.end(); it++) for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
printLongArg((*it)); printLongArg((*it));
@@ -163,17 +163,17 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
std::cout << "<refsect1>" << std::endl; std::cout << "<refsect1>" << std::endl;
std::cout << "<title>Version</title>" << std::endl; std::cout << "<title>Version</title>" << std::endl;
std::cout << "<para>" << std::endl; std::cout << "<para>" << std::endl;
std::cout << xversion << std::endl; std::cout << xversion << std::endl;
std::cout << "</para>" << std::endl; std::cout << "</para>" << std::endl;
std::cout << "</refsect1>" << std::endl; std::cout << "</refsect1>" << std::endl;
std::cout << "</refentry>" << std::endl; std::cout << "</refentry>" << std::endl;
} }
inline void DocBookOutput::failure( CmdLineInterface& _cmd, inline void DocBookOutput::failure( CmdLineInterface& _cmd,
ArgException& e ) ArgException& e )
{ {
static_cast<void>(_cmd); // unused static_cast<void>(_cmd); // unused
std::cout << e.what() << std::endl; std::cout << e.what() << std::endl;
throw ExitException(1); throw ExitException(1);
@@ -211,15 +211,15 @@ inline void DocBookOutput::basename( std::string& s )
inline void DocBookOutput::printShortArg(Arg* a) inline void DocBookOutput::printShortArg(Arg* a)
{ {
std::string lt = "&lt;"; std::string lt = "&lt;";
std::string gt = "&gt;"; std::string gt = "&gt;";
std::string id = a->shortID(); std::string id = a->shortID();
substituteSpecialChars(id,'<',lt); substituteSpecialChars(id,'<',lt);
substituteSpecialChars(id,'>',gt); substituteSpecialChars(id,'>',gt);
removeChar(id,'['); removeChar(id,'[');
removeChar(id,']'); removeChar(id,']');
std::string choice = "opt"; std::string choice = "opt";
if ( a->isRequired() ) if ( a->isRequired() )
choice = "plain"; choice = "plain";
@@ -251,8 +251,8 @@ inline void DocBookOutput::printShortArg(Arg* a)
inline void DocBookOutput::printLongArg(Arg* a) inline void DocBookOutput::printLongArg(Arg* a)
{ {
std::string lt = "&lt;"; std::string lt = "&lt;";
std::string gt = "&gt;"; std::string gt = "&gt;";
std::string desc = a->getDescription(); std::string desc = a->getDescription();
substituteSpecialChars(desc,'<',lt); substituteSpecialChars(desc,'<',lt);
@@ -296,4 +296,4 @@ inline void DocBookOutput::printLongArg(Arg* a)
} }
} //namespace TCLAP } //namespace TCLAP
#endif #endif

View File

@@ -1,23 +1,23 @@
/****************************************************************************** /******************************************************************************
* *
* file: HelpVisitor.h * file: HelpVisitor.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_HELP_VISITOR_H #ifndef TCLAP_HELP_VISITOR_H
#define TCLAP_HELP_VISITOR_H #define TCLAP_HELP_VISITOR_H
@@ -44,12 +44,12 @@ class HelpVisitor: public Visitor
protected: protected:
/** /**
* The CmdLine the output will be generated for. * The CmdLine the output will be generated for.
*/ */
CmdLineInterface* _cmd; CmdLineInterface* _cmd;
/** /**
* The output object. * The output object.
*/ */
CmdLineOutput** _out; CmdLineOutput** _out;
@@ -58,17 +58,17 @@ class HelpVisitor: public Visitor
/** /**
* Constructor. * Constructor.
* \param cmd - The CmdLine the output will be generated for. * \param cmd - The CmdLine the output will be generated for.
* \param out - The type of output. * \param out - The type of output.
*/ */
HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out)
: Visitor(), _cmd( cmd ), _out( out ) { } : Visitor(), _cmd( cmd ), _out( out ) { }
/** /**
* Calls the usage method of the CmdLineOutput for the * Calls the usage method of the CmdLineOutput for the
* specified CmdLine. * specified CmdLine.
*/ */
void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } void visit() { (*_out)->usage(*_cmd); throw ExitException(0); }
}; };
} }

View File

@@ -1,23 +1,23 @@
/****************************************************************************** /******************************************************************************
* *
* file: IgnoreRestVisitor.h * file: IgnoreRestVisitor.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_IGNORE_REST_VISITOR_H #ifndef TCLAP_IGNORE_REST_VISITOR_H

View File

@@ -1,22 +1,22 @@
/****************************************************************************** /******************************************************************************
* *
* file: MultiArg.h * file: MultiArg.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
@@ -39,7 +39,7 @@ template<class T>
class MultiArg : public Arg class MultiArg : public Arg
{ {
public: public:
typedef std::vector<T> container_type; typedef std::vector<T> container_type;
typedef typename container_type::iterator iterator; typedef typename container_type::iterator iterator;
typedef typename container_type::const_iterator const_iterator; typedef typename container_type::const_iterator const_iterator;
@@ -56,7 +56,7 @@ protected:
std::string _typeDesc; std::string _typeDesc;
/** /**
* A list of constraint on this Arg. * A list of constraint on this Arg.
*/ */
Constraint<T>* _constraint; Constraint<T>* _constraint;
@@ -117,7 +117,7 @@ public:
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
MultiArg( const std::string& flag, MultiArg( const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
@@ -146,7 +146,7 @@ public:
bool req, bool req,
Constraint<T>* constraint, Constraint<T>* constraint,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* Constructor. * Constructor.
* \param flag - The one character flag that identifies this * \param flag - The one character flag that identifies this
@@ -163,14 +163,14 @@ public:
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
MultiArg( const std::string& flag, MultiArg( const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
Constraint<T>* constraint, Constraint<T>* constraint,
CmdLineInterface& parser, CmdLineInterface& parser,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* Handles the processing of the argument. * Handles the processing of the argument.
* This re-implements the Arg version of this method to set the * This re-implements the Arg version of this method to set the
@@ -179,7 +179,7 @@ public:
* \param i - Pointer the the current argument in the list. * \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. Passed from main(). * \param args - Mutable list of strings. Passed from main().
*/ */
virtual bool processArg(int* i, std::vector<std::string>& args); virtual bool processArg(int* i, std::vector<std::string>& args);
/** /**
* Returns a vector of type T containing the values parsed from * Returns a vector of type T containing the values parsed from
@@ -200,13 +200,13 @@ public:
const_iterator end() const { return _values.end(); } const_iterator end() const { return _values.end(); }
/** /**
* Returns the a short id string. Used in the usage. * Returns the a short id string. Used in the usage.
* \param val - value to be used. * \param val - value to be used.
*/ */
virtual std::string shortID(const std::string& val="val") const; virtual std::string shortID(const std::string& val="val") const;
/** /**
* Returns the a long id string. Used in the usage. * Returns the a long id string. Used in the usage.
* \param val - value to be used. * \param val - value to be used.
*/ */
virtual std::string longID(const std::string& val="val") const; virtual std::string longID(const std::string& val="val") const;
@@ -218,7 +218,7 @@ public:
virtual bool isRequired() const; virtual bool isRequired() const;
virtual bool allowMore(); virtual bool allowMore();
virtual void reset(); virtual void reset();
private: private:
@@ -231,7 +231,7 @@ private:
}; };
template<class T> template<class T>
MultiArg<T>::MultiArg(const std::string& flag, MultiArg<T>::MultiArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
@@ -242,12 +242,12 @@ MultiArg<T>::MultiArg(const std::string& flag,
_typeDesc( typeDesc ), _typeDesc( typeDesc ),
_constraint( NULL ), _constraint( NULL ),
_allowMore(false) _allowMore(false)
{ {
_acceptsMultipleValues = true; _acceptsMultipleValues = true;
} }
template<class T> template<class T>
MultiArg<T>::MultiArg(const std::string& flag, MultiArg<T>::MultiArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
@@ -259,7 +259,7 @@ MultiArg<T>::MultiArg(const std::string& flag,
_typeDesc( typeDesc ), _typeDesc( typeDesc ),
_constraint( NULL ), _constraint( NULL ),
_allowMore(false) _allowMore(false)
{ {
parser.add( this ); parser.add( this );
_acceptsMultipleValues = true; _acceptsMultipleValues = true;
} }
@@ -268,7 +268,7 @@ MultiArg<T>::MultiArg(const std::string& flag,
* *
*/ */
template<class T> template<class T>
MultiArg<T>::MultiArg(const std::string& flag, MultiArg<T>::MultiArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
@@ -279,12 +279,12 @@ MultiArg<T>::MultiArg(const std::string& flag,
_typeDesc( constraint->shortID() ), _typeDesc( constraint->shortID() ),
_constraint( constraint ), _constraint( constraint ),
_allowMore(false) _allowMore(false)
{ {
_acceptsMultipleValues = true; _acceptsMultipleValues = true;
} }
template<class T> template<class T>
MultiArg<T>::MultiArg(const std::string& flag, MultiArg<T>::MultiArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
@@ -296,7 +296,7 @@ MultiArg<T>::MultiArg(const std::string& flag,
_typeDesc( constraint->shortID() ), _typeDesc( constraint->shortID() ),
_constraint( constraint ), _constraint( constraint ),
_allowMore(false) _allowMore(false)
{ {
parser.add( this ); parser.add( this );
_acceptsMultipleValues = true; _acceptsMultipleValues = true;
} }
@@ -305,7 +305,7 @@ template<class T>
const std::vector<T>& MultiArg<T>::getValue() { return _values; } const std::vector<T>& MultiArg<T>::getValue() { return _values; }
template<class T> template<class T>
bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
{ {
if ( _ignoreable && Arg::ignoreRest() ) if ( _ignoreable && Arg::ignoreRest() )
return false; return false;
@@ -321,7 +321,7 @@ bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
if ( argMatches( flag ) ) if ( argMatches( flag ) )
{ {
if ( Arg::delimiter() != ' ' && value == "" ) if ( Arg::delimiter() != ' ' && value == "" )
throw( ArgParseException( throw( ArgParseException(
"Couldn't find delimiter for this argument!", "Couldn't find delimiter for this argument!",
toString() ) ); toString() ) );
@@ -334,15 +334,15 @@ bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
else else
throw( ArgParseException("Missing a value for this argument!", throw( ArgParseException("Missing a value for this argument!",
toString() ) ); toString() ) );
} }
else else
_extractValue( value ); _extractValue( value );
/* /*
// continuing taking the args until we hit one with a start string // continuing taking the args until we hit one with a start string
while ( (unsigned int)(*i)+1 < args.size() && while ( (unsigned int)(*i)+1 < args.size() &&
args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
_extractValue( args[++(*i)] ); _extractValue( args[++(*i)] );
*/ */
@@ -395,7 +395,7 @@ bool MultiArg<T>::isRequired() const
} }
template<class T> template<class T>
void MultiArg<T>::_extractValue( const std::string& val ) void MultiArg<T>::_extractValue( const std::string& val )
{ {
try { try {
T tmp; T tmp;
@@ -409,10 +409,10 @@ void MultiArg<T>::_extractValue( const std::string& val )
if ( ! _constraint->check( _values.back() ) ) if ( ! _constraint->check( _values.back() ) )
throw( CmdLineParseException( "Value '" + val + throw( CmdLineParseException( "Value '" + val +
"' does not meet constraint: " + "' does not meet constraint: " +
_constraint->description(), _constraint->description(),
toString() ) ); toString() ) );
} }
template<class T> template<class T>
bool MultiArg<T>::allowMore() bool MultiArg<T>::allowMore()
{ {

View File

@@ -1,5 +1,5 @@
/****************************************************************************** /******************************************************************************
* *
* file: MultiSwitchArg.h * file: MultiSwitchArg.h
* *
@@ -61,12 +61,12 @@ class MultiSwitchArg : public SwitchArg
* used as a long flag on the command line. * used as a long flag on the command line.
* \param desc - A description of what the argument is for or * \param desc - A description of what the argument is for or
* does. * does.
* \param init - Optional. The initial/default value of this Arg. * \param init - Optional. The initial/default value of this Arg.
* Defaults to 0. * Defaults to 0.
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
MultiSwitchArg(const std::string& flag, MultiSwitchArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
int init = 0, int init = 0,
@@ -82,12 +82,12 @@ class MultiSwitchArg : public SwitchArg
* \param desc - A description of what the argument is for or * \param desc - A description of what the argument is for or
* does. * does.
* \param parser - A CmdLine parser object to add this Arg to * \param parser - A CmdLine parser object to add this Arg to
* \param init - Optional. The initial/default value of this Arg. * \param init - Optional. The initial/default value of this Arg.
* Defaults to 0. * Defaults to 0.
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
MultiSwitchArg(const std::string& flag, MultiSwitchArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
CmdLineInterface& parser, CmdLineInterface& parser,
@@ -103,7 +103,7 @@ class MultiSwitchArg : public SwitchArg
* \param args - Mutable list of strings. Passed * \param args - Mutable list of strings. Passed
* in from main(). * in from main().
*/ */
virtual bool processArg(int* i, std::vector<std::string>& args); virtual bool processArg(int* i, std::vector<std::string>& args);
/** /**
* Returns int, the number of times the switch has been set. * Returns int, the number of times the switch has been set.
@@ -119,7 +119,7 @@ class MultiSwitchArg : public SwitchArg
* Returns the longID for this Arg. * Returns the longID for this Arg.
*/ */
std::string longID(const std::string& val) const; std::string longID(const std::string& val) const;
void reset(); void reset();
}; };
@@ -138,15 +138,15 @@ _default( init )
{ } { }
inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, inline MultiSwitchArg::MultiSwitchArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
CmdLineInterface& parser, CmdLineInterface& parser,
int init, int init,
Visitor* v ) Visitor* v )
: SwitchArg(flag, name, desc, false, v), : SwitchArg(flag, name, desc, false, v),
_value( init ), _value( init ),
_default( init ) _default( init )
{ {
parser.add( this ); parser.add( this );
} }
@@ -178,7 +178,7 @@ inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args)
++_value; ++_value;
// Check for more in argument and increment value. // Check for more in argument and increment value.
while ( combinedSwitchesMatch( args[*i] ) ) while ( combinedSwitchesMatch( args[*i] ) )
++_value; ++_value;
_checkWithVisitor(); _checkWithVisitor();
@@ -189,13 +189,13 @@ inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args)
return false; return false;
} }
inline std::string inline std::string
MultiSwitchArg::shortID(const std::string& val) const MultiSwitchArg::shortID(const std::string& val) const
{ {
return Arg::shortID(val) + " ... "; return Arg::shortID(val) + " ... ";
} }
inline std::string inline std::string
MultiSwitchArg::longID(const std::string& val) const MultiSwitchArg::longID(const std::string& val) const
{ {
return Arg::longID(val) + " (accepted multiple times)"; return Arg::longID(val) + " (accepted multiple times)";

View File

@@ -1,24 +1,24 @@
/****************************************************************************** /******************************************************************************
* *
* file: OptionalUnlabeledTracker.h * file: OptionalUnlabeledTracker.h
* *
* Copyright (c) 2005, Michael E. Smoot . * Copyright (c) 2005, Michael E. Smoot .
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H #ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H
@@ -37,7 +37,7 @@ class OptionalUnlabeledTracker
static void gotOptional() { alreadyOptionalRef() = true; } static void gotOptional() { alreadyOptionalRef() = true; }
static bool& alreadyOptional() { return alreadyOptionalRef(); } static bool& alreadyOptional() { return alreadyOptionalRef(); }
private: private:

View File

@@ -30,7 +30,7 @@
#include <config.h> // To check for long long #include <config.h> // To check for long long
#endif #endif
// If Microsoft has already typedef'd wchar_t as an unsigned // If Microsoft has already typedef'd wchar_t as an unsigned
// short, then compiles will break because it's as if we're // short, then compiles will break because it's as if we're
// creating ArgTraits twice for unsigned short. Thus... // creating ArgTraits twice for unsigned short. Thus...
#ifdef _MSC_VER #ifdef _MSC_VER
@@ -123,7 +123,7 @@ struct ArgTraits<unsigned char> {
typedef ValueLike ValueCategory; typedef ValueLike ValueCategory;
}; };
// Microsoft implements size_t awkwardly. // Microsoft implements size_t awkwardly.
#if defined(_MSC_VER) && defined(_M_X64) #if defined(_MSC_VER) && defined(_M_X64)
/** /**
* size_ts have value-like semantics. * size_ts have value-like semantics.
@@ -205,4 +205,3 @@ void SetString(T &dst, const std::string &src)
} // namespace } // namespace
#endif #endif

View File

@@ -1,24 +1,24 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
/****************************************************************************** /******************************************************************************
* *
* file: StdOutput.h * file: StdOutput.h
* *
* Copyright (c) 2004, Michael E. Smoot * Copyright (c) 2004, Michael E. Smoot
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_STDCMDLINEOUTPUT_H #ifndef TCLAP_STDCMDLINEOUTPUT_H
#define TCLAP_STDCMDLINEOUTPUT_H #define TCLAP_STDCMDLINEOUTPUT_H
@@ -46,77 +46,77 @@ class StdOutput : public CmdLineOutput
public: public:
/** /**
* Prints the usage to stdout. Can be overridden to * Prints the usage to stdout. Can be overridden to
* produce alternative behavior. * produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
*/ */
virtual void usage(CmdLineInterface& c); virtual void usage(CmdLineInterface& c);
/** /**
* Prints the version to stdout. Can be overridden * Prints the version to stdout. Can be overridden
* to produce alternative behavior. * to produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
*/ */
virtual void version(CmdLineInterface& c); virtual void version(CmdLineInterface& c);
/** /**
* Prints (to stderr) an error message, short usage * Prints (to stderr) an error message, short usage
* Can be overridden to produce alternative behavior. * Can be overridden to produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
* \param e - The ArgException that caused the failure. * \param e - The ArgException that caused the failure.
*/ */
virtual void failure(CmdLineInterface& c, virtual void failure(CmdLineInterface& c,
ArgException& e ); ArgException& e );
protected: protected:
/** /**
* Writes a brief usage message with short args. * Writes a brief usage message with short args.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
* \param os - The stream to write the message to. * \param os - The stream to write the message to.
*/ */
void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; void _shortUsage( CmdLineInterface& c, std::ostream& os ) const;
/** /**
* Writes a longer usage message with long and short args, * Writes a longer usage message with long and short args,
* provides descriptions and prints message. * provides descriptions and prints message.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
* \param os - The stream to write the message to. * \param os - The stream to write the message to.
*/ */
void _longUsage( CmdLineInterface& c, std::ostream& os ) const; void _longUsage( CmdLineInterface& c, std::ostream& os ) const;
/** /**
* This function inserts line breaks and indents long strings * This function inserts line breaks and indents long strings
* according the params input. It will only break lines at spaces, * according the params input. It will only break lines at spaces,
* commas and pipes. * commas and pipes.
* \param os - The stream to be printed to. * \param os - The stream to be printed to.
* \param s - The string to be printed. * \param s - The string to be printed.
* \param maxWidth - The maxWidth allowed for the output line. * \param maxWidth - The maxWidth allowed for the output line.
* \param indentSpaces - The number of spaces to indent the first line. * \param indentSpaces - The number of spaces to indent the first line.
* \param secondLineOffset - The number of spaces to indent the second * \param secondLineOffset - The number of spaces to indent the second
* and all subsequent lines in addition to indentSpaces. * and all subsequent lines in addition to indentSpaces.
*/ */
void spacePrint( std::ostream& os, void spacePrint( std::ostream& os,
const std::string& s, const std::string& s,
int maxWidth, int maxWidth,
int indentSpaces, int indentSpaces,
int secondLineOffset ) const; int secondLineOffset ) const;
}; };
inline void StdOutput::version(CmdLineInterface& _cmd) inline void StdOutput::version(CmdLineInterface& _cmd)
{ {
std::string progName = _cmd.getProgramName(); std::string progName = _cmd.getProgramName();
std::string xversion = _cmd.getVersion(); std::string xversion = _cmd.getVersion();
std::cout << std::endl << progName << " version: " std::cout << std::endl << progName << " version: "
<< xversion << std::endl << std::endl; << xversion << std::endl << std::endl;
} }
inline void StdOutput::usage(CmdLineInterface& _cmd ) inline void StdOutput::usage(CmdLineInterface& _cmd )
{ {
std::cout << std::endl << "USAGE: " << std::endl << std::endl; std::cout << std::endl << "USAGE: " << std::endl << std::endl;
_shortUsage( _cmd, std::cout ); _shortUsage( _cmd, std::cout );
@@ -124,12 +124,12 @@ inline void StdOutput::usage(CmdLineInterface& _cmd )
_longUsage( _cmd, std::cout ); _longUsage( _cmd, std::cout );
std::cout << std::endl; std::cout << std::endl;
} }
inline void StdOutput::failure( CmdLineInterface& _cmd, inline void StdOutput::failure( CmdLineInterface& _cmd,
ArgException& e ) ArgException& e )
{ {
std::string progName = _cmd.getProgramName(); std::string progName = _cmd.getProgramName();
@@ -140,10 +140,10 @@ inline void StdOutput::failure( CmdLineInterface& _cmd,
{ {
std::cerr << "Brief USAGE: " << std::endl; std::cerr << "Brief USAGE: " << std::endl;
_shortUsage( _cmd, std::cerr ); _shortUsage( _cmd, std::cerr );
std::cerr << std::endl << "For complete USAGE and HELP type: " std::cerr << std::endl << "For complete USAGE and HELP type: "
<< std::endl << " " << progName << " --help" << std::endl << " " << progName << " --help"
<< std::endl << std::endl; << std::endl << std::endl;
} }
else else
@@ -152,8 +152,8 @@ inline void StdOutput::failure( CmdLineInterface& _cmd,
throw ExitException(1); throw ExitException(1);
} }
inline void inline void
StdOutput::_shortUsage( CmdLineInterface& _cmd, StdOutput::_shortUsage( CmdLineInterface& _cmd,
std::ostream& os ) const std::ostream& os ) const
{ {
std::list<Arg*> argList = _cmd.getArgList(); std::list<Arg*> argList = _cmd.getArgList();
@@ -167,7 +167,7 @@ StdOutput::_shortUsage( CmdLineInterface& _cmd,
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
{ {
s += " {"; s += " {";
for ( ArgVectorIterator it = xorList[i].begin(); for ( ArgVectorIterator it = xorList[i].begin();
it != xorList[i].end(); it++ ) it != xorList[i].end(); it++ )
s += (*it)->shortID() + "|"; s += (*it)->shortID() + "|";
@@ -179,7 +179,7 @@ StdOutput::_shortUsage( CmdLineInterface& _cmd,
if ( !xorHandler.contains( (*it) ) ) if ( !xorHandler.contains( (*it) ) )
s += " " + (*it)->shortID(); s += " " + (*it)->shortID();
// if the program name is too long, then adjust the second line offset // if the program name is too long, then adjust the second line offset
int secondLineOffset = static_cast<int>(progName.length()) + 2; int secondLineOffset = static_cast<int>(progName.length()) + 2;
if ( secondLineOffset > 75/2 ) if ( secondLineOffset > 75/2 )
secondLineOffset = static_cast<int>(75/2); secondLineOffset = static_cast<int>(75/2);
@@ -187,8 +187,8 @@ StdOutput::_shortUsage( CmdLineInterface& _cmd,
spacePrint( os, s, 75, 3, secondLineOffset ); spacePrint( os, s, 75, 3, secondLineOffset );
} }
inline void inline void
StdOutput::_longUsage( CmdLineInterface& _cmd, StdOutput::_longUsage( CmdLineInterface& _cmd,
std::ostream& os ) const std::ostream& os ) const
{ {
std::list<Arg*> argList = _cmd.getArgList(); std::list<Arg*> argList = _cmd.getArgList();
@@ -196,11 +196,11 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
XorHandler xorHandler = _cmd.getXorHandler(); XorHandler xorHandler = _cmd.getXorHandler();
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
// first the xor // first the xor
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
{ {
for ( ArgVectorIterator it = xorList[i].begin(); for ( ArgVectorIterator it = xorList[i].begin();
it != xorList[i].end(); it != xorList[i].end();
it++ ) it++ )
{ {
spacePrint( os, (*it)->longID(), 75, 3, 3 ); spacePrint( os, (*it)->longID(), 75, 3, 3 );
@@ -216,8 +216,8 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
for (ArgListIterator it = argList.begin(); it != argList.end(); it++) for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
if ( !xorHandler.contains( (*it) ) ) if ( !xorHandler.contains( (*it) ) )
{ {
spacePrint( os, (*it)->longID(), 75, 3, 3 ); spacePrint( os, (*it)->longID(), 75, 3, 3 );
spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
os << std::endl; os << std::endl;
} }
@@ -226,10 +226,10 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
spacePrint( os, message, 75, 3, 0 ); spacePrint( os, message, 75, 3, 0 );
} }
inline void StdOutput::spacePrint( std::ostream& os, inline void StdOutput::spacePrint( std::ostream& os,
const std::string& s, const std::string& s,
int maxWidth, int maxWidth,
int indentSpaces, int indentSpaces,
int secondLineOffset ) const int secondLineOffset ) const
{ {
int len = static_cast<int>(s.length()); int len = static_cast<int>(s.length());
@@ -242,19 +242,19 @@ inline void StdOutput::spacePrint( std::ostream& os,
{ {
// find the substring length // find the substring length
// int stringLen = std::min<int>( len - start, allowedLen ); // int stringLen = std::min<int>( len - start, allowedLen );
// doing it this way to support a VisualC++ 2005 bug // doing it this way to support a VisualC++ 2005 bug
using namespace std; using namespace std;
int stringLen = min<int>( len - start, allowedLen ); int stringLen = min<int>( len - start, allowedLen );
// trim the length so it doesn't end in middle of a word // trim the length so it doesn't end in middle of a word
if ( stringLen == allowedLen ) if ( stringLen == allowedLen )
while ( stringLen >= 0 && while ( stringLen >= 0 &&
s[stringLen+start] != ' ' && s[stringLen+start] != ' ' &&
s[stringLen+start] != ',' && s[stringLen+start] != ',' &&
s[stringLen+start] != '|' ) s[stringLen+start] != '|' )
stringLen--; stringLen--;
// ok, the word is longer than the line, so just split // ok, the word is longer than the line, so just split
// wherever the line ends // wherever the line ends
if ( stringLen <= 0 ) if ( stringLen <= 0 )
stringLen = allowedLen; stringLen = allowedLen;
@@ -264,7 +264,7 @@ inline void StdOutput::spacePrint( std::ostream& os,
if ( s[start+i] == '\n' ) if ( s[start+i] == '\n' )
stringLen = i+1; stringLen = i+1;
// print the indent // print the indent
for ( int i = 0; i < indentSpaces; i++ ) for ( int i = 0; i < indentSpaces; i++ )
os << " "; os << " ";
@@ -282,7 +282,7 @@ inline void StdOutput::spacePrint( std::ostream& os,
// so we don't start a line with a space // so we don't start a line with a space
while ( s[stringLen+start] == ' ' && start < len ) while ( s[stringLen+start] == ' ' && start < len )
start++; start++;
start += stringLen; start += stringLen;
} }
} }
@@ -295,4 +295,4 @@ inline void StdOutput::spacePrint( std::ostream& os,
} }
} //namespace TCLAP } //namespace TCLAP
#endif #endif

View File

@@ -1,24 +1,24 @@
/****************************************************************************** /******************************************************************************
* *
* file: SwitchArg.h * file: SwitchArg.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_SWITCH_ARG_H #ifndef TCLAP_SWITCH_ARG_H
@@ -61,17 +61,17 @@ class SwitchArg : public Arg
* used as a long flag on the command line. * used as a long flag on the command line.
* \param desc - A description of what the argument is for or * \param desc - A description of what the argument is for or
* does. * does.
* \param def - The default value for this Switch. * \param def - The default value for this Switch.
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
SwitchArg(const std::string& flag, SwitchArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool def = false, bool def = false,
Visitor* v = NULL); Visitor* v = NULL);
/** /**
* SwitchArg constructor. * SwitchArg constructor.
* \param flag - The one character flag that identifies this * \param flag - The one character flag that identifies this
@@ -85,14 +85,14 @@ class SwitchArg : public Arg
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
SwitchArg(const std::string& flag, SwitchArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
CmdLineInterface& parser, CmdLineInterface& parser,
bool def = false, bool def = false,
Visitor* v = NULL); Visitor* v = NULL);
/** /**
* Handles the processing of the argument. * Handles the processing of the argument.
* This re-implements the Arg version of this method to set the * This re-implements the Arg version of this method to set the
@@ -101,7 +101,7 @@ class SwitchArg : public Arg
* \param args - Mutable list of strings. Passed * \param args - Mutable list of strings. Passed
* in from main(). * in from main().
*/ */
virtual bool processArg(int* i, std::vector<std::string>& args); virtual bool processArg(int* i, std::vector<std::string>& args);
/** /**
* Checks a string to see if any of the chars in the string * Checks a string to see if any of the chars in the string
@@ -113,7 +113,7 @@ class SwitchArg : public Arg
* Returns bool, whether or not the switch has been set. * Returns bool, whether or not the switch has been set.
*/ */
bool getValue(); bool getValue();
virtual void reset(); virtual void reset();
private: private:
@@ -132,9 +132,9 @@ class SwitchArg : public Arg
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
//BEGIN SwitchArg.cpp //BEGIN SwitchArg.cpp
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
inline SwitchArg::SwitchArg(const std::string& flag, inline SwitchArg::SwitchArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool default_val, bool default_val,
Visitor* v ) Visitor* v )
: Arg(flag, name, desc, false, false, v), : Arg(flag, name, desc, false, false, v),
@@ -142,27 +142,27 @@ inline SwitchArg::SwitchArg(const std::string& flag,
_default( default_val ) _default( default_val )
{ } { }
inline SwitchArg::SwitchArg(const std::string& flag, inline SwitchArg::SwitchArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
CmdLineInterface& parser, CmdLineInterface& parser,
bool default_val, bool default_val,
Visitor* v ) Visitor* v )
: Arg(flag, name, desc, false, false, v), : Arg(flag, name, desc, false, false, v),
_value( default_val ), _value( default_val ),
_default(default_val) _default(default_val)
{ {
parser.add( this ); parser.add( this );
} }
inline bool SwitchArg::getValue() { return _value; } inline bool SwitchArg::getValue() { return _value; }
inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) inline bool SwitchArg::lastCombined(std::string& combinedSwitches )
{ {
for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
if ( combinedSwitches[i] != Arg::blankChar() ) if ( combinedSwitches[i] != Arg::blankChar() )
return false; return false;
return true; return true;
} }
@@ -173,32 +173,32 @@ inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches )
combinedSwitches[0] != Arg::flagStartString()[0] ) combinedSwitches[0] != Arg::flagStartString()[0] )
return false; return false;
// make sure it isn't a long name // make sure it isn't a long name
if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) ==
Arg::nameStartString() ) Arg::nameStartString() )
return false; return false;
// make sure the delimiter isn't in the string // make sure the delimiter isn't in the string
if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos )
return false; return false;
// ok, we're not specifying a ValueArg, so we know that we have // ok, we're not specifying a ValueArg, so we know that we have
// a combined switch list. // a combined switch list.
for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
if ( _flag.length() > 0 && if ( _flag.length() > 0 &&
combinedSwitches[i] == _flag[0] && combinedSwitches[i] == _flag[0] &&
_flag[0] != Arg::flagStartString()[0] ) _flag[0] != Arg::flagStartString()[0] )
{ {
// update the combined switches so this one is no longer present // update the combined switches so this one is no longer present
// this is necessary so that no unlabeled args are matched // this is necessary so that no unlabeled args are matched
// later in the processing. // later in the processing.
//combinedSwitches.erase(i,1); //combinedSwitches.erase(i,1);
combinedSwitches[i] = Arg::blankChar(); combinedSwitches[i] = Arg::blankChar();
return true; return true;
} }
// none of the switches passed in the list match. // none of the switches passed in the list match.
return false; return false;
} }
inline void SwitchArg::commonProcessing() inline void SwitchArg::commonProcessing()
@@ -207,7 +207,7 @@ inline void SwitchArg::commonProcessing()
throw(CmdLineParseException( throw(CmdLineParseException(
"Mutually exclusive argument already set!", toString())); "Mutually exclusive argument already set!", toString()));
if ( _alreadySet ) if ( _alreadySet )
throw(CmdLineParseException("Argument already set!", toString())); throw(CmdLineParseException("Argument already set!", toString()));
_alreadySet = true; _alreadySet = true;
@@ -235,16 +235,16 @@ inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args)
// if a substring matches the flag as part of a combination // if a substring matches the flag as part of a combination
else if ( combinedSwitchesMatch( args[*i] ) ) else if ( combinedSwitchesMatch( args[*i] ) )
{ {
// check again to ensure we don't misinterpret // check again to ensure we don't misinterpret
// this as a MultiSwitchArg // this as a MultiSwitchArg
if ( combinedSwitchesMatch( args[*i] ) ) if ( combinedSwitchesMatch( args[*i] ) )
throw(CmdLineParseException("Argument already set!", throw(CmdLineParseException("Argument already set!",
toString())); toString()));
commonProcessing(); commonProcessing();
// We only want to return true if we've found the last combined // We only want to return true if we've found the last combined
// match in the string, otherwise we return true so that other // match in the string, otherwise we return true so that other
// switches in the combination will have a chance to match. // switches in the combination will have a chance to match.
return lastCombined( args[*i] ); return lastCombined( args[*i] );
} }
@@ -255,7 +255,7 @@ inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args)
inline void SwitchArg::reset() inline void SwitchArg::reset()
{ {
Arg::reset(); Arg::reset();
_value = _default; _value = _default;
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
//End SwitchArg.cpp //End SwitchArg.cpp

View File

@@ -1,23 +1,23 @@
/****************************************************************************** /******************************************************************************
* *
* file: UnlabeledMultiArg.h * file: UnlabeledMultiArg.h
* *
* Copyright (c) 2003, Michael E. Smoot. * Copyright (c) 2003, Michael E. Smoot.
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H #ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H
@@ -33,7 +33,7 @@ namespace TCLAP {
/** /**
* Just like a MultiArg, except that the arguments are unlabeled. Basically, * Just like a MultiArg, except that the arguments are unlabeled. Basically,
* this Arg will slurp up everything that hasn't been matched to another * this Arg will slurp up everything that hasn't been matched to another
* Arg. * Arg.
*/ */
template<class T> template<class T>
@@ -52,9 +52,9 @@ class UnlabeledMultiArg : public MultiArg<T>
using MultiArg<T>::toString; using MultiArg<T>::toString;
public: public:
/** /**
* Constructor. * Constructor.
* \param name - The name of the Arg. Note that this is used for * \param name - The name of the Arg. Note that this is used for
* identification, not as a long flag. * identification, not as a long flag.
* \param desc - A description of what the argument is for or * \param desc - A description of what the argument is for or
@@ -77,7 +77,7 @@ class UnlabeledMultiArg : public MultiArg<T>
bool ignoreable = false, bool ignoreable = false,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* Constructor. * Constructor.
* \param name - The name of the Arg. Note that this is used for * \param name - The name of the Arg. Note that this is used for
* identification, not as a long flag. * identification, not as a long flag.
* \param desc - A description of what the argument is for or * \param desc - A description of what the argument is for or
@@ -101,9 +101,9 @@ class UnlabeledMultiArg : public MultiArg<T>
CmdLineInterface& parser, CmdLineInterface& parser,
bool ignoreable = false, bool ignoreable = false,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* Constructor. * Constructor.
* \param name - The name of the Arg. Note that this is used for * \param name - The name of the Arg. Note that this is used for
* identification, not as a long flag. * identification, not as a long flag.
* \param desc - A description of what the argument is for or * \param desc - A description of what the argument is for or
@@ -125,7 +125,7 @@ class UnlabeledMultiArg : public MultiArg<T>
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* Constructor. * Constructor.
* \param name - The name of the Arg. Note that this is used for * \param name - The name of the Arg. Note that this is used for
* identification, not as a long flag. * identification, not as a long flag.
* \param desc - A description of what the argument is for or * \param desc - A description of what the argument is for or
@@ -140,14 +140,14 @@ class UnlabeledMultiArg : public MultiArg<T>
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
UnlabeledMultiArg( const std::string& name, UnlabeledMultiArg( const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
Constraint<T>* constraint, Constraint<T>* constraint,
CmdLineInterface& parser, CmdLineInterface& parser,
bool ignoreable = false, bool ignoreable = false,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* Handles the processing of the argument. * Handles the processing of the argument.
* This re-implements the Arg version of this method to set the * This re-implements the Arg version of this method to set the
@@ -156,7 +156,7 @@ class UnlabeledMultiArg : public MultiArg<T>
* \param i - Pointer the the current argument in the list. * \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. Passed from main(). * \param args - Mutable list of strings. Passed from main().
*/ */
virtual bool processArg(int* i, std::vector<std::string>& args); virtual bool processArg(int* i, std::vector<std::string>& args);
/** /**
* Returns the a short id string. Used in the usage. * Returns the a short id string. Used in the usage.
@@ -184,28 +184,28 @@ class UnlabeledMultiArg : public MultiArg<T>
}; };
template<class T> template<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
const std::string& typeDesc, const std::string& typeDesc,
bool ignoreable, bool ignoreable,
Visitor* v) Visitor* v)
: MultiArg<T>("", name, desc, req, typeDesc, v) : MultiArg<T>("", name, desc, req, typeDesc, v)
{ {
_ignoreable = ignoreable; _ignoreable = ignoreable;
OptionalUnlabeledTracker::check(true, toString()); OptionalUnlabeledTracker::check(true, toString());
} }
template<class T> template<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
const std::string& typeDesc, const std::string& typeDesc,
CmdLineInterface& parser, CmdLineInterface& parser,
bool ignoreable, bool ignoreable,
Visitor* v) Visitor* v)
: MultiArg<T>("", name, desc, req, typeDesc, v) : MultiArg<T>("", name, desc, req, typeDesc, v)
{ {
_ignoreable = ignoreable; _ignoreable = ignoreable;
OptionalUnlabeledTracker::check(true, toString()); OptionalUnlabeledTracker::check(true, toString());
parser.add( this ); parser.add( this );
@@ -213,28 +213,28 @@ UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
template<class T> template<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
Constraint<T>* constraint, Constraint<T>* constraint,
bool ignoreable, bool ignoreable,
Visitor* v) Visitor* v)
: MultiArg<T>("", name, desc, req, constraint, v) : MultiArg<T>("", name, desc, req, constraint, v)
{ {
_ignoreable = ignoreable; _ignoreable = ignoreable;
OptionalUnlabeledTracker::check(true, toString()); OptionalUnlabeledTracker::check(true, toString());
} }
template<class T> template<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
Constraint<T>* constraint, Constraint<T>* constraint,
CmdLineInterface& parser, CmdLineInterface& parser,
bool ignoreable, bool ignoreable,
Visitor* v) Visitor* v)
: MultiArg<T>("", name, desc, req, constraint, v) : MultiArg<T>("", name, desc, req, constraint, v)
{ {
_ignoreable = ignoreable; _ignoreable = ignoreable;
OptionalUnlabeledTracker::check(true, toString()); OptionalUnlabeledTracker::check(true, toString());
parser.add( this ); parser.add( this );
@@ -242,7 +242,7 @@ UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
template<class T> template<class T>
bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args) bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args)
{ {
if ( _hasBlanks( args[*i] ) ) if ( _hasBlanks( args[*i] ) )
@@ -251,14 +251,14 @@ bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args)
// never ignore an unlabeled multi arg // never ignore an unlabeled multi arg
// always take the first value, regardless of the start string // always take the first value, regardless of the start string
_extractValue( args[(*i)] ); _extractValue( args[(*i)] );
/* /*
// continue taking args until we hit the end or a start string // continue taking args until we hit the end or a start string
while ( (unsigned int)(*i)+1 < args.size() && while ( (unsigned int)(*i)+1 < args.size() &&
args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
_extractValue( args[++(*i)] ); _extractValue( args[++(*i)] );
*/ */

View File

@@ -1,24 +1,24 @@
/****************************************************************************** /******************************************************************************
* *
* file: UnlabeledValueArg.h * file: UnlabeledValueArg.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H #ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H
@@ -72,18 +72,18 @@ class UnlabeledValueArg : public ValueArg<T>
* of the program. * of the program.
* \param ignoreable - Allows you to specify that this argument can be * \param ignoreable - Allows you to specify that this argument can be
* ignored if the '--' flag is set. This defaults to false (cannot * ignored if the '--' flag is set. This defaults to false (cannot
* be ignored) and should generally stay that way unless you have * be ignored) and should generally stay that way unless you have
* some special need for certain arguments to be ignored. * some special need for certain arguments to be ignored.
* \param v - Optional Vistor. You should leave this blank unless * \param v - Optional Vistor. You should leave this blank unless
* you have a very good reason. * you have a very good reason.
*/ */
UnlabeledValueArg( const std::string& name, UnlabeledValueArg( const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T value, T value,
const std::string& typeDesc, const std::string& typeDesc,
bool ignoreable = false, bool ignoreable = false,
Visitor* v = NULL); Visitor* v = NULL);
/** /**
* UnlabeledValueArg constructor. * UnlabeledValueArg constructor.
@@ -102,20 +102,20 @@ class UnlabeledValueArg : public ValueArg<T>
* \param parser - A CmdLine parser object to add this Arg to * \param parser - A CmdLine parser object to add this Arg to
* \param ignoreable - Allows you to specify that this argument can be * \param ignoreable - Allows you to specify that this argument can be
* ignored if the '--' flag is set. This defaults to false (cannot * ignored if the '--' flag is set. This defaults to false (cannot
* be ignored) and should generally stay that way unless you have * be ignored) and should generally stay that way unless you have
* some special need for certain arguments to be ignored. * some special need for certain arguments to be ignored.
* \param v - Optional Vistor. You should leave this blank unless * \param v - Optional Vistor. You should leave this blank unless
* you have a very good reason. * you have a very good reason.
*/ */
UnlabeledValueArg( const std::string& name, UnlabeledValueArg( const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T value, T value,
const std::string& typeDesc, const std::string& typeDesc,
CmdLineInterface& parser, CmdLineInterface& parser,
bool ignoreable = false, bool ignoreable = false,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* UnlabeledValueArg constructor. * UnlabeledValueArg constructor.
* \param name - A one word name for the argument. Note that this is used for * \param name - A one word name for the argument. Note that this is used for
@@ -130,20 +130,20 @@ class UnlabeledValueArg : public ValueArg<T>
* to constrain this Arg. * to constrain this Arg.
* \param ignoreable - Allows you to specify that this argument can be * \param ignoreable - Allows you to specify that this argument can be
* ignored if the '--' flag is set. This defaults to false (cannot * ignored if the '--' flag is set. This defaults to false (cannot
* be ignored) and should generally stay that way unless you have * be ignored) and should generally stay that way unless you have
* some special need for certain arguments to be ignored. * some special need for certain arguments to be ignored.
* \param v - Optional Vistor. You should leave this blank unless * \param v - Optional Vistor. You should leave this blank unless
* you have a very good reason. * you have a very good reason.
*/ */
UnlabeledValueArg( const std::string& name, UnlabeledValueArg( const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T value, T value,
Constraint<T>* constraint, Constraint<T>* constraint,
bool ignoreable = false, bool ignoreable = false,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* UnlabeledValueArg constructor. * UnlabeledValueArg constructor.
* \param name - A one word name for the argument. Note that this is used for * \param name - A one word name for the argument. Note that this is used for
@@ -159,29 +159,29 @@ class UnlabeledValueArg : public ValueArg<T>
* \param parser - A CmdLine parser object to add this Arg to * \param parser - A CmdLine parser object to add this Arg to
* \param ignoreable - Allows you to specify that this argument can be * \param ignoreable - Allows you to specify that this argument can be
* ignored if the '--' flag is set. This defaults to false (cannot * ignored if the '--' flag is set. This defaults to false (cannot
* be ignored) and should generally stay that way unless you have * be ignored) and should generally stay that way unless you have
* some special need for certain arguments to be ignored. * some special need for certain arguments to be ignored.
* \param v - Optional Vistor. You should leave this blank unless * \param v - Optional Vistor. You should leave this blank unless
* you have a very good reason. * you have a very good reason.
*/ */
UnlabeledValueArg( const std::string& name, UnlabeledValueArg( const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T value, T value,
Constraint<T>* constraint, Constraint<T>* constraint,
CmdLineInterface& parser, CmdLineInterface& parser,
bool ignoreable = false, bool ignoreable = false,
Visitor* v = NULL); Visitor* v = NULL);
/** /**
* Handles the processing of the argument. * Handles the processing of the argument.
* This re-implements the Arg version of this method to set the * This re-implements the Arg version of this method to set the
* _value of the argument appropriately. Handling specific to * _value of the argument appropriately. Handling specific to
* unlabled arguments. * unlabled arguments.
* \param i - Pointer the the current argument in the list. * \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. * \param args - Mutable list of strings.
*/ */
virtual bool processArg(int* i, std::vector<std::string>& args); virtual bool processArg(int* i, std::vector<std::string>& args);
/** /**
* Overrides shortID for specific behavior. * Overrides shortID for specific behavior.
@@ -210,15 +210,15 @@ class UnlabeledValueArg : public ValueArg<T>
* Constructor implemenation. * Constructor implemenation.
*/ */
template<class T> template<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T val, T val,
const std::string& typeDesc, const std::string& typeDesc,
bool ignoreable, bool ignoreable,
Visitor* v) Visitor* v)
: ValueArg<T>("", name, desc, req, val, typeDesc, v) : ValueArg<T>("", name, desc, req, val, typeDesc, v)
{ {
_ignoreable = ignoreable; _ignoreable = ignoreable;
OptionalUnlabeledTracker::check(req, toString()); OptionalUnlabeledTracker::check(req, toString());
@@ -226,8 +226,8 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
} }
template<class T> template<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T val, T val,
const std::string& typeDesc, const std::string& typeDesc,
@@ -235,7 +235,7 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
bool ignoreable, bool ignoreable,
Visitor* v) Visitor* v)
: ValueArg<T>("", name, desc, req, val, typeDesc, v) : ValueArg<T>("", name, desc, req, val, typeDesc, v)
{ {
_ignoreable = ignoreable; _ignoreable = ignoreable;
OptionalUnlabeledTracker::check(req, toString()); OptionalUnlabeledTracker::check(req, toString());
parser.add( this ); parser.add( this );
@@ -245,22 +245,22 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
* Constructor implemenation. * Constructor implemenation.
*/ */
template<class T> template<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T val, T val,
Constraint<T>* constraint, Constraint<T>* constraint,
bool ignoreable, bool ignoreable,
Visitor* v) Visitor* v)
: ValueArg<T>("", name, desc, req, val, constraint, v) : ValueArg<T>("", name, desc, req, val, constraint, v)
{ {
_ignoreable = ignoreable; _ignoreable = ignoreable;
OptionalUnlabeledTracker::check(req, toString()); OptionalUnlabeledTracker::check(req, toString());
} }
template<class T> template<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T val, T val,
Constraint<T>* constraint, Constraint<T>* constraint,
@@ -268,7 +268,7 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
bool ignoreable, bool ignoreable,
Visitor* v) Visitor* v)
: ValueArg<T>("", name, desc, req, val, constraint, v) : ValueArg<T>("", name, desc, req, val, constraint, v)
{ {
_ignoreable = ignoreable; _ignoreable = ignoreable;
OptionalUnlabeledTracker::check(req, toString()); OptionalUnlabeledTracker::check(req, toString());
parser.add( this ); parser.add( this );
@@ -278,17 +278,17 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
* Implementation of processArg(). * Implementation of processArg().
*/ */
template<class T> template<class T>
bool UnlabeledValueArg<T>::processArg(int *i, std::vector<std::string>& args) bool UnlabeledValueArg<T>::processArg(int *i, std::vector<std::string>& args)
{ {
if ( _alreadySet ) if ( _alreadySet )
return false; return false;
if ( _hasBlanks( args[*i] ) ) if ( _hasBlanks( args[*i] ) )
return false; return false;
// never ignore an unlabeled arg // never ignore an unlabeled arg
_extractValue( args[*i] ); _extractValue( args[*i] );
_alreadySet = true; _alreadySet = true;
return true; return true;
@@ -313,8 +313,8 @@ std::string UnlabeledValueArg<T>::longID(const std::string& val) const
static_cast<void>(val); // Ignore input, don't warn static_cast<void>(val); // Ignore input, don't warn
// Ideally we would like to be able to use RTTI to return the name // Ideally we would like to be able to use RTTI to return the name
// of the type required for this argument. However, g++ at least, // of the type required for this argument. However, g++ at least,
// doesn't appear to return terribly useful "names" of the types. // doesn't appear to return terribly useful "names" of the types.
return std::string("<") + _typeDesc + ">"; return std::string("<") + _typeDesc + ">";
} }

View File

@@ -1,23 +1,23 @@
/****************************************************************************** /******************************************************************************
* *
* file: ValueArg.h * file: ValueArg.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_VALUE_ARGUMENT_H #ifndef TCLAP_VALUE_ARGUMENT_H
@@ -40,7 +40,7 @@ namespace TCLAP {
* Instead use an UnlabeledValueArg. * Instead use an UnlabeledValueArg.
*/ */
template<class T> template<class T>
class ValueArg : public Arg class ValueArg : public Arg
{ {
protected: protected:
@@ -67,7 +67,7 @@ class ValueArg : public Arg
std::string _typeDesc; std::string _typeDesc;
/** /**
* A Constraint this Arg must conform to. * A Constraint this Arg must conform to.
*/ */
Constraint<T>* _constraint; Constraint<T>* _constraint;
@@ -75,7 +75,7 @@ class ValueArg : public Arg
* Extracts the value from the string. * Extracts the value from the string.
* Attempts to parse string as type T, if this fails an exception * Attempts to parse string as type T, if this fails an exception
* is thrown. * is thrown.
* \param val - value to be parsed. * \param val - value to be parsed.
*/ */
void _extractValue( const std::string& val ); void _extractValue( const std::string& val );
@@ -83,9 +83,9 @@ class ValueArg : public Arg
/** /**
* Labeled ValueArg constructor. * Labeled ValueArg constructor.
* You could conceivably call this constructor with a blank flag, * You could conceivably call this constructor with a blank flag,
* but that would make you a bad person. It would also cause * but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument, * an exception to be thrown. If you want an unlabeled argument,
* use the other constructor. * use the other constructor.
* \param flag - The one character flag that identifies this * \param flag - The one character flag that identifies this
* argument on the command line. * argument on the command line.
@@ -104,20 +104,20 @@ class ValueArg : public Arg
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
ValueArg( const std::string& flag, ValueArg( const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T value, T value,
const std::string& typeDesc, const std::string& typeDesc,
Visitor* v = NULL); Visitor* v = NULL);
/** /**
* Labeled ValueArg constructor. * Labeled ValueArg constructor.
* You could conceivably call this constructor with a blank flag, * You could conceivably call this constructor with a blank flag,
* but that would make you a bad person. It would also cause * but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument, * an exception to be thrown. If you want an unlabeled argument,
* use the other constructor. * use the other constructor.
* \param flag - The one character flag that identifies this * \param flag - The one character flag that identifies this
* argument on the command line. * argument on the command line.
@@ -137,20 +137,20 @@ class ValueArg : public Arg
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
ValueArg( const std::string& flag, ValueArg( const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T value, T value,
const std::string& typeDesc, const std::string& typeDesc,
CmdLineInterface& parser, CmdLineInterface& parser,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* Labeled ValueArg constructor. * Labeled ValueArg constructor.
* You could conceivably call this constructor with a blank flag, * You could conceivably call this constructor with a blank flag,
* but that would make you a bad person. It would also cause * but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument, * an exception to be thrown. If you want an unlabeled argument,
* use the other constructor. * use the other constructor.
* \param flag - The one character flag that identifies this * \param flag - The one character flag that identifies this
* argument on the command line. * argument on the command line.
@@ -168,20 +168,20 @@ class ValueArg : public Arg
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
ValueArg( const std::string& flag, ValueArg( const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T value, T value,
Constraint<T>* constraint, Constraint<T>* constraint,
CmdLineInterface& parser, CmdLineInterface& parser,
Visitor* v = NULL ); Visitor* v = NULL );
/** /**
* Labeled ValueArg constructor. * Labeled ValueArg constructor.
* You could conceivably call this constructor with a blank flag, * You could conceivably call this constructor with a blank flag,
* but that would make you a bad person. It would also cause * but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument, * an exception to be thrown. If you want an unlabeled argument,
* use the other constructor. * use the other constructor.
* \param flag - The one character flag that identifies this * \param flag - The one character flag that identifies this
* argument on the command line. * argument on the command line.
@@ -198,10 +198,10 @@ class ValueArg : public Arg
* \param v - An optional visitor. You probably should not * \param v - An optional visitor. You probably should not
* use this unless you have a very good reason. * use this unless you have a very good reason.
*/ */
ValueArg( const std::string& flag, ValueArg( const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T value, T value,
Constraint<T>* constraint, Constraint<T>* constraint,
Visitor* v = NULL ); Visitor* v = NULL );
@@ -212,10 +212,10 @@ class ValueArg : public Arg
* _value of the argument appropriately. It knows the difference * _value of the argument appropriately. It knows the difference
* between labeled and unlabeled. * between labeled and unlabeled.
* \param i - Pointer the the current argument in the list. * \param i - Pointer the the current argument in the list.
* \param args - Mutable list of strings. Passed * \param args - Mutable list of strings. Passed
* in from main(). * in from main().
*/ */
virtual bool processArg(int* i, std::vector<std::string>& args); virtual bool processArg(int* i, std::vector<std::string>& args);
/** /**
* Returns the value of the argument. * Returns the value of the argument.
@@ -233,7 +233,7 @@ class ValueArg : public Arg
* \param val - value to be used. * \param val - value to be used.
*/ */
virtual std::string longID(const std::string& val = "val") const; virtual std::string longID(const std::string& val = "val") const;
virtual void reset() ; virtual void reset() ;
private: private:
@@ -249,10 +249,10 @@ private:
* Constructor implementation. * Constructor implementation.
*/ */
template<class T> template<class T>
ValueArg<T>::ValueArg(const std::string& flag, ValueArg<T>::ValueArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T val, T val,
const std::string& typeDesc, const std::string& typeDesc,
Visitor* v) Visitor* v)
@@ -264,10 +264,10 @@ ValueArg<T>::ValueArg(const std::string& flag,
{ } { }
template<class T> template<class T>
ValueArg<T>::ValueArg(const std::string& flag, ValueArg<T>::ValueArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T val, T val,
const std::string& typeDesc, const std::string& typeDesc,
CmdLineInterface& parser, CmdLineInterface& parser,
@@ -277,15 +277,15 @@ ValueArg<T>::ValueArg(const std::string& flag,
_default( val ), _default( val ),
_typeDesc( typeDesc ), _typeDesc( typeDesc ),
_constraint( NULL ) _constraint( NULL )
{ {
parser.add( this ); parser.add( this );
} }
template<class T> template<class T>
ValueArg<T>::ValueArg(const std::string& flag, ValueArg<T>::ValueArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T val, T val,
Constraint<T>* constraint, Constraint<T>* constraint,
Visitor* v) Visitor* v)
@@ -297,10 +297,10 @@ ValueArg<T>::ValueArg(const std::string& flag,
{ } { }
template<class T> template<class T>
ValueArg<T>::ValueArg(const std::string& flag, ValueArg<T>::ValueArg(const std::string& flag,
const std::string& name, const std::string& name,
const std::string& desc, const std::string& desc,
bool req, bool req,
T val, T val,
Constraint<T>* constraint, Constraint<T>* constraint,
CmdLineInterface& parser, CmdLineInterface& parser,
@@ -310,7 +310,7 @@ ValueArg<T>::ValueArg(const std::string& flag,
_default( val ), _default( val ),
_typeDesc( constraint->shortID() ), _typeDesc( constraint->shortID() ),
_constraint( constraint ) _constraint( constraint )
{ {
parser.add( this ); parser.add( this );
} }
@@ -344,22 +344,22 @@ bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
{ {
if ( _xorSet ) if ( _xorSet )
throw( CmdLineParseException( throw( CmdLineParseException(
"Mutually exclusive argument already set!", "Mutually exclusive argument already set!",
toString()) ); toString()) );
else else
throw( CmdLineParseException("Argument already set!", throw( CmdLineParseException("Argument already set!",
toString()) ); toString()) );
} }
if ( Arg::delimiter() != ' ' && value == "" ) if ( Arg::delimiter() != ' ' && value == "" )
throw( ArgParseException( throw( ArgParseException(
"Couldn't find delimiter for this argument!", "Couldn't find delimiter for this argument!",
toString() ) ); toString() ) );
if ( value == "" ) if ( value == "" )
{ {
(*i)++; (*i)++;
if ( static_cast<unsigned int>(*i) < args.size() ) if ( static_cast<unsigned int>(*i) < args.size() )
_extractValue( args[*i] ); _extractValue( args[*i] );
else else
throw( ArgParseException("Missing a value for this argument!", throw( ArgParseException("Missing a value for this argument!",
@@ -367,11 +367,11 @@ bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
} }
else else
_extractValue( value ); _extractValue( value );
_alreadySet = true; _alreadySet = true;
_checkWithVisitor(); _checkWithVisitor();
return true; return true;
} }
else else
return false; return false;
} }
@@ -383,7 +383,7 @@ template<class T>
std::string ValueArg<T>::shortID(const std::string& val) const std::string ValueArg<T>::shortID(const std::string& val) const
{ {
static_cast<void>(val); // Ignore input, don't warn static_cast<void>(val); // Ignore input, don't warn
return Arg::shortID( _typeDesc ); return Arg::shortID( _typeDesc );
} }
/** /**
@@ -393,22 +393,22 @@ template<class T>
std::string ValueArg<T>::longID(const std::string& val) const std::string ValueArg<T>::longID(const std::string& val) const
{ {
static_cast<void>(val); // Ignore input, don't warn static_cast<void>(val); // Ignore input, don't warn
return Arg::longID( _typeDesc ); return Arg::longID( _typeDesc );
} }
template<class T> template<class T>
void ValueArg<T>::_extractValue( const std::string& val ) void ValueArg<T>::_extractValue( const std::string& val )
{ {
try { try {
ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory()); ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory());
} catch( ArgParseException &e) { } catch( ArgParseException &e) {
throw ArgParseException(e.error(), toString()); throw ArgParseException(e.error(), toString());
} }
if ( _constraint != NULL ) if ( _constraint != NULL )
if ( ! _constraint->check( _value ) ) if ( ! _constraint->check( _value ) )
throw( CmdLineParseException( "Value '" + val + throw( CmdLineParseException( "Value '" + val +
+ "' does not meet constraint: " + "' does not meet constraint: "
+ _constraint->description(), + _constraint->description(),
toString() ) ); toString() ) );
} }

View File

@@ -1,24 +1,24 @@
/****************************************************************************** /******************************************************************************
* *
* file: ValuesConstraint.h * file: ValuesConstraint.h
* *
* Copyright (c) 2005, Michael E. Smoot * Copyright (c) 2005, Michael E. Smoot
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_VALUESCONSTRAINT_H #ifndef TCLAP_VALUESCONSTRAINT_H
#define TCLAP_VALUESCONSTRAINT_H #define TCLAP_VALUESCONSTRAINT_H
@@ -54,10 +54,10 @@ class ValuesConstraint : public Constraint<T>
public: public:
/** /**
* Constructor. * Constructor.
* \param allowed - vector of allowed values. * \param allowed - vector of allowed values.
*/ */
ValuesConstraint(std::vector<T>& allowed); ValuesConstraint(std::vector<T>& allowed);
/** /**
* Virtual destructor. * Virtual destructor.
@@ -65,7 +65,7 @@ class ValuesConstraint : public Constraint<T>
virtual ~ValuesConstraint() {} virtual ~ValuesConstraint() {}
/** /**
* Returns a description of the Constraint. * Returns a description of the Constraint.
*/ */
virtual std::string description() const; virtual std::string description() const;
@@ -77,14 +77,14 @@ class ValuesConstraint : public Constraint<T>
/** /**
* The method used to verify that the value parsed from the command * The method used to verify that the value parsed from the command
* line meets the constraint. * line meets the constraint.
* \param value - The value that will be checked. * \param value - The value that will be checked.
*/ */
virtual bool check(const T& value) const; virtual bool check(const T& value) const;
protected: protected:
/** /**
* The list of valid values. * The list of valid values.
*/ */
std::vector<T> _allowed; std::vector<T> _allowed;
@@ -99,7 +99,7 @@ template<class T>
ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed) ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed)
: _allowed(allowed), : _allowed(allowed),
_typeDesc("") _typeDesc("")
{ {
for ( unsigned int i = 0; i < _allowed.size(); i++ ) for ( unsigned int i = 0; i < _allowed.size(); i++ )
{ {
@@ -113,7 +113,7 @@ ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed)
os << _allowed[i]; os << _allowed[i];
std::string temp( os.str() ); std::string temp( os.str() );
if ( i > 0 ) if ( i > 0 )
_typeDesc += "|"; _typeDesc += "|";
@@ -126,23 +126,22 @@ bool ValuesConstraint<T>::check( const T& val ) const
{ {
if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() )
return false; return false;
else else
return true; return true;
} }
template<class T> template<class T>
std::string ValuesConstraint<T>::shortID() const std::string ValuesConstraint<T>::shortID() const
{ {
return _typeDesc; return _typeDesc;
} }
template<class T> template<class T>
std::string ValuesConstraint<T>::description() const std::string ValuesConstraint<T>::description() const
{ {
return _typeDesc; return _typeDesc;
} }
} //namespace TCLAP } //namespace TCLAP
#endif #endif

View File

@@ -1,24 +1,24 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
/****************************************************************************** /******************************************************************************
* *
* file: VersionVisitor.h * file: VersionVisitor.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_VERSION_VISITOR_H #ifndef TCLAP_VERSION_VISITOR_H
@@ -51,7 +51,7 @@ class VersionVisitor: public Visitor
CmdLineInterface* _cmd; CmdLineInterface* _cmd;
/** /**
* The output object. * The output object.
*/ */
CmdLineOutput** _out; CmdLineOutput** _out;
@@ -59,19 +59,19 @@ class VersionVisitor: public Visitor
/** /**
* Constructor. * Constructor.
* \param cmd - The CmdLine the output is generated for. * \param cmd - The CmdLine the output is generated for.
* \param out - The type of output. * \param out - The type of output.
*/ */
VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out )
: Visitor(), _cmd( cmd ), _out( out ) { } : Visitor(), _cmd( cmd ), _out( out ) { }
/** /**
* Calls the version method of the output object using the * Calls the version method of the output object using the
* specified CmdLine. * specified CmdLine.
*/ */
void visit() { void visit() {
(*_out)->version(*_cmd); (*_out)->version(*_cmd);
throw ExitException(0); throw ExitException(0);
} }
}; };

View File

@@ -1,23 +1,23 @@
/****************************************************************************** /******************************************************************************
* *
* file: Visitor.h * file: Visitor.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_VISITOR_H #ifndef TCLAP_VISITOR_H

View File

@@ -1,24 +1,24 @@
/****************************************************************************** /******************************************************************************
* *
* file: XorHandler.h * file: XorHandler.h
* *
* Copyright (c) 2003, Michael E. Smoot . * Copyright (c) 2003, Michael E. Smoot .
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_XORHANDLER_H #ifndef TCLAP_XORHANDLER_H
#define TCLAP_XORHANDLER_H #define TCLAP_XORHANDLER_H
@@ -56,12 +56,12 @@ class XorHandler
* \param ors - list of Arg* that will be xor'd. * \param ors - list of Arg* that will be xor'd.
*/ */
void add( std::vector<Arg*>& ors ); void add( std::vector<Arg*>& ors );
/** /**
* Checks whether the specified Arg is in one of the xor lists and * Checks whether the specified Arg is in one of the xor lists and
* if it does match one, returns the size of the xor list that the * if it does match one, returns the size of the xor list that the
* Arg matched. If the Arg matches, then it also sets the rest of * Arg matched. If the Arg matches, then it also sets the rest of
* the Arg's in the list. You shouldn't use this. * the Arg's in the list. You shouldn't use this.
* \param a - The Arg to be checked. * \param a - The Arg to be checked.
*/ */
int check( const Arg* a ); int check( const Arg* a );
@@ -84,7 +84,7 @@ class XorHandler
*/ */
bool contains( const Arg* a ); bool contains( const Arg* a );
std::vector< std::vector<Arg*> >& getXorList(); std::vector< std::vector<Arg*> >& getXorList();
}; };
@@ -93,24 +93,24 @@ class XorHandler
//BEGIN XOR.cpp //BEGIN XOR.cpp
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
inline void XorHandler::add( std::vector<Arg*>& ors ) inline void XorHandler::add( std::vector<Arg*>& ors )
{ {
_orList.push_back( ors ); _orList.push_back( ors );
} }
inline int XorHandler::check( const Arg* a ) inline int XorHandler::check( const Arg* a )
{ {
// iterate over each XOR list // iterate over each XOR list
for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ ) for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ )
{ {
// if the XOR list contains the arg.. // if the XOR list contains the arg..
ArgVectorIterator ait = std::find( _orList[i].begin(), ArgVectorIterator ait = std::find( _orList[i].begin(),
_orList[i].end(), a ); _orList[i].end(), a );
if ( ait != _orList[i].end() ) if ( ait != _orList[i].end() )
{ {
// first check to see if a mutually exclusive switch // first check to see if a mutually exclusive switch
// has not already been set // has not already been set
for ( ArgVectorIterator it = _orList[i].begin(); for ( ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end(); it != _orList[i].end();
it++ ) it++ )
if ( a != (*it) && (*it)->isSet() ) if ( a != (*it) && (*it)->isSet() )
throw(CmdLineParseException( throw(CmdLineParseException(
@@ -118,8 +118,8 @@ inline int XorHandler::check( const Arg* a )
(*it)->toString())); (*it)->toString()));
// go through and set each arg that is not a // go through and set each arg that is not a
for ( ArgVectorIterator it = _orList[i].begin(); for ( ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end(); it != _orList[i].end();
it++ ) it++ )
if ( a != (*it) ) if ( a != (*it) )
(*it)->xorSet(); (*it)->xorSet();
@@ -141,16 +141,16 @@ inline int XorHandler::check( const Arg* a )
inline bool XorHandler::contains( const Arg* a ) inline bool XorHandler::contains( const Arg* a )
{ {
for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ ) for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ )
for ( ArgVectorIterator it = _orList[i].begin(); for ( ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end(); it != _orList[i].end();
it++ ) it++ )
if ( a == (*it) ) if ( a == (*it) )
return true; return true;
return false; return false;
} }
inline std::vector< std::vector<Arg*> >& XorHandler::getXorList() inline std::vector< std::vector<Arg*> >& XorHandler::getXorList()
{ {
return _orList; return _orList;
} }
@@ -163,4 +163,4 @@ inline std::vector< std::vector<Arg*> >& XorHandler::getXorList()
} //namespace TCLAP } //namespace TCLAP
#endif #endif

View File

@@ -1,24 +1,24 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
/****************************************************************************** /******************************************************************************
* *
* file: ZshCompletionOutput.h * file: ZshCompletionOutput.h
* *
* Copyright (c) 2006, Oliver Kiddle * Copyright (c) 2006, Oliver Kiddle
* All rights reverved. * All rights reverved.
* *
* See the file COPYING in the top directory of this distribution for * See the file COPYING in the top directory of this distribution for
* more information. * more information.
* *
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
* *
*****************************************************************************/ *****************************************************************************/
#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H #ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H
#define TCLAP_ZSHCOMPLETIONOUTPUT_H #define TCLAP_ZSHCOMPLETIONOUTPUT_H
@@ -48,24 +48,24 @@ class ZshCompletionOutput : public CmdLineOutput
ZshCompletionOutput(); ZshCompletionOutput();
/** /**
* Prints the usage to stdout. Can be overridden to * Prints the usage to stdout. Can be overridden to
* produce alternative behavior. * produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
*/ */
virtual void usage(CmdLineInterface& c); virtual void usage(CmdLineInterface& c);
/** /**
* Prints the version to stdout. Can be overridden * Prints the version to stdout. Can be overridden
* to produce alternative behavior. * to produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
*/ */
virtual void version(CmdLineInterface& c); virtual void version(CmdLineInterface& c);
/** /**
* Prints (to stderr) an error message, short usage * Prints (to stderr) an error message, short usage
* Can be overridden to produce alternative behavior. * Can be overridden to produce alternative behavior.
* \param c - The CmdLine object the output is generated for. * \param c - The CmdLine object the output is generated for.
* \param e - The ArgException that caused the failure. * \param e - The ArgException that caused the failure.
*/ */
virtual void failure(CmdLineInterface& c, virtual void failure(CmdLineInterface& c,
ArgException& e ); ArgException& e );
@@ -272,7 +272,7 @@ inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Ar
{ {
XorHandler xorHandler = _cmd.getXorHandler(); XorHandler xorHandler = _cmd.getXorHandler();
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
if (a->getName() == "help" || a->getName() == "version") if (a->getName() == "help" || a->getName() == "version")
{ {
return "(-)"; return "(-)";
@@ -309,13 +309,13 @@ inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Ar
return list.str(); return list.str();
} }
} }
// wasn't found in xor list // wasn't found in xor list
if (!a->getFlag().empty()) { if (!a->getFlag().empty()) {
list << "(" << a->flagStartChar() << a->getFlag() << ' ' << list << "(" << a->flagStartChar() << a->getFlag() << ' ' <<
a->nameStartString() << a->getName() << ')'; a->nameStartString() << a->getName() << ')';
} }
return list.str(); return list.str();
} }