mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-06 01:16:50 +08:00
14
README.md
14
README.md
@@ -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.
|
||||
|
||||
For example, the following output is created by analyzing this image:
|
||||
For example, the following output is created by analyzing this image:
|
||||

|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Detailed command line usage:
|
||||
```
|
||||
user@linux:~/openalpr$ alpr --help
|
||||
|
||||
USAGE:
|
||||
USAGE:
|
||||
|
||||
alpr [-t <region code>] [-r <runtime_dir>] [-n <topN>]
|
||||
[--seek <integer_ms>] [-c <country_code>]
|
||||
@@ -47,7 +47,7 @@ USAGE:
|
||||
<image_file_path>
|
||||
|
||||
|
||||
Where:
|
||||
Where:
|
||||
|
||||
-t <region code>, --template_region <region code>
|
||||
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
|
||||
|
||||
-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
|
||||
|
||||
--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
|
||||
|
||||
-d, --detect_region
|
||||
@@ -100,7 +100,7 @@ OpenALPR compiles and runs on Linux, Mac OSX and Windows.
|
||||
|
||||
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/)
|
||||
|
||||
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
|
||||
http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
|
||||
|
@@ -14,7 +14,7 @@ ocr_min_font_point = 6
|
||||
; Minimum OCR confidence percent to consider.
|
||||
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
|
||||
postprocess_confidence_skip_level = 75
|
||||
|
||||
@@ -110,7 +110,3 @@ min_plate_size_width_px = 100
|
||||
min_plate_size_height_px = 20
|
||||
|
||||
ocr_language = leu
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
base @@@####
|
||||
base @@@####
|
||||
base @@@###
|
||||
base ###@@@
|
||||
al #@##@##
|
||||
al ##@##@#
|
||||
al #@##@##
|
||||
al ##@##@#
|
||||
al @@#####
|
||||
al #####@@
|
||||
al #@####@
|
||||
|
@@ -1,26 +1,26 @@
|
||||
project(src)
|
||||
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
|
||||
SET(OpenCV_DIR "${CMAKE_SOURCE_DIR}/../libraries/opencv/")
|
||||
SET(Tesseract_DIR "${CMAKE_SOURCE_DIR}/../libraries/tesseract-ocr")
|
||||
|
||||
|
||||
include_directories(
|
||||
${Tesseract_DIR}/api
|
||||
${Tesseract_DIR}/ccutil/
|
||||
${Tesseract_DIR}/ccstruct/
|
||||
${Tesseract_DIR}/ccmain/
|
||||
)
|
||||
|
||||
|
||||
IF (WIN32)
|
||||
add_definitions( -DWINDOWS)
|
||||
add_definitions( -DNOMINMAX)
|
||||
|
||||
link_directories( ${Tesseract_DIR}/vs2008/LIB_Release/ )
|
||||
|
||||
link_directories( ${Tesseract_DIR}/vs2008/LIB_Release/ )
|
||||
ELSE()
|
||||
|
||||
link_directories( ${Tesseract_DIR}/api/.libs/ )
|
||||
link_directories( ${Tesseract_DIR}/api/.libs/ )
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@ ADD_EXECUTABLE( alpr main.cpp )
|
||||
|
||||
IF (WIN32)
|
||||
# Extra linker dependencies for Windows
|
||||
TARGET_LINK_LIBRARIES(alpr
|
||||
TARGET_LINK_LIBRARIES(alpr
|
||||
openalpr
|
||||
support
|
||||
${OpenCV_LIBS}
|
||||
${OpenCV_LIBS}
|
||||
libtesseract302-static
|
||||
liblept168
|
||||
liblept168-static-mtdll
|
||||
@@ -54,17 +54,16 @@ IF (WIN32)
|
||||
zlib125-static-mtdll
|
||||
ws2_32.lib
|
||||
)
|
||||
|
||||
|
||||
ELSE()
|
||||
|
||||
TARGET_LINK_LIBRARIES(alpr
|
||||
TARGET_LINK_LIBRARIES(alpr
|
||||
openalpr
|
||||
support
|
||||
${OpenCV_LIBS}
|
||||
${OpenCV_LIBS}
|
||||
tesseract
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
|
||||
add_subdirectory(openalpr)
|
||||
add_subdirectory(misc_utilities)
|
||||
|
||||
|
532
src/main.cpp
532
src/main.cpp
@@ -1,268 +1,264 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
|
||||
|
||||
#include "tclap/CmdLine.h"
|
||||
#include "support/filesystem.h"
|
||||
#include "support/timing.h"
|
||||
#include "alpr.h"
|
||||
|
||||
|
||||
|
||||
const std::string MAIN_WINDOW_NAME = "ALPR main window";
|
||||
|
||||
|
||||
const bool SAVE_LAST_VIDEO_STILL = false;
|
||||
const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg";
|
||||
|
||||
|
||||
/** Function Headers */
|
||||
bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson);
|
||||
|
||||
|
||||
bool measureProcessingTime = false;
|
||||
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
std::string filename;
|
||||
std::string runtimePath = "";
|
||||
bool outputJson = false;
|
||||
int seektoms = 0;
|
||||
bool detectRegion = false;
|
||||
std::string templateRegion;
|
||||
std::string country;
|
||||
int topn;
|
||||
|
||||
try {
|
||||
|
||||
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::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<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<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 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);
|
||||
|
||||
cmd.add( fileArg );
|
||||
cmd.add( countryCodeArg );
|
||||
cmd.add( seekToMsArg );
|
||||
cmd.add( topNArg );
|
||||
cmd.add( runtimeDirArg );
|
||||
cmd.add( templateRegionArg );
|
||||
|
||||
cmd.parse( argc, argv );
|
||||
|
||||
filename = fileArg.getValue();
|
||||
|
||||
country = countryCodeArg.getValue();
|
||||
seektoms = seekToMsArg.getValue();
|
||||
outputJson = jsonSwitch.getValue();
|
||||
runtimePath = runtimeDirArg.getValue();
|
||||
detectRegion = detectRegionSwitch.getValue();
|
||||
templateRegion = templateRegionArg.getValue();
|
||||
topn = topNArg.getValue();
|
||||
measureProcessingTime = clockSwitch.getValue();
|
||||
|
||||
} catch (TCLAP::ArgException &e) // catch any exceptions
|
||||
{
|
||||
std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::Mat frame;
|
||||
|
||||
|
||||
Alpr alpr(country, runtimePath);
|
||||
alpr.setTopN(topn);
|
||||
|
||||
if (detectRegion)
|
||||
alpr.setDetectRegion(detectRegion);
|
||||
|
||||
if (strcmp(templateRegion.c_str(), "") != 0)
|
||||
{
|
||||
alpr.setDefaultRegion(templateRegion);
|
||||
}
|
||||
|
||||
if (alpr.isLoaded() == false)
|
||||
{
|
||||
std::cerr << "Error loading OpenAlpr" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(filename.c_str(), "webcam") == 0)
|
||||
{
|
||||
int framenum = 0;
|
||||
cv::VideoCapture cap(0);
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
std::cout << "Error opening webcam" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (cap.read(frame) == true)
|
||||
{
|
||||
detectandshow(&alpr, frame, "", outputJson);
|
||||
cv::waitKey(1);
|
||||
framenum++;
|
||||
}
|
||||
}
|
||||
else if (hasEnding(filename, ".avi") || hasEnding(filename, ".mp4") || hasEnding(filename, ".webm") || hasEnding(filename, ".flv"))
|
||||
{
|
||||
if (fileExists(filename.c_str()))
|
||||
{
|
||||
int framenum = 0;
|
||||
|
||||
cv::VideoCapture cap=cv::VideoCapture();
|
||||
cap.open(filename);
|
||||
cap.set(CV_CAP_PROP_POS_MSEC, seektoms);
|
||||
|
||||
while (cap.read(frame) == true)
|
||||
{
|
||||
if (SAVE_LAST_VIDEO_STILL == true)
|
||||
{
|
||||
cv::imwrite(LAST_VIDEO_STILL_LOCATION, frame);
|
||||
}
|
||||
std::cout << "Frame: " << framenum << std::endl;
|
||||
|
||||
detectandshow( &alpr, frame, "", outputJson);
|
||||
//create a 1ms delay
|
||||
cv::waitKey(1);
|
||||
framenum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Video file not found: " << filename << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
else if (hasEnding(filename, ".png") || hasEnding(filename, ".jpg") || hasEnding(filename, ".gif"))
|
||||
{
|
||||
if (fileExists(filename.c_str()))
|
||||
{
|
||||
frame = cv::imread( filename );
|
||||
|
||||
detectandshow( &alpr, frame, "", outputJson);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Image file not found: " << filename << std::endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (DirectoryExists(filename.c_str()))
|
||||
{
|
||||
std::vector<std::string> files = getFilesInDir(filename.c_str());
|
||||
|
||||
std::sort( files.begin(), files.end(), stringCompare );
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
if (hasEnding(files[i], ".jpg") || hasEnding(files[i], ".png"))
|
||||
{
|
||||
std::string fullpath = filename + "/" + files[i];
|
||||
std::cout << fullpath << std::endl;
|
||||
frame = cv::imread( fullpath.c_str() );
|
||||
if (detectandshow( &alpr, frame, "", outputJson))
|
||||
{
|
||||
//while ((char) cv::waitKey(50) != 'c') { }
|
||||
}
|
||||
else
|
||||
{
|
||||
//cv::waitKey(50);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unknown file type" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson)
|
||||
{
|
||||
|
||||
|
||||
std::vector<uchar> buffer;
|
||||
cv::imencode(".bmp", frame, buffer );
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
std::vector<AlprResult> results = alpr->recognize(buffer);
|
||||
|
||||
|
||||
if (writeJson)
|
||||
{
|
||||
std::cout << alpr->toJson(results) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
timespec endTime;
|
||||
getTime(&endTime);
|
||||
if (measureProcessingTime)
|
||||
std::cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << std::endl;
|
||||
|
||||
|
||||
if (results.size() > 0)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
|
||||
|
||||
#include "tclap/CmdLine.h"
|
||||
#include "support/filesystem.h"
|
||||
#include "support/timing.h"
|
||||
#include "alpr.h"
|
||||
|
||||
|
||||
|
||||
const std::string MAIN_WINDOW_NAME = "ALPR main window";
|
||||
|
||||
|
||||
const bool SAVE_LAST_VIDEO_STILL = false;
|
||||
const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg";
|
||||
|
||||
|
||||
/** Function Headers */
|
||||
bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson);
|
||||
|
||||
|
||||
bool measureProcessingTime = false;
|
||||
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
std::string filename;
|
||||
std::string runtimePath = "";
|
||||
bool outputJson = false;
|
||||
int seektoms = 0;
|
||||
bool detectRegion = false;
|
||||
std::string templateRegion;
|
||||
std::string country;
|
||||
int topn;
|
||||
|
||||
try {
|
||||
|
||||
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::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<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<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 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);
|
||||
|
||||
cmd.add( fileArg );
|
||||
cmd.add( countryCodeArg );
|
||||
cmd.add( seekToMsArg );
|
||||
cmd.add( topNArg );
|
||||
cmd.add( runtimeDirArg );
|
||||
cmd.add( templateRegionArg );
|
||||
|
||||
cmd.parse( argc, argv );
|
||||
|
||||
filename = fileArg.getValue();
|
||||
|
||||
country = countryCodeArg.getValue();
|
||||
seektoms = seekToMsArg.getValue();
|
||||
outputJson = jsonSwitch.getValue();
|
||||
runtimePath = runtimeDirArg.getValue();
|
||||
detectRegion = detectRegionSwitch.getValue();
|
||||
templateRegion = templateRegionArg.getValue();
|
||||
topn = topNArg.getValue();
|
||||
measureProcessingTime = clockSwitch.getValue();
|
||||
|
||||
} catch (TCLAP::ArgException &e) // catch any exceptions
|
||||
{
|
||||
std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::Mat frame;
|
||||
|
||||
|
||||
Alpr alpr(country, runtimePath);
|
||||
alpr.setTopN(topn);
|
||||
|
||||
if (detectRegion)
|
||||
alpr.setDetectRegion(detectRegion);
|
||||
|
||||
if (strcmp(templateRegion.c_str(), "") != 0)
|
||||
{
|
||||
alpr.setDefaultRegion(templateRegion);
|
||||
}
|
||||
|
||||
if (alpr.isLoaded() == false)
|
||||
{
|
||||
std::cerr << "Error loading OpenAlpr" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(filename.c_str(), "webcam") == 0)
|
||||
{
|
||||
int framenum = 0;
|
||||
cv::VideoCapture cap(0);
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
std::cout << "Error opening webcam" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (cap.read(frame) == true)
|
||||
{
|
||||
detectandshow(&alpr, frame, "", outputJson);
|
||||
cv::waitKey(1);
|
||||
framenum++;
|
||||
}
|
||||
}
|
||||
else if (hasEnding(filename, ".avi") || hasEnding(filename, ".mp4") || hasEnding(filename, ".webm") || hasEnding(filename, ".flv"))
|
||||
{
|
||||
if (fileExists(filename.c_str()))
|
||||
{
|
||||
int framenum = 0;
|
||||
|
||||
cv::VideoCapture cap=cv::VideoCapture();
|
||||
cap.open(filename);
|
||||
cap.set(CV_CAP_PROP_POS_MSEC, seektoms);
|
||||
|
||||
while (cap.read(frame) == true)
|
||||
{
|
||||
if (SAVE_LAST_VIDEO_STILL == true)
|
||||
{
|
||||
cv::imwrite(LAST_VIDEO_STILL_LOCATION, frame);
|
||||
}
|
||||
std::cout << "Frame: " << framenum << std::endl;
|
||||
|
||||
detectandshow( &alpr, frame, "", outputJson);
|
||||
//create a 1ms delay
|
||||
cv::waitKey(1);
|
||||
framenum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Video file not found: " << filename << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
else if (hasEnding(filename, ".png") || hasEnding(filename, ".jpg") || hasEnding(filename, ".gif"))
|
||||
{
|
||||
if (fileExists(filename.c_str()))
|
||||
{
|
||||
frame = cv::imread( filename );
|
||||
|
||||
detectandshow( &alpr, frame, "", outputJson);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Image file not found: " << filename << std::endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (DirectoryExists(filename.c_str()))
|
||||
{
|
||||
std::vector<std::string> files = getFilesInDir(filename.c_str());
|
||||
|
||||
std::sort( files.begin(), files.end(), stringCompare );
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
if (hasEnding(files[i], ".jpg") || hasEnding(files[i], ".png"))
|
||||
{
|
||||
std::string fullpath = filename + "/" + files[i];
|
||||
std::cout << fullpath << std::endl;
|
||||
frame = cv::imread( fullpath.c_str() );
|
||||
if (detectandshow( &alpr, frame, "", outputJson))
|
||||
{
|
||||
//while ((char) cv::waitKey(50) != 'c') { }
|
||||
}
|
||||
else
|
||||
{
|
||||
//cv::waitKey(50);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unknown file type" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson)
|
||||
{
|
||||
|
||||
|
||||
std::vector<uchar> buffer;
|
||||
cv::imencode(".bmp", frame, buffer );
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
std::vector<AlprResult> results = alpr->recognize(buffer);
|
||||
|
||||
|
||||
if (writeJson)
|
||||
{
|
||||
std::cout << alpr->toJson(results) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
timespec endTime;
|
||||
getTime(&endTime);
|
||||
if (measureProcessingTime)
|
||||
std::cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << std::endl;
|
||||
|
||||
|
||||
if (results.size() > 0)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
@@ -4,35 +4,33 @@ target_link_libraries(openalpr)
|
||||
|
||||
|
||||
ADD_EXECUTABLE( sortstate sortstate.cpp )
|
||||
TARGET_LINK_LIBRARIES(sortstate
|
||||
TARGET_LINK_LIBRARIES(sortstate
|
||||
openalpr
|
||||
support
|
||||
${OpenCV_LIBS}
|
||||
${OpenCV_LIBS}
|
||||
tesseract
|
||||
)
|
||||
|
||||
|
||||
ADD_EXECUTABLE( classifychars classifychars.cpp )
|
||||
TARGET_LINK_LIBRARIES(classifychars
|
||||
TARGET_LINK_LIBRARIES(classifychars
|
||||
openalpr
|
||||
support
|
||||
${OpenCV_LIBS}
|
||||
${OpenCV_LIBS}
|
||||
tesseract
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
ADD_EXECUTABLE( benchmark benchmark.cpp )
|
||||
TARGET_LINK_LIBRARIES(benchmark
|
||||
TARGET_LINK_LIBRARIES(benchmark
|
||||
openalpr
|
||||
support
|
||||
${OpenCV_LIBS}
|
||||
${OpenCV_LIBS}
|
||||
tesseract
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
ADD_EXECUTABLE( prepcharsfortraining prepcharsfortraining.cpp )
|
||||
TARGET_LINK_LIBRARIES(prepcharsfortraining
|
||||
TARGET_LINK_LIBRARIES(prepcharsfortraining
|
||||
support
|
||||
${OpenCV_LIBS}
|
||||
${OpenCV_LIBS}
|
||||
)
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -39,9 +39,9 @@
|
||||
|
||||
// Given a directory full of lp images (named [statecode]#.png) crop out the alphanumeric characters.
|
||||
// These will be used to train the OCR
|
||||
|
||||
|
||||
void outputStats(vector<double> datapoints);
|
||||
|
||||
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
string country;
|
||||
@@ -49,8 +49,8 @@ int main( int argc, const char** argv )
|
||||
string inDir;
|
||||
string outDir;
|
||||
Mat frame;
|
||||
|
||||
|
||||
|
||||
|
||||
//Check if user specify image to process
|
||||
if(argc == 5)
|
||||
{
|
||||
@@ -58,17 +58,17 @@ int main( int argc, const char** argv )
|
||||
benchmarkName = argv[2];
|
||||
inDir = argv[3];
|
||||
outDir = argv[4];
|
||||
|
||||
|
||||
|
||||
|
||||
}else{
|
||||
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("\n");
|
||||
printf("\ttest names are: speed, segocr, detection\n\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (DirectoryExists(inDir.c_str()) == false)
|
||||
{
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
vector<string> files = getFilesInDir(inDir.c_str());
|
||||
sort( files.begin(), files.end(), stringCompare );
|
||||
|
||||
|
||||
|
||||
|
||||
if (benchmarkName.compare("segocr") == 0)
|
||||
{
|
||||
Config* config = new Config(country);
|
||||
Config* config = new Config(country);
|
||||
config->debugOff();
|
||||
|
||||
|
||||
OCR* ocr = new OCR(config);
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
if (hasEnding(files[i], ".png"))
|
||||
@@ -101,51 +101,51 @@ int main( int argc, const char** argv )
|
||||
|
||||
frame = imread( fullpath.c_str() );
|
||||
resize(frame, frame, Size(config->ocrImageWidthPx, config->ocrImageHeightPx));
|
||||
|
||||
|
||||
Rect plateCoords;
|
||||
plateCoords.x = 0;
|
||||
plateCoords.y = 0;
|
||||
plateCoords.width = frame.cols;
|
||||
plateCoords.height = frame.rows;
|
||||
|
||||
|
||||
char statecode[3];
|
||||
statecode[0] = files[i][0];
|
||||
statecode[1] = files[i][1];
|
||||
statecode[2] = '\0';
|
||||
string statecodestr(statecode);
|
||||
|
||||
|
||||
CharacterRegion charRegion(frame, config);
|
||||
|
||||
|
||||
if (abs(charRegion.getTopLine().angle) > 4)
|
||||
{
|
||||
// Rotate image:
|
||||
Mat rotated(frame.size(), frame.type());
|
||||
Mat rot_mat( 2, 3, CV_32FC1 );
|
||||
Point center = Point( frame.cols/2, frame.rows/2 );
|
||||
|
||||
|
||||
rot_mat = getRotationMatrix2D( center, charRegion.getTopLine().angle, 1.0 );
|
||||
warpAffine( frame, rotated, rot_mat, frame.size() );
|
||||
|
||||
|
||||
rotated.copyTo(frame);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CharacterSegmenter charSegmenter(frame, charRegion.thresholdsInverted(), config);
|
||||
ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters);
|
||||
ocr->postProcessor->analyze(statecode, 25);
|
||||
|
||||
|
||||
cout << files[i] << "," << statecode << "," << ocr->postProcessor->bestChars << endl;
|
||||
|
||||
|
||||
|
||||
imshow("Current LP", frame);
|
||||
waitKey(5);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
delete config;
|
||||
delete ocr;
|
||||
}
|
||||
@@ -153,42 +153,42 @@ int main( int argc, const char** argv )
|
||||
{
|
||||
Config config(country);
|
||||
RegionDetector plateDetector(&config);
|
||||
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
if (hasEnding(files[i], ".png"))
|
||||
{
|
||||
string fullpath = inDir + "/" + files[i];
|
||||
frame = imread( fullpath.c_str() );
|
||||
|
||||
|
||||
vector<Rect> regions = plateDetector.detect(frame);
|
||||
|
||||
|
||||
imshow("Current LP", frame);
|
||||
waitKey(5);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else if (benchmarkName.compare("speed") == 0)
|
||||
{
|
||||
// Benchmarks speed of region detection, plate analysis, and OCR
|
||||
|
||||
|
||||
timespec startTime;
|
||||
timespec endTime;
|
||||
|
||||
|
||||
Config config(country);
|
||||
config.debugOff();
|
||||
|
||||
|
||||
AlprImpl alpr(country);
|
||||
alpr.config->debugOff();
|
||||
alpr.setDetectRegion(true);
|
||||
|
||||
|
||||
RegionDetector plateDetector(&config);
|
||||
StateIdentifier stateIdentifier(&config);
|
||||
OCR ocr(&config);
|
||||
|
||||
|
||||
vector<double> endToEndTimes;
|
||||
vector<double> regionDetectionTimes;
|
||||
vector<double> stateIdTimes;
|
||||
@@ -196,33 +196,33 @@ int main( int argc, const char** argv )
|
||||
vector<double> lpAnalysisNegativeTimes;
|
||||
vector<double> ocrTimes;
|
||||
vector<double> postProcessTimes;
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
if (hasEnding(files[i], ".png"))
|
||||
{
|
||||
cout << "Image: " << files[i] << endl;
|
||||
|
||||
|
||||
string fullpath = inDir + "/" + files[i];
|
||||
frame = imread( fullpath.c_str() );
|
||||
|
||||
|
||||
|
||||
|
||||
getTime(&startTime);
|
||||
alpr.recognize(frame);
|
||||
getTime(&endTime);
|
||||
double endToEndTime = diffclock(startTime, endTime);
|
||||
cout << " -- End to End recognition time: " << endToEndTime << "ms." << endl;
|
||||
endToEndTimes.push_back(endToEndTime);
|
||||
|
||||
|
||||
getTime(&startTime);
|
||||
vector<Rect> regions = plateDetector.detect(frame);
|
||||
getTime(&endTime);
|
||||
|
||||
|
||||
double regionDetectionTime = diffclock(startTime, endTime);
|
||||
cout << " -- Region detection time: " << regionDetectionTime << "ms." << endl;
|
||||
regionDetectionTimes.push_back(regionDetectionTime);
|
||||
|
||||
|
||||
for (int z = 0; z < regions.size(); z++)
|
||||
{
|
||||
getTime(&startTime);
|
||||
@@ -232,26 +232,26 @@ int main( int argc, const char** argv )
|
||||
double stateidTime = diffclock(startTime, endTime);
|
||||
cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl;
|
||||
stateIdTimes.push_back(stateidTime);
|
||||
|
||||
|
||||
getTime(&startTime);
|
||||
LicensePlateCandidate lp(frame, regions[z], &config);
|
||||
lp.recognize();
|
||||
getTime(&endTime);
|
||||
double analysisTime = diffclock(startTime, endTime);
|
||||
cout << "\tRegion " << z << ": Analysis time: " << analysisTime << "ms." << endl;
|
||||
|
||||
|
||||
if (lp.confidence > 10)
|
||||
{
|
||||
lpAnalysisPositiveTimes.push_back(analysisTime);
|
||||
|
||||
|
||||
|
||||
|
||||
getTime(&startTime);
|
||||
ocr.performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters);
|
||||
getTime(&endTime);
|
||||
double ocrTime = diffclock(startTime, endTime);
|
||||
cout << "\tRegion " << z << ": OCR time: " << ocrTime << "ms." << endl;
|
||||
ocrTimes.push_back(ocrTime);
|
||||
|
||||
|
||||
getTime(&startTime);
|
||||
ocr.postProcessor->analyze("", 25);
|
||||
getTime(&endTime);
|
||||
@@ -264,40 +264,40 @@ int main( int argc, const char** argv )
|
||||
lpAnalysisNegativeTimes.push_back(analysisTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
waitKey(5);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
cout << endl << "---------------------" << endl;
|
||||
|
||||
|
||||
|
||||
|
||||
cout << "End to End Time Statistics:" << endl;
|
||||
outputStats(endToEndTimes);
|
||||
cout << endl;
|
||||
|
||||
|
||||
cout << "Region Detection Time Statistics:" << endl;
|
||||
outputStats(regionDetectionTimes);
|
||||
cout << endl;
|
||||
|
||||
|
||||
cout << "State ID Time Statistics:" << endl;
|
||||
outputStats(stateIdTimes);
|
||||
cout << endl;
|
||||
|
||||
|
||||
cout << "Positive Region Analysis Time Statistics:" << endl;
|
||||
outputStats(lpAnalysisPositiveTimes);
|
||||
cout << endl;
|
||||
|
||||
|
||||
cout << "Negative Region Analysis Time Statistics:" << endl;
|
||||
outputStats(lpAnalysisNegativeTimes);
|
||||
cout << endl;
|
||||
|
||||
|
||||
cout << "OCR Time Statistics:" << endl;
|
||||
outputStats(ocrTimes);
|
||||
cout << endl;
|
||||
|
||||
|
||||
cout << "Post Processing Time Statistics:" << endl;
|
||||
outputStats(postProcessTimes);
|
||||
cout << endl;
|
||||
@@ -306,41 +306,41 @@ int main( int argc, const char** argv )
|
||||
{
|
||||
Alpr alpr(country);
|
||||
alpr.setDetectRegion(true);
|
||||
|
||||
|
||||
ofstream outputdatafile;
|
||||
|
||||
|
||||
outputdatafile.open("results.txt");
|
||||
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
if (hasEnding(files[i], ".png"))
|
||||
{
|
||||
string fullpath = inDir + "/" + files[i];
|
||||
frame = imread( fullpath.c_str() );
|
||||
|
||||
|
||||
vector<uchar> buffer;
|
||||
imencode(".bmp", frame, buffer );
|
||||
|
||||
|
||||
vector<AlprResult> results = alpr.recognize(buffer);
|
||||
|
||||
|
||||
outputdatafile << files[i] << ": ";
|
||||
for (int z = 0; z < results.size(); z++)
|
||||
{
|
||||
outputdatafile << results[z].bestPlate.characters << ", ";
|
||||
}
|
||||
outputdatafile << endl;
|
||||
|
||||
|
||||
imshow("Current LP", frame);
|
||||
waitKey(5);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
outputdatafile.close();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -43,7 +43,7 @@ const int RIGHT_ARROW_KEY = 3;
|
||||
const int SPACE_KEY = 32;
|
||||
const int ENTER_KEY = 13;
|
||||
const int ESCAPE_KEY = 27;
|
||||
|
||||
|
||||
const int DOWN_ARROW_KEY = 1;
|
||||
const int UP_ARROW_KEY= 0;
|
||||
const int DASHBOARD_COLUMNS = 9;
|
||||
@@ -54,7 +54,7 @@ const int RIGHT_ARROW_KEY = 83;
|
||||
const int SPACE_KEY = 32;
|
||||
const int ENTER_KEY = 10;
|
||||
const int ESCAPE_KEY = 27;
|
||||
|
||||
|
||||
const int DOWN_ARROW_KEY = 84;
|
||||
const int UP_ARROW_KEY= 82;
|
||||
const int DASHBOARD_COLUMNS = 3;
|
||||
@@ -64,35 +64,35 @@ const int DASHBOARD_COLUMNS = 3;
|
||||
|
||||
void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex);
|
||||
vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state);
|
||||
|
||||
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
|
||||
|
||||
string inDir;
|
||||
string outDir;
|
||||
Mat frame;
|
||||
|
||||
|
||||
|
||||
|
||||
//Check if user specify image to process
|
||||
if(argc == 3)
|
||||
{
|
||||
inDir = argv[1];
|
||||
outDir = argv[2];
|
||||
|
||||
|
||||
|
||||
|
||||
}else{
|
||||
printf("Use:\n\t%s indirectory outdirectory\n",argv[0]);
|
||||
printf("Ex: \n\t%s ./pics/ ./out \n",argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (DirectoryExists(outDir.c_str()) == false)
|
||||
{
|
||||
printf("Output dir does not exist\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
cout << "Usage: " << endl;
|
||||
cout << "\tn -- Next 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[0-9A-Z] -- Identify a character (saves the image)" << endl;
|
||||
cout << "\tESC/Ent/Space -- Back to plate selection" << endl;
|
||||
|
||||
|
||||
Config* config = new Config("eu");
|
||||
OCR ocr(config);
|
||||
|
||||
|
||||
if (DirectoryExists(inDir.c_str()))
|
||||
{
|
||||
vector<string> files = getFilesInDir(inDir.c_str());
|
||||
|
||||
|
||||
sort( files.begin(), files.end(), stringCompare );
|
||||
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
if (hasEnding(files[i], ".png") || hasEnding(files[i], ".jpg"))
|
||||
@@ -122,57 +122,57 @@ int main( int argc, const char** argv )
|
||||
cout << fullpath << endl;
|
||||
frame = imread( fullpath.c_str() );
|
||||
resize(frame, frame, Size(config->ocrImageWidthPx, config->ocrImageHeightPx));
|
||||
|
||||
|
||||
imshow ("Original", frame);
|
||||
|
||||
|
||||
|
||||
|
||||
char statecode[3];
|
||||
statecode[0] = files[i][0];
|
||||
statecode[1] = files[i][1];
|
||||
statecode[2] = '\0';
|
||||
string statecodestr(statecode);
|
||||
|
||||
|
||||
CharacterRegion regionizer(frame, config);
|
||||
|
||||
|
||||
if (abs(regionizer.getTopLine().angle) > 4)
|
||||
{
|
||||
// Rotate image:
|
||||
Mat rotated(frame.size(), frame.type());
|
||||
Mat rot_mat( 2, 3, CV_32FC1 );
|
||||
Point center = Point( frame.cols/2, frame.rows/2 );
|
||||
|
||||
|
||||
rot_mat = getRotationMatrix2D( center, regionizer.getTopLine().angle, 1.0 );
|
||||
warpAffine( frame, rotated, rot_mat, frame.size() );
|
||||
|
||||
|
||||
rotated.copyTo(frame);
|
||||
}
|
||||
|
||||
|
||||
CharacterSegmenter charSegmenter(frame, regionizer.thresholdsInverted(), config);
|
||||
|
||||
|
||||
//ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters);
|
||||
|
||||
|
||||
ocr.performOCR(charSegmenter.getThresholds(), charSegmenter.characters);
|
||||
ocr.postProcessor->analyze(statecodestr, 25);
|
||||
cout << "OCR results: " << ocr.postProcessor->bestChars << endl;
|
||||
|
||||
|
||||
|
||||
|
||||
vector<bool> selectedBoxes(charSegmenter.getThresholds().size());
|
||||
for (int z = 0; z < charSegmenter.getThresholds().size(); z++)
|
||||
selectedBoxes[z] = false;
|
||||
|
||||
|
||||
int curDashboardSelection = 0;
|
||||
|
||||
|
||||
vector<char> humanInputs(charSegmenter.characters.size());
|
||||
|
||||
|
||||
for (int z = 0; z < charSegmenter.characters.size(); z++)
|
||||
humanInputs[z] = ' ';
|
||||
|
||||
|
||||
showDashboard(charSegmenter.getThresholds(), selectedBoxes, 0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char waitkey = (char) waitKey(50);
|
||||
|
||||
|
||||
while (waitkey != 'n' && waitkey != 'p') // Next image
|
||||
{
|
||||
if (waitkey == LEFT_ARROW_KEY) // left arrow key
|
||||
@@ -233,17 +233,17 @@ int main( int argc, const char** argv )
|
||||
// Save
|
||||
if (somethingSelected && chardataTagged)
|
||||
{
|
||||
|
||||
|
||||
for (int c = 0; c < charSegmenter.characters.size(); c++)
|
||||
{
|
||||
if (humanInputs[c] == ' ')
|
||||
continue;
|
||||
|
||||
|
||||
for (int t = 0; t < charSegmenter.getThresholds().size(); t++)
|
||||
{
|
||||
if (selectedBoxes[t] == false)
|
||||
continue;
|
||||
|
||||
|
||||
stringstream filename;
|
||||
Mat cropped = charSegmenter.getThresholds()[t](charSegmenter.characters[c]);
|
||||
filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i];
|
||||
@@ -257,34 +257,34 @@ int main( int argc, const char** argv )
|
||||
else if (chardataTagged == false)
|
||||
cout << "You have not tagged any characters" << endl;
|
||||
}
|
||||
|
||||
|
||||
waitkey = (char) waitKey(50);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (waitkey == 'p')
|
||||
i = i - 2;
|
||||
if (i < -1)
|
||||
i = -1;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex)
|
||||
{
|
||||
vector<Mat> vecCopy;
|
||||
|
||||
|
||||
if (selectedIndex < 0)
|
||||
selectedIndex = 0;
|
||||
if (selectedIndex >= images.size())
|
||||
selectedIndex = images.size() -1;
|
||||
|
||||
|
||||
for (int i = 0; i < images.size(); i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
vecCopy.push_back(imgCopy);
|
||||
}
|
||||
|
||||
|
||||
Mat dashboard = drawImageDashboard(vecCopy, vecCopy[0].type(), DASHBOARD_COLUMNS);
|
||||
|
||||
|
||||
imshow("Selection dashboard", dashboard);
|
||||
}
|
||||
|
||||
vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state)
|
||||
{
|
||||
int curCharIdx = 0;
|
||||
|
||||
|
||||
vector<char> humanInputs(charRegions.size());
|
||||
for (int i = 0; i < charRegions.size(); i++)
|
||||
humanInputs[i] = (char) SPACE_KEY;
|
||||
|
||||
|
||||
|
||||
|
||||
char waitkey = (char) waitKey(50);
|
||||
while (waitkey != ENTER_KEY && waitkey != ESCAPE_KEY)
|
||||
{
|
||||
Mat imgCopy(image.size(), image.type());
|
||||
image.copyTo(imgCopy);
|
||||
cvtColor(imgCopy, imgCopy, CV_GRAY2BGR);
|
||||
|
||||
|
||||
rectangle(imgCopy, charRegions[curCharIdx], Scalar(0, 255, 0), 1);
|
||||
|
||||
|
||||
imshow("Character selector", imgCopy);
|
||||
|
||||
|
||||
if (waitkey == LEFT_ARROW_KEY)
|
||||
curCharIdx--;
|
||||
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
|
||||
humanInputs[curCharIdx] = toupper((char) waitkey);
|
||||
curCharIdx++;
|
||||
|
||||
|
||||
if (curCharIdx >= charRegions.size())
|
||||
{
|
||||
waitkey = (char) ENTER_KEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (curCharIdx < 0)
|
||||
curCharIdx = 0;
|
||||
if (curCharIdx >= charRegions.size())
|
||||
curCharIdx = charRegions.size() -1;
|
||||
|
||||
|
||||
waitkey = (char) waitKey(50);
|
||||
}
|
||||
|
||||
|
||||
if (waitkey == ENTER_KEY)
|
||||
{
|
||||
// Save all the inputs
|
||||
@@ -360,11 +360,11 @@ vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state
|
||||
if (humanInputs[i] != (char) SPACE_KEY)
|
||||
cout << "Tagged " << state << " char code: '" << humanInputs[i] << "' at char position: " << i << endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
destroyWindow("Character selector");
|
||||
|
||||
|
||||
|
||||
|
||||
return humanInputs;
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -35,89 +35,89 @@
|
||||
// Also creates a box file so Tesseract can recognize it
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
|
||||
|
||||
string inDir;
|
||||
|
||||
|
||||
|
||||
|
||||
//Check if user specify image to process
|
||||
if(argc == 2)
|
||||
{
|
||||
inDir = argv[1];
|
||||
|
||||
|
||||
}else{
|
||||
printf("Use:\n\t%s input dir \n",argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (DirectoryExists(inDir.c_str()) == false)
|
||||
{
|
||||
printf("Output dir does not exist\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
cout << "Usage: " << endl;
|
||||
cout << "\tinputdir -- input dir for benchmark data" << endl;
|
||||
|
||||
|
||||
|
||||
|
||||
if (DirectoryExists(inDir.c_str()))
|
||||
{
|
||||
const int X_OFFSET = 10;
|
||||
const int Y_OFFSET = 10;
|
||||
|
||||
|
||||
const int PAGE_MARGIN_X = 70;
|
||||
const int PAGE_MARGIN_Y = 70;
|
||||
const int HORIZONTAL_RESOLUTION = 3500;
|
||||
|
||||
|
||||
const int TILE_WIDTH = 55;
|
||||
const int CHAR_HORIZ_OFFSET = 40;
|
||||
const int TILE_HEIGHT = 70;
|
||||
const int CHAR_VERT_OFFSET = 48;
|
||||
|
||||
|
||||
vector<string> files = getFilesInDir(inDir.c_str());
|
||||
|
||||
|
||||
sort( files.begin(), files.end(), stringCompare );
|
||||
|
||||
|
||||
|
||||
|
||||
int tiles_per_row = ((float) (HORIZONTAL_RESOLUTION - (PAGE_MARGIN_X * 2))) / ((float) TILE_WIDTH);
|
||||
int lines = files.size() / (tiles_per_row);
|
||||
int vertical_resolution = (lines * TILE_HEIGHT) + (PAGE_MARGIN_Y * 2) ;
|
||||
cout << tiles_per_row << " : " << vertical_resolution << endl;
|
||||
|
||||
|
||||
Mat bigTif = Mat::zeros(Size(HORIZONTAL_RESOLUTION, vertical_resolution), CV_8U);
|
||||
bitwise_not(bigTif, bigTif);
|
||||
|
||||
|
||||
stringstream boxFileOut;
|
||||
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
int col = i % tiles_per_row;
|
||||
int line = i / tiles_per_row;
|
||||
|
||||
|
||||
int xPos = (col * TILE_WIDTH) + PAGE_MARGIN_X;
|
||||
int yPos = (line * TILE_HEIGHT) + PAGE_MARGIN_Y;
|
||||
|
||||
|
||||
if (hasEnding(files[i], ".png") || hasEnding(files[i], ".jpg"))
|
||||
{
|
||||
string fullpath = inDir + "/" + files[i];
|
||||
|
||||
cout << "Processing file: " << (i + 1) << " of " << files.size() << endl;
|
||||
|
||||
|
||||
char charcode = files[i][0];
|
||||
|
||||
|
||||
Mat characterImg = imread(fullpath);
|
||||
Mat charImgCopy = Mat::zeros(Size(150, 150), characterImg.type());
|
||||
bitwise_not(charImgCopy, charImgCopy);
|
||||
|
||||
|
||||
characterImg.copyTo(charImgCopy(Rect(X_OFFSET, Y_OFFSET, characterImg.cols, characterImg.rows)));
|
||||
cvtColor(charImgCopy, charImgCopy, CV_BGR2GRAY);
|
||||
bitwise_not(charImgCopy, charImgCopy);
|
||||
|
||||
|
||||
vector<vector<Point> > contours;
|
||||
|
||||
|
||||
//imshow("copy", charImgCopy);
|
||||
findContours(charImgCopy, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
|
||||
|
||||
|
||||
Rect tallestRect(0, 0, 0, 0);
|
||||
for (int c = 0; c < contours.size(); c++)
|
||||
{
|
||||
@@ -125,23 +125,23 @@ int main( int argc, const char** argv )
|
||||
if (tmpRect.height > tallestRect.height)
|
||||
tallestRect = tmpRect;
|
||||
}
|
||||
|
||||
|
||||
//cout << tallestRect.x << ":" << tallestRect.y << " -- " << tallestRect.width << ":" << tallestRect.height << endl;
|
||||
|
||||
|
||||
Rect cropRect(0, tallestRect.y - Y_OFFSET, tallestRect.width, tallestRect.height);
|
||||
|
||||
|
||||
|
||||
|
||||
//cout << "Cropped: " << cropRect.x << ":" << cropRect.y << " -- " << cropRect.width << ":" << cropRect.height << endl;
|
||||
Mat cropped(characterImg, cropRect);
|
||||
cvtColor(cropped, cropped, CV_BGR2GRAY);
|
||||
|
||||
|
||||
Rect destinationRect(xPos + (CHAR_HORIZ_OFFSET - tallestRect.width), yPos + (CHAR_VERT_OFFSET - tallestRect.height), tallestRect.width, tallestRect.height);
|
||||
|
||||
|
||||
//cout << "1" << endl;
|
||||
|
||||
|
||||
cropped.copyTo(bigTif(destinationRect));
|
||||
|
||||
|
||||
|
||||
|
||||
int x1= destinationRect.x - 2;
|
||||
int y1 = (vertical_resolution - destinationRect.y - destinationRect.height) - 2;
|
||||
int x2 = (destinationRect.x + destinationRect.width) + 2;
|
||||
@@ -150,24 +150,22 @@ int main( int argc, const char** argv )
|
||||
boxFileOut << charcode << " " << x1 << " " << y1 << " ";
|
||||
boxFileOut << x2 << " " << y2 ;
|
||||
boxFileOut << " 0" << endl;
|
||||
|
||||
|
||||
//rectangle(characterImg, tallestRect, Scalar(0, 255, 0));
|
||||
//imshow("characterImg", cropped);
|
||||
|
||||
|
||||
waitKey(2);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
imwrite("combined.tif", bigTif);
|
||||
ofstream boxFile("combined.box", std::ios::out);
|
||||
boxFile << boxFileOut.str();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -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.
|
||||
|
||||
bool detectPlate( StateIdentifier* identifier, Mat frame);
|
||||
|
||||
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
|
||||
|
||||
string inDir;
|
||||
string outDir;
|
||||
Mat frame;
|
||||
|
||||
|
||||
|
||||
|
||||
//Check if user specify image to process
|
||||
if(argc == 3 )
|
||||
{
|
||||
inDir = argv[1];
|
||||
outDir = argv[2];
|
||||
outDir = outDir + "/";
|
||||
|
||||
|
||||
|
||||
|
||||
}else{
|
||||
printf("Use:\n\t%s directory \n",argv[0]);
|
||||
printf("Ex: \n\t%s ./pics/ \n",argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Config config("us");
|
||||
StateIdentifier identifier(&config);
|
||||
|
||||
|
||||
if (DirectoryExists(outDir.c_str()) == false)
|
||||
{
|
||||
printf("Output dir does not exist\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (DirectoryExists(inDir.c_str()))
|
||||
{
|
||||
vector<string> files = getFilesInDir(inDir.c_str());
|
||||
|
||||
|
||||
for (int i = 0; i< files.size(); i++)
|
||||
{
|
||||
if (hasEnding(files[i], ".png"))
|
||||
@@ -80,26 +80,26 @@ int main( int argc, const char** argv )
|
||||
string fullpath = inDir + "/" + files[i];
|
||||
cout << fullpath << endl;
|
||||
frame = imread( fullpath.c_str() );
|
||||
|
||||
|
||||
char code[4];
|
||||
int confidence = identifier.recognize(frame, code);
|
||||
|
||||
|
||||
if (confidence <= 20)
|
||||
{
|
||||
code[0] = 'z';
|
||||
code[1] = 'z';
|
||||
confidence = 100;
|
||||
}
|
||||
|
||||
|
||||
//imshow("Plate", frame);
|
||||
if (confidence > 20)
|
||||
{
|
||||
cout << confidence << " : " << code;
|
||||
|
||||
|
||||
ostringstream convert; // stream used for the conversion
|
||||
convert << i; // insert the textual representation of 'Number' in the characters in the stream
|
||||
|
||||
|
||||
|
||||
|
||||
string copyCommand = "cp \"" + fullpath + "\" " + outDir + code + convert.str() + ".png";
|
||||
system( copyCommand.c_str() );
|
||||
waitKey(50);
|
||||
@@ -108,10 +108,10 @@ int main( int argc, const char** argv )
|
||||
else
|
||||
waitKey(50);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool detectPlate( StateIdentifier* identifier, Mat frame);
|
||||
bool detectPlate( StateIdentifier* identifier, Mat frame);
|
||||
|
@@ -25,7 +25,7 @@ set(lpr_source_files
|
||||
cjson.c
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
add_subdirectory(simpleini)
|
||||
add_subdirectory(support)
|
||||
@@ -35,4 +35,4 @@ add_library(openalpr ${lpr_source_files})
|
||||
|
||||
|
||||
# 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/")
|
||||
|
@@ -1,75 +1,75 @@
|
||||
#ifndef _TREXPP_H_
|
||||
#define _TREXPP_H_
|
||||
/***************************************************************
|
||||
T-Rex a tiny regular expression library
|
||||
|
||||
Copyright (C) 2003-2004 Alberto Demichelis
|
||||
|
||||
This software is provided 'as-is', without any express
|
||||
or implied warranty. In no event will the authors be held
|
||||
liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for
|
||||
any purpose, including commercial applications, and to alter
|
||||
it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but
|
||||
is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any
|
||||
source distribution.
|
||||
|
||||
****************************************************************/
|
||||
|
||||
extern "C" {
|
||||
#include "trex.h"
|
||||
}
|
||||
|
||||
struct TRexParseException{TRexParseException(const TRexChar *c):desc(c){}const TRexChar *desc;};
|
||||
|
||||
class TRexpp {
|
||||
public:
|
||||
TRexpp() { _exp = (TRex *)0; }
|
||||
~TRexpp() { CleanUp(); }
|
||||
// compiles a regular expression
|
||||
void Compile(const TRexChar *pattern) {
|
||||
const TRexChar *error;
|
||||
CleanUp();
|
||||
if(!(_exp = trex_compile(pattern,&error)))
|
||||
throw TRexParseException(error);
|
||||
}
|
||||
// return true if the given text match the expression
|
||||
bool Match(const TRexChar* text) {
|
||||
return _exp?(trex_match(_exp,text) != 0):false;
|
||||
}
|
||||
// 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) {
|
||||
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
|
||||
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;
|
||||
}
|
||||
bool GetSubExp(int n, const TRexChar** out_begin, int *out_len)
|
||||
{
|
||||
TRexMatch match;
|
||||
TRexBool res = _exp?(trex_getsubexp(_exp,n,&match)):TRex_False;
|
||||
if(res) {
|
||||
*out_begin = match.begin;
|
||||
*out_len = match.len;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int GetSubExpCount() { return _exp?trex_getsubexpcount(_exp):0; }
|
||||
private:
|
||||
void CleanUp() { if(_exp) trex_free(_exp); _exp = (TRex *)0; }
|
||||
TRex *_exp;
|
||||
};
|
||||
#endif //_TREXPP_H_
|
||||
#ifndef _TREXPP_H_
|
||||
#define _TREXPP_H_
|
||||
/***************************************************************
|
||||
T-Rex a tiny regular expression library
|
||||
|
||||
Copyright (C) 2003-2004 Alberto Demichelis
|
||||
|
||||
This software is provided 'as-is', without any express
|
||||
or implied warranty. In no event will the authors be held
|
||||
liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for
|
||||
any purpose, including commercial applications, and to alter
|
||||
it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but
|
||||
is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any
|
||||
source distribution.
|
||||
|
||||
****************************************************************/
|
||||
|
||||
extern "C" {
|
||||
#include "trex.h"
|
||||
}
|
||||
|
||||
struct TRexParseException{TRexParseException(const TRexChar *c):desc(c){}const TRexChar *desc;};
|
||||
|
||||
class TRexpp {
|
||||
public:
|
||||
TRexpp() { _exp = (TRex *)0; }
|
||||
~TRexpp() { CleanUp(); }
|
||||
// compiles a regular expression
|
||||
void Compile(const TRexChar *pattern) {
|
||||
const TRexChar *error;
|
||||
CleanUp();
|
||||
if(!(_exp = trex_compile(pattern,&error)))
|
||||
throw TRexParseException(error);
|
||||
}
|
||||
// return true if the given text match the expression
|
||||
bool Match(const TRexChar* text) {
|
||||
return _exp?(trex_match(_exp,text) != 0):false;
|
||||
}
|
||||
// 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) {
|
||||
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
|
||||
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;
|
||||
}
|
||||
bool GetSubExp(int n, const TRexChar** out_begin, int *out_len)
|
||||
{
|
||||
TRexMatch match;
|
||||
TRexBool res = _exp?(trex_getsubexp(_exp,n,&match)):TRex_False;
|
||||
if(res) {
|
||||
*out_begin = match.begin;
|
||||
*out_len = match.len;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int GetSubExpCount() { return _exp?trex_getsubexpcount(_exp):0; }
|
||||
private:
|
||||
void CleanUp() { if(_exp) trex_free(_exp); _exp = (TRex *)0; }
|
||||
TRex *_exp;
|
||||
};
|
||||
#endif //_TREXPP_H_
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
|
||||
// ALPR code
|
||||
|
||||
|
||||
Alpr::Alpr(const std::string country, const std::string 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);
|
||||
return impl->recognize(img);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer)
|
||||
{
|
||||
// Not sure if this actually works
|
||||
cv::Mat img = cv::imdecode(Mat(imageBuffer), 1);
|
||||
|
||||
|
||||
return impl->recognize(img);
|
||||
}
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -30,7 +30,7 @@ struct AlprPlate
|
||||
{
|
||||
std::string characters;
|
||||
float overall_confidence;
|
||||
|
||||
|
||||
bool matches_template;
|
||||
//int char_confidence[];
|
||||
};
|
||||
@@ -46,16 +46,16 @@ class AlprResult
|
||||
public:
|
||||
AlprResult();
|
||||
virtual ~AlprResult();
|
||||
|
||||
|
||||
int requested_topn;
|
||||
int result_count;
|
||||
|
||||
|
||||
AlprPlate bestPlate;
|
||||
std::vector<AlprPlate> topNPlates;
|
||||
|
||||
|
||||
float processing_time_ms;
|
||||
AlprCoordinate plate_points[4];
|
||||
|
||||
|
||||
int regionConfidence;
|
||||
std::string region;
|
||||
};
|
||||
@@ -73,16 +73,16 @@ class Alpr
|
||||
void setDetectRegion(bool detectRegion);
|
||||
void setTopN(int topN);
|
||||
void setDefaultRegion(std::string region);
|
||||
|
||||
|
||||
std::vector<AlprResult> recognize(std::string filepath);
|
||||
std::vector<AlprResult> recognize(std::vector<unsigned char> imageBuffer);
|
||||
|
||||
|
||||
std::string toJson(const std::vector<AlprResult> results);
|
||||
|
||||
|
||||
bool isLoaded();
|
||||
|
||||
|
||||
private:
|
||||
AlprImpl* impl;
|
||||
};
|
||||
|
||||
#endif // APLR_H
|
||||
#endif // APLR_H
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -26,32 +26,32 @@ AlprImpl::AlprImpl(const std::string country, const std::string runtimeDir)
|
||||
plateDetector = new RegionDetector(config);
|
||||
stateIdentifier = new StateIdentifier(config);
|
||||
ocr = new OCR(config);
|
||||
|
||||
|
||||
this->detectRegion = DEFAULT_DETECT_REGION;
|
||||
this->topN = DEFAULT_TOPN;
|
||||
this->defaultRegion = "";
|
||||
|
||||
|
||||
if (config->opencl_enabled)
|
||||
{
|
||||
|
||||
|
||||
cv::ocl::PlatformsInfo platinfo;
|
||||
cv::ocl::getOpenCLPlatforms(platinfo);
|
||||
|
||||
|
||||
for (int i = 0; i < platinfo.size(); i++)
|
||||
{
|
||||
std::cout << platinfo[i]->platformName << std::endl;
|
||||
}
|
||||
|
||||
|
||||
cv::ocl::DevicesInfo devices;
|
||||
cv::ocl::getOpenCLDevices(devices, cv::ocl::CVCL_DEVICE_TYPE_CPU);
|
||||
|
||||
|
||||
for (int i = 0; i < devices.size(); i++)
|
||||
std:: cout << devices[i]->deviceName << std::endl;
|
||||
|
||||
|
||||
if (devices.size() > 0)
|
||||
{
|
||||
cv::ocl::setDevice(devices[0]);
|
||||
|
||||
|
||||
cout << "Using OpenCL Device: " << devices[0]->deviceName << endl;
|
||||
}
|
||||
else
|
||||
@@ -73,9 +73,9 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
||||
{
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
vector<AlprResult> response;
|
||||
|
||||
|
||||
|
||||
vector<Rect> plateRegions = plateDetector->detect(img);
|
||||
|
||||
@@ -86,24 +86,24 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
||||
{
|
||||
timespec platestarttime;
|
||||
getTime(&platestarttime);
|
||||
|
||||
|
||||
LicensePlateCandidate lp(img, plateRegions[i], config);
|
||||
|
||||
|
||||
lp.recognize();
|
||||
|
||||
|
||||
|
||||
if (lp.confidence > 10)
|
||||
{
|
||||
AlprResult plateResult;
|
||||
plateResult.region = defaultRegion;
|
||||
plateResult.regionConfidence = 0;
|
||||
|
||||
|
||||
for (int pointidx = 0; pointidx < 4; pointidx++)
|
||||
{
|
||||
plateResult.plate_points[pointidx].x = (int) lp.plateCorners[pointidx].x;
|
||||
plateResult.plate_points[pointidx].y = (int) lp.plateCorners[pointidx].y;
|
||||
}
|
||||
|
||||
|
||||
if (detectRegion)
|
||||
{
|
||||
char statecode[4];
|
||||
@@ -113,26 +113,26 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
||||
plateResult.region = statecode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ocr->performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters);
|
||||
|
||||
|
||||
ocr->postProcessor->analyze(plateResult.region, topN);
|
||||
|
||||
//plateResult.characters = ocr->postProcessor->bestChars;
|
||||
const vector<PPResult> ppResults = ocr->postProcessor->getResults();
|
||||
|
||||
|
||||
int bestPlateIndex = 0;
|
||||
|
||||
|
||||
for (int pp = 0; pp < ppResults.size(); pp++)
|
||||
{
|
||||
if (pp >= topN)
|
||||
break;
|
||||
|
||||
|
||||
// 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)
|
||||
bestPlateIndex = pp;
|
||||
|
||||
|
||||
if (ppResults[pp].letters.size() >= config->postProcessMinCharacters &&
|
||||
ppResults[pp].letters.size() <= config->postProcessMaxCharacters)
|
||||
{
|
||||
@@ -144,32 +144,32 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
||||
}
|
||||
}
|
||||
plateResult.result_count = plateResult.topNPlates.size();
|
||||
|
||||
|
||||
if (plateResult.topNPlates.size() > 0)
|
||||
plateResult.bestPlate = plateResult.topNPlates[bestPlateIndex];
|
||||
|
||||
|
||||
timespec plateEndTime;
|
||||
getTime(&plateEndTime);
|
||||
plateResult.processing_time_ms = diffclock(platestarttime, plateEndTime);
|
||||
|
||||
|
||||
if (plateResult.result_count > 0)
|
||||
response.push_back(plateResult);
|
||||
|
||||
|
||||
if (config->debugGeneral)
|
||||
{
|
||||
rectangle(img, plateRegions[i], Scalar(0, 255, 0), 2);
|
||||
for (int z = 0; z < 4; z++)
|
||||
line(img, lp.plateCorners[z], lp.plateCorners[(z + 1) % 4], Scalar(255,0,255), 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (config->debugGeneral)
|
||||
rectangle(img, plateRegions[i], Scalar(0, 0, 255), 2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (config->debugTiming)
|
||||
@@ -178,7 +178,7 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
||||
getTime(&endTime);
|
||||
cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||
}
|
||||
|
||||
|
||||
if (config->debugGeneral && config->debugShowImages)
|
||||
{
|
||||
displayImage(config, "Main Image", img);
|
||||
@@ -191,21 +191,21 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
||||
|
||||
string AlprImpl::toJson(const vector< AlprResult > results)
|
||||
{
|
||||
cJSON *root = cJSON_CreateArray();
|
||||
|
||||
cJSON *root = cJSON_CreateArray();
|
||||
|
||||
for (int i = 0; i < results.size(); i++)
|
||||
{
|
||||
cJSON *resultObj = createJsonObj( &results[i] );
|
||||
cJSON_AddItemToArray(root, resultObj);
|
||||
}
|
||||
|
||||
|
||||
// Print the JSON object to a string and return
|
||||
char *out;
|
||||
out=cJSON_PrintUnformatted(root);
|
||||
cJSON_Delete(root);
|
||||
|
||||
|
||||
string response(out);
|
||||
|
||||
|
||||
free(out);
|
||||
return response;
|
||||
}
|
||||
@@ -215,18 +215,18 @@ string AlprImpl::toJson(const vector< AlprResult > results)
|
||||
cJSON* AlprImpl::createJsonObj(const AlprResult* result)
|
||||
{
|
||||
cJSON *root, *coords, *candidates;
|
||||
|
||||
root=cJSON_CreateObject();
|
||||
|
||||
|
||||
root=cJSON_CreateObject();
|
||||
|
||||
cJSON_AddStringToObject(root,"plate", result->bestPlate.characters.c_str());
|
||||
cJSON_AddNumberToObject(root,"confidence", result->bestPlate.overall_confidence);
|
||||
cJSON_AddNumberToObject(root,"matches_template", result->bestPlate.matches_template);
|
||||
|
||||
|
||||
cJSON_AddStringToObject(root,"region", result->region.c_str());
|
||||
cJSON_AddNumberToObject(root,"region_confidence", result->regionConfidence);
|
||||
|
||||
|
||||
cJSON_AddNumberToObject(root,"processing_time_ms", result->processing_time_ms);
|
||||
|
||||
|
||||
cJSON_AddItemToObject(root, "coordinates", coords=cJSON_CreateArray());
|
||||
for (int i=0;i<4;i++)
|
||||
{
|
||||
@@ -237,8 +237,8 @@ cJSON* AlprImpl::createJsonObj(const AlprResult* result)
|
||||
|
||||
cJSON_AddItemToArray(coords, coords_object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
cJSON_AddItemToObject(root, "candidates", candidates=cJSON_CreateArray());
|
||||
for (int i = 0; i < result->topNPlates.size(); i++)
|
||||
{
|
||||
@@ -250,7 +250,7 @@ cJSON* AlprImpl::createJsonObj(const AlprResult* result)
|
||||
|
||||
cJSON_AddItemToArray(candidates, candidate_object);
|
||||
}
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -267,4 +267,3 @@ void AlprImpl::setDefaultRegion(string region)
|
||||
{
|
||||
this->defaultRegion = region;
|
||||
}
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include "opencv2/ocl/ocl.hpp"
|
||||
|
||||
|
||||
|
||||
|
||||
#define DEFAULT_TOPN 25
|
||||
@@ -48,28 +48,28 @@ class AlprImpl
|
||||
virtual ~AlprImpl();
|
||||
|
||||
std::vector<AlprResult> recognize(cv::Mat img);
|
||||
|
||||
|
||||
void applyRegionTemplate(AlprResult* result, std::string region);
|
||||
|
||||
|
||||
void setDetectRegion(bool detectRegion);
|
||||
void setTopN(int topn);
|
||||
void setDefaultRegion(string region);
|
||||
|
||||
|
||||
std::string toJson(const vector<AlprResult> results);
|
||||
|
||||
|
||||
Config* config;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
RegionDetector* plateDetector;
|
||||
StateIdentifier* stateIdentifier;
|
||||
OCR* ocr;
|
||||
|
||||
|
||||
int topN;
|
||||
bool detectRegion;
|
||||
std::string defaultRegion;
|
||||
|
||||
|
||||
cJSON* createJsonObj(const AlprResult* result);
|
||||
};
|
||||
|
||||
#endif // ALPRIMPL_H
|
||||
#endif // ALPRIMPL_H
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -54,7 +54,7 @@ float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy) {
|
||||
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
int winx, int winy, float k) {
|
||||
|
||||
|
||||
float dR = BINARIZEWOLF_DEFAULTDR;
|
||||
|
||||
|
||||
float m, s, max_s;
|
||||
float th=0;
|
||||
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_s = Mat::zeros (im.rows, im.cols, CV_32F);
|
||||
max_s = calcLocalStats (im, map_m, map_s, winx, winy);
|
||||
|
||||
|
||||
minMaxLoc(im, &min_I, &max_I);
|
||||
|
||||
|
||||
Mat thsurf (im.rows, im.cols, CV_32F);
|
||||
|
||||
|
||||
// Create the threshold surface, including border processing
|
||||
// ----------------------------------------------------
|
||||
|
||||
@@ -151,12 +151,12 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
|
||||
case WOLFJOLION:
|
||||
th = m + k * (s/max_s-1) * (m-min_I);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
cerr << "Unknown threshold type in ImageThresholder::surfaceNiblackImproved()\n";
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
thsurf.fset(i+wxh,j,th);
|
||||
|
||||
if (i==0) {
|
||||
@@ -205,10 +205,10 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
|
||||
thsurf.fset(i,u,th);
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int y=0; y<im.rows; ++y)
|
||||
for (int x=0; x<im.cols; ++x)
|
||||
|
||||
|
||||
for (int y=0; y<im.rows; ++y)
|
||||
for (int x=0; x<im.cols; ++x)
|
||||
{
|
||||
if (im.uget(x,y) >= thsurf.fget(x,y))
|
||||
{
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -30,7 +30,7 @@
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
enum NiblackVersion
|
||||
enum NiblackVersion
|
||||
{
|
||||
NIBLACK=0,
|
||||
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
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -40,64 +40,62 @@ class CharacterAnalysis
|
||||
|
||||
bool hasPlateMask;
|
||||
Mat plateMask;
|
||||
|
||||
|
||||
Mat bestThreshold;
|
||||
vector<vector<Point> > bestContours;
|
||||
vector<Vec4i> bestHierarchy;
|
||||
vector<bool> bestCharSegments;
|
||||
int bestCharSegmentsCount;
|
||||
|
||||
|
||||
LineSegment topLine;
|
||||
LineSegment bottomLine;
|
||||
vector<Point> linePolygon;
|
||||
vector<Point> charArea;
|
||||
|
||||
|
||||
LineSegment charBoxTop;
|
||||
LineSegment charBoxBottom;
|
||||
LineSegment charBoxLeft;
|
||||
LineSegment charBoxRight;
|
||||
|
||||
|
||||
bool thresholdsInverted;
|
||||
|
||||
|
||||
vector<Mat> thresholds;
|
||||
vector<vector<vector<Point> > > allContours;
|
||||
vector<vector<Vec4i> > allHierarchy;
|
||||
vector<vector<bool> > charSegments;
|
||||
|
||||
|
||||
void analyze();
|
||||
|
||||
|
||||
Mat getCharacterMask();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Config* config;
|
||||
|
||||
|
||||
Mat img_gray;
|
||||
|
||||
|
||||
Mat findOuterBoxMask( );
|
||||
|
||||
|
||||
|
||||
|
||||
bool isPlateInverted();
|
||||
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> 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> filterByOuterMask(vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
|
||||
|
||||
|
||||
vector<Point> getCharArea();
|
||||
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<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);
|
||||
|
||||
|
||||
int getGoodIndicesCount(vector<bool> goodIndices);
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // CHARACTERANALYSIS_H
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -25,22 +25,22 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
||||
{
|
||||
this->config = config;
|
||||
this->debug = config->debugCharRegions;
|
||||
|
||||
|
||||
this->confidence = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (this->debug)
|
||||
cout << "Starting CharacterRegion identification" << endl;
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
|
||||
|
||||
charAnalysis = new CharacterAnalysis(img, config);
|
||||
charAnalysis->analyze();
|
||||
|
||||
|
||||
|
||||
|
||||
if (this->debug)
|
||||
{
|
||||
vector<Mat> tempDash;
|
||||
@@ -49,15 +49,15 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
||||
Mat tmp(charAnalysis->thresholds[z].size(), charAnalysis->thresholds[z].type());
|
||||
charAnalysis->thresholds[z].copyTo(tmp);
|
||||
cvtColor(tmp, tmp, CV_GRAY2BGR);
|
||||
|
||||
|
||||
tempDash.push_back(tmp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Mat bestVal(charAnalysis->bestThreshold.size(), charAnalysis->bestThreshold.type());
|
||||
charAnalysis->bestThreshold.copyTo(bestVal);
|
||||
cvtColor(bestVal, bestVal, CV_GRAY2BGR);
|
||||
|
||||
|
||||
for (int z = 0; z < charAnalysis->bestContours.size(); z++)
|
||||
{
|
||||
Scalar dcolor(255,0,0);
|
||||
@@ -70,73 +70,73 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (this->debug)
|
||||
{
|
||||
/*
|
||||
Mat img_contours(img_threshold.size(), CV_8U);
|
||||
img_threshold.copyTo(img_contours);
|
||||
cvtColor(img_contours, img_contours, CV_GRAY2RGB);
|
||||
|
||||
|
||||
vector<vector<Point> > allowedContours;
|
||||
for (int i = 0; i < contours.size(); i++)
|
||||
{
|
||||
if (charSegments[i])
|
||||
allowedContours.push_back(contours[i]);
|
||||
}
|
||||
|
||||
|
||||
drawContours(img_contours, contours,
|
||||
-1, // draw all contours
|
||||
cv::Scalar(255,0,0), // in blue
|
||||
1); // with a thickness of 1
|
||||
|
||||
|
||||
drawContours(img_contours, allowedContours,
|
||||
-1, // draw all contours
|
||||
cv::Scalar(0,255,0), // in green
|
||||
1); // with a thickness of 1
|
||||
|
||||
|
||||
|
||||
|
||||
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));
|
||||
|
||||
|
||||
|
||||
|
||||
if (charAnalysis->linePolygon.size() > 0)
|
||||
{
|
||||
|
||||
|
||||
int confidenceDrainers = 0;
|
||||
int charSegmentCount = charAnalysis->bestCharSegmentsCount;
|
||||
if (charSegmentCount == 1)
|
||||
confidenceDrainers += 91;
|
||||
else if (charSegmentCount < 5)
|
||||
confidenceDrainers += (5 - charSegmentCount) * 10;
|
||||
|
||||
|
||||
int absangle = abs(charAnalysis->topLine.angle);
|
||||
if (absangle > 10)
|
||||
confidenceDrainers += 91;
|
||||
else if (absangle > 1)
|
||||
confidenceDrainers += (10 - absangle) * 5;
|
||||
|
||||
|
||||
|
||||
|
||||
if (confidenceDrainers >= 100)
|
||||
this->confidence=1;
|
||||
else
|
||||
this->confidence = 100 - confidenceDrainers;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
getTime(&endTime);
|
||||
cout << "Character Region Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
CharacterRegion::~CharacterRegion()
|
||||
@@ -150,45 +150,43 @@ Mat CharacterRegion::getPlateMask()
|
||||
{
|
||||
return charAnalysis->plateMask;
|
||||
}
|
||||
|
||||
|
||||
LineSegment CharacterRegion::getTopLine()
|
||||
{
|
||||
return charAnalysis->topLine;
|
||||
return charAnalysis->topLine;
|
||||
}
|
||||
|
||||
LineSegment CharacterRegion::getBottomLine()
|
||||
{
|
||||
return charAnalysis->bottomLine;
|
||||
return charAnalysis->bottomLine;
|
||||
}
|
||||
|
||||
vector<Point> CharacterRegion::getCharArea()
|
||||
{
|
||||
return charAnalysis->charArea;
|
||||
return charAnalysis->charArea;
|
||||
}
|
||||
|
||||
|
||||
LineSegment CharacterRegion::getCharBoxTop()
|
||||
{
|
||||
return charAnalysis->charBoxTop;
|
||||
return charAnalysis->charBoxTop;
|
||||
}
|
||||
|
||||
LineSegment CharacterRegion::getCharBoxBottom()
|
||||
{
|
||||
return charAnalysis->charBoxBottom;
|
||||
return charAnalysis->charBoxBottom;
|
||||
}
|
||||
|
||||
LineSegment CharacterRegion::getCharBoxLeft()
|
||||
{
|
||||
return charAnalysis->charBoxLeft;
|
||||
return charAnalysis->charBoxLeft;
|
||||
}
|
||||
|
||||
LineSegment CharacterRegion::getCharBoxRight()
|
||||
{
|
||||
return charAnalysis->charBoxRight;
|
||||
return charAnalysis->charBoxRight;
|
||||
}
|
||||
|
||||
|
||||
bool CharacterRegion::thresholdsInverted()
|
||||
{
|
||||
return charAnalysis->thresholdsInverted;
|
||||
return charAnalysis->thresholdsInverted;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -40,47 +40,45 @@ class CharacterRegion
|
||||
virtual ~CharacterRegion();
|
||||
|
||||
CharacterAnalysis *charAnalysis;
|
||||
|
||||
|
||||
int confidence;
|
||||
Mat getPlateMask();
|
||||
|
||||
|
||||
LineSegment getTopLine();
|
||||
LineSegment getBottomLine();
|
||||
//vector<Point> getLinePolygon();
|
||||
vector<Point> getCharArea();
|
||||
|
||||
|
||||
LineSegment getCharBoxTop();
|
||||
LineSegment getCharBoxBottom();
|
||||
LineSegment getCharBoxLeft();
|
||||
LineSegment getCharBoxRight();
|
||||
|
||||
|
||||
bool thresholdsInverted();
|
||||
|
||||
|
||||
protected:
|
||||
Config* config;
|
||||
bool debug;
|
||||
|
||||
|
||||
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> 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> 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> 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);
|
||||
Mat getCharacterMask(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
|
||||
|
||||
|
||||
vector<Rect> wrapContours(vector<vector<Point> > contours);
|
||||
bool verifySize(Mat r, float minHeightPx, float maxHeightPx);
|
||||
|
||||
|
||||
int getGoodIndicesCount(vector<bool> goodIndices);
|
||||
|
||||
|
||||
bool isPlateInverted(Mat threshold, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // CHARACTERREGION_H
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -53,53 +53,51 @@ class CharacterSegmenter
|
||||
|
||||
vector<Rect> characters;
|
||||
int confidence;
|
||||
|
||||
|
||||
vector<Mat> getThresholds();
|
||||
|
||||
|
||||
private:
|
||||
Config* config;
|
||||
|
||||
|
||||
CharacterAnalysis* charAnalysis;
|
||||
|
||||
|
||||
LineSegment top;
|
||||
LineSegment bottom;
|
||||
|
||||
|
||||
vector<Mat> imgDbgGeneral;
|
||||
vector<Mat> imgDbgCleanStages;
|
||||
|
||||
|
||||
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> 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<Point> getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices);
|
||||
int getGoodIndicesCount(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);
|
||||
|
||||
|
||||
void removeSmallContours(vector<Mat> thresholds, vector<vector<vector<Point > > > allContours, float avgCharWidth, float avgCharHeight);
|
||||
|
||||
|
||||
Mat getVerticalHistogram(Mat img, Mat mask);
|
||||
vector<Rect> getHistogramBoxes(VerticalHistogram histogram, float avgCharWidth, float avgCharHeight, float* score);
|
||||
vector<Rect> getBestCharBoxes(Mat img, vector<Rect> charBoxes, float avgCharWidth);
|
||||
vector<Rect> combineCloseBoxes( vector<Rect> charBoxes, float avgCharWidth);
|
||||
|
||||
|
||||
vector<Rect> get1DHits(Mat img, int yOffset);
|
||||
|
||||
|
||||
void cleanCharRegions(vector<Mat> thresholds, vector<Rect> charRegions);
|
||||
void cleanBasedOnColor(vector<Mat> thresholds, Mat colorMask, vector<Rect> charRegions);
|
||||
void cleanMostlyFullBoxes(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);
|
||||
|
||||
|
||||
int getLongestBlobLengthBetweenLines(Mat img, int col);
|
||||
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
#endif // CHARACTERSEGMENTER_H
|
||||
|
||||
|
||||
|
@@ -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 */
|
||||
|
||||
|
||||
item->valuedouble=n;
|
||||
item->valueint=(int)n;
|
||||
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;
|
||||
if (*str!='\"') {ep=str;return 0;} /* not a string! */
|
||||
|
||||
|
||||
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. */
|
||||
if (!out) return 0;
|
||||
|
||||
|
||||
ptr=str+1;ptr2=out;
|
||||
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;
|
||||
|
||||
|
||||
switch (len) {
|
||||
case 4: *--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)
|
||||
{
|
||||
const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
|
||||
|
||||
|
||||
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++;}
|
||||
|
||||
|
||||
out=(char*)cJSON_malloc(len+3);
|
||||
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;
|
||||
cJSON *child=item->child;
|
||||
int numentries=0,i=0,fail=0;
|
||||
|
||||
|
||||
/* How many entries in the array? */
|
||||
while (child) numentries++,child=child->next;
|
||||
/* 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;
|
||||
child=child->next;
|
||||
}
|
||||
|
||||
|
||||
/* If we didn't fail, try to malloc the output string */
|
||||
if (!fail) out=(char*)cJSON_malloc(len);
|
||||
/* If that fails, we fail. */
|
||||
@@ -387,7 +387,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
|
||||
cJSON_free(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Compose the output array. */
|
||||
*out='[';
|
||||
ptr=out+1;*ptr=0;
|
||||
@@ -399,7 +399,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
|
||||
}
|
||||
cJSON_free(entries);
|
||||
*ptr++=']';*ptr++=0;
|
||||
return out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Build an object from the text. */
|
||||
@@ -407,11 +407,11 @@ static const char *parse_object(cJSON *item,const char *value)
|
||||
{
|
||||
cJSON *child;
|
||||
if (*value!='{') {ep=value;return 0;} /* not an object! */
|
||||
|
||||
|
||||
item->type=cJSON_Object;
|
||||
value=skip(value+1);
|
||||
if (*value=='}') return value+1; /* empty array. */
|
||||
|
||||
|
||||
item->child=child=cJSON_New_Item();
|
||||
if (!item->child) return 0;
|
||||
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! */
|
||||
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
|
||||
|
||||
while (*value==',')
|
||||
{
|
||||
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. */
|
||||
if (!value) return 0;
|
||||
}
|
||||
|
||||
|
||||
if (*value=='}') return value+1; /* end of array */
|
||||
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;
|
||||
child=child->next;
|
||||
}
|
||||
|
||||
|
||||
/* Try to allocate the output string */
|
||||
if (!fail) out=(char*)cJSON_malloc(len);
|
||||
if (!out) fail=1;
|
||||
@@ -486,7 +486,7 @@ static char *print_object(cJSON *item,int depth,int fmt)
|
||||
cJSON_free(names);cJSON_free(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Compose the output: */
|
||||
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
|
||||
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;
|
||||
cJSON_free(names[i]);cJSON_free(entries[i]);
|
||||
}
|
||||
|
||||
|
||||
cJSON_free(names);cJSON_free(entries);
|
||||
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
|
||||
*ptr++='}';*ptr++=0;
|
||||
return out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Get Array size/item / object item. */
|
||||
@@ -593,4 +593,4 @@ void cJSON_Minify(char *json)
|
||||
else *into++=*json++; // All other characters.
|
||||
}
|
||||
*into=0; // and null-terminate.
|
||||
}
|
||||
}
|
||||
|
@@ -1,16 +1,16 @@
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -36,7 +36,7 @@ extern "C"
|
||||
#define cJSON_String 4
|
||||
#define cJSON_Array 5
|
||||
#define cJSON_Object 6
|
||||
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
|
||||
/* 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. */
|
||||
extern const char *cJSON_GetErrorPtr(void);
|
||||
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
extern cJSON *cJSON_CreateNull(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 cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
|
||||
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
|
||||
|
||||
|
||||
/* Update array items. */
|
||||
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
|
||||
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -24,31 +24,31 @@
|
||||
|
||||
ColorFilter::ColorFilter(Mat image, Mat characterMask, Config* config)
|
||||
{
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
this->config = config;
|
||||
|
||||
|
||||
this->debug = config->debugColorFiler;
|
||||
|
||||
|
||||
|
||||
this->grayscale = imageIsGrayscale(image);
|
||||
|
||||
|
||||
if (this->debug)
|
||||
cout << "ColorFilter: isGrayscale = " << grayscale << endl;
|
||||
|
||||
|
||||
this->hsv = Mat(image.size(), image.type());
|
||||
cvtColor( image, this->hsv, CV_BGR2HSV );
|
||||
preprocessImage();
|
||||
|
||||
|
||||
this->charMask = characterMask;
|
||||
|
||||
|
||||
this->colorMask = Mat(image.size(), CV_8U);
|
||||
|
||||
|
||||
findCharColors();
|
||||
|
||||
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
@@ -72,7 +72,7 @@ bool ColorFilter::imageIsGrayscale(Mat image)
|
||||
int r = (int) image.at<Vec3b>(row, col)[0];
|
||||
int g = (int) image.at<Vec3b>(row, col)[1];
|
||||
int b = (int) image.at<Vec3b>(row, col)[2];
|
||||
|
||||
|
||||
if (r == g == b)
|
||||
{
|
||||
// So far so good
|
||||
@@ -84,7 +84,7 @@ bool ColorFilter::imageIsGrayscale(Mat image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ void ColorFilter::preprocessImage()
|
||||
vector<Mat> channels;
|
||||
split(this->hsv,channels);
|
||||
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
|
||||
@@ -102,14 +102,14 @@ void ColorFilter::preprocessImage()
|
||||
void ColorFilter::findCharColors()
|
||||
{
|
||||
int MINIMUM_SATURATION = 45;
|
||||
|
||||
|
||||
if (this->debug)
|
||||
cout << "ColorFilter::findCharColors" << endl;
|
||||
|
||||
|
||||
//charMask.copyTo(this->colorMask);
|
||||
this->colorMask = Mat::zeros(charMask.size(), CV_8U);
|
||||
bitwise_not(this->colorMask, this->colorMask);
|
||||
|
||||
|
||||
Mat erodedCharMask(charMask.size(), CV_8U);
|
||||
Mat element = getStructuringElement( 1,
|
||||
Size( 2 + 1, 2+1 ),
|
||||
@@ -120,80 +120,80 @@ void ColorFilter::findCharColors()
|
||||
vector<Vec4i> hierarchy;
|
||||
findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
vector<float> hMeans, sMeans, vMeans;
|
||||
vector<float> hStdDevs, sStdDevs, vStdDevs;
|
||||
|
||||
|
||||
for (int i = 0; i < contours.size(); i++)
|
||||
{
|
||||
if (hierarchy[i][3] != -1)
|
||||
continue;
|
||||
|
||||
|
||||
Mat singleCharMask = Mat::zeros(hsv.size(), CV_8U);
|
||||
|
||||
|
||||
drawContours(singleCharMask, contours,
|
||||
i, // draw this contour
|
||||
cv::Scalar(255,255,255), // in
|
||||
CV_FILLED,
|
||||
8,
|
||||
cv::Scalar(255,255,255), // in
|
||||
CV_FILLED,
|
||||
8,
|
||||
hierarchy
|
||||
);
|
||||
|
||||
);
|
||||
|
||||
// get rid of the outline by drawing a 1 pixel width black line
|
||||
drawContours(singleCharMask, contours,
|
||||
i, // draw this contour
|
||||
cv::Scalar(0,0,0), // in
|
||||
1,
|
||||
8,
|
||||
cv::Scalar(0,0,0), // in
|
||||
1,
|
||||
8,
|
||||
hierarchy
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
//drawAndWait(&singleCharMask);
|
||||
|
||||
Scalar mean;
|
||||
Scalar stddev;
|
||||
meanStdDev(hsv, mean, stddev, singleCharMask);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (mean[0] == 0 && mean[1] == 0 && mean[2] == 0)
|
||||
continue;
|
||||
|
||||
|
||||
hMeans.push_back(mean[0]);
|
||||
sMeans.push_back(mean[1]);
|
||||
vMeans.push_back(mean[2]);
|
||||
hStdDevs.push_back(stddev[0]);
|
||||
sStdDevs.push_back(stddev[1]);
|
||||
vStdDevs.push_back(stddev[2]);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (hMeans.size() == 0)
|
||||
return;
|
||||
|
||||
|
||||
int bestHueIndex = this->getMajorityOpinion(hMeans, .65, 30);
|
||||
int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35);
|
||||
int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30);
|
||||
|
||||
|
||||
|
||||
|
||||
if (sMeans[bestSatIndex] < MINIMUM_SATURATION)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
bool doHueFilter = false, doSatFilter = false, doValFilter = false;
|
||||
float hueMin, hueMax;
|
||||
float satMin, satMax;
|
||||
float valMin, valMax;
|
||||
|
||||
|
||||
if (this->debug)
|
||||
cout << "ColorFilter Winning indices:" << endl;
|
||||
if (bestHueIndex != -1)
|
||||
@@ -201,64 +201,64 @@ void ColorFilter::findCharColors()
|
||||
doHueFilter = true;
|
||||
hueMin = hMeans[bestHueIndex] - (2 * hStdDevs[bestHueIndex]);
|
||||
hueMax = hMeans[bestHueIndex] + (2 * hStdDevs[bestHueIndex]);
|
||||
|
||||
|
||||
if (abs(hueMin - hueMax) < 20)
|
||||
{
|
||||
hueMin = hMeans[bestHueIndex] - 20;
|
||||
hueMax = hMeans[bestHueIndex] + 20;
|
||||
}
|
||||
|
||||
|
||||
if (hueMin < 0)
|
||||
hueMin = 0;
|
||||
if (hueMax > 180)
|
||||
hueMax = 180;
|
||||
|
||||
|
||||
if (this->debug)
|
||||
cout << "ColorFilter Hue: " << bestHueIndex << " : " << setw(7) << hMeans[bestHueIndex] << " -- " << hueMin << "-" << hueMax << endl;
|
||||
}
|
||||
if (bestSatIndex != -1)
|
||||
{
|
||||
doSatFilter = true;
|
||||
|
||||
|
||||
satMin = sMeans[bestSatIndex] - (2 * sStdDevs[bestSatIndex]);
|
||||
satMax = sMeans[bestSatIndex] + (2 * sStdDevs[bestSatIndex]);
|
||||
|
||||
|
||||
if (abs(satMin - satMax) < 20)
|
||||
{
|
||||
satMin = sMeans[bestSatIndex] - 20;
|
||||
satMax = sMeans[bestSatIndex] + 20;
|
||||
}
|
||||
|
||||
|
||||
if (satMin < 0)
|
||||
satMin = 0;
|
||||
if (satMax > 255)
|
||||
satMax = 255;
|
||||
|
||||
|
||||
if (this->debug)
|
||||
cout << "ColorFilter Sat: " << bestSatIndex << " : " << setw(7) << sMeans[bestSatIndex] << " -- " << satMin << "-" << satMax << endl;
|
||||
}
|
||||
if (bestValIndex != -1)
|
||||
{
|
||||
doValFilter = true;
|
||||
|
||||
|
||||
valMin = vMeans[bestValIndex] - (1.5 * vStdDevs[bestValIndex]);
|
||||
valMax = vMeans[bestValIndex] + (1.5 * vStdDevs[bestValIndex]);
|
||||
|
||||
|
||||
if (abs(valMin - valMax) < 20)
|
||||
{
|
||||
valMin = vMeans[bestValIndex] - 20;
|
||||
valMax = vMeans[bestValIndex] + 20;
|
||||
}
|
||||
|
||||
|
||||
if (valMin < 0)
|
||||
valMin = 0;
|
||||
if (valMax > 255)
|
||||
valMax = 255;
|
||||
|
||||
|
||||
if (this->debug)
|
||||
cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type());
|
||||
@@ -266,7 +266,7 @@ void ColorFilter::findCharColors()
|
||||
Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U);
|
||||
Mat debugMask = Mat::zeros(hsv.size(), CV_8U);
|
||||
bitwise_not(debugMask, debugMask);
|
||||
|
||||
|
||||
for (int row = 0; row < charMask.rows; row++)
|
||||
{
|
||||
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 s = (int) hsv.at<Vec3b>(row, col)[1];
|
||||
int v = (int) hsv.at<Vec3b>(row, col)[2];
|
||||
|
||||
|
||||
bool hPasses = true;
|
||||
bool sPasses = true;
|
||||
bool vPasses = true;
|
||||
|
||||
int vDistance = abs(v - vMeans[bestValIndex]);
|
||||
|
||||
|
||||
imgDebugHueOnly.at<Vec3b>(row, col)[0] = h;
|
||||
imgDebugHueOnly.at<Vec3b>(row, col)[1] = 255;
|
||||
imgDebugHueOnly.at<Vec3b>(row, col)[2] = 255;
|
||||
|
||||
|
||||
imgDebug.at<Vec3b>(row, col)[0] = 255;
|
||||
imgDebug.at<Vec3b>(row, col)[1] = 255;
|
||||
imgDebug.at<Vec3b>(row, col)[2] = 255;
|
||||
|
||||
|
||||
if (doHueFilter && (h < hueMin || h > hueMax))
|
||||
{
|
||||
hPasses = false;
|
||||
@@ -305,20 +305,20 @@ void ColorFilter::findCharColors()
|
||||
vPasses = false;
|
||||
imgDebug.at<Vec3b>(row, col)[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
//if (pixelPasses)
|
||||
// colorMask.at<uchar>(row, col) = 255;
|
||||
//else
|
||||
//imgDebug.at<Vec3b>(row, col)[0] = hPasses & 255;
|
||||
//imgDebug.at<Vec3b>(row, col)[1] = sPasses & 255;
|
||||
//imgDebug.at<Vec3b>(row, col)[2] = vPasses & 255;
|
||||
|
||||
|
||||
if ((hPasses) || (hPasses && sPasses))//(hPasses && vPasses) || (sPasses && vPasses) ||
|
||||
this->colorMask.at<uchar>(row, col) = 255;
|
||||
else
|
||||
this->colorMask.at<uchar>(row, col) = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses))
|
||||
{
|
||||
vDistance = pow(vDistance, 0.9);
|
||||
@@ -332,11 +332,11 @@ void ColorFilter::findCharColors()
|
||||
imgDistanceFromCenter.at<uchar>(row, col) = vDistance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
vector<Mat> debugImagesSet;
|
||||
|
||||
|
||||
if (this->debug)
|
||||
{
|
||||
debugImagesSet.push_back(addLabel(charMask, "Charecter mask"));
|
||||
@@ -345,40 +345,40 @@ void ColorFilter::findCharColors()
|
||||
colorMask.copyTo(maskCopy);
|
||||
debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Mat bigElement = getStructuringElement( 1,
|
||||
Size( 3 + 1, 3+1 ),
|
||||
Point( 1, 1 ) );
|
||||
|
||||
|
||||
Mat smallElement = getStructuringElement( 1,
|
||||
Size( 1 + 1, 1+1 ),
|
||||
Point( 1, 1 ) );
|
||||
|
||||
|
||||
morphologyEx(this->colorMask, this->colorMask, MORPH_CLOSE, bigElement);
|
||||
//dilate(this->colorMask, this->colorMask, bigElement);
|
||||
|
||||
|
||||
Mat combined(charMask.size(), charMask.type());
|
||||
bitwise_and(charMask, colorMask, combined);
|
||||
|
||||
|
||||
if (this->debug)
|
||||
{
|
||||
debugImagesSet.push_back(addLabel(colorMask, "Color Mask After"));
|
||||
|
||||
debugImagesSet.push_back(addLabel(combined, "Combined"));
|
||||
|
||||
|
||||
//displayImage(config, "COLOR filter Mask", colorMask);
|
||||
debugImagesSet.push_back(addLabel(imgDebug, "Color filter Debug"));
|
||||
|
||||
|
||||
cvtColor(imgDebugHueOnly, imgDebugHueOnly, CV_HSV2BGR);
|
||||
debugImagesSet.push_back(addLabel(imgDebugHueOnly, "Color Filter Hue"));
|
||||
|
||||
|
||||
equalizeHist(imgDistanceFromCenter, imgDistanceFromCenter);
|
||||
debugImagesSet.push_back(addLabel(imgDistanceFromCenter, "COLOR filter Distance"));
|
||||
|
||||
|
||||
debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off"));
|
||||
|
||||
|
||||
|
||||
|
||||
Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3);
|
||||
displayImage(config, "Color Filter Images", dashboard);
|
||||
}
|
||||
@@ -394,7 +394,7 @@ int ColorFilter::getMajorityOpinion(vector<float> values, float minPercentAgreem
|
||||
float bestPercentAgreement = 0;
|
||||
float lowestOverallDiff = 1000000000;
|
||||
int bestPercentAgreementIndex = -1;
|
||||
|
||||
|
||||
for (int i = 0; i < values.size(); i++)
|
||||
{
|
||||
int valuesInRange = 0;
|
||||
@@ -404,10 +404,10 @@ int ColorFilter::getMajorityOpinion(vector<float> values, float minPercentAgreem
|
||||
float diff = abs(values[i] - values[j]);
|
||||
if (diff < maxValDifference)
|
||||
valuesInRange++;
|
||||
|
||||
|
||||
overallDiff += diff;
|
||||
}
|
||||
|
||||
|
||||
float percentAgreement = ((float) valuesInRange) / ((float) values.size());
|
||||
if (overallDiff < lowestOverallDiff && percentAgreement >= bestPercentAgreement && percentAgreement >= minPercentAgreement)
|
||||
{
|
||||
@@ -416,6 +416,6 @@ int ColorFilter::getMajorityOpinion(vector<float> values, float minPercentAgreem
|
||||
lowestOverallDiff = overallDiff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return bestPercentAgreementIndex;
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -43,23 +43,23 @@ class ColorFilter
|
||||
Mat colorMask;
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Config* config;
|
||||
bool debug;
|
||||
|
||||
|
||||
Mat hsv;
|
||||
Mat charMask;
|
||||
|
||||
|
||||
|
||||
|
||||
bool grayscale;
|
||||
|
||||
|
||||
void preprocessImage();
|
||||
void findCharColors();
|
||||
|
||||
|
||||
bool imageIsGrayscale(Mat image);
|
||||
int getMajorityOpinion(vector<float> values, float minPercentAgreement, float maxValDifference);
|
||||
};
|
||||
|
||||
#endif // COLORFILTER_H
|
||||
#endif // COLORFILTER_H
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -23,15 +23,15 @@
|
||||
Config::Config(const std::string country, const std::string runtimeBaseDir)
|
||||
{
|
||||
this->runtimeBaseDir = runtimeBaseDir;
|
||||
|
||||
|
||||
ini = new CSimpleIniA();
|
||||
|
||||
|
||||
char* envRuntimeDir;
|
||||
envRuntimeDir = getenv (ENV_VARIABLE_RUNTIME_DIR);
|
||||
if (runtimeBaseDir.compare("") != 0)
|
||||
{
|
||||
// User has supplied a runtime directory. Use that.
|
||||
|
||||
|
||||
}
|
||||
else if (envRuntimeDir!=NULL)
|
||||
{
|
||||
@@ -43,9 +43,9 @@ Config::Config(const std::string country, const std::string runtimeBaseDir)
|
||||
// Use the default
|
||||
this->runtimeBaseDir = DEFAULT_RUNTIME_DIR;
|
||||
}
|
||||
|
||||
|
||||
string configFile = (this->runtimeBaseDir + CONFIG_FILE);
|
||||
|
||||
|
||||
if (DirectoryExists(this->runtimeBaseDir.c_str()) == false)
|
||||
{
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ini->LoadFile(configFile.c_str());
|
||||
|
||||
|
||||
this->country = country;
|
||||
|
||||
|
||||
loadValues(country);
|
||||
}
|
||||
Config::~Config()
|
||||
@@ -70,56 +70,56 @@ Config::~Config()
|
||||
|
||||
void Config::loadValues(string country)
|
||||
{
|
||||
|
||||
|
||||
opencl_enabled = getBoolean("common", "opencl_enabled", false);
|
||||
maxPlateWidthPercent = getFloat("common", "max_plate_width_percent", 100);
|
||||
maxPlateHeightPercent = getFloat("common", "max_plate_height_percent", 100);
|
||||
|
||||
minPlateSizeWidthPx = getInt(country, "min_plate_size_width_px", 100);
|
||||
minPlateSizeHeightPx = getInt(country, "min_plate_size_height_px", 100);
|
||||
|
||||
|
||||
plateWidthMM = getFloat(country, "plate_width_mm", 100);
|
||||
plateHeightMM = getFloat(country, "plate_height_mm", 100);
|
||||
|
||||
|
||||
charHeightMM = getFloat(country, "char_height_mm", 100);
|
||||
charWidthMM = getFloat(country, "char_width_mm", 100);
|
||||
charWhitespaceTopMM = getFloat(country, "char_whitespace_top_mm", 100);
|
||||
charWhitespaceBotMM = getFloat(country, "char_whitespace_bot_mm", 100);
|
||||
|
||||
|
||||
templateWidthPx = getInt(country, "template_max_width_px", 100);
|
||||
templateHeightPx = getInt(country, "template_max_height_px", 100);
|
||||
|
||||
|
||||
float ocrImagePercent = getFloat("common", "ocr_img_size_percent", 100);
|
||||
ocrImageWidthPx = round(((float) templateWidthPx) * ocrImagePercent);
|
||||
ocrImageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
|
||||
|
||||
|
||||
|
||||
float stateIdImagePercent = getFloat("common", "state_id_img_size_percent", 100);
|
||||
stateIdImageWidthPx = round(((float)templateWidthPx) * ocrImagePercent);
|
||||
stateIdimageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
|
||||
|
||||
|
||||
|
||||
charAnalysisMinPercent = getFloat(country, "char_analysis_min_pct", 0);
|
||||
charAnalysisHeightRange = getFloat(country, "char_analysis_height_range", 0);
|
||||
charAnalysisHeightStepSize = getFloat(country, "char_analysis_height_step_size", 0);
|
||||
charAnalysisNumSteps = getInt(country, "char_analysis_height_num_steps", 0);
|
||||
|
||||
|
||||
segmentationMinBoxWidthPx = getInt(country, "segmentation_min_box_width_px", 0);
|
||||
segmentationMinCharHeightPercent = getFloat(country, "segmentation_min_charheight_percent", 0);
|
||||
segmentationMaxCharWidthvsAverage = getFloat(country, "segmentation_max_segment_width_percent_vs_average", 0);
|
||||
|
||||
|
||||
plateLinesSensitivityVertical = getFloat(country, "plateline_sensitivity_vertical", 0);
|
||||
plateLinesSensitivityHorizontal = getFloat(country, "plateline_sensitivity_horizontal", 0);
|
||||
|
||||
|
||||
ocrLanguage = getString(country, "ocr_language", "none");
|
||||
ocrMinFontSize = getInt("common", "ocr_min_font_point", 100);
|
||||
|
||||
|
||||
postProcessMinConfidence = getFloat("common", "postprocess_min_confidence", 100);
|
||||
postProcessConfidenceSkipLevel = getFloat("common", "postprocess_confidence_skip_level", 100);
|
||||
postProcessMaxSubstitutions = getInt("common", "postprocess_max_substitutions", 100);
|
||||
postProcessMinCharacters = getInt("common", "postprocess_min_characers", 100);
|
||||
postProcessMaxCharacters = getInt("common", "postprocess_max_characers", 100);
|
||||
|
||||
|
||||
debugGeneral = getBoolean("debug", "general", false);
|
||||
debugTiming = getBoolean("debug", "timing", false);
|
||||
debugStateId = getBoolean("debug", "state_id", false);
|
||||
@@ -132,7 +132,7 @@ void Config::loadValues(string country)
|
||||
debugOcr = getBoolean("debug", "ocr", false);
|
||||
debugPostProcess = getBoolean("debug", "postprocess", false);
|
||||
debugShowImages = getBoolean("debug", "show_images", false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
float val = atof(pszValue);
|
||||
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;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
int val = atoi(pszValue);
|
||||
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;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
int val = atoi(pszValue);
|
||||
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;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
string val = string(pszValue);
|
||||
return val;
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -42,54 +42,54 @@ class Config
|
||||
virtual ~Config();
|
||||
|
||||
string country;
|
||||
|
||||
|
||||
bool opencl_enabled;
|
||||
|
||||
|
||||
float maxPlateWidthPercent;
|
||||
float maxPlateHeightPercent;
|
||||
|
||||
|
||||
float minPlateSizeWidthPx;
|
||||
float minPlateSizeHeightPx;
|
||||
|
||||
|
||||
float plateWidthMM;
|
||||
float plateHeightMM;
|
||||
|
||||
|
||||
float charHeightMM;
|
||||
float charWidthMM;
|
||||
float charWhitespaceTopMM;
|
||||
float charWhitespaceBotMM;
|
||||
|
||||
|
||||
int templateWidthPx;
|
||||
int templateHeightPx;
|
||||
|
||||
|
||||
int ocrImageWidthPx;
|
||||
int ocrImageHeightPx;
|
||||
|
||||
|
||||
int stateIdImageWidthPx;
|
||||
int stateIdimageHeightPx;
|
||||
|
||||
|
||||
float charAnalysisMinPercent;
|
||||
float charAnalysisHeightRange;
|
||||
float charAnalysisHeightStepSize;
|
||||
int charAnalysisNumSteps;
|
||||
|
||||
|
||||
float plateLinesSensitivityVertical;
|
||||
float plateLinesSensitivityHorizontal;
|
||||
|
||||
int segmentationMinBoxWidthPx;
|
||||
float segmentationMinCharHeightPercent;
|
||||
float segmentationMaxCharWidthvsAverage;
|
||||
|
||||
|
||||
string ocrLanguage;
|
||||
int ocrMinFontSize;
|
||||
|
||||
|
||||
float postProcessMinConfidence;
|
||||
float postProcessConfidenceSkipLevel;
|
||||
int postProcessMaxSubstitutions;
|
||||
int postProcessMinCharacters;
|
||||
int postProcessMaxCharacters;
|
||||
|
||||
|
||||
|
||||
bool debugGeneral;
|
||||
bool debugTiming;
|
||||
bool debugStateId;
|
||||
@@ -102,9 +102,9 @@ class Config
|
||||
bool debugOcr;
|
||||
bool debugPostProcess;
|
||||
bool debugShowImages;
|
||||
|
||||
|
||||
void debugOff();
|
||||
|
||||
|
||||
string getKeypointsRuntimeDir();
|
||||
string getCascadeRuntimeDir();
|
||||
string getPostProcessRuntimeDir();
|
||||
@@ -114,9 +114,9 @@ private:
|
||||
CSimpleIniA* ini;
|
||||
|
||||
string runtimeBaseDir;
|
||||
|
||||
|
||||
void loadValues(string country);
|
||||
|
||||
|
||||
int getInt(string section, string key, int defaultValue);
|
||||
float getFloat(string section, string key, float defaultValue);
|
||||
string getString(string section, string key, string defaultValue);
|
||||
@@ -124,4 +124,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif // CONFIG_H
|
||||
#endif // CONFIG_H
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -26,4 +26,4 @@
|
||||
#define DEFAULT_RUNTIME_DIR "/default_runtime_data_dir/"
|
||||
#endif
|
||||
|
||||
#define ENV_VARIABLE_RUNTIME_DIR "OPENALPR_RUNTIME_DIR"
|
||||
#define ENV_VARIABLE_RUNTIME_DIR "OPENALPR_RUNTIME_DIR"
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -29,13 +29,13 @@ const float MAX_DISTANCE_TO_MATCH = 100.0f;
|
||||
FeatureMatcher::FeatureMatcher(Config* config)
|
||||
{
|
||||
this->config = config;
|
||||
|
||||
|
||||
//this->descriptorMatcher = DescriptorMatcher::create( "BruteForce-HammingLUT" );
|
||||
this->descriptorMatcher = new BFMatcher(NORM_HAMMING, false);
|
||||
|
||||
|
||||
//this->descriptorMatcher = DescriptorMatcher::create( "FlannBased" );
|
||||
|
||||
|
||||
|
||||
|
||||
this->detector = new FastFeatureDetector(10, true);
|
||||
this->extractor = new BRISK(10, 1, 0.9);
|
||||
}
|
||||
@@ -45,11 +45,11 @@ FeatureMatcher::~FeatureMatcher()
|
||||
for (int i = 0; i < trainingImgKeypoints.size(); i++)
|
||||
trainingImgKeypoints[i].clear();
|
||||
trainingImgKeypoints.clear();
|
||||
|
||||
|
||||
descriptorMatcher.release();
|
||||
detector.release();
|
||||
extractor.release();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ bool FeatureMatcher::isLoaded()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,13 +75,13 @@ void FeatureMatcher::surfStyleMatching( const Mat& queryDescriptors, vector<KeyP
|
||||
vector<DMatch>& matches12 )
|
||||
{
|
||||
vector<vector<DMatch> > matchesKnn;
|
||||
|
||||
|
||||
this->descriptorMatcher->radiusMatch(queryDescriptors, matchesKnn, MAX_DISTANCE_TO_MATCH);
|
||||
|
||||
|
||||
|
||||
|
||||
vector<DMatch> tempMatches;
|
||||
_surfStyleMatching(queryDescriptors, matchesKnn, tempMatches);
|
||||
|
||||
|
||||
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
|
||||
if (matchesKnn[descInd].size() > 1)
|
||||
{
|
||||
|
||||
|
||||
// Next throw out matches with a crappy score
|
||||
// Ignore... already handled by the radiusMatch
|
||||
//if (matchesKnn[descInd][0].distance < MAX_DISTANCE_TO_MATCH)
|
||||
//{
|
||||
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
|
||||
if (matchesKnn[descInd][0].imgIdx == matchesKnn[descInd][1].imgIdx)
|
||||
{
|
||||
@@ -125,20 +125,20 @@ void FeatureMatcher::_surfStyleMatching(const Mat& queryDescriptors, vector<vect
|
||||
already_exists = true;
|
||||
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))
|
||||
{
|
||||
already_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Good match.
|
||||
if (already_exists == false)
|
||||
matches12.push_back(matchesKnn[descInd][0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//}
|
||||
}
|
||||
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:
|
||||
// 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
|
||||
|
||||
|
||||
//for (unsigned int first_index = 0; first_index < matches.size(); ++first_index)
|
||||
//{
|
||||
|
||||
//matches12.push_back(match);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 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
|
||||
void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints, const vector<DMatch> inputMatches, vector<DMatch> &outputMatches)
|
||||
{
|
||||
|
||||
|
||||
Rect crissCrossAreaVertical(0, 0, config->stateIdImageWidthPx, config->stateIdimageHeightPx * 2);
|
||||
Rect crissCrossAreaHorizontal(0, 0, config->stateIdImageWidthPx * 2, config->stateIdimageHeightPx);
|
||||
|
||||
|
||||
for (int i = 0; i < billMapping.size(); i++)
|
||||
{
|
||||
vector<DMatch> matchesForOnePlate;
|
||||
@@ -179,32 +179,32 @@ void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints,
|
||||
if (inputMatches[j].imgIdx == i)
|
||||
matchesForOnePlate.push_back(inputMatches[j]);
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
vector<LineSegment> vlines;
|
||||
vector<LineSegment> hlines;
|
||||
vector<int> matchIdx;
|
||||
|
||||
|
||||
for (int j = 0; j < matchesForOnePlate.size(); j++)
|
||||
{
|
||||
KeyPoint tkp = trainingImgKeypoints[i][matchesForOnePlate[j].trainIdx];
|
||||
KeyPoint qkp = queryKeypoints[matchesForOnePlate[j].queryIdx];
|
||||
|
||||
|
||||
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));
|
||||
matchIdx.push_back(j);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Iterate through each line (n^2) removing the one with the most criss-crosses until there are none left.
|
||||
int mostIntersections = 1;
|
||||
while (mostIntersections > 0 && vlines.size() > 0)
|
||||
{
|
||||
int mostIntersectionsIndex = -1;
|
||||
mostIntersections = 0;
|
||||
|
||||
|
||||
for (int j = 0; j < vlines.size(); j++)
|
||||
{
|
||||
int intrCount = 0;
|
||||
@@ -223,14 +223,14 @@ void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints,
|
||||
intrCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (intrCount > mostIntersections)
|
||||
{
|
||||
mostIntersections = intrCount;
|
||||
mostIntersectionsIndex = j;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mostIntersectionsIndex >= 0)
|
||||
{
|
||||
if (this->config->debugStateId)
|
||||
@@ -239,75 +239,75 @@ void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints,
|
||||
hlines.erase(hlines.begin() + mostIntersectionsIndex);
|
||||
matchIdx.erase(matchIdx.begin() + mostIntersectionsIndex);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Push the non-crisscrosses back on the list
|
||||
for (int j = 0; j < matchIdx.size(); j++)
|
||||
{
|
||||
outputMatches.push_back(matchesForOnePlate[matchIdx[j]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Returns true if successful, false otherwise
|
||||
bool FeatureMatcher::loadRecognitionSet(string country)
|
||||
{
|
||||
std::ostringstream out;
|
||||
std::ostringstream out;
|
||||
out << config->getKeypointsRuntimeDir() << "/" << country << "/";
|
||||
string country_dir = out.str();
|
||||
|
||||
|
||||
|
||||
if (DirectoryExists(country_dir.c_str()))
|
||||
{
|
||||
vector<Mat> trainImages;
|
||||
vector<string> plateFiles = getFilesInDir(country_dir.c_str());
|
||||
|
||||
|
||||
for (int i = 0; i < plateFiles.size(); i++)
|
||||
{
|
||||
if (hasEnding(plateFiles[i], ".jpg") == false)
|
||||
continue;
|
||||
|
||||
|
||||
string fullpath = country_dir + plateFiles[i];
|
||||
Mat img = imread( fullpath );
|
||||
|
||||
|
||||
// convert to gray and resize to the size of the templates
|
||||
cvtColor(img, img, CV_BGR2GRAY);
|
||||
resize(img, img, getSizeMaintainingAspect(img, config->stateIdImageWidthPx, config->stateIdimageHeightPx));
|
||||
|
||||
|
||||
if( img.empty() )
|
||||
{
|
||||
cout << "Can not read images" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Mat descriptors;
|
||||
|
||||
vector<KeyPoint> keypoints;
|
||||
detector->detect( img, keypoints );
|
||||
extractor->compute(img, keypoints, descriptors);
|
||||
|
||||
|
||||
if (descriptors.cols > 0)
|
||||
{
|
||||
billMapping.push_back(plateFiles[i].substr(0, 2));
|
||||
trainImages.push_back(descriptors);
|
||||
trainingImgKeypoints.push_back(keypoints);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
this->descriptorMatcher->add(trainImages);
|
||||
this->descriptorMatcher->train();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -317,16 +317,16 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
||||
)
|
||||
{
|
||||
RecognitionResult result;
|
||||
|
||||
|
||||
result.haswinner = false;
|
||||
|
||||
Mat queryDescriptors;
|
||||
vector<KeyPoint> queryKeypoints;
|
||||
|
||||
|
||||
detector->detect( queryImg, queryKeypoints );
|
||||
extractor->compute(queryImg, queryKeypoints, queryDescriptors);
|
||||
|
||||
|
||||
|
||||
|
||||
if (queryKeypoints.size() <= 5)
|
||||
{
|
||||
@@ -337,27 +337,27 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
vector<DMatch> filteredMatches;
|
||||
|
||||
surfStyleMatching( queryDescriptors, queryKeypoints, filteredMatches );
|
||||
|
||||
|
||||
|
||||
// Create and initialize the counts to 0
|
||||
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 < filteredMatches.size(); i++)
|
||||
{
|
||||
bill_match_counts[filteredMatches[i].imgIdx]++;
|
||||
//if (filteredMatches[i].imgIdx
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
float max_count = 0; // represented as a percent (0 to 100)
|
||||
int secondmost_count = 0;
|
||||
int maxcount_index = -1;
|
||||
@@ -368,25 +368,25 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
||||
secondmost_count = max_count;
|
||||
if (secondmost_count <= 2) // A value of 1 or 2 is effectively 0
|
||||
secondmost_count = 0;
|
||||
|
||||
|
||||
max_count = bill_match_counts[i];
|
||||
maxcount_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float score = ((max_count - secondmost_count - 3) / 10) * 100;
|
||||
if (score < 0)
|
||||
score = 0;
|
||||
else if (score > 100)
|
||||
score = 100;
|
||||
|
||||
|
||||
|
||||
if (score > 0)
|
||||
{
|
||||
result.haswinner = true;
|
||||
result.winner = billMapping[maxcount_index];
|
||||
result.confidence = score;
|
||||
|
||||
|
||||
if (drawOnImage)
|
||||
{
|
||||
vector<KeyPoint> positiveMatches;
|
||||
@@ -397,36 +397,35 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
||||
positiveMatches.push_back( queryKeypoints[filteredMatches[i].queryIdx] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Mat tmpImg;
|
||||
drawKeypoints( queryImg, queryKeypoints, tmpImg, CV_RGB(185, 0, 0), DrawMatchesFlags::DEFAULT );
|
||||
drawKeypoints( tmpImg, positiveMatches, *outputImage, CV_RGB(0, 255, 0), DrawMatchesFlags::DEFAULT );
|
||||
|
||||
|
||||
if (result.haswinner == true)
|
||||
{
|
||||
|
||||
std::ostringstream out;
|
||||
|
||||
std::ostringstream out;
|
||||
out << result.winner << " (" << result.confidence << "%)";
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (this->config->debugStateId)
|
||||
{
|
||||
|
||||
|
||||
for (int i = 0; i < billMapping.size(); i++)
|
||||
{
|
||||
cout << billMapping[i] << " : " << bill_match_counts[i] << endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -55,31 +55,31 @@ class FeatureMatcher
|
||||
|
||||
RecognitionResult recognize( const Mat& queryImg, bool drawOnImage, Mat* outputImage,
|
||||
bool debug_on, vector<int> debug_matches_array );
|
||||
|
||||
|
||||
|
||||
bool loadRecognitionSet(string country);
|
||||
|
||||
|
||||
bool isLoaded();
|
||||
|
||||
int numTrainingElements();
|
||||
|
||||
|
||||
private:
|
||||
Config* config;
|
||||
|
||||
|
||||
Ptr<DescriptorMatcher> descriptorMatcher;
|
||||
Ptr<FastFeatureDetector> detector;
|
||||
Ptr<BRISK> extractor;
|
||||
|
||||
|
||||
vector<vector<KeyPoint> > trainingImgKeypoints;
|
||||
|
||||
|
||||
|
||||
|
||||
vector<vector<KeyPoint> > trainingImgKeypoints;
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
vector<string> billMapping;
|
||||
|
||||
|
||||
|
||||
|
||||
void surfStyleMatching( const Mat& queryDescriptors, vector<KeyPoint> queryKeypoints,
|
||||
@@ -88,5 +88,3 @@ class FeatureMatcher
|
||||
};
|
||||
|
||||
#endif // FEATUREMATCHER_H
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -23,7 +23,7 @@
|
||||
LicensePlateCandidate::LicensePlateCandidate(Mat frame, Rect regionOfInterest, Config* config)
|
||||
{
|
||||
this->config = config;
|
||||
|
||||
|
||||
this->frame = frame;
|
||||
this->plateRegion = regionOfInterest;
|
||||
}
|
||||
@@ -37,61 +37,61 @@ LicensePlateCandidate::~LicensePlateCandidate()
|
||||
void LicensePlateCandidate::recognize()
|
||||
{
|
||||
charSegmenter = NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
this->confidence = 0;
|
||||
|
||||
|
||||
int expandX = round(this->plateRegion.width * 0.15);
|
||||
int expandY = round(this->plateRegion.height * 0.10);
|
||||
// expand box by 15% in all directions
|
||||
Rect expandedRegion = expandRect( this->plateRegion, expandX, expandY, frame.cols, frame.rows) ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Mat plate_bgr = Mat(frame, expandedRegion);
|
||||
resize(plate_bgr, plate_bgr, Size(config->templateWidthPx, config->templateHeightPx));
|
||||
|
||||
|
||||
Mat plate_bgr_cleaned = Mat(plate_bgr.size(), plate_bgr.type());
|
||||
this->cleanupColors(plate_bgr, plate_bgr_cleaned);
|
||||
|
||||
|
||||
|
||||
|
||||
CharacterRegion charRegion(plate_bgr, config);
|
||||
|
||||
|
||||
|
||||
|
||||
if (charRegion.confidence > 10)
|
||||
{
|
||||
|
||||
|
||||
PlateLines plateLines(config);
|
||||
//Mat boogedy = charRegion.getPlateMask();
|
||||
|
||||
|
||||
plateLines.processImage(charRegion.getPlateMask(), 1.15);
|
||||
plateLines.processImage(plate_bgr_cleaned, 0.9);
|
||||
|
||||
|
||||
PlateCorners cornerFinder(plate_bgr, &plateLines, &charRegion, config);
|
||||
vector<Point> smallPlateCorners = cornerFinder.findPlateCorners();
|
||||
|
||||
|
||||
if (cornerFinder.confidence > 0)
|
||||
{
|
||||
this->plateCorners = transformPointsToOriginalImage(frame, plate_bgr, expandedRegion, smallPlateCorners);
|
||||
|
||||
|
||||
|
||||
|
||||
this->deskewed = deSkewPlate(frame, this->plateCorners);
|
||||
|
||||
|
||||
|
||||
charSegmenter = new CharacterSegmenter(deskewed, charRegion.thresholdsInverted(), config);
|
||||
|
||||
|
||||
|
||||
|
||||
//this->recognizedText = ocr->recognizedText;
|
||||
//strcpy(this->recognizedText, ocr.recognizedText);
|
||||
|
||||
|
||||
this->confidence = 100;
|
||||
|
||||
|
||||
}
|
||||
charRegion.confidence = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -106,30 +106,30 @@ vector<Point2f> LicensePlateCandidate::transformPointsToOriginalImage(Mat bigIma
|
||||
{
|
||||
float bigX = (corners[i].x * ((float) region.width / smallImage.cols));
|
||||
float bigY = (corners[i].y * ((float) region.height / smallImage.rows));
|
||||
|
||||
|
||||
bigX = bigX + region.x;
|
||||
bigY = bigY + region.y;
|
||||
|
||||
|
||||
cornerPoints.push_back(Point2f(bigX, bigY));
|
||||
}
|
||||
|
||||
|
||||
return cornerPoints;
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
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 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));
|
||||
|
||||
|
||||
float w = distanceBetweenPoints(leftEdge.midpoint(), rightEdge.midpoint());
|
||||
float h = distanceBetweenPoints(bottomEdge.midpoint(), topEdge.midpoint());
|
||||
float aspect = w/h;
|
||||
|
||||
|
||||
int width = config->ocrImageWidthPx;
|
||||
int height = round(((float) width) / aspect);
|
||||
if (height > config->ocrImageHeightPx)
|
||||
@@ -137,9 +137,9 @@ Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners)
|
||||
height = config->ocrImageHeightPx;
|
||||
width = round(((float) height) * aspect);
|
||||
}
|
||||
|
||||
|
||||
Mat deskewed(height, width, frame.type());
|
||||
|
||||
|
||||
// Corners of the destination image
|
||||
vector<Point2f> quad_pts;
|
||||
quad_pts.push_back(Point2f(0, 0));
|
||||
@@ -152,10 +152,10 @@ Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners)
|
||||
|
||||
// Apply perspective transformation
|
||||
warpPerspective(inputImage, deskewed, transmtx, deskewed.size());
|
||||
|
||||
|
||||
if (this->config->debugGeneral)
|
||||
displayImage(config, "quadrilateral", deskewed);
|
||||
|
||||
|
||||
return deskewed;
|
||||
}
|
||||
|
||||
@@ -164,13 +164,13 @@ void LicensePlateCandidate::cleanupColors(Mat inputImage, Mat outputImage)
|
||||
{
|
||||
if (this->config->debugGeneral)
|
||||
cout << "LicensePlate::cleanupColors" << endl;
|
||||
|
||||
|
||||
//Mat normalized(inputImage.size(), inputImage.type());
|
||||
|
||||
|
||||
Mat intermediate(inputImage.size(), inputImage.type());
|
||||
|
||||
|
||||
normalize(inputImage, intermediate, 0, 255, CV_MINMAX );
|
||||
|
||||
|
||||
// Equalize intensity:
|
||||
if(intermediate.channels() >= 3)
|
||||
{
|
||||
@@ -189,14 +189,14 @@ void LicensePlateCandidate::cleanupColors(Mat inputImage, Mat outputImage)
|
||||
|
||||
//ycrcb.release();
|
||||
}
|
||||
|
||||
|
||||
bilateralFilter(intermediate, outputImage, 3, 25, 35);
|
||||
|
||||
|
||||
|
||||
|
||||
bilateralFilter(intermediate, outputImage, 3, 25, 35);
|
||||
|
||||
|
||||
if (this->config->debugGeneral)
|
||||
{
|
||||
displayImage(config, "After cleanup", outputImage);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -54,28 +54,28 @@ class LicensePlateCandidate
|
||||
float confidence; // 0-100
|
||||
//vector<Point> points; // top-left, top-right, bottom-right, bottom-left
|
||||
vector<Point2f> plateCorners;
|
||||
|
||||
|
||||
void recognize();
|
||||
|
||||
|
||||
Mat deskewed;
|
||||
CharacterSegmenter* charSegmenter;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Config* config;
|
||||
|
||||
|
||||
|
||||
|
||||
Mat frame;
|
||||
Rect plateRegion;
|
||||
|
||||
|
||||
void cleanupColors(Mat inputImage, Mat outputImage);
|
||||
Mat filterByCharacterHue(vector<vector<Point> > charRegionContours);
|
||||
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);
|
||||
Mat deSkewPlate(Mat inputImage, vector<Point2f> corners);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // STAGE2_H
|
||||
#endif // STAGE2_H
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -25,9 +25,9 @@
|
||||
OCR::OCR(Config* config)
|
||||
{
|
||||
this->config = config;
|
||||
|
||||
|
||||
this->postProcessor = new PostProcess(config);
|
||||
|
||||
|
||||
tesseract=new TessBaseAPI();
|
||||
|
||||
// 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());
|
||||
putenv(tessdataPrefix.data());
|
||||
|
||||
|
||||
|
||||
|
||||
tesseract->Init("", config->ocrLanguage.c_str() );
|
||||
tesseract->SetVariable("save_blob_choices", "T");
|
||||
//tesseract->SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNPQRSTUVWXYZ1234567890");
|
||||
//tesseract->SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNPQRSTUVWXYZ1234567890");
|
||||
tesseract->SetPageSegMode(PSM_SINGLE_CHAR);
|
||||
}
|
||||
|
||||
@@ -53,56 +53,56 @@ OCR::~OCR()
|
||||
|
||||
void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
|
||||
|
||||
postProcessor->clear();
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < thresholds.size(); i++)
|
||||
{
|
||||
|
||||
|
||||
// Make it black text on white background
|
||||
bitwise_not(thresholds[i], thresholds[i]);
|
||||
tesseract->SetImage((uchar*) thresholds[i].data, thresholds[i].size().width, thresholds[i].size().height, thresholds[i].channels(), thresholds[i].step1());
|
||||
|
||||
|
||||
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++)
|
||||
{
|
||||
Rect expandedRegion = expandRect( charRegions[j], 2, 2, thresholds[i].cols, thresholds[i].rows) ;
|
||||
|
||||
|
||||
tesseract->SetRectangle(expandedRegion.x, expandedRegion.y, expandedRegion.width, expandedRegion.height);
|
||||
tesseract->Recognize(NULL);
|
||||
|
||||
|
||||
tesseract::ResultIterator* ri = tesseract->GetIterator();
|
||||
tesseract::PageIteratorLevel level = tesseract::RIL_SYMBOL;
|
||||
do {
|
||||
const char* symbol = ri->GetUTF8Text(level);
|
||||
float conf = ri->Confidence(level);
|
||||
|
||||
|
||||
bool dontcare;
|
||||
int fontindex = 0;
|
||||
int pointsize = 0;
|
||||
const char* fontName = ri->WordFontAttributes(&dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &pointsize, &fontindex);
|
||||
|
||||
|
||||
if(symbol != 0 && pointsize >= config->ocrMinFontSize) {
|
||||
postProcessor->addLetter(*symbol, j, conf);
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
bool indent = false;
|
||||
tesseract::ChoiceIterator ci(*ri);
|
||||
do {
|
||||
const char* choice = ci.GetUTF8Text();
|
||||
|
||||
postProcessor->addLetter(*choice, j, ci.Confidence());
|
||||
|
||||
|
||||
|
||||
|
||||
//letterScores.addScore(*choice, j, ci.Confidence() - MIN_CONFIDENCE);
|
||||
if (this->config->debugOcr)
|
||||
{
|
||||
@@ -110,36 +110,31 @@ void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
||||
printf("\t- ");
|
||||
printf("%s conf: %f\n", choice, ci.Confidence());
|
||||
}
|
||||
|
||||
|
||||
indent = true;
|
||||
} while(ci.Next());
|
||||
}
|
||||
|
||||
|
||||
if (this->config->debugOcr)
|
||||
printf("---------------------------------------------\n");
|
||||
|
||||
|
||||
delete[] symbol;
|
||||
} while((ri->Next(level)));
|
||||
|
||||
|
||||
delete ri;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
getTime(&endTime);
|
||||
cout << "OCR Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "utility.h"
|
||||
#include "postprocess.h"
|
||||
#include "config.h"
|
||||
@@ -45,22 +45,22 @@ class OCR
|
||||
public:
|
||||
OCR(Config* config);
|
||||
virtual ~OCR();
|
||||
|
||||
|
||||
void performOCR(vector<Mat> thresholds, vector<Rect> charRegions);
|
||||
|
||||
|
||||
PostProcess* postProcessor;
|
||||
//string recognizedText;
|
||||
//float confidence;
|
||||
//float overallConfidence;
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Config* config;
|
||||
|
||||
|
||||
TessBaseAPI *tesseract;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -23,20 +23,20 @@
|
||||
PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegion* charRegion, Config* config)
|
||||
{
|
||||
this->config = config;
|
||||
|
||||
|
||||
if (this->config->debugPlateCorners)
|
||||
cout << "PlateCorners constructor" << endl;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
this->inputImage = inputImage;
|
||||
this->plateLines = plateLines;
|
||||
this->charRegion = charRegion;
|
||||
|
||||
this->bestHorizontalScore = 9999999999999;
|
||||
this->bestVerticalScore = 9999999999999;
|
||||
|
||||
|
||||
|
||||
|
||||
Point topPoint = charRegion->getTopLine().midpoint();
|
||||
Point bottomPoint = charRegion->getBottomLine().closestPointOnSegmentTo(topPoint);
|
||||
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.
|
||||
// Adjust the char height for the difference in size...
|
||||
//this->charHeight = ((float) inputImage.size().height / (float) TEMPLATE_PLATE_HEIGHT) * this->charHeight;
|
||||
|
||||
|
||||
this->charAngle = angleBetweenPoints(charRegion->getCharArea()[0], charRegion->getCharArea()[1]);
|
||||
}
|
||||
|
||||
@@ -58,61 +58,61 @@ vector<Point> PlateCorners::findPlateCorners()
|
||||
{
|
||||
if (this->config->debugPlateCorners)
|
||||
cout << "PlateCorners::findPlateCorners" << endl;
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
int horizontalLines = this->plateLines->horizontalLines.size();
|
||||
int verticalLines = this->plateLines->verticalLines.size();
|
||||
|
||||
|
||||
|
||||
|
||||
// layout horizontal lines
|
||||
for (int h1 = NO_LINE; h1 < horizontalLines; h1++)
|
||||
{
|
||||
for (int h2 = NO_LINE; h2 < horizontalLines; h2++)
|
||||
{
|
||||
if (h1 == h2 && h1 != NO_LINE) continue;
|
||||
|
||||
|
||||
this->scoreHorizontals(h1, h2);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// layout vertical lines
|
||||
for (int v1 = NO_LINE; v1 < verticalLines; v1++)
|
||||
{
|
||||
for (int v2 = NO_LINE; v2 < verticalLines; v2++)
|
||||
{
|
||||
if (v1 == v2 && v1 != NO_LINE) continue;
|
||||
|
||||
|
||||
this->scoreVerticals(v1, v2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (this->config->debugPlateCorners)
|
||||
{
|
||||
|
||||
|
||||
cout << "Drawing debug stuff..." << endl;
|
||||
|
||||
|
||||
Mat imgCorners = Mat(inputImage.size(), inputImage.type());
|
||||
inputImage.copyTo(imgCorners);
|
||||
for (int i = 0; i < 4; i++)
|
||||
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->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->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.
|
||||
if (bestLeft.p1.x == 0 && bestLeft.p1.y == 0 && bestLeft.p2.x == 0 && bestLeft.p2.y == 0)
|
||||
confidence = 0;
|
||||
@@ -120,49 +120,49 @@ vector<Point> PlateCorners::findPlateCorners()
|
||||
confidence = 0;
|
||||
else
|
||||
confidence = 100;
|
||||
|
||||
|
||||
vector<Point> corners;
|
||||
corners.push_back(bestTop.intersection(bestLeft));
|
||||
corners.push_back(bestTop.intersection(bestRight));
|
||||
corners.push_back(bestBottom.intersection(bestRight));
|
||||
corners.push_back(bestBottom.intersection(bestLeft));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
getTime(&endTime);
|
||||
cout << "Plate Corners Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||
}
|
||||
|
||||
|
||||
return corners;
|
||||
}
|
||||
|
||||
|
||||
void PlateCorners::scoreVerticals(int v1, int v2)
|
||||
{
|
||||
|
||||
|
||||
float score = 0; // Lower is better
|
||||
|
||||
|
||||
LineSegment left;
|
||||
LineSegment right;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
float charHeightToPlateWidthRatio = config->plateWidthMM / config->charHeightMM;
|
||||
float idealPixelWidth = this->charHeight * (charHeightToPlateWidthRatio * 1.05); // Add 10% so we don't clip any characters
|
||||
|
||||
|
||||
if (v1 == NO_LINE && v2 == NO_LINE)
|
||||
{
|
||||
//return;
|
||||
Point centerTop = charRegion->getCharBoxTop().midpoint();
|
||||
Point centerBottom = charRegion->getCharBoxBottom().midpoint();
|
||||
LineSegment centerLine = LineSegment(centerBottom.x, centerBottom.y, centerTop.x, centerTop.y);
|
||||
|
||||
|
||||
left = centerLine.getParallelLine(idealPixelWidth / 2);
|
||||
right = centerLine.getParallelLine(-1 * idealPixelWidth / 2 );
|
||||
|
||||
|
||||
score += SCORING_MISSING_SEGMENT_PENALTY_VERTICAL * 2;
|
||||
}
|
||||
else if (v1 != NO_LINE && v2 != NO_LINE)
|
||||
@@ -182,109 +182,109 @@ void PlateCorners::scoreVerticals(int v1, int v2)
|
||||
right = left.getParallelLine(-1 * idealPixelWidth);
|
||||
score += SCORING_MISSING_SEGMENT_PENALTY_VERTICAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Make sure this line is to the left of our license plate letters
|
||||
if (left.isPointBelowLine(charRegion->getCharBoxLeft().midpoint()) == false)
|
||||
return;
|
||||
|
||||
|
||||
// Make sure this line is to the right of our license plate letters
|
||||
if (right.isPointBelowLine(charRegion->getCharBoxRight().midpoint()))
|
||||
return;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Score "Distance from the edge...
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 distanceFromEdge = leftDistanceFromEdge + rightDistanceFromEdge;
|
||||
score += distanceFromEdge * SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Score "Boxiness" of the 4 lines. How close is it to a parallelogram?
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float verticalAngleDiff = abs(left.angle - right.angle);
|
||||
|
||||
|
||||
score += (verticalAngleDiff) * SCORING_BOXINESS_WEIGHT;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SCORE the shape wrt character position and height relative to position
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Point leftMidLinePoint = left.closestPointOnSegmentTo(charRegion->getCharBoxLeft().midpoint());
|
||||
Point rightMidLinePoint = right.closestPointOnSegmentTo(charRegion->getCharBoxRight().midpoint());
|
||||
|
||||
|
||||
float plateDistance = abs(idealPixelWidth - distanceBetweenPoints(leftMidLinePoint, rightMidLinePoint));
|
||||
|
||||
|
||||
score += plateDistance * SCORING_VERTICALDISTANCE_WEIGHT;
|
||||
|
||||
|
||||
if (score < this->bestVerticalScore)
|
||||
{
|
||||
float scorecomponent;
|
||||
|
||||
|
||||
|
||||
|
||||
if (this->config->debugPlateCorners)
|
||||
{
|
||||
cout << "xx xx Score: charHeight " << this->charHeight << endl;
|
||||
cout << "xx xx Score: idealwidth " << idealPixelWidth << endl;
|
||||
cout << "xx xx Score: v1,v2= " << v1 << "," << v2 << endl;
|
||||
cout << "xx xx Score: Left= " << left.str() << endl;
|
||||
cout << "xx xx Score: Right= " << right.str() << endl;
|
||||
|
||||
cout << "xx xx Score: charHeight " << this->charHeight << endl;
|
||||
cout << "xx xx Score: idealwidth " << idealPixelWidth << endl;
|
||||
cout << "xx xx Score: v1,v2= " << v1 << "," << v2 << endl;
|
||||
cout << "xx xx Score: Left= " << left.str() << endl;
|
||||
cout << "xx xx Score: Right= " << right.str() << endl;
|
||||
|
||||
cout << "Vertical breakdown Score:" << 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 << " -- 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 << " -- 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: " << score << endl;
|
||||
}
|
||||
|
||||
|
||||
this->bestVerticalScore = score;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// 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
|
||||
void PlateCorners::scoreHorizontals(int h1, int h2)
|
||||
{
|
||||
|
||||
|
||||
//if (this->debug)
|
||||
// cout << "PlateCorners::scorePlate" << endl;
|
||||
|
||||
|
||||
float score = 0; // Lower is better
|
||||
|
||||
|
||||
LineSegment top;
|
||||
LineSegment bottom;
|
||||
|
||||
|
||||
float charHeightToPlateHeightRatio = config->plateHeightMM / config->charHeightMM;
|
||||
float idealPixelHeight = this->charHeight * charHeightToPlateHeightRatio;
|
||||
|
||||
|
||||
float idealPixelHeight = this->charHeight * charHeightToPlateHeightRatio;
|
||||
|
||||
|
||||
if (h1 == NO_LINE && h2 == NO_LINE)
|
||||
{
|
||||
// return;
|
||||
Point centerLeft = charRegion->getCharBoxLeft().midpoint();
|
||||
Point centerRight = charRegion->getCharBoxRight().midpoint();
|
||||
LineSegment centerLine = LineSegment(centerLeft.x, centerLeft.y, centerRight.x, centerRight.y);
|
||||
|
||||
|
||||
top = centerLine.getParallelLine(idealPixelHeight / 2);
|
||||
bottom = centerLine.getParallelLine(-1 * idealPixelHeight / 2 );
|
||||
|
||||
@@ -307,141 +307,141 @@ void PlateCorners::scoreHorizontals(int h1, int h2)
|
||||
bottom = top.getParallelLine(-1 * idealPixelHeight);
|
||||
score += SCORING_MISSING_SEGMENT_PENALTY_HORIZONTAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Make sure this line is above our license plate letters
|
||||
if (top.isPointBelowLine(charRegion->getCharBoxTop().midpoint()) == false)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
// Make sure this line is below our license plate letters
|
||||
if (bottom.isPointBelowLine(charRegion->getCharBoxBottom().midpoint()))
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 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?
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float horizontalAngleDiff = abs(top.angle - bottom.angle);
|
||||
|
||||
|
||||
|
||||
|
||||
score += (horizontalAngleDiff) * SCORING_BOXINESS_WEIGHT;
|
||||
// if (this->debug)
|
||||
// cout << "PlateCorners boxiness score: " << (horizontalAngleDiff + verticalAngleDiff) * SCORING_BOXINESS_WEIGHT << endl;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SCORE the shape wrt character position and height relative to position
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Point topPoint = top.midpoint();
|
||||
Point botPoint = bottom.closestPointOnSegmentTo(topPoint);
|
||||
float plateHeightPx = distanceBetweenPoints(topPoint, botPoint);
|
||||
|
||||
|
||||
// Get the height difference
|
||||
|
||||
|
||||
|
||||
|
||||
float heightRatio = charHeight / plateHeightPx;
|
||||
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)
|
||||
float heightRatioDiff = abs(heightRatio - idealHeightRatio);
|
||||
// Ideal ratio == ~.45
|
||||
|
||||
|
||||
// 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
|
||||
// float topDistance = distanceBetweenPoints(topMidLinePoint, charRegion->getCharBoxTop().midpoint());
|
||||
// float bottomDistance = distanceBetweenPoints(bottomMidLinePoint, charRegion->getCharBoxBottom().midpoint());
|
||||
|
||||
|
||||
// float idealTopDistance = charHeight * (TOP_WHITESPACE_HEIGHT_MM / CHARACTER_HEIGHT_MM);
|
||||
// float idealBottomDistance = charHeight * (BOTTOM_WHITESPACE_HEIGHT_MM / CHARACTER_HEIGHT_MM);
|
||||
// float distScore = abs(topDistance - idealTopDistance) + abs(bottomDistance - idealBottomDistance);
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Point charAreaMidPoint = charRegion->getCharBoxLeft().midpoint();
|
||||
Point topLineSpot = top.closestPointOnSegmentTo(charAreaMidPoint);
|
||||
Point botLineSpot = bottom.closestPointOnSegmentTo(charAreaMidPoint);
|
||||
|
||||
|
||||
float topDistanceFromMiddle = distanceBetweenPoints(topLineSpot, charAreaMidPoint);
|
||||
float bottomDistanceFromMiddle = distanceBetweenPoints(topLineSpot, charAreaMidPoint);
|
||||
|
||||
|
||||
float idealDistanceFromMiddle = idealPixelHeight / 2;
|
||||
|
||||
|
||||
float middleScore = abs(topDistanceFromMiddle - idealDistanceFromMiddle) + abs(bottomDistanceFromMiddle - idealDistanceFromMiddle);
|
||||
|
||||
score += middleScore * SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT;
|
||||
|
||||
|
||||
// if (this->debug)
|
||||
// {
|
||||
// cout << "PlateCorners boxiness score: " << avgRatio * SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT << endl;
|
||||
// cout << "PlateCorners boxiness score: " << distScore * SCORING_PLATEHEIGHT_WEIGHT << endl;
|
||||
// }
|
||||
//////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////
|
||||
// SCORE: the shape for angles matching the character region
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
float charanglediff = abs(charAngle - top.angle) + abs(charAngle - bottom.angle);
|
||||
|
||||
|
||||
|
||||
|
||||
score += charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT;
|
||||
|
||||
|
||||
// if (this->debug)
|
||||
// cout << "PlateCorners boxiness score: " << charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT << endl;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (score < this->bestHorizontalScore)
|
||||
{
|
||||
float scorecomponent;
|
||||
|
||||
|
||||
if (this->config->debugPlateCorners)
|
||||
{
|
||||
cout << "xx xx Score: charHeight " << this->charHeight << endl;
|
||||
cout << "xx xx Score: idealHeight " << idealPixelHeight << endl;
|
||||
cout << "xx xx Score: h1,h2= " << h1 << "," << h2 << endl;
|
||||
cout << "xx xx Score: Top= " << top.str() << endl;
|
||||
cout << "xx xx Score: Bottom= " << bottom.str() << endl;
|
||||
|
||||
cout << "xx xx Score: charHeight " << this->charHeight << endl;
|
||||
cout << "xx xx Score: idealHeight " << idealPixelHeight << endl;
|
||||
cout << "xx xx Score: h1,h2= " << h1 << "," << h2 << endl;
|
||||
cout << "xx xx Score: Top= " << top.str() << endl;
|
||||
cout << "xx xx Score: Bottom= " << bottom.str() << endl;
|
||||
|
||||
cout << "Horizontal breakdown Score:" << 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 << " -- 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 << " -- 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 << " -- 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: " << score << endl;
|
||||
}
|
||||
this->bestHorizontalScore = score;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -36,13 +36,13 @@ using namespace std;
|
||||
#define SCORING_MISSING_SEGMENT_PENALTY_VERTICAL 10
|
||||
#define SCORING_MISSING_SEGMENT_PENALTY_HORIZONTAL 15
|
||||
|
||||
#define SCORING_BOXINESS_WEIGHT 0.8
|
||||
#define SCORING_PLATEHEIGHT_WEIGHT 2.2
|
||||
#define SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT 0.05
|
||||
#define SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT 1.1
|
||||
#define SCORING_VERTICALDISTANCE_WEIGHT 0.1
|
||||
#define SCORING_BOXINESS_WEIGHT 0.8
|
||||
#define SCORING_PLATEHEIGHT_WEIGHT 2.2
|
||||
#define SCORING_TOP_BOTTOM_SPACE_VS_CHARHEIGHT_WEIGHT 0.05
|
||||
#define SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT 1.1
|
||||
#define SCORING_VERTICALDISTANCE_WEIGHT 0.1
|
||||
|
||||
#define SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT 0.05
|
||||
#define SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT 0.05
|
||||
|
||||
class PlateCorners
|
||||
{
|
||||
@@ -50,33 +50,31 @@ class PlateCorners
|
||||
public:
|
||||
PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegion* charRegion, Config* config);
|
||||
virtual ~PlateCorners();
|
||||
|
||||
|
||||
vector<Point> findPlateCorners();
|
||||
|
||||
|
||||
float confidence;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Config* config;
|
||||
Mat inputImage;
|
||||
float charHeight;
|
||||
float charAngle;
|
||||
|
||||
|
||||
float bestHorizontalScore;
|
||||
float bestVerticalScore;
|
||||
LineSegment bestTop;
|
||||
LineSegment bestBottom;
|
||||
LineSegment bestLeft;
|
||||
LineSegment bestRight;
|
||||
|
||||
|
||||
PlateLines* plateLines;
|
||||
CharacterRegion* charRegion;
|
||||
|
||||
|
||||
void scoreHorizontals( int h1, int h2 );
|
||||
void scoreVerticals( int v1, int v2 );
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // PLATELINES_H
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -24,10 +24,10 @@ PlateLines::PlateLines(Config* config)
|
||||
{
|
||||
this->config = config;
|
||||
this->debug = config->debugPlateLines;
|
||||
|
||||
|
||||
if (debug)
|
||||
cout << "PlateLines constructor" << endl;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -36,18 +36,18 @@ PlateLines::~PlateLines()
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void PlateLines::processImage(Mat inputImage, float sensitivity)
|
||||
{
|
||||
if (this->debug)
|
||||
cout << "PlateLines findLines" << endl;
|
||||
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
|
||||
|
||||
Mat smoothed(inputImage.size(), inputImage.type());
|
||||
inputImage.copyTo(smoothed);
|
||||
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 ) );
|
||||
|
||||
morphologyEx( smoothed, smoothed, MORPH_CLOSE, element );
|
||||
|
||||
|
||||
morph_size = 1;
|
||||
element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
||||
|
||||
|
||||
//morphologyEx( thresholded, thresholded, MORPH_GRADIENT, element );
|
||||
|
||||
|
||||
morph_size = 1;
|
||||
element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
||||
morphologyEx( smoothed, smoothed, MORPH_OPEN, element );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Mat edges(inputImage.size(), inputImage.type());
|
||||
Canny(smoothed, edges, 66, 133);
|
||||
|
||||
|
||||
|
||||
|
||||
vector<LineSegment> hlines = this->getLines(edges, sensitivity, false);
|
||||
vector<LineSegment> vlines = this->getLines(edges, sensitivity, true);
|
||||
for (int i = 0; i < hlines.size(); i++)
|
||||
this->horizontalLines.push_back(hlines[i]);
|
||||
for (int i = 0; i < vlines.size(); i++)
|
||||
this->verticalLines.push_back(vlines[i]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// if debug is enabled, draw the image
|
||||
if (this->debug)
|
||||
@@ -90,27 +90,27 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
|
||||
edges.copyTo(debugImgVert);
|
||||
cvtColor(debugImgHoriz,debugImgHoriz,CV_GRAY2BGR);
|
||||
cvtColor(debugImgVert,debugImgVert,CV_GRAY2BGR);
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
vector<Mat> images;
|
||||
images.push_back(debugImgHoriz);
|
||||
images.push_back(debugImgVert);
|
||||
|
||||
|
||||
Mat dashboard = drawImageDashboard(images, debugImgVert.type(), 1);
|
||||
displayImage(config, "Hough Lines", dashboard);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
@@ -118,27 +118,27 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
|
||||
cout << "Plate Lines Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||
}
|
||||
//smoothed.release();
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////// METHOD2!!!!!!!////////////////////
|
||||
|
||||
|
||||
/*
|
||||
Mat imgBlur;
|
||||
Mat imgCanny;
|
||||
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_size = 1;
|
||||
//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 );
|
||||
|
||||
|
||||
|
||||
|
||||
Mat imgShaped;
|
||||
imgCanny.copyTo(imgShaped);
|
||||
//Find contours of possibles characters
|
||||
@@ -147,26 +147,26 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
|
||||
biggestShapes, // a vector of contours
|
||||
CV_RETR_EXTERNAL, // retrieve the external contours
|
||||
CV_CHAIN_APPROX_SIMPLE ); // all pixels of each contours
|
||||
|
||||
|
||||
// Draw blue contours on a white image
|
||||
//cvtColor(imgShaped, imgShaped, CV_GRAY2RGB);
|
||||
cv::drawContours(imgShaped,biggestShapes,
|
||||
-1, // draw all contours
|
||||
cv::Scalar(255,255,255), // in blue
|
||||
1); // with a thickness of 1
|
||||
|
||||
|
||||
displayImage(config, "Blurred", imgCanny);
|
||||
displayImage(config, "Blurred Contours", imgShaped);
|
||||
|
||||
|
||||
vector<Rect> shapeRects( biggestShapes.size() );
|
||||
|
||||
|
||||
vector<vector<Point> >hull( biggestShapes.size() );
|
||||
for( int i = 0; i < biggestShapes.size(); i++ )
|
||||
{
|
||||
{
|
||||
//approxPolyDP( Mat(biggestShapes[i]), shapeRects[i], 3, true );
|
||||
convexHull( biggestShapes[i], hull[i], false );
|
||||
//approxPolyDP( biggestShapes[i], hull[i], 10, true );
|
||||
|
||||
|
||||
//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> filteredLines;
|
||||
|
||||
|
||||
int sensitivity;
|
||||
|
||||
|
||||
LSWMS lswms(Size(edges.cols, edges.rows), 3, 155, false);
|
||||
|
||||
|
||||
vector<LSEG> lsegs;
|
||||
vector<double> errors;
|
||||
lswms.run(edges, lsegs, errors);
|
||||
|
||||
|
||||
|
||||
|
||||
for( size_t i = 0; i < lsegs.size(); i++ )
|
||||
{
|
||||
|
||||
|
||||
if (vertical)
|
||||
{
|
||||
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);
|
||||
else
|
||||
candidate = LineSegment(lsegs[i][1].x, lsegs[i][1].y, lsegs[i][0].x, lsegs[i][0].y);
|
||||
|
||||
|
||||
cout << "VERT Angle: " << candidate.angle << endl;
|
||||
//if ((candidate.angle > 70 && candidate.angle < 110) || (candidate.angle > 250 && candidate.angle < 290))
|
||||
//{
|
||||
// good vertical
|
||||
filteredLines.push_back(candidate);
|
||||
|
||||
|
||||
//}
|
||||
}
|
||||
else
|
||||
@@ -215,26 +215,26 @@ vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical)
|
||||
else
|
||||
candidate = LineSegment(lsegs[i][1].x, lsegs[i][1].y, lsegs[i][0].x, lsegs[i][0].y);
|
||||
cout << "HORIZAngle: " << candidate.angle << endl;
|
||||
|
||||
|
||||
//if ( (candidate.angle > -20 && candidate.angle < 20) || (candidate.angle > 160 && candidate.angle < 200))
|
||||
//{
|
||||
// good horizontal
|
||||
filteredLines.push_back(candidate);
|
||||
|
||||
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if debug is enabled, draw the image
|
||||
if (this->debug)
|
||||
{
|
||||
Mat debugImg(edges.size(), edges.type());
|
||||
edges.copyTo(debugImg);
|
||||
cvtColor(debugImg,debugImg,CV_GRAY2BGR);
|
||||
|
||||
|
||||
for( size_t i = 0; i < filteredLines.size(); i++ )
|
||||
{
|
||||
|
||||
|
||||
line( debugImg, filteredLines[i].p1, filteredLines[i].p2, Scalar(0,0,255), 1, CV_AA);
|
||||
}
|
||||
if (vertical)
|
||||
@@ -242,7 +242,7 @@ vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical)
|
||||
else
|
||||
displayImage(config, "Lines Horizontal", debugImg);
|
||||
}
|
||||
|
||||
|
||||
return filteredLines;
|
||||
}
|
||||
*/
|
||||
@@ -252,47 +252,47 @@ vector<LineSegment> PlateLines::getLines(Mat edges, float sensitivityMultiplier,
|
||||
{
|
||||
if (this->debug)
|
||||
cout << "PlateLines::getLines" << endl;
|
||||
|
||||
|
||||
static int HORIZONTAL_SENSITIVITY = config->plateLinesSensitivityHorizontal;
|
||||
static int VERTICAL_SENSITIVITY = config->plateLinesSensitivityVertical;
|
||||
|
||||
|
||||
vector<Vec2f> allLines;
|
||||
vector<LineSegment> filteredLines;
|
||||
|
||||
|
||||
int sensitivity;
|
||||
if (vertical)
|
||||
sensitivity = VERTICAL_SENSITIVITY * (1.0 / sensitivityMultiplier);
|
||||
else
|
||||
sensitivity = HORIZONTAL_SENSITIVITY * (1.0 / sensitivityMultiplier);
|
||||
|
||||
|
||||
HoughLines( edges, allLines, 1, CV_PI/180, sensitivity, 0, 0 );
|
||||
|
||||
|
||||
|
||||
|
||||
for( size_t i = 0; i < allLines.size(); i++ )
|
||||
{
|
||||
float rho = allLines[i][0], theta = allLines[i][1];
|
||||
Point pt1, pt2;
|
||||
double a = cos(theta), b = sin(theta);
|
||||
double x0 = a*rho, y0 = b*rho;
|
||||
|
||||
|
||||
double angle = theta * (180 / CV_PI);
|
||||
pt1.x = cvRound(x0 + 1000*(-b));
|
||||
pt1.y = cvRound(y0 + 1000*(a));
|
||||
pt2.x = cvRound(x0 - 1000*(-b));
|
||||
pt2.y = cvRound(y0 - 1000*(a));
|
||||
|
||||
|
||||
if (vertical)
|
||||
{
|
||||
if (angle < 20 || angle > 340 || (angle > 160 && angle < 210))
|
||||
{
|
||||
// good vertical
|
||||
|
||||
|
||||
LineSegment line;
|
||||
if (pt1.y <= pt2.y)
|
||||
line = LineSegment(pt2.x, pt2.y, pt1.x, pt1.y);
|
||||
else
|
||||
line = LineSegment(pt1.x, pt1.y, pt2.x, pt2.y);
|
||||
|
||||
|
||||
// Get rid of the -1000, 1000 stuff. Terminate at the edges of the image
|
||||
// Helps with debugging/rounding issues later
|
||||
LineSegment top(0, 0, edges.cols, 0);
|
||||
@@ -304,28 +304,28 @@ vector<LineSegment> PlateLines::getLines(Mat edges, float sensitivityMultiplier,
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
if ( (angle > 70 && angle < 110) || (angle > 250 && angle < 290))
|
||||
{
|
||||
// good horizontal
|
||||
|
||||
|
||||
LineSegment line;
|
||||
if (pt1.x <= pt2.x)
|
||||
line = LineSegment(pt1.x, pt1.y, pt2.x, pt2.y);
|
||||
else
|
||||
line =LineSegment(pt2.x, pt2.y, pt1.x, pt1.y);
|
||||
|
||||
|
||||
// Get rid of the -1000, 1000 stuff. Terminate at the edges of the image
|
||||
// Helps with debugging/ rounding issues later
|
||||
int newY1 = line.getPointAt(0);
|
||||
int newY2 = line.getPointAt(edges.cols);
|
||||
|
||||
|
||||
filteredLines.push_back(LineSegment(0, newY1, edges.cols, newY2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return filteredLines;
|
||||
}
|
||||
|
||||
@@ -337,11 +337,11 @@ Mat PlateLines::customGrayscaleConversion(Mat src)
|
||||
{
|
||||
Mat img_hsv;
|
||||
cvtColor(src,img_hsv,CV_BGR2HSV);
|
||||
|
||||
|
||||
|
||||
|
||||
Mat grayscale = Mat(img_hsv.size(), CV_8U );
|
||||
Mat hue(img_hsv.size(), CV_8U );
|
||||
|
||||
|
||||
for (int row = 0; row < img_hsv.rows; row++)
|
||||
{
|
||||
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 s = (int) img_hsv.at<Vec3b>(row, col)[1];
|
||||
int v = (int) img_hsv.at<Vec3b>(row, col)[2];
|
||||
|
||||
|
||||
int pixval = pow(v, 1.05);
|
||||
|
||||
|
||||
|
||||
|
||||
if (pixval > 255)
|
||||
pixval = 255;
|
||||
grayscale.at<uchar>(row, col) = pixval;
|
||||
|
||||
|
||||
hue.at<uchar>(row, col) = h * (255.0 / 180.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//displayImage(config, "Hue", hue);
|
||||
return grayscale;
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -38,24 +38,22 @@ class PlateLines
|
||||
public:
|
||||
PlateLines(Config* config);
|
||||
virtual ~PlateLines();
|
||||
|
||||
|
||||
void processImage(Mat img, float sensitivity=1.0);
|
||||
|
||||
vector<LineSegment> horizontalLines;
|
||||
vector<LineSegment> verticalLines;
|
||||
|
||||
|
||||
vector<Point> winningCorners;
|
||||
|
||||
|
||||
private:
|
||||
Config* config;
|
||||
bool debug;
|
||||
|
||||
|
||||
|
||||
|
||||
Mat customGrayscaleConversion(Mat src);
|
||||
void findLines(Mat inputImage);
|
||||
vector<LineSegment> getLines(Mat edges, float sensitivityMultiplier, bool vertical);
|
||||
};
|
||||
|
||||
#endif // PLATELINES_H
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -23,19 +23,19 @@
|
||||
PostProcess::PostProcess(Config* config)
|
||||
{
|
||||
this->config = config;
|
||||
|
||||
|
||||
stringstream filename;
|
||||
filename << config->getPostProcessRuntimeDir() << "/" << config->country << ".patterns";
|
||||
|
||||
|
||||
std::ifstream infile(filename.str().c_str());
|
||||
|
||||
|
||||
|
||||
string region, pattern;
|
||||
while (infile >> region >> pattern)
|
||||
{
|
||||
RegexRule* rule = new RegexRule(region, pattern);
|
||||
//cout << "REGION: " << region << " PATTERN: " << pattern << endl;
|
||||
|
||||
|
||||
if (rules.find(region) == rules.end())
|
||||
{
|
||||
vector<RegexRule*> newRule;
|
||||
@@ -49,7 +49,7 @@ PostProcess::PostProcess(Config* config)
|
||||
rules[region] = oldRule;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//vector<RegexRule> test = rules["base"];
|
||||
//for (int i = 0; i < test.size(); i++)
|
||||
// cout << "Rule: " << test[i].regex << endl;
|
||||
@@ -66,7 +66,7 @@ PostProcess::~PostProcess()
|
||||
{
|
||||
delete iter->second[i];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,28 +75,28 @@ void PostProcess::addLetter(char letter, int charposition, float score)
|
||||
{
|
||||
if (score < config->postProcessMinConfidence)
|
||||
return;
|
||||
|
||||
|
||||
insertLetter(letter, charposition, score);
|
||||
|
||||
|
||||
if (score < config->postProcessConfidenceSkipLevel)
|
||||
{
|
||||
float adjustedScore = abs(config->postProcessConfidenceSkipLevel - score) + config->postProcessMinConfidence;
|
||||
insertLetter(SKIP_CHAR, charposition, adjustedScore );
|
||||
}
|
||||
|
||||
|
||||
//if (letter == '0')
|
||||
//{
|
||||
// insertLetter('O', charposition, score - 0.5);
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PostProcess::insertLetter(char letter, int charposition, float score)
|
||||
{
|
||||
|
||||
|
||||
score = score - config->postProcessMinConfidence;
|
||||
|
||||
|
||||
|
||||
|
||||
int existingIndex = -1;
|
||||
if (letters.size() < charposition + 1)
|
||||
{
|
||||
@@ -106,7 +106,7 @@ void PostProcess::insertLetter(char letter, int charposition, float score)
|
||||
letters.push_back(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < letters[charposition].size(); i++)
|
||||
{
|
||||
if (letters[charposition][i].letter == letter &&
|
||||
@@ -116,7 +116,7 @@ void PostProcess::insertLetter(char letter, int charposition, float score)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (existingIndex == -1)
|
||||
{
|
||||
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].totalscore = letters[charposition][existingIndex].totalscore + score;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -142,23 +142,23 @@ void PostProcess::clear()
|
||||
letters[i].clear();
|
||||
}
|
||||
letters.resize(0);
|
||||
|
||||
|
||||
unknownCharPositions.clear();
|
||||
unknownCharPositions.resize(0);
|
||||
allPossibilities.clear();
|
||||
//allPossibilities.resize(0);
|
||||
|
||||
|
||||
bestChars = "";
|
||||
matchesTemplate = false;
|
||||
}
|
||||
void PostProcess::analyze(string templateregion, int topn)
|
||||
{
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Get a list of missing positions
|
||||
for (int i = letters.size() -1; i >= 0; i--)
|
||||
{
|
||||
@@ -167,38 +167,38 @@ void PostProcess::analyze(string templateregion, int topn)
|
||||
unknownCharPositions.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (letters.size() == 0)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
// Sort the letters as they are
|
||||
for (int i = 0; i < letters.size(); i++)
|
||||
{
|
||||
if (letters[i].size() > 0)
|
||||
sort(letters[i].begin(), letters[i].end(), letterCompare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (this->config->debugPostProcess)
|
||||
{
|
||||
|
||||
|
||||
// Print all letters
|
||||
for (int i = 0; i < letters.size(); i++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 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
|
||||
// because it would be impossible for them to be a part of our topN results.
|
||||
vector<int> maxDepth = getMaxDepth(topn);
|
||||
|
||||
|
||||
for (int i = 0; i < letters.size(); i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//getTopN();
|
||||
vector<Letter> tmp;
|
||||
findAllPermutations(tmp, 0, config->postProcessMaxSubstitutions);
|
||||
|
||||
|
||||
|
||||
|
||||
timespec sortStartTime;
|
||||
getTime(&sortStartTime);
|
||||
|
||||
|
||||
int numelements = topn;
|
||||
if (allPossibilities.size() < topn)
|
||||
numelements = allPossibilities.size() - 1;
|
||||
|
||||
|
||||
partial_sort( allPossibilities.begin(), allPossibilities.begin() + numelements, allPossibilities.end(), wordCompare );
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec sortEndTime;
|
||||
getTime(&sortEndTime);
|
||||
cout << " -- PostProcess Sort Time: " << diffclock(sortStartTime, sortEndTime) << "ms." << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
matchesTemplate = false;
|
||||
|
||||
|
||||
|
||||
|
||||
if (templateregion != "")
|
||||
{
|
||||
vector<RegexRule*> regionRules = rules[templateregion];
|
||||
|
||||
|
||||
for (int i = 0; i < allPossibilities.size(); i++)
|
||||
{
|
||||
for (int j = 0; j < regionRules.size(); j++)
|
||||
@@ -250,16 +250,16 @@ void PostProcess::analyze(string templateregion, int topn)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (i >= topn - 1)
|
||||
break;
|
||||
//if (matchesTemplate || i >= TOP_N - 1)
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (matchesTemplate)
|
||||
{
|
||||
for (int z = 0; z < allPossibilities.size(); z++)
|
||||
@@ -275,26 +275,26 @@ void PostProcess::analyze(string templateregion, int topn)
|
||||
{
|
||||
bestChars = allPossibilities[0].letters;
|
||||
}
|
||||
|
||||
|
||||
// Now adjust the confidence scores to a percentage value
|
||||
if (allPossibilities.size() > 0)
|
||||
{
|
||||
float maxPercentScore = calculateMaxConfidenceScore();
|
||||
float highestRelativeScore = (float) allPossibilities[0].totalscore;
|
||||
|
||||
|
||||
for (int i = 0; i < allPossibilities.size(); i++)
|
||||
{
|
||||
allPossibilities[i].totalscore = maxPercentScore * (allPossibilities[i].totalscore / highestRelativeScore);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (this->config->debugPostProcess)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
// Print top words
|
||||
for (int i = 0; i < allPossibilities.size(); i++)
|
||||
{
|
||||
@@ -302,22 +302,22 @@ void PostProcess::analyze(string templateregion, int topn)
|
||||
if (allPossibilities[i].letters == bestChars)
|
||||
cout << " <--- ";
|
||||
cout << endl;
|
||||
|
||||
|
||||
if (i >= topn - 1)
|
||||
break;
|
||||
}
|
||||
cout << allPossibilities.size() << " total permutations" << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
getTime(&endTime);
|
||||
cout << "PostProcess Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||
}
|
||||
|
||||
|
||||
if (this->config->debugPostProcess)
|
||||
cout << "PostProcess Analysis Complete: " << bestChars << " -- MATCH: " << matchesTemplate << endl;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ void PostProcess::analyze(string templateregion, int topn)
|
||||
float PostProcess::calculateMaxConfidenceScore()
|
||||
{
|
||||
// Take the best score for each char position and average it.
|
||||
|
||||
|
||||
float totalScore = 0;
|
||||
int numScores = 0;
|
||||
// Get a list of missing positions
|
||||
@@ -337,15 +337,15 @@ float PostProcess::calculateMaxConfidenceScore()
|
||||
numScores++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (numScores == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
return totalScore / ((float) numScores);
|
||||
}
|
||||
|
||||
// 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
|
||||
// X-99 Y-95 Z-90
|
||||
// Q-55 R-80
|
||||
@@ -356,23 +356,23 @@ float PostProcess::calculateMaxConfidenceScore()
|
||||
// Y-95 Z-90
|
||||
vector<int> PostProcess::getMaxDepth(int topn)
|
||||
{
|
||||
|
||||
|
||||
vector<int> depth;
|
||||
for (int i = 0; i < letters.size(); i++)
|
||||
depth.push_back(0);
|
||||
|
||||
|
||||
int nextLeastDropCharPos = getNextLeastDrop(depth);
|
||||
while (nextLeastDropCharPos != -1)
|
||||
{
|
||||
if (getPermutationCount(depth) >= topn)
|
||||
break;
|
||||
|
||||
|
||||
depth[nextLeastDropCharPos] = depth[nextLeastDropCharPos] + 1;
|
||||
|
||||
|
||||
nextLeastDropCharPos = getNextLeastDrop(depth);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ int PostProcess::getPermutationCount(vector<int> depth)
|
||||
{
|
||||
permutationCount *= (depth[i] + 1);
|
||||
}
|
||||
|
||||
|
||||
return permutationCount;
|
||||
}
|
||||
|
||||
@@ -391,21 +391,21 @@ int PostProcess::getNextLeastDrop(vector<int> depth)
|
||||
{
|
||||
int nextLeastDropCharPos = -1;
|
||||
float leastNextDrop = 99999999999;
|
||||
|
||||
|
||||
for (int i = 0; i < letters.size(); i++)
|
||||
{
|
||||
if (depth[i] + 1 >= letters[i].size())
|
||||
continue;
|
||||
|
||||
|
||||
float drop = letters[i][depth[i]].totalscore - letters[i][depth[i]+1].totalscore;
|
||||
|
||||
|
||||
if (drop < leastNextDrop)
|
||||
{
|
||||
nextLeastDropCharPos = i;
|
||||
leastNextDrop = drop;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nextLeastDropCharPos;
|
||||
}
|
||||
|
||||
@@ -416,14 +416,14 @@ const vector<PPResult> PostProcess::getResults()
|
||||
|
||||
void PostProcess::findAllPermutations(vector<Letter> prevletters, int charPos, int substitutionsLeft)
|
||||
{
|
||||
|
||||
|
||||
if (substitutionsLeft < 0)
|
||||
return;
|
||||
|
||||
|
||||
// Add my letter to the chain and recurse
|
||||
for (int i = 0; i < letters[charPos].size(); i++)
|
||||
{
|
||||
|
||||
|
||||
if (charPos == letters.size() - 1)
|
||||
{
|
||||
// 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.totalscore = possibility.totalscore + prevletters[z].totalscore;
|
||||
}
|
||||
|
||||
|
||||
if (letters[charPos][i].letter != SKIP_CHAR)
|
||||
possibility.letters = possibility.letters + letters[charPos][i].letter;
|
||||
possibility.totalscore = possibility.totalscore +letters[charPos][i].totalscore;
|
||||
|
||||
|
||||
allPossibilities.push_back(possibility);
|
||||
}
|
||||
else
|
||||
{
|
||||
prevletters.push_back(letters[charPos][i]);
|
||||
|
||||
|
||||
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 )
|
||||
findAllPermutations(prevletters, charPos + 1, substitutionsLeft - 1);
|
||||
else
|
||||
findAllPermutations(prevletters, charPos + 1, substitutionsLeft);
|
||||
|
||||
|
||||
prevletters.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (letters[charPos].size() == 0)
|
||||
{
|
||||
// No letters for this char position...
|
||||
@@ -465,8 +465,8 @@ void PostProcess::findAllPermutations(vector<Letter> prevletters, int charPos, i
|
||||
findAllPermutations(prevletters, charPos + 1, substitutionsLeft);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ RegexRule::RegexRule(string region, string pattern)
|
||||
{
|
||||
this->original = pattern;
|
||||
this->region = region;
|
||||
|
||||
|
||||
numchars = 0;
|
||||
for (int i = 0; i < pattern.size(); i++)
|
||||
{
|
||||
@@ -503,7 +503,7 @@ RegexRule::RegexRule(string region, string pattern)
|
||||
i++;
|
||||
}
|
||||
this->regex = this->regex + ']';
|
||||
|
||||
|
||||
}
|
||||
else if (pattern.at(i) == '?')
|
||||
{
|
||||
@@ -518,12 +518,12 @@ RegexRule::RegexRule(string region, string pattern)
|
||||
{
|
||||
this->regex = this->regex + "\\d";
|
||||
}
|
||||
|
||||
|
||||
numchars++;
|
||||
}
|
||||
|
||||
|
||||
trexp.Compile(this->regex.c_str());
|
||||
|
||||
|
||||
//cout << "AA " << this->region << ": " << original << " regex: " << regex << endl;
|
||||
//for (int z = 0; z < this->skipPositions.size(); z++)
|
||||
// cout << "AA Skip position: " << skipPositions[z] << endl;
|
||||
@@ -534,7 +534,7 @@ bool RegexRule::match(string text)
|
||||
{
|
||||
if (text.length() != numchars)
|
||||
return false;
|
||||
|
||||
|
||||
return trexp.Match(text.c_str());
|
||||
}
|
||||
|
||||
@@ -552,10 +552,10 @@ string RegexRule::filterSkips(string text)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (skip == false)
|
||||
response = response + text[i];
|
||||
}
|
||||
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -35,7 +35,7 @@ using namespace std;
|
||||
|
||||
#define SKIP_CHAR '~'
|
||||
|
||||
struct Letter
|
||||
struct Letter
|
||||
{
|
||||
char letter;
|
||||
int charposition;
|
||||
@@ -60,10 +60,10 @@ class RegexRule
|
||||
public:
|
||||
RegexRule(string region, string pattern);
|
||||
|
||||
|
||||
|
||||
bool match(string text);
|
||||
string filterSkips(string text);
|
||||
|
||||
|
||||
private:
|
||||
int numchars;
|
||||
TRexpp trexp;
|
||||
@@ -79,34 +79,34 @@ class PostProcess
|
||||
public:
|
||||
PostProcess(Config* config);
|
||||
~PostProcess();
|
||||
|
||||
|
||||
void addLetter(char letter, int charposition, float score);
|
||||
|
||||
|
||||
void clear();
|
||||
void analyze(string templateregion, int topn);
|
||||
|
||||
|
||||
string bestChars;
|
||||
bool matchesTemplate;
|
||||
|
||||
|
||||
const vector<PPResult> getResults();
|
||||
|
||||
|
||||
private:
|
||||
Config* config;
|
||||
//void getTopN();
|
||||
void findAllPermutations(vector<Letter> prevletters, int charPos, int substitutionsLeft);
|
||||
|
||||
|
||||
void insertLetter(char letter, int charPosition, float score);
|
||||
|
||||
|
||||
map<string, vector<RegexRule*> > rules;
|
||||
|
||||
|
||||
float calculateMaxConfidenceScore();
|
||||
|
||||
|
||||
vector<vector<Letter> > letters;
|
||||
vector<int> unknownCharPositions;
|
||||
|
||||
|
||||
|
||||
|
||||
vector<PPResult> allPossibilities;
|
||||
|
||||
|
||||
// Functions used to prune the list of letters (based on topn) to improve performance
|
||||
vector<int> getMaxDepth(int topn);
|
||||
int getPermutationCount(vector<int> depth);
|
||||
@@ -118,18 +118,18 @@ class LetterScores
|
||||
{
|
||||
public:
|
||||
LetterScores(int numCharPositions);
|
||||
|
||||
|
||||
void addScore(char letter, int charposition, float score);
|
||||
|
||||
|
||||
vector<char> getBestScore();
|
||||
float getConfidence();
|
||||
|
||||
|
||||
private:
|
||||
int numCharPositions;
|
||||
|
||||
|
||||
vector<char> letters;
|
||||
vector<int> charpositions;
|
||||
vector<float> scores;
|
||||
};
|
||||
*/
|
||||
#endif // POSTPROCESS_H
|
||||
#endif // POSTPROCESS_H
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -27,18 +27,18 @@ RegionDetector::RegionDetector(Config* config)
|
||||
this->config = config;
|
||||
// Don't scale. Can change this in the future (i.e., maximum resolution preference, or some such).
|
||||
this->scale_factor = 1.0f;
|
||||
|
||||
|
||||
// Load either the regular or OpenCL version of the cascade classifier
|
||||
if (config->opencl_enabled)
|
||||
{
|
||||
this->plate_cascade = new ocl::OclCascadeClassifier();
|
||||
this->plate_cascade = new ocl::OclCascadeClassifier();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->plate_cascade = new CascadeClassifier();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if( this->plate_cascade->load( config->getCascadeRuntimeDir() + config->country + ".xml" ) )
|
||||
{
|
||||
this->loaded = true;
|
||||
@@ -46,11 +46,11 @@ RegionDetector::RegionDetector(Config* config)
|
||||
else
|
||||
{
|
||||
this->loaded = false;
|
||||
printf("--(!)Error loading classifier\n");
|
||||
printf("--(!)Error loading classifier\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
RegionDetector::~RegionDetector()
|
||||
@@ -68,10 +68,10 @@ bool RegionDetector::isLoaded()
|
||||
|
||||
vector<Rect> RegionDetector::detect(Mat frame)
|
||||
{
|
||||
|
||||
|
||||
Mat frame_gray;
|
||||
cvtColor( frame, frame_gray, CV_BGR2GRAY );
|
||||
|
||||
|
||||
vector<Rect> regionsOfInterest = doCascade(frame_gray);
|
||||
|
||||
return regionsOfInterest;
|
||||
@@ -84,19 +84,19 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
|
||||
//float scale_factor = 1;
|
||||
int w = frame.size().width;
|
||||
int h = frame.size().height;
|
||||
|
||||
|
||||
vector<Rect> plates;
|
||||
|
||||
equalizeHist( frame, frame );
|
||||
resize(frame, frame, Size(w * this->scale_factor, h * this->scale_factor));
|
||||
|
||||
|
||||
//-- Detect plates
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
if (config->opencl_enabled)
|
||||
{
|
||||
ocl::oclMat openclFrame(frame);
|
||||
@@ -104,14 +104,14 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
plate_cascade->detectMultiScale( frame, plates, 1.1, 3,
|
||||
|
||||
plate_cascade->detectMultiScale( frame, plates, 1.1, 3,
|
||||
0,
|
||||
//0|CV_HAAR_SCALE_IMAGE,
|
||||
minSize, maxSize );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
@@ -120,15 +120,15 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
for( int i = 0; i < plates.size(); i++ )
|
||||
{
|
||||
plates[i].x = plates[i].x / scale_factor;
|
||||
plates[i].y = plates[i].y / 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;
|
||||
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/core/core.hpp"
|
||||
@@ -36,10 +36,10 @@
|
||||
#include "support/timing.h"
|
||||
#include "constants.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class RegionDetector
|
||||
{
|
||||
|
||||
@@ -52,17 +52,17 @@ class RegionDetector
|
||||
|
||||
private:
|
||||
Config* config;
|
||||
|
||||
|
||||
float scale_factor;
|
||||
CascadeClassifier* plate_cascade;
|
||||
|
||||
|
||||
bool loaded;
|
||||
|
||||
|
||||
vector<Rect> doCascade(Mat frame);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // REGIONDETECTOR_H
|
||||
|
@@ -4,5 +4,5 @@ set(simpleini_source_files
|
||||
ConvertUTF.c
|
||||
)
|
||||
|
||||
|
||||
add_library(simpleini ${simpleini_source_files})
|
||||
|
||||
add_library(simpleini ${simpleini_source_files})
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright 2001-2004 Unicode, Inc.
|
||||
*
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
@@ -10,9 +10,9 @@
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
@@ -59,7 +59,7 @@ static const UTF32 halfMask = 0x3FFUL;
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF32toUTF16 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF32* source = *sourceStart;
|
||||
@@ -108,7 +108,7 @@ ConversionResult ConvertUTF32toUTF16 (
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF16toUTF32 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
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
|
||||
* in a UTF-8 sequence.
|
||||
*/
|
||||
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
||||
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
||||
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
|
||||
|
||||
/*
|
||||
@@ -212,7 +212,7 @@ static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF16* source = *sourceStart;
|
||||
@@ -221,7 +221,7 @@ ConversionResult ConvertUTF16toUTF8 (
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
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. */
|
||||
ch = *source++;
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
@@ -334,7 +334,7 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
@@ -407,7 +407,7 @@ ConversionResult ConvertUTF8toUTF16 (
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF32toUTF8 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF32* source = *sourceStart;
|
||||
@@ -416,7 +416,7 @@ ConversionResult ConvertUTF32toUTF8 (
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const UTF32 byteMask = 0xBF;
|
||||
const UTF32 byteMark = 0x80;
|
||||
const UTF32 byteMark = 0x80;
|
||||
ch = *source++;
|
||||
if (flags == strictConversion ) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
@@ -438,7 +438,7 @@ ConversionResult ConvertUTF32toUTF8 (
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
result = sourceIllegal;
|
||||
}
|
||||
|
||||
|
||||
target += bytesToWrite;
|
||||
if (target > targetEnd) {
|
||||
--source; /* Back up source pointer! */
|
||||
@@ -460,7 +460,7 @@ ConversionResult ConvertUTF32toUTF8 (
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF32 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright 2001-2004 Unicode, Inc.
|
||||
*
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
@@ -10,9 +10,9 @@
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* 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,
|
||||
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.
|
||||
|
||||
The return result indicates whether the conversion was successful,
|
||||
@@ -71,7 +71,7 @@
|
||||
sequence is malformed. When "sourceIllegal" is returned, the source
|
||||
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
|
||||
malformed sequence.
|
||||
malformed sequence.
|
||||
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
@@ -117,27 +117,27 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
|
||||
ConversionResult ConvertUTF8toUTF32 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF32toUTF8 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
|
||||
ConversionResult ConvertUTF16toUTF32 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF32toUTF16 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
|
||||
|
@@ -78,14 +78,14 @@ ini.GetAllKeys("section-name", keys);
|
||||
|
||||
```c++
|
||||
// get the value of a key
|
||||
const char * pszValue = ini.GetValue("section-name",
|
||||
const char * pszValue = ini.GetValue("section-name",
|
||||
"key-name", NULL /*default*/);
|
||||
|
||||
// get the value of a key which may have multiple
|
||||
// values. If bHasMultipleValues is true, then just
|
||||
// get the value of a key which may have multiple
|
||||
// values. If bHasMultipleValues is true, then just
|
||||
// one value has been returned
|
||||
bool bHasMultipleValues;
|
||||
pszValue = ini.GetValue("section-name", "key-name",
|
||||
pszValue = ini.GetValue("section-name", "key-name",
|
||||
NULL /*default*/, &bHasMultipleValues);
|
||||
|
||||
// get all values of a key with multiple values
|
||||
@@ -97,7 +97,7 @@ values.sort(CSimpleIniA::Entry::LoadOrder());
|
||||
|
||||
// output all of the items
|
||||
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);
|
||||
}
|
||||
```
|
||||
@@ -108,20 +108,20 @@ for (i = values.begin(); i != values.end(); ++i) {
|
||||
// adding a new section
|
||||
rc = ini.SetValue("new-section", NULL, NULL);
|
||||
if (rc < 0) return false;
|
||||
printf("section: %s\n", rc == SI_INSERTED ?
|
||||
printf("section: %s\n", rc == SI_INSERTED ?
|
||||
"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)
|
||||
rc = ini.SetValue("new-section", "new-key", "value");
|
||||
if (rc < 0) return false;
|
||||
printf("key: %s\n", rc == SI_INSERTED ?
|
||||
printf("key: %s\n", rc == SI_INSERTED ?
|
||||
"inserted" : "updated");
|
||||
|
||||
// changing the value of a key
|
||||
rc = ini.SetValue("section", "key", "updated-value");
|
||||
if (rc < 0) return false;
|
||||
printf("key: %s\n", rc == SI_INSERTED ?
|
||||
printf("key: %s\n", rc == SI_INSERTED ?
|
||||
"inserted" : "updated");
|
||||
```
|
||||
|
||||
@@ -130,7 +130,7 @@ printf("key: %s\n", rc == SI_INSERTED ?
|
||||
```c++
|
||||
// deleting a key from a section. Optionally the entire
|
||||
// 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*/);
|
||||
|
||||
// deleting an entire section and all keys in it
|
||||
|
@@ -1,5 +1,5 @@
|
||||
; Syntax file for ini files - contributed by Brodie Thiesfield
|
||||
;
|
||||
;
|
||||
; Suggested Colors:
|
||||
; Comments (;#) Comments, Comments 2 Green
|
||||
; Sections Characters Red
|
||||
@@ -13,24 +13,24 @@ IgnoreCase = Yes
|
||||
KeyWordLength = 1
|
||||
BracketChars =
|
||||
OperatorChars =
|
||||
PreprocStart =
|
||||
PreprocStart =
|
||||
SyntaxStart =
|
||||
SyntaxEnd =
|
||||
HexPrefix =
|
||||
CommentStart =
|
||||
CommentEnd =
|
||||
CommentStartAlt =
|
||||
CommentEndAlt =
|
||||
CommentStart =
|
||||
CommentEnd =
|
||||
CommentStartAlt =
|
||||
CommentEndAlt =
|
||||
SingleComment = #
|
||||
SingleCommentCol =
|
||||
SingleCommentAlt = ;
|
||||
SingleCommentColAlt =
|
||||
SingleCommentEsc =
|
||||
StringsSpanLines = No
|
||||
StringStart =
|
||||
StringEnd =
|
||||
StringStart =
|
||||
StringEnd =
|
||||
StringAlt = =
|
||||
StringEsc =
|
||||
StringEsc =
|
||||
CharStart = [
|
||||
CharEnd = ]
|
||||
CharEsc =
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -163,7 +163,7 @@
|
||||
SI_NO_MBCS. This is defined automatically on Windows CE platforms.
|
||||
|
||||
@section contrib CONTRIBUTIONS
|
||||
|
||||
|
||||
- 2010/05/03: Tobias Gehrig: added GetDoubleValue()
|
||||
|
||||
@section licence MIT LICENCE
|
||||
@@ -530,7 +530,7 @@ public:
|
||||
bool IsMultiLine() const { return m_bAllowMultiLine; }
|
||||
|
||||
/** 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.
|
||||
|
||||
\param a_bSpaces Add spaces around the equals sign?
|
||||
@@ -541,7 +541,7 @@ public:
|
||||
|
||||
/** Query the status of spaces output */
|
||||
bool UsingSpaces() const { return m_bSpaces; }
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/** @}
|
||||
@{ @name Loading INI Data */
|
||||
@@ -771,8 +771,8 @@ public:
|
||||
) const;
|
||||
|
||||
/** 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
|
||||
order if desired. Search this file for ".sort" for an example. Only
|
||||
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
|
||||
unique key names are returned.
|
||||
|
||||
NOTE! This structure contains only pointers to strings. The actual
|
||||
@@ -793,8 +793,8 @@ public:
|
||||
) const;
|
||||
|
||||
/** 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
|
||||
of the returned strings is NOT DEFINED. You can sort the names into
|
||||
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
|
||||
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
|
||||
@@ -915,7 +915,7 @@ public:
|
||||
|
||||
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.
|
||||
For all other values the default is returned. Character comparisons are
|
||||
For all other values the default is returned. Character comparisons are
|
||||
case-insensitive.
|
||||
|
||||
@param a_pSection Section to search
|
||||
@@ -954,9 +954,9 @@ public:
|
||||
character starting every line).
|
||||
@param a_bForceReplace Should all existing values in a multi-key INI
|
||||
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
|
||||
with a_bForceReplace = true, is that the load
|
||||
with a_bForceReplace = true, is that the load
|
||||
order and comment will be preserved this way.
|
||||
|
||||
@return SI_Error See error definitions
|
||||
@@ -978,19 +978,19 @@ public:
|
||||
when multiple keys are enabled.
|
||||
|
||||
@param a_pSection Section to add or update
|
||||
@param a_pKey Key to add or update.
|
||||
@param a_nValue Value to set.
|
||||
@param a_pComment Comment to be associated with the key. See the
|
||||
@param a_pKey Key to add or update.
|
||||
@param a_nValue Value to set.
|
||||
@param a_pComment Comment to be associated with the key. See the
|
||||
notes on SetValue() for comments.
|
||||
@param a_bUseHex By default the value will be written to the file
|
||||
in decimal format. Set this to true to write it
|
||||
@param a_bUseHex By default the value will be written to the file
|
||||
in decimal format. Set this to true to write it
|
||||
as hexadecimal.
|
||||
@param a_bForceReplace Should all existing values in a multi-key INI
|
||||
file be replaced with this entry. This option has
|
||||
no effect if not using multi-key files. The
|
||||
difference between Delete/SetLongValue and
|
||||
SetLongValue with a_bForceReplace = true, is that
|
||||
the load order and comment will be preserved this
|
||||
no effect if not using multi-key files. The
|
||||
difference between Delete/SetLongValue and
|
||||
SetLongValue with a_bForceReplace = true, is that
|
||||
the load order and comment will be preserved this
|
||||
way.
|
||||
|
||||
@return SI_Error See error definitions
|
||||
@@ -1010,16 +1010,16 @@ public:
|
||||
when multiple keys are enabled.
|
||||
|
||||
@param a_pSection Section to add or update
|
||||
@param a_pKey Key to add or update.
|
||||
@param a_nValue Value to set.
|
||||
@param a_pComment Comment to be associated with the key. See the
|
||||
@param a_pKey Key to add or update.
|
||||
@param a_nValue Value to set.
|
||||
@param a_pComment Comment to be associated with the key. See the
|
||||
notes on SetValue() for comments.
|
||||
@param a_bForceReplace Should all existing values in a multi-key INI
|
||||
file be replaced with this entry. This option has
|
||||
no effect if not using multi-key files. The
|
||||
difference between Delete/SetDoubleValue and
|
||||
SetDoubleValue with a_bForceReplace = true, is that
|
||||
the load order and comment will be preserved this
|
||||
no effect if not using multi-key files. The
|
||||
difference between Delete/SetDoubleValue and
|
||||
SetDoubleValue with a_bForceReplace = true, is that
|
||||
the load order and comment will be preserved this
|
||||
way.
|
||||
|
||||
@return SI_Error See error definitions
|
||||
@@ -1038,16 +1038,16 @@ public:
|
||||
when multiple keys are enabled.
|
||||
|
||||
@param a_pSection Section to add or update
|
||||
@param a_pKey Key to add or update.
|
||||
@param a_bValue Value to set.
|
||||
@param a_pComment Comment to be associated with the key. See the
|
||||
@param a_pKey Key to add or update.
|
||||
@param a_bValue Value to set.
|
||||
@param a_pComment Comment to be associated with the key. See the
|
||||
notes on SetValue() for comments.
|
||||
@param a_bForceReplace Should all existing values in a multi-key INI
|
||||
file be replaced with this entry. This option has
|
||||
no effect if not using multi-key files. The
|
||||
difference between Delete/SetBoolValue and
|
||||
SetBoolValue with a_bForceReplace = true, is that
|
||||
the load order and comment will be preserved this
|
||||
no effect if not using multi-key files. The
|
||||
difference between Delete/SetBoolValue and
|
||||
SetBoolValue with a_bForceReplace = true, is that
|
||||
the load order and comment will be preserved this
|
||||
way.
|
||||
|
||||
@return SI_Error See error definitions
|
||||
@@ -1141,9 +1141,9 @@ private:
|
||||
comment character starting every line).
|
||||
@param a_bForceReplace Should all existing values in a multi-key INI
|
||||
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
|
||||
with a_bForceReplace = true, is that the load
|
||||
with a_bForceReplace = true, is that the load
|
||||
order and comment will be preserved this way.
|
||||
@param a_bCopyStrings Should copies of the strings be made or not.
|
||||
If false then the pointers will be used as is.
|
||||
@@ -1238,7 +1238,7 @@ private:
|
||||
|
||||
/** Should spaces be written out surrounding the equals sign? */
|
||||
bool m_bSpaces;
|
||||
|
||||
|
||||
/** Next order value, used to ensure sections and keys are output in the
|
||||
same order that they are loaded/added.
|
||||
*/
|
||||
@@ -1358,14 +1358,14 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::LoadFile(
|
||||
if (lSize == 0) {
|
||||
return SI_OK;
|
||||
}
|
||||
|
||||
|
||||
// allocate and ensure NULL terminated
|
||||
char * pData = new char[lSize+1];
|
||||
if (!pData) {
|
||||
return SI_NOMEM;
|
||||
}
|
||||
pData[lSize] = 0;
|
||||
|
||||
|
||||
// load data into buffer
|
||||
fseek(a_fpFile, 0, SEEK_SET);
|
||||
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
|
||||
if (*pszSuffix) {
|
||||
return a_nDefault;
|
||||
if (*pszSuffix) {
|
||||
return a_nDefault;
|
||||
}
|
||||
|
||||
return nValue;
|
||||
}
|
||||
|
||||
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
|
||||
SI_Error
|
||||
SI_Error
|
||||
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetLongValue(
|
||||
const SI_CHAR * a_pSection,
|
||||
const SI_CHAR * a_pKey,
|
||||
@@ -2050,7 +2050,7 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetLongValue(
|
||||
// convert to output text
|
||||
SI_CHAR szOutput[64];
|
||||
SI_CONVERTER c(m_bStoreIsUtf8);
|
||||
c.ConvertFromStore(szInput, strlen(szInput) + 1,
|
||||
c.ConvertFromStore(szInput, strlen(szInput) + 1,
|
||||
szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
|
||||
|
||||
// actually add it
|
||||
@@ -2081,15 +2081,15 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetDoubleValue(
|
||||
double nValue = strtod(szValue, &pszSuffix);
|
||||
|
||||
// any invalid strings will return the default value
|
||||
if (!pszSuffix || *pszSuffix) {
|
||||
return a_nDefault;
|
||||
if (!pszSuffix || *pszSuffix) {
|
||||
return a_nDefault;
|
||||
}
|
||||
|
||||
return nValue;
|
||||
}
|
||||
|
||||
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
|
||||
SI_Error
|
||||
SI_Error
|
||||
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetDoubleValue(
|
||||
const SI_CHAR * a_pSection,
|
||||
const SI_CHAR * a_pKey,
|
||||
@@ -2112,7 +2112,7 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetDoubleValue(
|
||||
// convert to output text
|
||||
SI_CHAR szOutput[64];
|
||||
SI_CONVERTER c(m_bStoreIsUtf8);
|
||||
c.ConvertFromStore(szInput, strlen(szInput) + 1,
|
||||
c.ConvertFromStore(szInput, strlen(szInput) + 1,
|
||||
szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
|
||||
|
||||
// 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>
|
||||
SI_Error
|
||||
SI_Error
|
||||
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetBoolValue(
|
||||
const SI_CHAR * a_pSection,
|
||||
const SI_CHAR * a_pKey,
|
||||
@@ -2173,13 +2173,13 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::SetBoolValue(
|
||||
// convert to output text
|
||||
SI_CHAR szOutput[64];
|
||||
SI_CONVERTER c(m_bStoreIsUtf8);
|
||||
c.ConvertFromStore(pszInput, strlen(pszInput) + 1,
|
||||
c.ConvertFromStore(pszInput, strlen(pszInput) + 1,
|
||||
szOutput, sizeof(szOutput) / sizeof(SI_CHAR));
|
||||
|
||||
// actually add it
|
||||
return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true);
|
||||
}
|
||||
|
||||
|
||||
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
|
||||
bool
|
||||
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetAllValues(
|
||||
@@ -3383,4 +3383,3 @@ typedef CSimpleIniTempl<wchar_t,
|
||||
#endif
|
||||
|
||||
#endif // INCLUDED_SimpleIni_h
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -23,15 +23,15 @@
|
||||
StateIdentifier::StateIdentifier(Config* config)
|
||||
{
|
||||
this->config = config;
|
||||
|
||||
|
||||
featureMatcher = new FeatureMatcher(config);
|
||||
|
||||
|
||||
if (featureMatcher->isLoaded() == false)
|
||||
{
|
||||
cout << "Can not create detector or descriptor extractor or descriptor matcher of given types" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
featureMatcher->loadRecognitionSet(config->country);
|
||||
}
|
||||
|
||||
@@ -43,56 +43,55 @@ StateIdentifier::~StateIdentifier()
|
||||
int StateIdentifier::recognize(Mat img, Rect frame, char* stateCode)
|
||||
{
|
||||
Mat croppedImage = Mat(img, frame);
|
||||
|
||||
|
||||
return this->recognize(croppedImage, stateCode);
|
||||
}
|
||||
// Attempts to recognize the plate. Returns a confidence level. Updates teh "stateCode" variable
|
||||
// Attempts to recognize the plate. Returns a confidence level. Updates teh "stateCode" variable
|
||||
// with the value of the country/state
|
||||
int StateIdentifier::recognize(Mat img, char* stateCode)
|
||||
{
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
|
||||
cvtColor(img, img, CV_BGR2GRAY);
|
||||
|
||||
|
||||
resize(img, img, getSizeMaintainingAspect(img, config->stateIdImageWidthPx, config->stateIdimageHeightPx));
|
||||
|
||||
|
||||
Mat plateImg(img.size(), img.type());
|
||||
//plateImg = equalizeBrightness(img);
|
||||
img.copyTo(plateImg);
|
||||
|
||||
|
||||
Mat debugImg(plateImg.size(), plateImg.type());
|
||||
plateImg.copyTo(debugImg);
|
||||
vector<int> matchesArray(featureMatcher->numTrainingElements());
|
||||
|
||||
|
||||
|
||||
|
||||
RecognitionResult result = featureMatcher->recognize(plateImg, true, &debugImg, true, matchesArray );
|
||||
|
||||
|
||||
if (this->config->debugStateId)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
displayImage(config, "State Identifier1", plateImg);
|
||||
displayImage(config, "State Identifier", debugImg);
|
||||
cout << result.haswinner << " : " << result.confidence << " : " << result.winner << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
getTime(&endTime);
|
||||
cout << "State Identification Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (result.haswinner == false)
|
||||
return 0;
|
||||
|
||||
|
||||
strcpy(stateCode, result.winner.c_str());
|
||||
|
||||
|
||||
|
||||
|
||||
return result.confidence;
|
||||
}
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -39,20 +39,18 @@ class StateIdentifier
|
||||
|
||||
int recognize(Mat img, Rect frame, char* stateCode);
|
||||
int recognize(Mat img, char* stateCode);
|
||||
|
||||
|
||||
//int confidence;
|
||||
|
||||
|
||||
protected:
|
||||
Config* config;
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
FeatureMatcher* featureMatcher;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // STATEIDENTIFIER_H
|
||||
|
||||
|
||||
|
@@ -5,5 +5,5 @@ set(support_source_files
|
||||
timing.cpp
|
||||
)
|
||||
|
||||
|
||||
add_library(support ${support_source_files})
|
||||
|
||||
add_library(support ${support_source_files})
|
||||
|
@@ -22,7 +22,7 @@ bool DirectoryExists( const char* pzPath )
|
||||
|
||||
if (pDir != NULL)
|
||||
{
|
||||
bExists = true;
|
||||
bExists = true;
|
||||
(void) closedir (pDir);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ bool fileExists( const char* pzPath )
|
||||
if (pzPath == NULL) return false;
|
||||
|
||||
bool fExists = false;
|
||||
std::ifstream f(pzPath);
|
||||
std::ifstream f(pzPath);
|
||||
fExists = f.is_open();
|
||||
f.close();
|
||||
return fExists;
|
||||
@@ -43,9 +43,9 @@ bool fileExists( const char* pzPath )
|
||||
std::vector<std::string> getFilesInDir(const char* dirPath)
|
||||
{
|
||||
DIR *dir;
|
||||
|
||||
|
||||
std::vector<std::string> files;
|
||||
|
||||
|
||||
struct dirent *ent;
|
||||
if ((dir = opendir (dirPath)) != NULL) {
|
||||
/* print all the files and directories within directory */
|
||||
@@ -59,7 +59,7 @@ std::vector<std::string> getFilesInDir(const char* dirPath)
|
||||
perror ("");
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
@@ -73,4 +73,4 @@ bool stringCompare( const std::string &left, const std::string &right ){
|
||||
if( left.size() < right.size() )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -23,8 +23,8 @@
|
||||
bool DirectoryExists( const char* pzPath );
|
||||
bool fileExists( const char* pzPath );
|
||||
std::vector<std::string> getFilesInDir(const char* dirPath);
|
||||
|
||||
|
||||
bool stringCompare( const std::string &left, const std::string &right );
|
||||
|
||||
|
||||
#endif // FILESYSTEM_H
|
||||
|
||||
|
||||
#endif // FILESYSTEM_H
|
||||
|
@@ -76,8 +76,8 @@ double diffclock(timespec time1,timespec time2)
|
||||
{
|
||||
timespec delta = diff(time1,time2);
|
||||
double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_usec) / 1000.0);
|
||||
|
||||
|
||||
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
|
||||
@@ -116,13 +116,13 @@ void getTime(timespec* time)
|
||||
}
|
||||
double diffclock(timespec time1,timespec time2)
|
||||
{
|
||||
|
||||
|
||||
timespec delta = diff(time1,time2);
|
||||
double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_nsec) / 1000000.0);
|
||||
|
||||
|
||||
|
||||
|
||||
return milliseconds;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,6 @@
|
||||
|
||||
void getTime(timespec* time);
|
||||
double diffclock(timespec time1,timespec time2);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -33,7 +33,7 @@
|
||||
* capital W) in order to maintain compatibility with MingW.
|
||||
*
|
||||
* 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().
|
||||
* Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
|
||||
*
|
||||
@@ -410,11 +410,11 @@ _wreaddir(
|
||||
if (datap) {
|
||||
size_t n;
|
||||
DWORD attr;
|
||||
|
||||
|
||||
/* Pointer to directory entry to return */
|
||||
entp = &dirp->ent;
|
||||
|
||||
/*
|
||||
/*
|
||||
* 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
|
||||
* to PATH_MAX characters and zero-terminate the buffer.
|
||||
@@ -570,12 +570,12 @@ dirent_next(
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Open directory stream using plain old C-string.
|
||||
*/
|
||||
static DIR*
|
||||
opendir(
|
||||
const char *dirname)
|
||||
const char *dirname)
|
||||
{
|
||||
struct DIR *dirp;
|
||||
int error;
|
||||
@@ -608,7 +608,7 @@ opendir(
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
* Cannot convert file name to wide-character string. This
|
||||
* occurs if the string contains invalid multi-byte sequences or
|
||||
* the output buffer is too small to contain the resulting
|
||||
@@ -646,7 +646,7 @@ opendir(
|
||||
*/
|
||||
static struct dirent*
|
||||
readdir(
|
||||
DIR *dirp)
|
||||
DIR *dirp)
|
||||
{
|
||||
WIN32_FIND_DATAW *datap;
|
||||
struct dirent *entp;
|
||||
@@ -661,7 +661,7 @@ readdir(
|
||||
error = dirent_wcstombs_s(
|
||||
&n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
|
||||
|
||||
/*
|
||||
/*
|
||||
* If the file name cannot be represented by a multi-byte string,
|
||||
* then attempt to use old 8+3 file name. This allows traditional
|
||||
* Unix-code to access some file names despite of unicode
|
||||
@@ -674,7 +674,7 @@ readdir(
|
||||
if (error && datap->cAlternateFileName[0] != '\0') {
|
||||
error = dirent_wcstombs_s(
|
||||
&n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
|
||||
sizeof (datap->cAlternateFileName) /
|
||||
sizeof (datap->cAlternateFileName) /
|
||||
sizeof (datap->cAlternateFileName[0]));
|
||||
}
|
||||
|
||||
@@ -702,7 +702,7 @@ readdir(
|
||||
entp->d_reclen = sizeof (struct dirent);
|
||||
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
* Cannot convert file name to multi-byte string so construct
|
||||
* an errornous directory entry and return that. Note that
|
||||
* we cannot return NULL as that would stop the processing
|
||||
@@ -730,7 +730,7 @@ readdir(
|
||||
*/
|
||||
static int
|
||||
closedir(
|
||||
DIR *dirp)
|
||||
DIR *dirp)
|
||||
{
|
||||
int ok;
|
||||
if (dirp) {
|
||||
@@ -757,7 +757,7 @@ closedir(
|
||||
*/
|
||||
static void
|
||||
rewinddir(
|
||||
DIR* dirp)
|
||||
DIR* dirp)
|
||||
{
|
||||
/* Rewind wide-character string directory stream */
|
||||
_wrewinddir (dirp->wdirp);
|
||||
@@ -886,4 +886,3 @@ dirent_set_errno(
|
||||
}
|
||||
#endif
|
||||
#endif /*DIRENT_H*/
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
#ifndef _UNISTD_H
|
||||
#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
|
||||
* Please add functionality as neeeded
|
||||
* Please add functionality as neeeded
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -31,7 +31,7 @@
|
||||
#define STDERR_FILENO 2
|
||||
/* should be in some equivalent to <sys/types.h> */
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
@@ -39,4 +39,4 @@ typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#endif /* unistd.h */
|
||||
#endif /* unistd.h */
|
||||
|
@@ -2,6 +2,6 @@
|
||||
#include <math.h>
|
||||
|
||||
static inline double round(double val)
|
||||
{
|
||||
{
|
||||
return floor(val + 0.5);
|
||||
}
|
||||
}
|
||||
|
1285
src/openalpr/trex.c
1285
src/openalpr/trex.c
File diff suppressed because it is too large
Load Diff
@@ -1,67 +1,67 @@
|
||||
#ifndef _TREX_H_
|
||||
#define _TREX_H_
|
||||
/***************************************************************
|
||||
T-Rex a tiny regular expression library
|
||||
|
||||
Copyright (C) 2003-2006 Alberto Demichelis
|
||||
|
||||
This software is provided 'as-is', without any express
|
||||
or implied warranty. In no event will the authors be held
|
||||
liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for
|
||||
any purpose, including commercial applications, and to alter
|
||||
it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but
|
||||
is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any
|
||||
source distribution.
|
||||
|
||||
****************************************************************/
|
||||
|
||||
#ifdef _UNICODE
|
||||
#define TRexChar unsigned short
|
||||
#define MAX_CHAR 0xFFFF
|
||||
#define _TREXC(c) L##c
|
||||
#define trex_strlen wcslen
|
||||
#define trex_printf wprintf
|
||||
#else
|
||||
#define TRexChar char
|
||||
#define MAX_CHAR 0xFF
|
||||
#define _TREXC(c) (c)
|
||||
#define trex_strlen strlen
|
||||
#define trex_printf printf
|
||||
#endif
|
||||
|
||||
#ifndef TREX_API
|
||||
#define TREX_API extern
|
||||
#endif
|
||||
|
||||
#define TRex_True 1
|
||||
#define TRex_False 0
|
||||
|
||||
typedef unsigned int TRexBool;
|
||||
typedef struct TRex TRex;
|
||||
|
||||
typedef struct {
|
||||
const TRexChar *begin;
|
||||
int len;
|
||||
} TRexMatch;
|
||||
|
||||
TREX_API TRex *trex_compile(const TRexChar *pattern,const TRexChar **error);
|
||||
TREX_API void trex_free(TRex *exp);
|
||||
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_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 TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp);
|
||||
|
||||
#endif
|
||||
#ifndef _TREX_H_
|
||||
#define _TREX_H_
|
||||
/***************************************************************
|
||||
T-Rex a tiny regular expression library
|
||||
|
||||
Copyright (C) 2003-2006 Alberto Demichelis
|
||||
|
||||
This software is provided 'as-is', without any express
|
||||
or implied warranty. In no event will the authors be held
|
||||
liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for
|
||||
any purpose, including commercial applications, and to alter
|
||||
it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but
|
||||
is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any
|
||||
source distribution.
|
||||
|
||||
****************************************************************/
|
||||
|
||||
#ifdef _UNICODE
|
||||
#define TRexChar unsigned short
|
||||
#define MAX_CHAR 0xFFFF
|
||||
#define _TREXC(c) L##c
|
||||
#define trex_strlen wcslen
|
||||
#define trex_printf wprintf
|
||||
#else
|
||||
#define TRexChar char
|
||||
#define MAX_CHAR 0xFF
|
||||
#define _TREXC(c) (c)
|
||||
#define trex_strlen strlen
|
||||
#define trex_printf printf
|
||||
#endif
|
||||
|
||||
#ifndef TREX_API
|
||||
#define TREX_API extern
|
||||
#endif
|
||||
|
||||
#define TRex_True 1
|
||||
#define TRex_False 0
|
||||
|
||||
typedef unsigned int TRexBool;
|
||||
typedef struct TRex TRex;
|
||||
|
||||
typedef struct {
|
||||
const TRexChar *begin;
|
||||
int len;
|
||||
} TRexMatch;
|
||||
|
||||
TREX_API TRex *trex_compile(const TRexChar *pattern,const TRexChar **error);
|
||||
TREX_API void trex_free(TRex *exp);
|
||||
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_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 TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp);
|
||||
|
||||
#endif
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -26,14 +26,14 @@
|
||||
Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, int maxY)
|
||||
{
|
||||
Rect expandedRegion = Rect(original);
|
||||
|
||||
|
||||
float halfX = round((float) expandXPixels / 2.0);
|
||||
float halfY = round((float) expandYPixels / 2.0);
|
||||
expandedRegion.x = expandedRegion.x - halfX;
|
||||
expandedRegion.width = expandedRegion.width + expandXPixels;
|
||||
expandedRegion.y = expandedRegion.y - halfY;
|
||||
expandedRegion.height = expandedRegion.height + expandYPixels;
|
||||
|
||||
|
||||
if (expandedRegion.x < 0)
|
||||
expandedRegion.x = 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;
|
||||
if (expandedRegion.y + expandedRegion.height > maxY)
|
||||
expandedRegion.height = maxY - expandedRegion.y;
|
||||
|
||||
|
||||
return expandedRegion;
|
||||
}
|
||||
|
||||
Mat drawImageDashboard(vector<Mat> images, int imageType, int numColumns)
|
||||
{
|
||||
int numRows = ceil((float) images.size() / (float) numColumns);
|
||||
|
||||
|
||||
Mat dashboard(Size(images[0].cols * numColumns, images[0].rows * numRows), imageType);
|
||||
|
||||
|
||||
for (int i = 0; i < numColumns * numRows; i++)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return dashboard;
|
||||
}
|
||||
|
||||
@@ -73,20 +73,20 @@ Mat addLabel(Mat input, string label)
|
||||
const int extraHeight = 20;
|
||||
const Scalar bg(222,222,222);
|
||||
const Scalar fg(0,0,0);
|
||||
|
||||
|
||||
Rect destinationRect(border_size, extraHeight, input.cols, input.rows);
|
||||
Mat newImage(Size(input.cols + (border_size), input.rows + extraHeight + (border_size )), input.type());
|
||||
input.copyTo(newImage(destinationRect));
|
||||
|
||||
|
||||
cout << " Adding label " << label << endl;
|
||||
if (input.type() == CV_8U)
|
||||
cvtColor(newImage, newImage, CV_GRAY2BGR);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
rectangle(newImage, Point(0,0), Point(newImage.cols - 1, newImage.rows -1), border_color, border_size);
|
||||
|
||||
|
||||
return newImage;
|
||||
}
|
||||
|
||||
@@ -95,12 +95,12 @@ Mat addLabel(Mat input, string label)
|
||||
void drawAndWait(cv::Mat* frame)
|
||||
{
|
||||
cv::imshow("Temp Window", *frame);
|
||||
|
||||
|
||||
while (cv::waitKey(50) == -1)
|
||||
{
|
||||
// loop
|
||||
}
|
||||
|
||||
|
||||
cv::destroyWindow("Temp Window");
|
||||
}
|
||||
|
||||
@@ -114,35 +114,35 @@ vector<Mat> produceThresholds(const Mat img_gray, Config* config)
|
||||
{
|
||||
const int THRESHOLD_COUNT = 4;
|
||||
//Mat img_equalized = equalizeBrightness(img_gray);
|
||||
|
||||
|
||||
timespec startTime;
|
||||
getTime(&startTime);
|
||||
|
||||
vector<Mat> thresholds;
|
||||
|
||||
|
||||
for (int i = 0; i < THRESHOLD_COUNT; i++)
|
||||
thresholds.push_back(Mat(img_gray.size(), CV_8U));
|
||||
|
||||
|
||||
int i = 0;
|
||||
|
||||
|
||||
// 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 , 13, 3);
|
||||
//adaptiveThreshold(img_gray, thresholds[i++], 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV , 17, 3);
|
||||
|
||||
|
||||
// Wolf
|
||||
int k = 0, win=18;
|
||||
//NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
||||
//bitwise_not(thresholds[i-1], thresholds[i-1]);
|
||||
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
||||
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
||||
|
||||
|
||||
k = 1; win = 22;
|
||||
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
||||
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
||||
//NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
||||
//bitwise_not(thresholds[i-1], thresholds[i-1]);
|
||||
|
||||
|
||||
// Sauvola
|
||||
k = 1;
|
||||
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;
|
||||
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], SAUVOLA, 12, 12, 0.18 * k);
|
||||
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (config->debugTiming)
|
||||
{
|
||||
timespec endTime;
|
||||
getTime(&endTime);
|
||||
cout << " -- Produce Threshold Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||
}
|
||||
|
||||
|
||||
return thresholds;
|
||||
//threshold(img_equalized, img_threshold, 100, 255, THRESH_BINARY);
|
||||
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::sort(&array[0], &array[arraySize]);
|
||||
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)
|
||||
{
|
||||
|
||||
|
||||
// Divide the image by its morphologically closed counterpart
|
||||
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(19,19));
|
||||
Mat closed;
|
||||
@@ -193,7 +193,7 @@ Mat equalizeBrightness(Mat img)
|
||||
divide(img, closed, img, 1, CV_32FC1);
|
||||
normalize(img, img, 0, 255, NORM_MINMAX);
|
||||
img.convertTo(img, CV_8U); // convert back to unsigned int
|
||||
|
||||
|
||||
|
||||
return img;
|
||||
}
|
||||
@@ -201,7 +201,7 @@ Mat equalizeBrightness(Mat img)
|
||||
void drawRotatedRect(Mat* img, RotatedRect rect, Scalar color, int thickness)
|
||||
{
|
||||
|
||||
Point2f rect_points[4];
|
||||
Point2f rect_points[4];
|
||||
rect.points( rect_points );
|
||||
for( int j = 0; j < 4; j++ )
|
||||
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++)
|
||||
{
|
||||
int m = (int) mask.at<uchar>(row, col);
|
||||
|
||||
|
||||
if (m)
|
||||
{
|
||||
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 bl(rect.x, rect.y + rect.height);
|
||||
Point br(rect.x + rect.width, rect.y + rect.height);
|
||||
|
||||
|
||||
line(img, tl, br, 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 bsquared = (p2.y - p1.y)*(p2.y - p1.y);
|
||||
|
||||
|
||||
return sqrt(asquared + bsquared);
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ float angleBetweenPoints(Point p1, Point p2)
|
||||
{
|
||||
int deltaY = p2.y - p1.y;
|
||||
int deltaX = p2.x - p1.x;
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
float aspect = ((float) inputImg.cols) / ((float) inputImg.rows);
|
||||
|
||||
|
||||
if (maxWidth / 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;
|
||||
else
|
||||
this->slope = (float) (p2.y - p1.y) / (float) (p2.x - p1.x);
|
||||
|
||||
|
||||
this->length = distanceBetweenPoints(p1, p2);
|
||||
|
||||
|
||||
this->angle = angleBetweenPoints(p1, p2);
|
||||
}
|
||||
|
||||
@@ -314,15 +314,15 @@ float LineSegment::getPointAt(float x)
|
||||
Point LineSegment::closestPointOnSegmentTo(Point p)
|
||||
{
|
||||
float top = (p.x - p1.x) * (p2.x - p1.x) + (p.y - p1.y)*(p2.y - p1.y);
|
||||
|
||||
|
||||
float bottom = distanceBetweenPoints(p2, p1);
|
||||
bottom = bottom * bottom;
|
||||
|
||||
|
||||
float u = top / bottom;
|
||||
|
||||
|
||||
float x = p1.x + u * (p2.x - p1.x);
|
||||
float y = p1.y + u * (p2.y - p1.y);
|
||||
|
||||
|
||||
return Point(x, y);
|
||||
}
|
||||
|
||||
@@ -330,12 +330,12 @@ Point LineSegment::intersection(LineSegment line)
|
||||
{
|
||||
float c1, c2;
|
||||
float intersection_X = -1, intersection_Y= -1;
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
if( (slope - line.slope) == 0)
|
||||
{
|
||||
//std::cout << "No Intersection between the lines" << endl;
|
||||
@@ -344,7 +344,7 @@ Point LineSegment::intersection(LineSegment line)
|
||||
{
|
||||
// Line1 is vertical
|
||||
return Point(p1.x, line.getPointAt(p1.x));
|
||||
}
|
||||
}
|
||||
else if (line.p1.x == line.p2.x)
|
||||
{
|
||||
// Line2 is vertical
|
||||
@@ -354,11 +354,11 @@ Point LineSegment::intersection(LineSegment line)
|
||||
{
|
||||
intersection_X = (c2 - c1) / (slope - line.slope);
|
||||
intersection_Y = slope * intersection_X + c1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return Point(intersection_X, intersection_Y);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -375,7 +375,7 @@ Point LineSegment::midpoint()
|
||||
float diff = p2.x - p1.x;
|
||||
float midX = ((float) p1.x) + (diff / 2);
|
||||
int midY = getPointAt(midX);
|
||||
|
||||
|
||||
return Point(midX, midY);
|
||||
}
|
||||
|
||||
@@ -386,17 +386,12 @@ LineSegment LineSegment::getParallelLine(float distance)
|
||||
float angle = atan2( diff_x, diff_y);
|
||||
float dist_x = distance * cos(angle);
|
||||
float dist_y = -distance * sin(angle);
|
||||
|
||||
|
||||
int offsetX = (int)round(dist_x);
|
||||
int offsetY = (int)round(dist_y);
|
||||
|
||||
|
||||
LineSegment result(p1.x + offsetX, p1.y + offsetY,
|
||||
p2.x + offsetX, p2.y + offsetY);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -38,9 +38,9 @@
|
||||
#include "binarize_wolf.h"
|
||||
#include <vector>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
struct LineSegment
|
||||
{
|
||||
@@ -50,70 +50,70 @@ struct LineSegment
|
||||
float y2;
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
class LineSegment
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
Point p1, p2;
|
||||
float slope;
|
||||
float length;
|
||||
float angle;
|
||||
|
||||
|
||||
// LineSegment(Point point1, Point point2);
|
||||
LineSegment();
|
||||
LineSegment(int x1, int y1, int x2, int y2);
|
||||
LineSegment(Point p1, Point p2);
|
||||
|
||||
|
||||
void init(int x1, int y1, int x2, int y2);
|
||||
|
||||
|
||||
bool isPointBelowLine(Point tp);
|
||||
|
||||
|
||||
float getPointAt(float x);
|
||||
|
||||
|
||||
Point closestPointOnSegmentTo(Point p);
|
||||
|
||||
|
||||
Point intersection(LineSegment line);
|
||||
|
||||
|
||||
LineSegment getParallelLine(float distance);
|
||||
|
||||
|
||||
Point midpoint();
|
||||
|
||||
|
||||
inline std::string str()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(" << p1.x << ", " << p1.y << ") : (" << p2.x << ", " << p2.y << ")";
|
||||
return ss.str() ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
double median(int array[], int arraySize);
|
||||
|
||||
vector<Mat> produceThresholds(const Mat img_gray, Config* config);
|
||||
|
||||
|
||||
Mat drawImageDashboard(vector<Mat> images, int imageType, int numColumns);
|
||||
|
||||
|
||||
void displayImage(Config* config, string windowName, cv::Mat frame);
|
||||
void drawAndWait(cv::Mat* frame);
|
||||
|
||||
|
||||
double distanceBetweenPoints(Point p1, Point p2);
|
||||
|
||||
|
||||
void drawRotatedRect(Mat* img, RotatedRect rect, Scalar color, int thickness);
|
||||
|
||||
|
||||
void drawX(Mat img, Rect rect, Scalar color, int thickness);
|
||||
void fillMask(Mat img, const Mat mask, Scalar color);
|
||||
|
||||
|
||||
float angleBetweenPoints(Point p1, Point p2);
|
||||
|
||||
|
||||
Size getSizeMaintainingAspect(Mat inputImg, int maxWidth, int maxHeight);
|
||||
|
||||
|
||||
Mat equalizeBrightness(Mat img);
|
||||
|
||||
|
||||
Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, int maxY);
|
||||
|
||||
|
||||
Mat addLabel(Mat input, string label);
|
||||
|
||||
|
||||
#endif // UTILITY_H
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -22,9 +22,9 @@
|
||||
VerticalHistogram::VerticalHistogram(Mat inputImage, Mat mask)
|
||||
{
|
||||
analyzeImage(inputImage, mask);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
VerticalHistogram::~VerticalHistogram()
|
||||
@@ -38,44 +38,44 @@ void VerticalHistogram::analyzeImage(Mat inputImage, Mat mask)
|
||||
{
|
||||
highestPeak = 0;
|
||||
lowestValley = inputImage.rows;
|
||||
|
||||
|
||||
|
||||
|
||||
histoImg = Mat::zeros(inputImage.size(), CV_8U);
|
||||
|
||||
|
||||
int columnCount;
|
||||
|
||||
|
||||
for (int col = 0; col < inputImage.cols; col++)
|
||||
{
|
||||
columnCount = 0;
|
||||
|
||||
|
||||
for (int row = 0; row < inputImage.rows; row++)
|
||||
{
|
||||
|
||||
|
||||
if (inputImage.at<uchar>(row, col) > 0 && mask.at<uchar>(row, col) > 0)
|
||||
columnCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
this->colHeights.push_back(columnCount);
|
||||
|
||||
|
||||
if (columnCount < lowestValley)
|
||||
lowestValley = columnCount;
|
||||
if (columnCount > highestPeak)
|
||||
highestPeak = columnCount;
|
||||
|
||||
|
||||
|
||||
|
||||
for (; columnCount > 0; columnCount--)
|
||||
histoImg.at<uchar>(inputImage.rows - columnCount, col) = 255;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int VerticalHistogram::getLocalMinimum(int leftX, int rightX)
|
||||
{
|
||||
int minimum = histoImg.rows + 1;
|
||||
int lowestX = leftX;
|
||||
|
||||
|
||||
for (int i = leftX; i <= rightX; i++)
|
||||
{
|
||||
if (colHeights[i] < minimum)
|
||||
@@ -84,7 +84,7 @@ int VerticalHistogram::getLocalMinimum(int leftX, int rightX)
|
||||
minimum = colHeights[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return lowestX;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ int VerticalHistogram::getLocalMaximum(int leftX, int rightX)
|
||||
{
|
||||
int maximum = -1;
|
||||
int highestX = leftX;
|
||||
|
||||
|
||||
for (int i = leftX; i <= rightX; i++)
|
||||
{
|
||||
if (colHeights[i] > maximum)
|
||||
@@ -101,8 +101,8 @@ int VerticalHistogram::getLocalMaximum(int leftX, int rightX)
|
||||
maximum = colHeights[i];
|
||||
}
|
||||
}
|
||||
|
||||
return highestX;
|
||||
|
||||
return highestX;
|
||||
}
|
||||
|
||||
int VerticalHistogram::getHeightAt(int x)
|
||||
@@ -113,78 +113,78 @@ int VerticalHistogram::getHeightAt(int x)
|
||||
void VerticalHistogram::findValleys()
|
||||
{
|
||||
int MINIMUM_PEAK_HEIGHT = (int) (((float) highestPeak) * 0.75);
|
||||
|
||||
|
||||
int totalWidth = colHeights.size();
|
||||
|
||||
|
||||
int midpoint = ((highestPeak - lowestValley) / 2) + lowestValley;
|
||||
|
||||
|
||||
HistogramDirection prevDirection = FALLING;
|
||||
|
||||
|
||||
int relativePeakHeight = 0;
|
||||
int valleyStart = 0;
|
||||
|
||||
|
||||
for (int i = 0; i < totalWidth; i++)
|
||||
{
|
||||
bool aboveMidpoint = (colHeights[i] >= midpoint);
|
||||
|
||||
|
||||
if (aboveMidpoint)
|
||||
{
|
||||
if (colHeights[i] > relativePeakHeight)
|
||||
relativePeakHeight = colHeights[i];
|
||||
|
||||
|
||||
|
||||
|
||||
prevDirection = FLAT;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
relativePeakHeight = 0;
|
||||
|
||||
|
||||
HistogramDirection direction = getHistogramDirection(i);
|
||||
|
||||
|
||||
if ((prevDirection == FALLING || prevDirection == FLAT) && direction == RISING)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
else if ((prevDirection == FALLING || prevDirection == FLAT) && direction == RISING)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
HistogramDirection VerticalHistogram::getHistogramDirection(int index)
|
||||
{
|
||||
int EXTRA_WIDTH_TO_AVERAGE = 2;
|
||||
|
||||
|
||||
float trailingAverage = 0;
|
||||
float forwardAverage = 0;
|
||||
|
||||
|
||||
int trailStartIndex = index - EXTRA_WIDTH_TO_AVERAGE;
|
||||
if (trailStartIndex < 0)
|
||||
trailStartIndex = 0;
|
||||
int forwardEndIndex = index + EXTRA_WIDTH_TO_AVERAGE;
|
||||
if (forwardEndIndex >= colHeights.size())
|
||||
forwardEndIndex = colHeights.size() - 1;
|
||||
|
||||
|
||||
for (int i = index; i >= trailStartIndex; i--)
|
||||
{
|
||||
trailingAverage += colHeights[i];
|
||||
}
|
||||
trailingAverage = trailingAverage / ((float) (1 + index - trailStartIndex));
|
||||
|
||||
|
||||
for (int i = index; i <= forwardEndIndex; i++)
|
||||
{
|
||||
forwardAverage += colHeights[i];
|
||||
}
|
||||
forwardAverage = forwardAverage / ((float) (1 + forwardEndIndex - index));
|
||||
|
||||
|
||||
|
||||
|
||||
float diff = forwardAverage - trailingAverage;
|
||||
float minDiff = ((float) (highestPeak - lowestValley)) * 0.10;
|
||||
|
||||
|
||||
if (diff > minDiff)
|
||||
return RISING;
|
||||
else if (diff < minDiff)
|
||||
@@ -192,5 +192,3 @@ HistogramDirection VerticalHistogram::getHistogramDirection(int index)
|
||||
else
|
||||
return FLAT;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2013 New Designs Unlimited, LLC
|
||||
* Opensource Automated License Plate Recognition [http://www.openalpr.com]
|
||||
*
|
||||
*
|
||||
* This file is part of OpenAlpr.
|
||||
*
|
||||
*
|
||||
* OpenAlpr is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* it under the terms of the GNU Affero General Public License
|
||||
* version 3 as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@@ -45,24 +45,24 @@ class VerticalHistogram
|
||||
virtual ~VerticalHistogram();
|
||||
|
||||
Mat histoImg;
|
||||
|
||||
|
||||
// Returns the lowest X position between two points.
|
||||
int getLocalMinimum(int leftX, int rightX);
|
||||
// Returns the highest X position between two points.
|
||||
int getLocalMaximum(int leftX, int rightX);
|
||||
|
||||
|
||||
int getHeightAt(int x);
|
||||
|
||||
|
||||
private:
|
||||
vector<int> colHeights;
|
||||
int highestPeak;
|
||||
int lowestValley;
|
||||
vector<Valley> valleys;
|
||||
|
||||
|
||||
void analyzeImage(Mat inputImage, Mat mask);
|
||||
void findValleys();
|
||||
|
||||
|
||||
HistogramDirection getHistogramDirection(int index);
|
||||
};
|
||||
|
||||
#endif // VERTICALHISTOGRAM_H
|
||||
#endif // VERTICALHISTOGRAM_H
|
||||
|
@@ -689,4 +689,3 @@ inline void Arg::reset()
|
||||
} //namespace TCLAP
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,24 +1,24 @@
|
||||
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: ArgException.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_ARG_EXCEPTION_H
|
||||
@@ -36,7 +36,7 @@ namespace TCLAP {
|
||||
class ArgException : public std::exception
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* \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.
|
||||
* 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& td = "Generic ArgException")
|
||||
: std::exception(),
|
||||
_errorText(text),
|
||||
_argId( id ),
|
||||
: std::exception(),
|
||||
_errorText(text),
|
||||
_argId( id ),
|
||||
_typeDescription(td)
|
||||
{ }
|
||||
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
@@ -66,20 +66,20 @@ class ArgException : public std::exception
|
||||
/**
|
||||
* Returns the argument id.
|
||||
*/
|
||||
std::string argId() const
|
||||
{
|
||||
std::string argId() const
|
||||
{
|
||||
if ( _argId == "undefined" )
|
||||
return " ";
|
||||
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;
|
||||
return ex.c_str();
|
||||
}
|
||||
@@ -90,7 +90,7 @@ class ArgException : public std::exception
|
||||
*/
|
||||
std::string typeDescription() const
|
||||
{
|
||||
return _typeDescription;
|
||||
return _typeDescription;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,19 +119,19 @@ class ArgException : public std::exception
|
||||
* parse the argument it has been passed.
|
||||
*/
|
||||
class ArgParseException : public ArgException
|
||||
{
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* \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.
|
||||
*/
|
||||
ArgParseException( const std::string& text = "undefined exception",
|
||||
ArgParseException( const std::string& text = "undefined exception",
|
||||
const std::string& id = "undefined" )
|
||||
: ArgException( text,
|
||||
id,
|
||||
std::string( "Exception found while parsing " ) +
|
||||
: ArgException( text,
|
||||
id,
|
||||
std::string( "Exception found while parsing " ) +
|
||||
std::string( "the value the Arg has been passed." ))
|
||||
{ }
|
||||
};
|
||||
@@ -146,12 +146,12 @@ class CmdLineParseException : public ArgException
|
||||
/**
|
||||
* Constructor.
|
||||
* \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.
|
||||
*/
|
||||
CmdLineParseException( const std::string& text = "undefined exception",
|
||||
CmdLineParseException( const std::string& text = "undefined exception",
|
||||
const std::string& id = "undefined" )
|
||||
: ArgException( text,
|
||||
: ArgException( text,
|
||||
id,
|
||||
std::string( "Exception found when the values ") +
|
||||
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.
|
||||
*/
|
||||
class SpecificationException : public ArgException
|
||||
@@ -170,16 +170,16 @@ class SpecificationException : public ArgException
|
||||
/**
|
||||
* Constructor.
|
||||
* \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.
|
||||
*/
|
||||
SpecificationException( const std::string& text = "undefined exception",
|
||||
const std::string& id = "undefined" )
|
||||
: ArgException( text,
|
||||
: ArgException( text,
|
||||
id,
|
||||
std::string("Exception found when an Arg object ")+
|
||||
std::string("is improperly defined by the ") +
|
||||
std::string("developer." ))
|
||||
std::string("developer." ))
|
||||
{ }
|
||||
|
||||
};
|
||||
@@ -197,4 +197,3 @@ private:
|
||||
} // namespace TCLAP
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -452,7 +452,7 @@ inline void CmdLine::parse(std::vector<std::string>& args)
|
||||
|
||||
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;
|
||||
for (ArgListIterator it = _argList.begin();
|
||||
@@ -619,7 +619,7 @@ inline void CmdLine::reset()
|
||||
{
|
||||
for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
|
||||
(*it)->reset();
|
||||
|
||||
|
||||
_progName.clear();
|
||||
}
|
||||
|
||||
|
@@ -1,24 +1,24 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: CmdLineInterface.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
|
||||
* All rights reverved.
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TCLAP_COMMANDLINE_INTERFACE_H
|
||||
#define TCLAP_COMMANDLINE_INTERFACE_H
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
namespace TCLAP {
|
||||
|
||||
|
||||
class Arg;
|
||||
class CmdLineOutput;
|
||||
class XorHandler;
|
||||
@@ -51,29 +51,29 @@ class CmdLineInterface
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* An alternative add. Functionally identical.
|
||||
* \param a - Argument to be added.
|
||||
* \param a - Argument to be added.
|
||||
*/
|
||||
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
|
||||
* not need to be called.
|
||||
* \param a - Argument to be added and xor'd.
|
||||
* \param b - 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.
|
||||
*/
|
||||
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.
|
||||
* \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;
|
||||
|
||||
@@ -86,7 +86,7 @@ class CmdLineInterface
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void parse(std::vector<std::string>& args);
|
||||
@@ -97,7 +97,7 @@ class CmdLineInterface
|
||||
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;
|
||||
|
||||
@@ -112,12 +112,12 @@ class CmdLineInterface
|
||||
virtual std::string& getProgramName()=0;
|
||||
|
||||
/**
|
||||
* Returns the argList.
|
||||
* Returns the argList.
|
||||
*/
|
||||
virtual std::list<Arg*>& getArgList()=0;
|
||||
|
||||
/**
|
||||
* Returns the XorHandler.
|
||||
* Returns the XorHandler.
|
||||
*/
|
||||
virtual XorHandler& getXorHandler()=0;
|
||||
|
||||
@@ -137,9 +137,9 @@ class CmdLineInterface
|
||||
*/
|
||||
virtual bool hasHelpAndVersion()=0;
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
@@ -147,4 +147,4 @@ class CmdLineInterface
|
||||
} //namespace
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -1,24 +1,24 @@
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: CmdLineOutput.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2004, Michael E. Smoot
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TCLAP_CMDLINEOUTPUT_H
|
||||
#define TCLAP_CMDLINEOUTPUT_H
|
||||
@@ -38,7 +38,7 @@ class ArgException;
|
||||
/**
|
||||
* The interface that any output object must implement.
|
||||
*/
|
||||
class CmdLineOutput
|
||||
class CmdLineOutput
|
||||
{
|
||||
|
||||
public:
|
||||
@@ -49,26 +49,26 @@ class CmdLineOutput
|
||||
virtual ~CmdLineOutput() {}
|
||||
|
||||
/**
|
||||
* Generates some sort of output for the USAGE.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* Generates some sort of output for the USAGE.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
*/
|
||||
virtual void usage(CmdLineInterface& c)=0;
|
||||
|
||||
/**
|
||||
* Generates some sort of output for the version.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* Generates some sort of output for the version.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
*/
|
||||
virtual void version(CmdLineInterface& c)=0;
|
||||
|
||||
/**
|
||||
* Generates some sort of output for a failure.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* \param e - The ArgException that caused the failure.
|
||||
* Generates some sort of output for a failure.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* \param e - The ArgException that caused the failure.
|
||||
*/
|
||||
virtual void failure( CmdLineInterface& c,
|
||||
virtual void failure( CmdLineInterface& c,
|
||||
ArgException& e )=0;
|
||||
|
||||
};
|
||||
|
||||
} //namespace TCLAP
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -1,24 +1,24 @@
|
||||
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: DocBookOutput.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2004, Michael E. Smoot
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TCLAP_DOCBOOKOUTPUT_H
|
||||
#define TCLAP_DOCBOOKOUTPUT_H
|
||||
@@ -37,7 +37,7 @@
|
||||
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.
|
||||
*/
|
||||
class DocBookOutput : public CmdLineOutput
|
||||
@@ -46,35 +46,35 @@ class DocBookOutput : public CmdLineOutput
|
||||
public:
|
||||
|
||||
/**
|
||||
* Prints the usage to stdout. Can be overridden to
|
||||
* Prints the usage to stdout. 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.
|
||||
*/
|
||||
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.
|
||||
* \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);
|
||||
|
||||
/**
|
||||
* Prints (to stderr) an error message, short usage
|
||||
* Prints (to stderr) an error message, short usage
|
||||
* Can be overridden to produce alternative behavior.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* \param e - The ArgException that caused the failure.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* \param e - The ArgException that caused the failure.
|
||||
*/
|
||||
virtual void failure(CmdLineInterface& c,
|
||||
virtual void failure(CmdLineInterface& c,
|
||||
ArgException& e );
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Substitutes the char r for string x in string s.
|
||||
* \param s - The string to operate on.
|
||||
* \param r - The char to replace.
|
||||
* \param x - What to replace r with.
|
||||
* \param s - The string to operate on.
|
||||
* \param r - The char to replace.
|
||||
* \param x - What to replace r with.
|
||||
*/
|
||||
void substituteSpecialChars( std::string& s, char r, std::string& x );
|
||||
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;
|
||||
}
|
||||
|
||||
inline void DocBookOutput::usage(CmdLineInterface& _cmd )
|
||||
inline void DocBookOutput::usage(CmdLineInterface& _cmd )
|
||||
{
|
||||
std::list<Arg*> argList = _cmd.getArgList();
|
||||
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++ )
|
||||
{
|
||||
std::cout << "<group choice='req'>" << std::endl;
|
||||
for ( ArgVectorIterator it = xorList[i].begin();
|
||||
for ( ArgVectorIterator it = xorList[i].begin();
|
||||
it != xorList[i].end(); it++ )
|
||||
printShortArg((*it));
|
||||
|
||||
std::cout << "</group>" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// rest of args
|
||||
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
||||
if ( !xorHandler.contains( (*it) ) )
|
||||
@@ -145,7 +145,7 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
|
||||
std::cout << "<refsect1>" << std::endl;
|
||||
std::cout << "<title>Description</title>" << 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 << "</refsect1>" << std::endl;
|
||||
|
||||
@@ -153,7 +153,7 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
|
||||
std::cout << "<title>Options</title>" << std::endl;
|
||||
|
||||
std::cout << "<variablelist>" << std::endl;
|
||||
|
||||
|
||||
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
||||
printLongArg((*it));
|
||||
|
||||
@@ -163,17 +163,17 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
|
||||
std::cout << "<refsect1>" << std::endl;
|
||||
std::cout << "<title>Version</title>" << std::endl;
|
||||
std::cout << "<para>" << std::endl;
|
||||
std::cout << xversion << std::endl;
|
||||
std::cout << xversion << std::endl;
|
||||
std::cout << "</para>" << std::endl;
|
||||
std::cout << "</refsect1>" << std::endl;
|
||||
|
||||
|
||||
std::cout << "</refentry>" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
inline void DocBookOutput::failure( CmdLineInterface& _cmd,
|
||||
ArgException& e )
|
||||
{
|
||||
ArgException& e )
|
||||
{
|
||||
static_cast<void>(_cmd); // unused
|
||||
std::cout << e.what() << std::endl;
|
||||
throw ExitException(1);
|
||||
@@ -211,15 +211,15 @@ inline void DocBookOutput::basename( std::string& s )
|
||||
|
||||
inline void DocBookOutput::printShortArg(Arg* a)
|
||||
{
|
||||
std::string lt = "<";
|
||||
std::string gt = ">";
|
||||
std::string lt = "<";
|
||||
std::string gt = ">";
|
||||
|
||||
std::string id = a->shortID();
|
||||
substituteSpecialChars(id,'<',lt);
|
||||
substituteSpecialChars(id,'>',gt);
|
||||
removeChar(id,'[');
|
||||
removeChar(id,']');
|
||||
|
||||
|
||||
std::string choice = "opt";
|
||||
if ( a->isRequired() )
|
||||
choice = "plain";
|
||||
@@ -251,8 +251,8 @@ inline void DocBookOutput::printShortArg(Arg* a)
|
||||
|
||||
inline void DocBookOutput::printLongArg(Arg* a)
|
||||
{
|
||||
std::string lt = "<";
|
||||
std::string gt = ">";
|
||||
std::string lt = "<";
|
||||
std::string gt = ">";
|
||||
|
||||
std::string desc = a->getDescription();
|
||||
substituteSpecialChars(desc,'<',lt);
|
||||
@@ -296,4 +296,4 @@ inline void DocBookOutput::printLongArg(Arg* a)
|
||||
}
|
||||
|
||||
} //namespace TCLAP
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -1,23 +1,23 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: HelpVisitor.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TCLAP_HELP_VISITOR_H
|
||||
#define TCLAP_HELP_VISITOR_H
|
||||
@@ -44,12 +44,12 @@ class HelpVisitor: public Visitor
|
||||
protected:
|
||||
|
||||
/**
|
||||
* The CmdLine the output will be generated for.
|
||||
* The CmdLine the output will be generated for.
|
||||
*/
|
||||
CmdLineInterface* _cmd;
|
||||
|
||||
/**
|
||||
* The output object.
|
||||
* The output object.
|
||||
*/
|
||||
CmdLineOutput** _out;
|
||||
|
||||
@@ -58,17 +58,17 @@ class HelpVisitor: public Visitor
|
||||
/**
|
||||
* Constructor.
|
||||
* \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 ) { }
|
||||
|
||||
/**
|
||||
* Calls the usage method of the CmdLineOutput for the
|
||||
* Calls the usage method of the CmdLineOutput for the
|
||||
* specified CmdLine.
|
||||
*/
|
||||
void visit() { (*_out)->usage(*_cmd); throw ExitException(0); }
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -1,23 +1,23 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: IgnoreRestVisitor.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_IGNORE_REST_VISITOR_H
|
||||
|
@@ -1,22 +1,22 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: MultiArg.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ template<class T>
|
||||
class MultiArg : public Arg
|
||||
{
|
||||
public:
|
||||
typedef std::vector<T> container_type;
|
||||
typedef std::vector<T> container_type;
|
||||
typedef typename container_type::iterator iterator;
|
||||
typedef typename container_type::const_iterator const_iterator;
|
||||
|
||||
@@ -56,7 +56,7 @@ protected:
|
||||
std::string _typeDesc;
|
||||
|
||||
/**
|
||||
* A list of constraint on this Arg.
|
||||
* A list of constraint on this Arg.
|
||||
*/
|
||||
Constraint<T>* _constraint;
|
||||
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
* \param v - An optional visitor. You probably should not
|
||||
* 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& desc,
|
||||
bool req,
|
||||
@@ -146,7 +146,7 @@ public:
|
||||
bool req,
|
||||
Constraint<T>* constraint,
|
||||
Visitor* v = NULL );
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* \param flag - The one character flag that identifies this
|
||||
@@ -163,14 +163,14 @@ public:
|
||||
* \param v - An optional visitor. You probably should not
|
||||
* 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& desc,
|
||||
bool req,
|
||||
Constraint<T>* constraint,
|
||||
CmdLineInterface& parser,
|
||||
Visitor* v = NULL );
|
||||
|
||||
|
||||
/**
|
||||
* Handles the processing of the argument.
|
||||
* 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 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
|
||||
@@ -200,13 +200,13 @@ public:
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
virtual std::string longID(const std::string& val="val") const;
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
virtual bool isRequired() const;
|
||||
|
||||
virtual bool allowMore();
|
||||
|
||||
|
||||
virtual void reset();
|
||||
|
||||
private:
|
||||
@@ -231,7 +231,7 @@ private:
|
||||
};
|
||||
|
||||
template<class T>
|
||||
MultiArg<T>::MultiArg(const std::string& flag,
|
||||
MultiArg<T>::MultiArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
@@ -242,12 +242,12 @@ MultiArg<T>::MultiArg(const std::string& flag,
|
||||
_typeDesc( typeDesc ),
|
||||
_constraint( NULL ),
|
||||
_allowMore(false)
|
||||
{
|
||||
{
|
||||
_acceptsMultipleValues = true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
MultiArg<T>::MultiArg(const std::string& flag,
|
||||
MultiArg<T>::MultiArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
@@ -259,7 +259,7 @@ MultiArg<T>::MultiArg(const std::string& flag,
|
||||
_typeDesc( typeDesc ),
|
||||
_constraint( NULL ),
|
||||
_allowMore(false)
|
||||
{
|
||||
{
|
||||
parser.add( this );
|
||||
_acceptsMultipleValues = true;
|
||||
}
|
||||
@@ -268,7 +268,7 @@ MultiArg<T>::MultiArg(const std::string& flag,
|
||||
*
|
||||
*/
|
||||
template<class T>
|
||||
MultiArg<T>::MultiArg(const std::string& flag,
|
||||
MultiArg<T>::MultiArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
@@ -279,12 +279,12 @@ MultiArg<T>::MultiArg(const std::string& flag,
|
||||
_typeDesc( constraint->shortID() ),
|
||||
_constraint( constraint ),
|
||||
_allowMore(false)
|
||||
{
|
||||
{
|
||||
_acceptsMultipleValues = true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
MultiArg<T>::MultiArg(const std::string& flag,
|
||||
MultiArg<T>::MultiArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
@@ -296,7 +296,7 @@ MultiArg<T>::MultiArg(const std::string& flag,
|
||||
_typeDesc( constraint->shortID() ),
|
||||
_constraint( constraint ),
|
||||
_allowMore(false)
|
||||
{
|
||||
{
|
||||
parser.add( this );
|
||||
_acceptsMultipleValues = true;
|
||||
}
|
||||
@@ -305,7 +305,7 @@ template<class T>
|
||||
const std::vector<T>& MultiArg<T>::getValue() { return _values; }
|
||||
|
||||
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() )
|
||||
return false;
|
||||
@@ -321,7 +321,7 @@ bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
||||
if ( argMatches( flag ) )
|
||||
{
|
||||
if ( Arg::delimiter() != ' ' && value == "" )
|
||||
throw( ArgParseException(
|
||||
throw( ArgParseException(
|
||||
"Couldn't find delimiter for this argument!",
|
||||
toString() ) );
|
||||
|
||||
@@ -334,15 +334,15 @@ bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
||||
else
|
||||
throw( ArgParseException("Missing a value for this argument!",
|
||||
toString() ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
_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() &&
|
||||
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)] );
|
||||
*/
|
||||
|
||||
@@ -395,7 +395,7 @@ bool MultiArg<T>::isRequired() const
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void MultiArg<T>::_extractValue( const std::string& val )
|
||||
void MultiArg<T>::_extractValue( const std::string& val )
|
||||
{
|
||||
try {
|
||||
T tmp;
|
||||
@@ -409,10 +409,10 @@ void MultiArg<T>::_extractValue( const std::string& val )
|
||||
if ( ! _constraint->check( _values.back() ) )
|
||||
throw( CmdLineParseException( "Value '" + val +
|
||||
"' does not meet constraint: " +
|
||||
_constraint->description(),
|
||||
_constraint->description(),
|
||||
toString() ) );
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
bool MultiArg<T>::allowMore()
|
||||
{
|
||||
|
@@ -1,5 +1,5 @@
|
||||
|
||||
/******************************************************************************
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: MultiSwitchArg.h
|
||||
*
|
||||
@@ -61,12 +61,12 @@ class MultiSwitchArg : public SwitchArg
|
||||
* used as a long flag on the command line.
|
||||
* \param desc - A description of what the argument is for or
|
||||
* does.
|
||||
* \param init - Optional. The initial/default value of this Arg.
|
||||
* \param init - Optional. The initial/default value of this Arg.
|
||||
* Defaults to 0.
|
||||
* \param v - An optional visitor. You probably should not
|
||||
* 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& desc,
|
||||
int init = 0,
|
||||
@@ -82,12 +82,12 @@ class MultiSwitchArg : public SwitchArg
|
||||
* \param desc - A description of what the argument is for or
|
||||
* does.
|
||||
* \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.
|
||||
* \param v - An optional visitor. You probably should not
|
||||
* 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& desc,
|
||||
CmdLineInterface& parser,
|
||||
@@ -103,7 +103,7 @@ class MultiSwitchArg : public SwitchArg
|
||||
* \param args - Mutable list of strings. Passed
|
||||
* 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.
|
||||
@@ -119,7 +119,7 @@ class MultiSwitchArg : public SwitchArg
|
||||
* Returns the longID for this Arg.
|
||||
*/
|
||||
std::string longID(const std::string& val) const;
|
||||
|
||||
|
||||
void reset();
|
||||
|
||||
};
|
||||
@@ -138,15 +138,15 @@ _default( init )
|
||||
{ }
|
||||
|
||||
inline MultiSwitchArg::MultiSwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
CmdLineInterface& parser,
|
||||
int init,
|
||||
Visitor* v )
|
||||
: SwitchArg(flag, name, desc, false, v),
|
||||
_value( init ),
|
||||
_default( init )
|
||||
{
|
||||
{
|
||||
parser.add( this );
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args)
|
||||
++_value;
|
||||
|
||||
// Check for more in argument and increment value.
|
||||
while ( combinedSwitchesMatch( args[*i] ) )
|
||||
while ( combinedSwitchesMatch( args[*i] ) )
|
||||
++_value;
|
||||
|
||||
_checkWithVisitor();
|
||||
@@ -189,13 +189,13 @@ inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
inline std::string
|
||||
MultiSwitchArg::shortID(const std::string& val) const
|
||||
{
|
||||
return Arg::shortID(val) + " ... ";
|
||||
}
|
||||
|
||||
inline std::string
|
||||
inline std::string
|
||||
MultiSwitchArg::longID(const std::string& val) const
|
||||
{
|
||||
return Arg::longID(val) + " (accepted multiple times)";
|
||||
|
@@ -1,24 +1,24 @@
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: OptionalUnlabeledTracker.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2005, Michael E. Smoot .
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H
|
||||
@@ -37,7 +37,7 @@ class OptionalUnlabeledTracker
|
||||
|
||||
static void gotOptional() { alreadyOptionalRef() = true; }
|
||||
|
||||
static bool& alreadyOptional() { return alreadyOptionalRef(); }
|
||||
static bool& alreadyOptional() { return alreadyOptionalRef(); }
|
||||
|
||||
private:
|
||||
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include <config.h> // To check for long long
|
||||
#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
|
||||
// creating ArgTraits twice for unsigned short. Thus...
|
||||
#ifdef _MSC_VER
|
||||
@@ -123,7 +123,7 @@ struct ArgTraits<unsigned char> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
|
||||
// Microsoft implements size_t awkwardly.
|
||||
// Microsoft implements size_t awkwardly.
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
/**
|
||||
* size_ts have value-like semantics.
|
||||
@@ -205,4 +205,3 @@ void SetString(T &dst, const std::string &src)
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,24 +1,24 @@
|
||||
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: StdOutput.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2004, Michael E. Smoot
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TCLAP_STDCMDLINEOUTPUT_H
|
||||
#define TCLAP_STDCMDLINEOUTPUT_H
|
||||
@@ -46,77 +46,77 @@ class StdOutput : public CmdLineOutput
|
||||
public:
|
||||
|
||||
/**
|
||||
* Prints the usage to stdout. Can be overridden to
|
||||
* Prints the usage to stdout. 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.
|
||||
*/
|
||||
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.
|
||||
* \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);
|
||||
|
||||
/**
|
||||
* Prints (to stderr) an error message, short usage
|
||||
* Prints (to stderr) an error message, short usage
|
||||
* Can be overridden to produce alternative behavior.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* \param e - The ArgException that caused the failure.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* \param e - The ArgException that caused the failure.
|
||||
*/
|
||||
virtual void failure(CmdLineInterface& c,
|
||||
virtual void failure(CmdLineInterface& c,
|
||||
ArgException& e );
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
* \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.
|
||||
*/
|
||||
void _longUsage( CmdLineInterface& c, std::ostream& os ) const;
|
||||
|
||||
/**
|
||||
* This function inserts line breaks and indents long strings
|
||||
* according the params input. It will only break lines at spaces,
|
||||
* This function inserts line breaks and indents long strings
|
||||
* according the params input. It will only break lines at spaces,
|
||||
* commas and pipes.
|
||||
* \param os - The stream to be printed to.
|
||||
* \param s - The string to be printed.
|
||||
* \param maxWidth - The maxWidth allowed for the output line.
|
||||
* \param indentSpaces - The number of spaces to indent the first line.
|
||||
* \param maxWidth - The maxWidth allowed for the output line.
|
||||
* \param indentSpaces - The number of spaces to indent the first line.
|
||||
* \param secondLineOffset - The number of spaces to indent the second
|
||||
* and all subsequent lines in addition to indentSpaces.
|
||||
*/
|
||||
void spacePrint( std::ostream& os,
|
||||
const std::string& s,
|
||||
int maxWidth,
|
||||
int indentSpaces,
|
||||
void spacePrint( std::ostream& os,
|
||||
const std::string& s,
|
||||
int maxWidth,
|
||||
int indentSpaces,
|
||||
int secondLineOffset ) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline void StdOutput::version(CmdLineInterface& _cmd)
|
||||
inline void StdOutput::version(CmdLineInterface& _cmd)
|
||||
{
|
||||
std::string progName = _cmd.getProgramName();
|
||||
std::string xversion = _cmd.getVersion();
|
||||
|
||||
std::cout << std::endl << progName << " version: "
|
||||
std::cout << std::endl << progName << " version: "
|
||||
<< 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 );
|
||||
|
||||
@@ -124,12 +124,12 @@ inline void StdOutput::usage(CmdLineInterface& _cmd )
|
||||
|
||||
_longUsage( _cmd, std::cout );
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
}
|
||||
|
||||
inline void StdOutput::failure( CmdLineInterface& _cmd,
|
||||
ArgException& e )
|
||||
ArgException& e )
|
||||
{
|
||||
std::string progName = _cmd.getProgramName();
|
||||
|
||||
@@ -140,10 +140,10 @@ inline void StdOutput::failure( CmdLineInterface& _cmd,
|
||||
{
|
||||
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::endl << " " << progName << " --help"
|
||||
std::cerr << std::endl << "For complete USAGE and HELP type: "
|
||||
<< std::endl << " " << progName << " --help"
|
||||
<< std::endl << std::endl;
|
||||
}
|
||||
else
|
||||
@@ -152,8 +152,8 @@ inline void StdOutput::failure( CmdLineInterface& _cmd,
|
||||
throw ExitException(1);
|
||||
}
|
||||
|
||||
inline void
|
||||
StdOutput::_shortUsage( CmdLineInterface& _cmd,
|
||||
inline void
|
||||
StdOutput::_shortUsage( CmdLineInterface& _cmd,
|
||||
std::ostream& os ) const
|
||||
{
|
||||
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++ )
|
||||
{
|
||||
s += " {";
|
||||
for ( ArgVectorIterator it = xorList[i].begin();
|
||||
for ( ArgVectorIterator it = xorList[i].begin();
|
||||
it != xorList[i].end(); it++ )
|
||||
s += (*it)->shortID() + "|";
|
||||
|
||||
@@ -179,7 +179,7 @@ StdOutput::_shortUsage( CmdLineInterface& _cmd,
|
||||
if ( !xorHandler.contains( (*it) ) )
|
||||
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;
|
||||
if ( secondLineOffset > 75/2 )
|
||||
secondLineOffset = static_cast<int>(75/2);
|
||||
@@ -187,8 +187,8 @@ StdOutput::_shortUsage( CmdLineInterface& _cmd,
|
||||
spacePrint( os, s, 75, 3, secondLineOffset );
|
||||
}
|
||||
|
||||
inline void
|
||||
StdOutput::_longUsage( CmdLineInterface& _cmd,
|
||||
inline void
|
||||
StdOutput::_longUsage( CmdLineInterface& _cmd,
|
||||
std::ostream& os ) const
|
||||
{
|
||||
std::list<Arg*> argList = _cmd.getArgList();
|
||||
@@ -196,11 +196,11 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
|
||||
XorHandler xorHandler = _cmd.getXorHandler();
|
||||
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 ( ArgVectorIterator it = xorList[i].begin();
|
||||
it != xorList[i].end();
|
||||
for ( ArgVectorIterator it = xorList[i].begin();
|
||||
it != xorList[i].end();
|
||||
it++ )
|
||||
{
|
||||
spacePrint( os, (*it)->longID(), 75, 3, 3 );
|
||||
@@ -216,8 +216,8 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
|
||||
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
||||
if ( !xorHandler.contains( (*it) ) )
|
||||
{
|
||||
spacePrint( os, (*it)->longID(), 75, 3, 3 );
|
||||
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
|
||||
spacePrint( os, (*it)->longID(), 75, 3, 3 );
|
||||
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
@@ -226,10 +226,10 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
|
||||
spacePrint( os, message, 75, 3, 0 );
|
||||
}
|
||||
|
||||
inline void StdOutput::spacePrint( std::ostream& os,
|
||||
const std::string& s,
|
||||
int maxWidth,
|
||||
int indentSpaces,
|
||||
inline void StdOutput::spacePrint( std::ostream& os,
|
||||
const std::string& s,
|
||||
int maxWidth,
|
||||
int indentSpaces,
|
||||
int secondLineOffset ) const
|
||||
{
|
||||
int len = static_cast<int>(s.length());
|
||||
@@ -242,19 +242,19 @@ inline void StdOutput::spacePrint( std::ostream& os,
|
||||
{
|
||||
// find the substring length
|
||||
// int stringLen = std::min<int>( len - start, allowedLen );
|
||||
// doing it this way to support a VisualC++ 2005 bug
|
||||
using namespace std;
|
||||
// doing it this way to support a VisualC++ 2005 bug
|
||||
using namespace std;
|
||||
int stringLen = min<int>( len - start, allowedLen );
|
||||
|
||||
// trim the length so it doesn't end in middle of a word
|
||||
if ( stringLen == allowedLen )
|
||||
while ( stringLen >= 0 &&
|
||||
s[stringLen+start] != ' ' &&
|
||||
s[stringLen+start] != ' ' &&
|
||||
s[stringLen+start] != ',' &&
|
||||
s[stringLen+start] != '|' )
|
||||
s[stringLen+start] != '|' )
|
||||
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
|
||||
if ( stringLen <= 0 )
|
||||
stringLen = allowedLen;
|
||||
@@ -264,7 +264,7 @@ inline void StdOutput::spacePrint( std::ostream& os,
|
||||
if ( s[start+i] == '\n' )
|
||||
stringLen = i+1;
|
||||
|
||||
// print the indent
|
||||
// print the indent
|
||||
for ( int i = 0; i < indentSpaces; i++ )
|
||||
os << " ";
|
||||
|
||||
@@ -282,7 +282,7 @@ inline void StdOutput::spacePrint( std::ostream& os,
|
||||
// so we don't start a line with a space
|
||||
while ( s[stringLen+start] == ' ' && start < len )
|
||||
start++;
|
||||
|
||||
|
||||
start += stringLen;
|
||||
}
|
||||
}
|
||||
@@ -295,4 +295,4 @@ inline void StdOutput::spacePrint( std::ostream& os,
|
||||
}
|
||||
|
||||
} //namespace TCLAP
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -1,24 +1,24 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: SwitchArg.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_SWITCH_ARG_H
|
||||
@@ -61,17 +61,17 @@ class SwitchArg : public Arg
|
||||
* used as a long flag on the command line.
|
||||
* \param desc - A description of what the argument is for or
|
||||
* 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
|
||||
* use this unless you have a very good reason.
|
||||
*/
|
||||
SwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
SwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool def = false,
|
||||
Visitor* v = NULL);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SwitchArg constructor.
|
||||
* \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
|
||||
* use this unless you have a very good reason.
|
||||
*/
|
||||
SwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
SwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
CmdLineInterface& parser,
|
||||
bool def = false,
|
||||
Visitor* v = NULL);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Handles the processing of the argument.
|
||||
* 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
|
||||
* 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
|
||||
@@ -113,7 +113,7 @@ class SwitchArg : public Arg
|
||||
* Returns bool, whether or not the switch has been set.
|
||||
*/
|
||||
bool getValue();
|
||||
|
||||
|
||||
virtual void reset();
|
||||
|
||||
private:
|
||||
@@ -132,9 +132,9 @@ class SwitchArg : public Arg
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//BEGIN SwitchArg.cpp
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
inline SwitchArg::SwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
inline SwitchArg::SwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool default_val,
|
||||
Visitor* v )
|
||||
: Arg(flag, name, desc, false, false, v),
|
||||
@@ -142,27 +142,27 @@ inline SwitchArg::SwitchArg(const std::string& flag,
|
||||
_default( default_val )
|
||||
{ }
|
||||
|
||||
inline SwitchArg::SwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
inline SwitchArg::SwitchArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
CmdLineInterface& parser,
|
||||
bool default_val,
|
||||
Visitor* v )
|
||||
: Arg(flag, name, desc, false, false, v),
|
||||
_value( default_val ),
|
||||
_default(default_val)
|
||||
{
|
||||
{
|
||||
parser.add( this );
|
||||
}
|
||||
|
||||
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++ )
|
||||
if ( combinedSwitches[i] != Arg::blankChar() )
|
||||
return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -173,32 +173,32 @@ inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches )
|
||||
combinedSwitches[0] != Arg::flagStartString()[0] )
|
||||
return false;
|
||||
|
||||
// make sure it isn't a long name
|
||||
if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) ==
|
||||
// make sure it isn't a long name
|
||||
if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) ==
|
||||
Arg::nameStartString() )
|
||||
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 )
|
||||
return false;
|
||||
|
||||
// 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++ )
|
||||
if ( _flag.length() > 0 &&
|
||||
if ( _flag.length() > 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
|
||||
// this is necessary so that no unlabeled args are matched
|
||||
// later in the processing.
|
||||
//combinedSwitches.erase(i,1);
|
||||
combinedSwitches[i] = Arg::blankChar();
|
||||
combinedSwitches[i] = Arg::blankChar();
|
||||
return true;
|
||||
}
|
||||
|
||||
// none of the switches passed in the list match.
|
||||
return false;
|
||||
// none of the switches passed in the list match.
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void SwitchArg::commonProcessing()
|
||||
@@ -207,7 +207,7 @@ inline void SwitchArg::commonProcessing()
|
||||
throw(CmdLineParseException(
|
||||
"Mutually exclusive argument already set!", toString()));
|
||||
|
||||
if ( _alreadySet )
|
||||
if ( _alreadySet )
|
||||
throw(CmdLineParseException("Argument already set!", toString()));
|
||||
|
||||
_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
|
||||
else if ( combinedSwitchesMatch( args[*i] ) )
|
||||
{
|
||||
// check again to ensure we don't misinterpret
|
||||
// this as a MultiSwitchArg
|
||||
// check again to ensure we don't misinterpret
|
||||
// this as a MultiSwitchArg
|
||||
if ( combinedSwitchesMatch( args[*i] ) )
|
||||
throw(CmdLineParseException("Argument already set!",
|
||||
throw(CmdLineParseException("Argument already set!",
|
||||
toString()));
|
||||
|
||||
commonProcessing();
|
||||
|
||||
// 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.
|
||||
return lastCombined( args[*i] );
|
||||
}
|
||||
@@ -255,7 +255,7 @@ inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args)
|
||||
inline void SwitchArg::reset()
|
||||
{
|
||||
Arg::reset();
|
||||
_value = _default;
|
||||
_value = _default;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//End SwitchArg.cpp
|
||||
|
@@ -1,23 +1,23 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: UnlabeledMultiArg.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot.
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H
|
||||
@@ -33,7 +33,7 @@ namespace TCLAP {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
template<class T>
|
||||
@@ -52,9 +52,9 @@ class UnlabeledMultiArg : public MultiArg<T>
|
||||
using MultiArg<T>::toString;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Constructor.
|
||||
* \param name - The name of the Arg. Note that this is used for
|
||||
* identification, not as a long flag.
|
||||
* \param desc - A description of what the argument is for or
|
||||
@@ -77,7 +77,7 @@ class UnlabeledMultiArg : public MultiArg<T>
|
||||
bool ignoreable = false,
|
||||
Visitor* v = NULL );
|
||||
/**
|
||||
* Constructor.
|
||||
* Constructor.
|
||||
* \param name - The name of the Arg. Note that this is used for
|
||||
* identification, not as a long flag.
|
||||
* \param desc - A description of what the argument is for or
|
||||
@@ -101,9 +101,9 @@ class UnlabeledMultiArg : public MultiArg<T>
|
||||
CmdLineInterface& parser,
|
||||
bool ignoreable = false,
|
||||
Visitor* v = NULL );
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Constructor.
|
||||
* \param name - The name of the Arg. Note that this is used for
|
||||
* identification, not as a long flag.
|
||||
* \param desc - A description of what the argument is for or
|
||||
@@ -125,7 +125,7 @@ class UnlabeledMultiArg : public MultiArg<T>
|
||||
Visitor* v = NULL );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Constructor.
|
||||
* \param name - The name of the Arg. Note that this is used for
|
||||
* identification, not as a long flag.
|
||||
* \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
|
||||
* use this unless you have a very good reason.
|
||||
*/
|
||||
UnlabeledMultiArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledMultiArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
Constraint<T>* constraint,
|
||||
CmdLineInterface& parser,
|
||||
bool ignoreable = false,
|
||||
Visitor* v = NULL );
|
||||
|
||||
|
||||
/**
|
||||
* Handles the processing of the argument.
|
||||
* 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 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.
|
||||
@@ -184,28 +184,28 @@ class UnlabeledMultiArg : public MultiArg<T>
|
||||
};
|
||||
|
||||
template<class T>
|
||||
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
const std::string& typeDesc,
|
||||
bool ignoreable,
|
||||
Visitor* v)
|
||||
: MultiArg<T>("", name, desc, req, typeDesc, v)
|
||||
{
|
||||
{
|
||||
_ignoreable = ignoreable;
|
||||
OptionalUnlabeledTracker::check(true, toString());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
const std::string& typeDesc,
|
||||
CmdLineInterface& parser,
|
||||
bool ignoreable,
|
||||
Visitor* v)
|
||||
: MultiArg<T>("", name, desc, req, typeDesc, v)
|
||||
{
|
||||
{
|
||||
_ignoreable = ignoreable;
|
||||
OptionalUnlabeledTracker::check(true, toString());
|
||||
parser.add( this );
|
||||
@@ -213,28 +213,28 @@ UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
|
||||
|
||||
template<class T>
|
||||
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
Constraint<T>* constraint,
|
||||
bool ignoreable,
|
||||
Visitor* v)
|
||||
: MultiArg<T>("", name, desc, req, constraint, v)
|
||||
{
|
||||
{
|
||||
_ignoreable = ignoreable;
|
||||
OptionalUnlabeledTracker::check(true, toString());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
Constraint<T>* constraint,
|
||||
CmdLineInterface& parser,
|
||||
bool ignoreable,
|
||||
Visitor* v)
|
||||
: MultiArg<T>("", name, desc, req, constraint, v)
|
||||
{
|
||||
{
|
||||
_ignoreable = ignoreable;
|
||||
OptionalUnlabeledTracker::check(true, toString());
|
||||
parser.add( this );
|
||||
@@ -242,7 +242,7 @@ UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
||||
|
||||
|
||||
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] ) )
|
||||
@@ -251,14 +251,14 @@ bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
||||
// 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)] );
|
||||
|
||||
/*
|
||||
// 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() &&
|
||||
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)] );
|
||||
*/
|
||||
|
||||
|
@@ -1,24 +1,24 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: UnlabeledValueArg.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H
|
||||
@@ -72,18 +72,18 @@ class UnlabeledValueArg : public ValueArg<T>
|
||||
* of the program.
|
||||
* \param ignoreable - Allows you to specify that this argument can be
|
||||
* 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.
|
||||
* \param v - Optional Vistor. You should leave this blank unless
|
||||
* you have a very good reason.
|
||||
*/
|
||||
UnlabeledValueArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledValueArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T value,
|
||||
const std::string& typeDesc,
|
||||
bool ignoreable = false,
|
||||
Visitor* v = NULL);
|
||||
Visitor* v = NULL);
|
||||
|
||||
/**
|
||||
* UnlabeledValueArg constructor.
|
||||
@@ -102,20 +102,20 @@ class UnlabeledValueArg : public ValueArg<T>
|
||||
* \param parser - A CmdLine parser object to add this Arg to
|
||||
* \param ignoreable - Allows you to specify that this argument can be
|
||||
* 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.
|
||||
* \param v - Optional Vistor. You should leave this blank unless
|
||||
* you have a very good reason.
|
||||
*/
|
||||
UnlabeledValueArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledValueArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T value,
|
||||
const std::string& typeDesc,
|
||||
CmdLineInterface& parser,
|
||||
bool ignoreable = false,
|
||||
Visitor* v = NULL );
|
||||
|
||||
Visitor* v = NULL );
|
||||
|
||||
/**
|
||||
* UnlabeledValueArg constructor.
|
||||
* \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.
|
||||
* \param ignoreable - Allows you to specify that this argument can be
|
||||
* 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.
|
||||
* \param v - Optional Vistor. You should leave this blank unless
|
||||
* you have a very good reason.
|
||||
*/
|
||||
UnlabeledValueArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledValueArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T value,
|
||||
Constraint<T>* constraint,
|
||||
bool ignoreable = false,
|
||||
Visitor* v = NULL );
|
||||
Visitor* v = NULL );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* UnlabeledValueArg constructor.
|
||||
* \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 ignoreable - Allows you to specify that this argument can be
|
||||
* 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.
|
||||
* \param v - Optional Vistor. You should leave this blank unless
|
||||
* you have a very good reason.
|
||||
*/
|
||||
UnlabeledValueArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledValueArg( const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T value,
|
||||
Constraint<T>* constraint,
|
||||
CmdLineInterface& parser,
|
||||
bool ignoreable = false,
|
||||
Visitor* v = NULL);
|
||||
|
||||
|
||||
/**
|
||||
* Handles the processing of the argument.
|
||||
* This re-implements the Arg version of this method to set the
|
||||
* _value of the argument appropriately. Handling specific to
|
||||
* unlabled arguments.
|
||||
* \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.
|
||||
@@ -210,15 +210,15 @@ class UnlabeledValueArg : public ValueArg<T>
|
||||
* Constructor implemenation.
|
||||
*/
|
||||
template<class T>
|
||||
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T val,
|
||||
const std::string& typeDesc,
|
||||
bool ignoreable,
|
||||
Visitor* v)
|
||||
: ValueArg<T>("", name, desc, req, val, typeDesc, v)
|
||||
{
|
||||
{
|
||||
_ignoreable = ignoreable;
|
||||
|
||||
OptionalUnlabeledTracker::check(req, toString());
|
||||
@@ -226,8 +226,8 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
}
|
||||
|
||||
template<class T>
|
||||
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T val,
|
||||
const std::string& typeDesc,
|
||||
@@ -235,7 +235,7 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
bool ignoreable,
|
||||
Visitor* v)
|
||||
: ValueArg<T>("", name, desc, req, val, typeDesc, v)
|
||||
{
|
||||
{
|
||||
_ignoreable = ignoreable;
|
||||
OptionalUnlabeledTracker::check(req, toString());
|
||||
parser.add( this );
|
||||
@@ -245,22 +245,22 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
* Constructor implemenation.
|
||||
*/
|
||||
template<class T>
|
||||
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T val,
|
||||
Constraint<T>* constraint,
|
||||
bool ignoreable,
|
||||
Visitor* v)
|
||||
: ValueArg<T>("", name, desc, req, val, constraint, v)
|
||||
{
|
||||
{
|
||||
_ignoreable = ignoreable;
|
||||
OptionalUnlabeledTracker::check(req, toString());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T val,
|
||||
Constraint<T>* constraint,
|
||||
@@ -268,7 +268,7 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
bool ignoreable,
|
||||
Visitor* v)
|
||||
: ValueArg<T>("", name, desc, req, val, constraint, v)
|
||||
{
|
||||
{
|
||||
_ignoreable = ignoreable;
|
||||
OptionalUnlabeledTracker::check(req, toString());
|
||||
parser.add( this );
|
||||
@@ -278,17 +278,17 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
||||
* Implementation of processArg().
|
||||
*/
|
||||
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 )
|
||||
return false;
|
||||
|
||||
|
||||
if ( _hasBlanks( args[*i] ) )
|
||||
return false;
|
||||
|
||||
// never ignore an unlabeled arg
|
||||
|
||||
|
||||
_extractValue( args[*i] );
|
||||
_alreadySet = 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
|
||||
|
||||
// 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,
|
||||
// doesn't appear to return terribly useful "names" of the types.
|
||||
// of the type required for this argument. However, g++ at least,
|
||||
// doesn't appear to return terribly useful "names" of the types.
|
||||
return std::string("<") + _typeDesc + ">";
|
||||
}
|
||||
|
||||
|
@@ -1,23 +1,23 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: ValueArg.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_VALUE_ARGUMENT_H
|
||||
@@ -40,7 +40,7 @@ namespace TCLAP {
|
||||
* Instead use an UnlabeledValueArg.
|
||||
*/
|
||||
template<class T>
|
||||
class ValueArg : public Arg
|
||||
class ValueArg : public Arg
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -67,7 +67,7 @@ class ValueArg : public Arg
|
||||
std::string _typeDesc;
|
||||
|
||||
/**
|
||||
* A Constraint this Arg must conform to.
|
||||
* A Constraint this Arg must conform to.
|
||||
*/
|
||||
Constraint<T>* _constraint;
|
||||
|
||||
@@ -75,7 +75,7 @@ class ValueArg : public Arg
|
||||
* Extracts the value from the string.
|
||||
* Attempts to parse string as type T, if this fails an exception
|
||||
* is thrown.
|
||||
* \param val - value to be parsed.
|
||||
* \param val - value to be parsed.
|
||||
*/
|
||||
void _extractValue( const std::string& val );
|
||||
|
||||
@@ -83,9 +83,9 @@ class ValueArg : public Arg
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
* \param flag - The one character flag that identifies this
|
||||
* argument on the command line.
|
||||
@@ -104,20 +104,20 @@ class ValueArg : public Arg
|
||||
* \param v - An optional visitor. You probably should not
|
||||
* use this unless you have a very good reason.
|
||||
*/
|
||||
ValueArg( const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
ValueArg( const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T value,
|
||||
const std::string& typeDesc,
|
||||
Visitor* v = NULL);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
* \param flag - The one character flag that identifies this
|
||||
* argument on the command line.
|
||||
@@ -137,20 +137,20 @@ class ValueArg : public Arg
|
||||
* \param v - An optional visitor. You probably should not
|
||||
* use this unless you have a very good reason.
|
||||
*/
|
||||
ValueArg( const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
ValueArg( const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T value,
|
||||
const std::string& typeDesc,
|
||||
CmdLineInterface& parser,
|
||||
Visitor* v = NULL );
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
* \param flag - The one character flag that identifies this
|
||||
* argument on the command line.
|
||||
@@ -168,20 +168,20 @@ class ValueArg : public Arg
|
||||
* \param v - An optional visitor. You probably should not
|
||||
* use this unless you have a very good reason.
|
||||
*/
|
||||
ValueArg( const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
ValueArg( const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T value,
|
||||
Constraint<T>* constraint,
|
||||
CmdLineInterface& parser,
|
||||
Visitor* v = NULL );
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
* \param flag - The one character flag that identifies this
|
||||
* argument on the command line.
|
||||
@@ -198,10 +198,10 @@ class ValueArg : public Arg
|
||||
* \param v - An optional visitor. You probably should not
|
||||
* use this unless you have a very good reason.
|
||||
*/
|
||||
ValueArg( const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
ValueArg( const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T value,
|
||||
Constraint<T>* constraint,
|
||||
Visitor* v = NULL );
|
||||
@@ -212,10 +212,10 @@ class ValueArg : public Arg
|
||||
* _value of the argument appropriately. It knows the difference
|
||||
* between labeled and unlabeled.
|
||||
* \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().
|
||||
*/
|
||||
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.
|
||||
@@ -233,7 +233,7 @@ class ValueArg : public Arg
|
||||
* \param val - value to be used.
|
||||
*/
|
||||
virtual std::string longID(const std::string& val = "val") const;
|
||||
|
||||
|
||||
virtual void reset() ;
|
||||
|
||||
private:
|
||||
@@ -249,10 +249,10 @@ private:
|
||||
* Constructor implementation.
|
||||
*/
|
||||
template<class T>
|
||||
ValueArg<T>::ValueArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
ValueArg<T>::ValueArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T val,
|
||||
const std::string& typeDesc,
|
||||
Visitor* v)
|
||||
@@ -264,10 +264,10 @@ ValueArg<T>::ValueArg(const std::string& flag,
|
||||
{ }
|
||||
|
||||
template<class T>
|
||||
ValueArg<T>::ValueArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
ValueArg<T>::ValueArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T val,
|
||||
const std::string& typeDesc,
|
||||
CmdLineInterface& parser,
|
||||
@@ -277,15 +277,15 @@ ValueArg<T>::ValueArg(const std::string& flag,
|
||||
_default( val ),
|
||||
_typeDesc( typeDesc ),
|
||||
_constraint( NULL )
|
||||
{
|
||||
{
|
||||
parser.add( this );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ValueArg<T>::ValueArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
ValueArg<T>::ValueArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T val,
|
||||
Constraint<T>* constraint,
|
||||
Visitor* v)
|
||||
@@ -297,10 +297,10 @@ ValueArg<T>::ValueArg(const std::string& flag,
|
||||
{ }
|
||||
|
||||
template<class T>
|
||||
ValueArg<T>::ValueArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
ValueArg<T>::ValueArg(const std::string& flag,
|
||||
const std::string& name,
|
||||
const std::string& desc,
|
||||
bool req,
|
||||
T val,
|
||||
Constraint<T>* constraint,
|
||||
CmdLineInterface& parser,
|
||||
@@ -310,7 +310,7 @@ ValueArg<T>::ValueArg(const std::string& flag,
|
||||
_default( val ),
|
||||
_typeDesc( constraint->shortID() ),
|
||||
_constraint( constraint )
|
||||
{
|
||||
{
|
||||
parser.add( this );
|
||||
}
|
||||
|
||||
@@ -344,22 +344,22 @@ bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
|
||||
{
|
||||
if ( _xorSet )
|
||||
throw( CmdLineParseException(
|
||||
"Mutually exclusive argument already set!",
|
||||
"Mutually exclusive argument already set!",
|
||||
toString()) );
|
||||
else
|
||||
throw( CmdLineParseException("Argument already set!",
|
||||
throw( CmdLineParseException("Argument already set!",
|
||||
toString()) );
|
||||
}
|
||||
|
||||
if ( Arg::delimiter() != ' ' && value == "" )
|
||||
throw( ArgParseException(
|
||||
throw( ArgParseException(
|
||||
"Couldn't find delimiter for this argument!",
|
||||
toString() ) );
|
||||
|
||||
if ( value == "" )
|
||||
{
|
||||
(*i)++;
|
||||
if ( static_cast<unsigned int>(*i) < args.size() )
|
||||
if ( static_cast<unsigned int>(*i) < args.size() )
|
||||
_extractValue( args[*i] );
|
||||
else
|
||||
throw( ArgParseException("Missing a value for this argument!",
|
||||
@@ -367,11 +367,11 @@ bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
|
||||
}
|
||||
else
|
||||
_extractValue( value );
|
||||
|
||||
|
||||
_alreadySet = true;
|
||||
_checkWithVisitor();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -383,7 +383,7 @@ template<class T>
|
||||
std::string ValueArg<T>::shortID(const std::string& val) const
|
||||
{
|
||||
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
|
||||
{
|
||||
static_cast<void>(val); // Ignore input, don't warn
|
||||
return Arg::longID( _typeDesc );
|
||||
return Arg::longID( _typeDesc );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ValueArg<T>::_extractValue( const std::string& val )
|
||||
void ValueArg<T>::_extractValue( const std::string& val )
|
||||
{
|
||||
try {
|
||||
ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory());
|
||||
} catch( ArgParseException &e) {
|
||||
throw ArgParseException(e.error(), toString());
|
||||
}
|
||||
|
||||
|
||||
if ( _constraint != NULL )
|
||||
if ( ! _constraint->check( _value ) )
|
||||
throw( CmdLineParseException( "Value '" + val +
|
||||
+ "' does not meet constraint: "
|
||||
throw( CmdLineParseException( "Value '" + val +
|
||||
+ "' does not meet constraint: "
|
||||
+ _constraint->description(),
|
||||
toString() ) );
|
||||
}
|
||||
|
@@ -1,24 +1,24 @@
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: ValuesConstraint.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2005, Michael E. Smoot
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TCLAP_VALUESCONSTRAINT_H
|
||||
#define TCLAP_VALUESCONSTRAINT_H
|
||||
@@ -54,10 +54,10 @@ class ValuesConstraint : public Constraint<T>
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* \param allowed - vector of allowed values.
|
||||
* Constructor.
|
||||
* \param allowed - vector of allowed values.
|
||||
*/
|
||||
ValuesConstraint(std::vector<T>& allowed);
|
||||
ValuesConstraint(std::vector<T>& allowed);
|
||||
|
||||
/**
|
||||
* Virtual destructor.
|
||||
@@ -65,7 +65,7 @@ class ValuesConstraint : public Constraint<T>
|
||||
virtual ~ValuesConstraint() {}
|
||||
|
||||
/**
|
||||
* Returns a description of the Constraint.
|
||||
* Returns a description of the Constraint.
|
||||
*/
|
||||
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
|
||||
* 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;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* The list of valid values.
|
||||
* The list of valid values.
|
||||
*/
|
||||
std::vector<T> _allowed;
|
||||
|
||||
@@ -99,7 +99,7 @@ template<class T>
|
||||
ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed)
|
||||
: _allowed(allowed),
|
||||
_typeDesc("")
|
||||
{
|
||||
{
|
||||
for ( unsigned int i = 0; i < _allowed.size(); i++ )
|
||||
{
|
||||
|
||||
@@ -113,7 +113,7 @@ ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed)
|
||||
|
||||
os << _allowed[i];
|
||||
|
||||
std::string temp( os.str() );
|
||||
std::string temp( os.str() );
|
||||
|
||||
if ( i > 0 )
|
||||
_typeDesc += "|";
|
||||
@@ -126,23 +126,22 @@ bool ValuesConstraint<T>::check( const T& val ) const
|
||||
{
|
||||
if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() )
|
||||
return false;
|
||||
else
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::string ValuesConstraint<T>::shortID() const
|
||||
{
|
||||
return _typeDesc;
|
||||
return _typeDesc;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::string ValuesConstraint<T>::description() const
|
||||
{
|
||||
return _typeDesc;
|
||||
return _typeDesc;
|
||||
}
|
||||
|
||||
|
||||
} //namespace TCLAP
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -1,24 +1,24 @@
|
||||
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: VersionVisitor.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_VERSION_VISITOR_H
|
||||
@@ -51,7 +51,7 @@ class VersionVisitor: public Visitor
|
||||
CmdLineInterface* _cmd;
|
||||
|
||||
/**
|
||||
* The output object.
|
||||
* The output object.
|
||||
*/
|
||||
CmdLineOutput** _out;
|
||||
|
||||
@@ -59,19 +59,19 @@ class VersionVisitor: public Visitor
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* \param cmd - The CmdLine the output is generated for.
|
||||
* \param out - The type of output.
|
||||
* \param cmd - The CmdLine the output is generated for.
|
||||
* \param out - The type of output.
|
||||
*/
|
||||
VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out )
|
||||
VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out )
|
||||
: Visitor(), _cmd( cmd ), _out( out ) { }
|
||||
|
||||
/**
|
||||
* Calls the version method of the output object using the
|
||||
* specified CmdLine.
|
||||
*/
|
||||
void visit() {
|
||||
(*_out)->version(*_cmd);
|
||||
throw ExitException(0);
|
||||
void visit() {
|
||||
(*_out)->version(*_cmd);
|
||||
throw ExitException(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -1,23 +1,23 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: Visitor.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef TCLAP_VISITOR_H
|
||||
|
@@ -1,24 +1,24 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: XorHandler.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, Michael E. Smoot .
|
||||
* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TCLAP_XORHANDLER_H
|
||||
#define TCLAP_XORHANDLER_H
|
||||
@@ -56,12 +56,12 @@ class XorHandler
|
||||
* \param ors - list of Arg* that will be xor'd.
|
||||
*/
|
||||
void add( std::vector<Arg*>& ors );
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
int check( const Arg* a );
|
||||
@@ -84,7 +84,7 @@ class XorHandler
|
||||
*/
|
||||
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
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
inline void XorHandler::add( std::vector<Arg*>& ors )
|
||||
{
|
||||
{
|
||||
_orList.push_back( ors );
|
||||
}
|
||||
|
||||
inline int XorHandler::check( const Arg* a )
|
||||
inline int XorHandler::check( const Arg* a )
|
||||
{
|
||||
// iterate over each XOR list
|
||||
for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ )
|
||||
{
|
||||
// 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 );
|
||||
if ( ait != _orList[i].end() )
|
||||
{
|
||||
// first check to see if a mutually exclusive switch
|
||||
// has not already been set
|
||||
for ( ArgVectorIterator it = _orList[i].begin();
|
||||
it != _orList[i].end();
|
||||
for ( ArgVectorIterator it = _orList[i].begin();
|
||||
it != _orList[i].end();
|
||||
it++ )
|
||||
if ( a != (*it) && (*it)->isSet() )
|
||||
throw(CmdLineParseException(
|
||||
@@ -118,8 +118,8 @@ inline int XorHandler::check( const Arg* a )
|
||||
(*it)->toString()));
|
||||
|
||||
// go through and set each arg that is not a
|
||||
for ( ArgVectorIterator it = _orList[i].begin();
|
||||
it != _orList[i].end();
|
||||
for ( ArgVectorIterator it = _orList[i].begin();
|
||||
it != _orList[i].end();
|
||||
it++ )
|
||||
if ( a != (*it) )
|
||||
(*it)->xorSet();
|
||||
@@ -141,16 +141,16 @@ inline int XorHandler::check( const Arg* a )
|
||||
inline bool XorHandler::contains( const Arg* a )
|
||||
{
|
||||
for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ )
|
||||
for ( ArgVectorIterator it = _orList[i].begin();
|
||||
it != _orList[i].end();
|
||||
it++ )
|
||||
for ( ArgVectorIterator it = _orList[i].begin();
|
||||
it != _orList[i].end();
|
||||
it++ )
|
||||
if ( a == (*it) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline std::vector< std::vector<Arg*> >& XorHandler::getXorList()
|
||||
inline std::vector< std::vector<Arg*> >& XorHandler::getXorList()
|
||||
{
|
||||
return _orList;
|
||||
}
|
||||
@@ -163,4 +163,4 @@ inline std::vector< std::vector<Arg*> >& XorHandler::getXorList()
|
||||
|
||||
} //namespace TCLAP
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -1,24 +1,24 @@
|
||||
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
/******************************************************************************
|
||||
*
|
||||
* file: ZshCompletionOutput.h
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2006, Oliver Kiddle
|
||||
* All rights reverved.
|
||||
*
|
||||
*
|
||||
* See the file COPYING in the top directory of this distribution for
|
||||
* more information.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* 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
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H
|
||||
#define TCLAP_ZSHCOMPLETIONOUTPUT_H
|
||||
@@ -48,24 +48,24 @@ class ZshCompletionOutput : public CmdLineOutput
|
||||
ZshCompletionOutput();
|
||||
|
||||
/**
|
||||
* Prints the usage to stdout. Can be overridden to
|
||||
* Prints the usage to stdout. 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.
|
||||
*/
|
||||
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.
|
||||
* \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);
|
||||
|
||||
/**
|
||||
* Prints (to stderr) an error message, short usage
|
||||
* Prints (to stderr) an error message, short usage
|
||||
* Can be overridden to produce alternative behavior.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* \param e - The ArgException that caused the failure.
|
||||
* \param c - The CmdLine object the output is generated for.
|
||||
* \param e - The ArgException that caused the failure.
|
||||
*/
|
||||
virtual void failure(CmdLineInterface& c,
|
||||
ArgException& e );
|
||||
@@ -272,7 +272,7 @@ inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Ar
|
||||
{
|
||||
XorHandler xorHandler = _cmd.getXorHandler();
|
||||
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
||||
|
||||
|
||||
if (a->getName() == "help" || a->getName() == "version")
|
||||
{
|
||||
return "(-)";
|
||||
@@ -309,13 +309,13 @@ inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Ar
|
||||
return list.str();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// wasn't found in xor list
|
||||
if (!a->getFlag().empty()) {
|
||||
list << "(" << a->flagStartChar() << a->getFlag() << ' ' <<
|
||||
a->nameStartString() << a->getName() << ')';
|
||||
}
|
||||
|
||||
|
||||
return list.str();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user