mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-06 09:46:55 +08:00
@@ -1,6 +1,5 @@
|
|||||||
[common]
|
[common]
|
||||||
|
|
||||||
|
|
||||||
ocr_img_size_percent = 1.33333333
|
ocr_img_size_percent = 1.33333333
|
||||||
state_id_img_size_percent = 2.0
|
state_id_img_size_percent = 2.0
|
||||||
|
|
||||||
@@ -39,8 +38,6 @@ ocr = 0
|
|||||||
postprocess = 0
|
postprocess = 0
|
||||||
show_images = 0
|
show_images = 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; Country Specific variables ;;;;
|
;;; Country Specific variables ;;;;
|
||||||
|
|
||||||
[us]
|
[us]
|
||||||
@@ -70,7 +67,6 @@ template_max_height_px = 60
|
|||||||
plateline_sensitivity_vertical = 25
|
plateline_sensitivity_vertical = 25
|
||||||
plateline_sensitivity_horizontal = 45
|
plateline_sensitivity_horizontal = 45
|
||||||
|
|
||||||
|
|
||||||
; Regions smaller than this will be disqualified
|
; Regions smaller than this will be disqualified
|
||||||
min_plate_size_width_px = 70
|
min_plate_size_width_px = 70
|
||||||
min_plate_size_height_px = 35
|
min_plate_size_height_px = 35
|
||||||
@@ -85,7 +81,6 @@ char_analysis_height_range = 0.15
|
|||||||
char_analysis_height_step_size = 0.10
|
char_analysis_height_step_size = 0.10
|
||||||
char_analysis_height_num_steps = 5
|
char_analysis_height_num_steps = 5
|
||||||
|
|
||||||
|
|
||||||
segmentation_min_box_width_px = 8
|
segmentation_min_box_width_px = 8
|
||||||
segmentation_min_charheight_percent = 0.5;
|
segmentation_min_charheight_percent = 0.5;
|
||||||
segmentation_max_segment_width_percent_vs_average = 2.0;
|
segmentation_max_segment_width_percent_vs_average = 2.0;
|
||||||
|
24
src/main.cpp
24
src/main.cpp
@@ -17,33 +17,25 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "opencv2/highgui/highgui.hpp"
|
#include "opencv2/highgui/highgui.hpp"
|
||||||
#include "opencv2/imgproc/imgproc.hpp"
|
#include "opencv2/imgproc/imgproc.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include "tclap/CmdLine.h"
|
#include "tclap/CmdLine.h"
|
||||||
#include "support/filesystem.h"
|
#include "support/filesystem.h"
|
||||||
#include "support/timing.h"
|
#include "support/timing.h"
|
||||||
#include "alpr.h"
|
#include "alpr.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const std::string MAIN_WINDOW_NAME = "ALPR main window";
|
const std::string MAIN_WINDOW_NAME = "ALPR main window";
|
||||||
|
|
||||||
|
|
||||||
const bool SAVE_LAST_VIDEO_STILL = false;
|
const bool SAVE_LAST_VIDEO_STILL = false;
|
||||||
const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg";
|
const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg";
|
||||||
|
|
||||||
|
|
||||||
/** Function Headers */
|
/** Function Headers */
|
||||||
bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson);
|
bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson);
|
||||||
|
|
||||||
|
|
||||||
bool measureProcessingTime = false;
|
bool measureProcessingTime = false;
|
||||||
|
|
||||||
int main( int argc, const char** argv )
|
int main( int argc, const char** argv )
|
||||||
@@ -57,7 +49,8 @@
|
|||||||
std::string country;
|
std::string country;
|
||||||
int topn;
|
int topn;
|
||||||
|
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
|
|
||||||
TCLAP::CmdLine cmd("OpenAlpr Command Line Utility", ' ', OPENALPR_VERSION);
|
TCLAP::CmdLine cmd("OpenAlpr Command Line Utility", ' ', OPENALPR_VERSION);
|
||||||
|
|
||||||
@@ -93,7 +86,8 @@
|
|||||||
topn = topNArg.getValue();
|
topn = topNArg.getValue();
|
||||||
measureProcessingTime = clockSwitch.getValue();
|
measureProcessingTime = clockSwitch.getValue();
|
||||||
|
|
||||||
} catch (TCLAP::ArgException &e) // catch any exceptions
|
}
|
||||||
|
catch (TCLAP::ArgException &e) // catch any exceptions
|
||||||
{
|
{
|
||||||
std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
|
std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -101,7 +95,6 @@
|
|||||||
|
|
||||||
cv::Mat frame;
|
cv::Mat frame;
|
||||||
|
|
||||||
|
|
||||||
Alpr alpr(country, runtimePath);
|
Alpr alpr(country, runtimePath);
|
||||||
alpr.setTopN(topn);
|
alpr.setTopN(topn);
|
||||||
|
|
||||||
@@ -179,7 +172,6 @@
|
|||||||
std::cerr << "Image file not found: " << filename << std::endl;
|
std::cerr << "Image file not found: " << filename << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (DirectoryExists(filename.c_str()))
|
else if (DirectoryExists(filename.c_str()))
|
||||||
{
|
{
|
||||||
@@ -212,27 +204,20 @@
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson)
|
bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
std::vector<uchar> buffer;
|
std::vector<uchar> buffer;
|
||||||
cv::imencode(".bmp", frame, buffer );
|
cv::imencode(".bmp", frame, buffer );
|
||||||
|
|
||||||
|
|
||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
std::vector<AlprResult> results = alpr->recognize(buffer);
|
std::vector<AlprResult> results = alpr->recognize(buffer);
|
||||||
|
|
||||||
|
|
||||||
if (writeJson)
|
if (writeJson)
|
||||||
{
|
{
|
||||||
std::cout << alpr->toJson(results) << std::endl;
|
std::cout << alpr->toJson(results) << std::endl;
|
||||||
@@ -256,7 +241,6 @@
|
|||||||
if (measureProcessingTime)
|
if (measureProcessingTime)
|
||||||
std::cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << std::endl;
|
std::cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << std::endl;
|
||||||
|
|
||||||
|
|
||||||
if (results.size() > 0)
|
if (results.size() > 0)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@@ -50,7 +50,6 @@ int main( int argc, const char** argv )
|
|||||||
string outDir;
|
string outDir;
|
||||||
Mat frame;
|
Mat frame;
|
||||||
|
|
||||||
|
|
||||||
//Check if user specify image to process
|
//Check if user specify image to process
|
||||||
if(argc == 5)
|
if(argc == 5)
|
||||||
{
|
{
|
||||||
@@ -59,8 +58,9 @@ int main( int argc, const char** argv )
|
|||||||
inDir = argv[3];
|
inDir = argv[3];
|
||||||
outDir = argv[4];
|
outDir = argv[4];
|
||||||
|
|
||||||
|
}
|
||||||
}else{
|
else
|
||||||
|
{
|
||||||
printf("Use:\n\t%s [country] [benchmark name] [img input dir] [results output dir]\n",argv[0]);
|
printf("Use:\n\t%s [country] [benchmark name] [img input dir] [results output dir]\n",argv[0]);
|
||||||
printf("\tex: %s us speed ./speed/usimages ./speed\n",argv[0]);
|
printf("\tex: %s us speed ./speed/usimages ./speed\n",argv[0]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -68,7 +68,6 @@ int main( int argc, const char** argv )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (DirectoryExists(inDir.c_str()) == false)
|
if (DirectoryExists(inDir.c_str()) == false)
|
||||||
{
|
{
|
||||||
printf("Input dir does not exist\n");
|
printf("Input dir does not exist\n");
|
||||||
@@ -80,11 +79,9 @@ int main( int argc, const char** argv )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vector<string> files = getFilesInDir(inDir.c_str());
|
vector<string> files = getFilesInDir(inDir.c_str());
|
||||||
sort( files.begin(), files.end(), stringCompare );
|
sort( files.begin(), files.end(), stringCompare );
|
||||||
|
|
||||||
|
|
||||||
if (benchmarkName.compare("segocr") == 0)
|
if (benchmarkName.compare("segocr") == 0)
|
||||||
{
|
{
|
||||||
Config* config = new Config(country);
|
Config* config = new Config(country);
|
||||||
@@ -92,7 +89,6 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
OCR* ocr = new OCR(config);
|
OCR* ocr = new OCR(config);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i< files.size(); i++)
|
for (int i = 0; i< files.size(); i++)
|
||||||
{
|
{
|
||||||
if (hasEnding(files[i], ".png"))
|
if (hasEnding(files[i], ".png"))
|
||||||
@@ -129,19 +125,15 @@ int main( int argc, const char** argv )
|
|||||||
rotated.copyTo(frame);
|
rotated.copyTo(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CharacterSegmenter charSegmenter(frame, charRegion.thresholdsInverted(), config);
|
CharacterSegmenter charSegmenter(frame, charRegion.thresholdsInverted(), config);
|
||||||
ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters);
|
ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters);
|
||||||
ocr->postProcessor->analyze(statecode, 25);
|
ocr->postProcessor->analyze(statecode, 25);
|
||||||
|
|
||||||
cout << files[i] << "," << statecode << "," << ocr->postProcessor->bestChars << endl;
|
cout << files[i] << "," << statecode << "," << ocr->postProcessor->bestChars << endl;
|
||||||
|
|
||||||
|
|
||||||
imshow("Current LP", frame);
|
imshow("Current LP", frame);
|
||||||
waitKey(5);
|
waitKey(5);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -166,7 +158,6 @@ int main( int argc, const char** argv )
|
|||||||
imshow("Current LP", frame);
|
imshow("Current LP", frame);
|
||||||
waitKey(5);
|
waitKey(5);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -197,7 +188,6 @@ int main( int argc, const char** argv )
|
|||||||
vector<double> ocrTimes;
|
vector<double> ocrTimes;
|
||||||
vector<double> postProcessTimes;
|
vector<double> postProcessTimes;
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i< files.size(); i++)
|
for (int i = 0; i< files.size(); i++)
|
||||||
{
|
{
|
||||||
if (hasEnding(files[i], ".png"))
|
if (hasEnding(files[i], ".png"))
|
||||||
@@ -207,7 +197,6 @@ int main( int argc, const char** argv )
|
|||||||
string fullpath = inDir + "/" + files[i];
|
string fullpath = inDir + "/" + files[i];
|
||||||
frame = imread( fullpath.c_str() );
|
frame = imread( fullpath.c_str() );
|
||||||
|
|
||||||
|
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
alpr.recognize(frame);
|
alpr.recognize(frame);
|
||||||
getTime(&endTime);
|
getTime(&endTime);
|
||||||
@@ -244,7 +233,6 @@ int main( int argc, const char** argv )
|
|||||||
{
|
{
|
||||||
lpAnalysisPositiveTimes.push_back(analysisTime);
|
lpAnalysisPositiveTimes.push_back(analysisTime);
|
||||||
|
|
||||||
|
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
ocr.performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters);
|
ocr.performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters);
|
||||||
getTime(&endTime);
|
getTime(&endTime);
|
||||||
@@ -273,7 +261,6 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
cout << endl << "---------------------" << endl;
|
cout << endl << "---------------------" << endl;
|
||||||
|
|
||||||
|
|
||||||
cout << "End to End Time Statistics:" << endl;
|
cout << "End to End Time Statistics:" << endl;
|
||||||
outputStats(endToEndTimes);
|
outputStats(endToEndTimes);
|
||||||
cout << endl;
|
cout << endl;
|
||||||
@@ -333,7 +320,6 @@ int main( int argc, const char** argv )
|
|||||||
imshow("Current LP", frame);
|
imshow("Current LP", frame);
|
||||||
waitKey(5);
|
waitKey(5);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,6 @@ const int DASHBOARD_COLUMNS = 3;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex);
|
void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex);
|
||||||
vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state);
|
vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state);
|
||||||
|
|
||||||
@@ -72,21 +71,20 @@ int main( int argc, const char** argv )
|
|||||||
string outDir;
|
string outDir;
|
||||||
Mat frame;
|
Mat frame;
|
||||||
|
|
||||||
|
|
||||||
//Check if user specify image to process
|
//Check if user specify image to process
|
||||||
if(argc == 3)
|
if(argc == 3)
|
||||||
{
|
{
|
||||||
inDir = argv[1];
|
inDir = argv[1];
|
||||||
outDir = argv[2];
|
outDir = argv[2];
|
||||||
|
|
||||||
|
}
|
||||||
}else{
|
else
|
||||||
|
{
|
||||||
printf("Use:\n\t%s indirectory outdirectory\n",argv[0]);
|
printf("Use:\n\t%s indirectory outdirectory\n",argv[0]);
|
||||||
printf("Ex: \n\t%s ./pics/ ./out \n",argv[0]);
|
printf("Ex: \n\t%s ./pics/ ./out \n",argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (DirectoryExists(outDir.c_str()) == false)
|
if (DirectoryExists(outDir.c_str()) == false)
|
||||||
{
|
{
|
||||||
printf("Output dir does not exist\n");
|
printf("Output dir does not exist\n");
|
||||||
@@ -125,7 +123,6 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
imshow ("Original", frame);
|
imshow ("Original", frame);
|
||||||
|
|
||||||
|
|
||||||
char statecode[3];
|
char statecode[3];
|
||||||
statecode[0] = files[i][0];
|
statecode[0] = files[i][0];
|
||||||
statecode[1] = files[i][1];
|
statecode[1] = files[i][1];
|
||||||
@@ -155,7 +152,6 @@ int main( int argc, const char** argv )
|
|||||||
ocr.postProcessor->analyze(statecodestr, 25);
|
ocr.postProcessor->analyze(statecodestr, 25);
|
||||||
cout << "OCR results: " << ocr.postProcessor->bestChars << endl;
|
cout << "OCR results: " << ocr.postProcessor->bestChars << endl;
|
||||||
|
|
||||||
|
|
||||||
vector<bool> selectedBoxes(charSegmenter.getThresholds().size());
|
vector<bool> selectedBoxes(charSegmenter.getThresholds().size());
|
||||||
for (int z = 0; z < charSegmenter.getThresholds().size(); z++)
|
for (int z = 0; z < charSegmenter.getThresholds().size(); z++)
|
||||||
selectedBoxes[z] = false;
|
selectedBoxes[z] = false;
|
||||||
@@ -169,8 +165,6 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
showDashboard(charSegmenter.getThresholds(), selectedBoxes, 0);
|
showDashboard(charSegmenter.getThresholds(), selectedBoxes, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char waitkey = (char) waitKey(50);
|
char waitkey = (char) waitKey(50);
|
||||||
|
|
||||||
while (waitkey != 'n' && waitkey != 'p') // Next image
|
while (waitkey != 'n' && waitkey != 'p') // Next image
|
||||||
@@ -267,7 +261,6 @@ int main( int argc, const char** argv )
|
|||||||
if (i < -1)
|
if (i < -1)
|
||||||
i = -1;
|
i = -1;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -275,7 +268,6 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex)
|
void showDashboard(vector<Mat> images, vector<bool> selectedImages, int selectedIndex)
|
||||||
{
|
{
|
||||||
vector<Mat> vecCopy;
|
vector<Mat> vecCopy;
|
||||||
@@ -315,7 +307,6 @@ vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state
|
|||||||
for (int i = 0; i < charRegions.size(); i++)
|
for (int i = 0; i < charRegions.size(); i++)
|
||||||
humanInputs[i] = (char) SPACE_KEY;
|
humanInputs[i] = (char) SPACE_KEY;
|
||||||
|
|
||||||
|
|
||||||
char waitkey = (char) waitKey(50);
|
char waitkey = (char) waitKey(50);
|
||||||
while (waitkey != ENTER_KEY && waitkey != ESCAPE_KEY)
|
while (waitkey != ENTER_KEY && waitkey != ESCAPE_KEY)
|
||||||
{
|
{
|
||||||
@@ -365,6 +356,5 @@ vector<char> showCharSelection(Mat image, vector<Rect> charRegions, string state
|
|||||||
|
|
||||||
destroyWindow("Character selector");
|
destroyWindow("Character selector");
|
||||||
|
|
||||||
|
|
||||||
return humanInputs;
|
return humanInputs;
|
||||||
}
|
}
|
||||||
|
@@ -29,8 +29,6 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace cv;
|
using namespace cv;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Takes a directory full of single char images, and plops them on a big tif files
|
// Takes a directory full of single char images, and plops them on a big tif files
|
||||||
// Also creates a box file so Tesseract can recognize it
|
// Also creates a box file so Tesseract can recognize it
|
||||||
int main( int argc, const char** argv )
|
int main( int argc, const char** argv )
|
||||||
@@ -38,18 +36,18 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
string inDir;
|
string inDir;
|
||||||
|
|
||||||
|
|
||||||
//Check if user specify image to process
|
//Check if user specify image to process
|
||||||
if(argc == 2)
|
if(argc == 2)
|
||||||
{
|
{
|
||||||
inDir = argv[1];
|
inDir = argv[1];
|
||||||
|
|
||||||
}else{
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
printf("Use:\n\t%s input dir \n",argv[0]);
|
printf("Use:\n\t%s input dir \n",argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (DirectoryExists(inDir.c_str()) == false)
|
if (DirectoryExists(inDir.c_str()) == false)
|
||||||
{
|
{
|
||||||
printf("Output dir does not exist\n");
|
printf("Output dir does not exist\n");
|
||||||
@@ -59,7 +57,6 @@ int main( int argc, const char** argv )
|
|||||||
cout << "Usage: " << endl;
|
cout << "Usage: " << endl;
|
||||||
cout << "\tinputdir -- input dir for benchmark data" << endl;
|
cout << "\tinputdir -- input dir for benchmark data" << endl;
|
||||||
|
|
||||||
|
|
||||||
if (DirectoryExists(inDir.c_str()))
|
if (DirectoryExists(inDir.c_str()))
|
||||||
{
|
{
|
||||||
const int X_OFFSET = 10;
|
const int X_OFFSET = 10;
|
||||||
@@ -78,7 +75,6 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
sort( files.begin(), files.end(), stringCompare );
|
sort( files.begin(), files.end(), stringCompare );
|
||||||
|
|
||||||
|
|
||||||
int tiles_per_row = ((float) (HORIZONTAL_RESOLUTION - (PAGE_MARGIN_X * 2))) / ((float) TILE_WIDTH);
|
int tiles_per_row = ((float) (HORIZONTAL_RESOLUTION - (PAGE_MARGIN_X * 2))) / ((float) TILE_WIDTH);
|
||||||
int lines = files.size() / (tiles_per_row);
|
int lines = files.size() / (tiles_per_row);
|
||||||
int vertical_resolution = (lines * TILE_HEIGHT) + (PAGE_MARGIN_Y * 2) ;
|
int vertical_resolution = (lines * TILE_HEIGHT) + (PAGE_MARGIN_Y * 2) ;
|
||||||
@@ -130,7 +126,6 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
Rect cropRect(0, tallestRect.y - Y_OFFSET, tallestRect.width, tallestRect.height);
|
Rect cropRect(0, tallestRect.y - Y_OFFSET, tallestRect.width, tallestRect.height);
|
||||||
|
|
||||||
|
|
||||||
//cout << "Cropped: " << cropRect.x << ":" << cropRect.y << " -- " << cropRect.width << ":" << cropRect.height << endl;
|
//cout << "Cropped: " << cropRect.x << ":" << cropRect.y << " -- " << cropRect.width << ":" << cropRect.height << endl;
|
||||||
Mat cropped(characterImg, cropRect);
|
Mat cropped(characterImg, cropRect);
|
||||||
cvtColor(cropped, cropped, CV_BGR2GRAY);
|
cvtColor(cropped, cropped, CV_BGR2GRAY);
|
||||||
@@ -141,7 +136,6 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
cropped.copyTo(bigTif(destinationRect));
|
cropped.copyTo(bigTif(destinationRect));
|
||||||
|
|
||||||
|
|
||||||
int x1= destinationRect.x - 2;
|
int x1= destinationRect.x - 2;
|
||||||
int y1 = (vertical_resolution - destinationRect.y - destinationRect.height) - 2;
|
int y1 = (vertical_resolution - destinationRect.y - destinationRect.height) - 2;
|
||||||
int x2 = (destinationRect.x + destinationRect.width) + 2;
|
int x2 = (destinationRect.x + destinationRect.width) + 2;
|
||||||
@@ -156,12 +150,10 @@ int main( int argc, const char** argv )
|
|||||||
|
|
||||||
waitKey(2);
|
waitKey(2);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
imwrite("combined.tif", bigTif);
|
imwrite("combined.tif", bigTif);
|
||||||
ofstream boxFile("combined.box", std::ios::out);
|
ofstream boxFile("combined.box", std::ios::out);
|
||||||
boxFile << boxFileOut.str();
|
boxFile << boxFileOut.str();
|
||||||
|
@@ -45,7 +45,6 @@ int main( int argc, const char** argv )
|
|||||||
string outDir;
|
string outDir;
|
||||||
Mat frame;
|
Mat frame;
|
||||||
|
|
||||||
|
|
||||||
//Check if user specify image to process
|
//Check if user specify image to process
|
||||||
if(argc == 3 )
|
if(argc == 3 )
|
||||||
{
|
{
|
||||||
@@ -53,8 +52,9 @@ int main( int argc, const char** argv )
|
|||||||
outDir = argv[2];
|
outDir = argv[2];
|
||||||
outDir = outDir + "/";
|
outDir = outDir + "/";
|
||||||
|
|
||||||
|
}
|
||||||
}else{
|
else
|
||||||
|
{
|
||||||
printf("Use:\n\t%s directory \n",argv[0]);
|
printf("Use:\n\t%s directory \n",argv[0]);
|
||||||
printf("Ex: \n\t%s ./pics/ \n",argv[0]);
|
printf("Ex: \n\t%s ./pics/ \n",argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -99,7 +99,6 @@ int main( int argc, const char** argv )
|
|||||||
ostringstream convert; // stream used for the conversion
|
ostringstream convert; // stream used for the conversion
|
||||||
convert << i; // insert the textual representation of 'Number' in the characters in the stream
|
convert << i; // insert the textual representation of 'Number' in the characters in the stream
|
||||||
|
|
||||||
|
|
||||||
string copyCommand = "cp \"" + fullpath + "\" " + outDir + code + convert.str() + ".png";
|
string copyCommand = "cp \"" + fullpath + "\" " + outDir + code + convert.str() + ".png";
|
||||||
system( copyCommand.c_str() );
|
system( copyCommand.c_str() );
|
||||||
waitKey(50);
|
waitKey(50);
|
||||||
|
@@ -31,45 +31,67 @@ extern "C" {
|
|||||||
#include "trex.h"
|
#include "trex.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TRexParseException{TRexParseException(const TRexChar *c):desc(c){}const TRexChar *desc;};
|
struct TRexParseException
|
||||||
|
{
|
||||||
|
TRexParseException(const TRexChar *c):desc(c) {} const TRexChar *desc;
|
||||||
|
};
|
||||||
|
|
||||||
class TRexpp {
|
class TRexpp
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
TRexpp() { _exp = (TRex *)0; }
|
TRexpp()
|
||||||
~TRexpp() { CleanUp(); }
|
{
|
||||||
|
_exp = (TRex *)0;
|
||||||
|
}
|
||||||
|
~TRexpp()
|
||||||
|
{
|
||||||
|
CleanUp();
|
||||||
|
}
|
||||||
// compiles a regular expression
|
// compiles a regular expression
|
||||||
void Compile(const TRexChar *pattern) {
|
void Compile(const TRexChar *pattern)
|
||||||
|
{
|
||||||
const TRexChar *error;
|
const TRexChar *error;
|
||||||
CleanUp();
|
CleanUp();
|
||||||
if(!(_exp = trex_compile(pattern,&error)))
|
if(!(_exp = trex_compile(pattern,&error)))
|
||||||
throw TRexParseException(error);
|
throw TRexParseException(error);
|
||||||
}
|
}
|
||||||
// return true if the given text match the expression
|
// return true if the given text match the expression
|
||||||
bool Match(const TRexChar* text) {
|
bool Match(const TRexChar* text)
|
||||||
|
{
|
||||||
return _exp?(trex_match(_exp,text) != 0):false;
|
return _exp?(trex_match(_exp,text) != 0):false;
|
||||||
}
|
}
|
||||||
// Searches for the first match of the expression in a zero terminated string
|
// Searches for the first match of the expression in a zero terminated string
|
||||||
bool Search(const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) {
|
bool Search(const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end)
|
||||||
|
{
|
||||||
return _exp?(trex_search(_exp,text,out_begin,out_end) != 0):false;
|
return _exp?(trex_search(_exp,text,out_begin,out_end) != 0):false;
|
||||||
}
|
}
|
||||||
// Searches for the first match of the expression in a string sarting at text_begin and ending at text_end
|
// Searches for the first match of the expression in a string sarting at text_begin and ending at text_end
|
||||||
bool SearchRange(const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) {
|
bool SearchRange(const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end)
|
||||||
|
{
|
||||||
return _exp?(trex_searchrange(_exp,text_begin,text_end,out_begin,out_end) != 0):false;
|
return _exp?(trex_searchrange(_exp,text_begin,text_end,out_begin,out_end) != 0):false;
|
||||||
}
|
}
|
||||||
bool GetSubExp(int n, const TRexChar** out_begin, int *out_len)
|
bool GetSubExp(int n, const TRexChar** out_begin, int *out_len)
|
||||||
{
|
{
|
||||||
TRexMatch match;
|
TRexMatch match;
|
||||||
TRexBool res = _exp?(trex_getsubexp(_exp,n,&match)):TRex_False;
|
TRexBool res = _exp?(trex_getsubexp(_exp,n,&match)):TRex_False;
|
||||||
if(res) {
|
if(res)
|
||||||
|
{
|
||||||
*out_begin = match.begin;
|
*out_begin = match.begin;
|
||||||
*out_len = match.len;
|
*out_len = match.len;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int GetSubExpCount() { return _exp?trex_getsubexpcount(_exp):0; }
|
int GetSubExpCount()
|
||||||
|
{
|
||||||
|
return _exp?trex_getsubexpcount(_exp):0;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
void CleanUp() { if(_exp) trex_free(_exp); _exp = (TRex *)0; }
|
void CleanUp()
|
||||||
|
{
|
||||||
|
if(_exp) trex_free(_exp);
|
||||||
|
_exp = (TRex *)0;
|
||||||
|
}
|
||||||
TRex *_exp;
|
TRex *_exp;
|
||||||
};
|
};
|
||||||
#endif //_TREXPP_H_
|
#endif //_TREXPP_H_
|
||||||
|
@@ -20,9 +20,6 @@
|
|||||||
#include "alpr.h"
|
#include "alpr.h"
|
||||||
#include "alpr_impl.h"
|
#include "alpr_impl.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ALPR code
|
// ALPR code
|
||||||
|
|
||||||
Alpr::Alpr(const std::string country, const std::string runtimeDir)
|
Alpr::Alpr(const std::string country, const std::string runtimeDir)
|
||||||
@@ -40,7 +37,6 @@ std::vector<AlprResult> Alpr::recognize(std::string filepath)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer)
|
std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer)
|
||||||
{
|
{
|
||||||
// Not sure if this actually works
|
// Not sure if this actually works
|
||||||
@@ -49,13 +45,11 @@ std::vector<AlprResult> Alpr::recognize(std::vector<unsigned char> imageBuffer)
|
|||||||
return impl->recognize(img);
|
return impl->recognize(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string Alpr::toJson(const vector< AlprResult > results)
|
string Alpr::toJson(const vector< AlprResult > results)
|
||||||
{
|
{
|
||||||
return impl->toJson(results);
|
return impl->toJson(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Alpr::setDetectRegion(bool detectRegion)
|
void Alpr::setDetectRegion(bool detectRegion)
|
||||||
{
|
{
|
||||||
impl->setDetectRegion(detectRegion);
|
impl->setDetectRegion(detectRegion);
|
||||||
@@ -74,11 +68,8 @@ bool Alpr::isLoaded()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Results code
|
// Results code
|
||||||
|
|
||||||
|
|
||||||
AlprResult::AlprResult()
|
AlprResult::AlprResult()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "alpr_impl.h"
|
#include "alpr_impl.h"
|
||||||
|
|
||||||
|
|
||||||
AlprImpl::AlprImpl(const std::string country, const std::string runtimeDir)
|
AlprImpl::AlprImpl(const std::string country, const std::string runtimeDir)
|
||||||
{
|
{
|
||||||
config = new Config(country, runtimeDir);
|
config = new Config(country, runtimeDir);
|
||||||
@@ -68,7 +67,6 @@ AlprImpl::~AlprImpl()
|
|||||||
delete ocr;
|
delete ocr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
||||||
{
|
{
|
||||||
timespec startTime;
|
timespec startTime;
|
||||||
@@ -76,10 +74,8 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
|||||||
|
|
||||||
vector<AlprResult> response;
|
vector<AlprResult> response;
|
||||||
|
|
||||||
|
|
||||||
vector<Rect> plateRegions = plateDetector->detect(img);
|
vector<Rect> plateRegions = plateDetector->detect(img);
|
||||||
|
|
||||||
|
|
||||||
// Recognize.
|
// Recognize.
|
||||||
|
|
||||||
for (int i = 0; i < plateRegions.size(); i++)
|
for (int i = 0; i < plateRegions.size(); i++)
|
||||||
@@ -91,7 +87,6 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
|||||||
|
|
||||||
lp.recognize();
|
lp.recognize();
|
||||||
|
|
||||||
|
|
||||||
if (lp.confidence > 10)
|
if (lp.confidence > 10)
|
||||||
{
|
{
|
||||||
AlprResult plateResult;
|
AlprResult plateResult;
|
||||||
@@ -114,7 +109,6 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ocr->performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters);
|
ocr->performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters);
|
||||||
|
|
||||||
ocr->postProcessor->analyze(plateResult.region, topN);
|
ocr->postProcessor->analyze(plateResult.region, topN);
|
||||||
@@ -162,7 +156,6 @@ std::vector<AlprResult> AlprImpl::recognize(cv::Mat img)
|
|||||||
line(img, lp.plateCorners[z], lp.plateCorners[(z + 1) % 4], Scalar(255,0,255), 2);
|
line(img, lp.plateCorners[z], lp.plateCorners[(z + 1) % 4], Scalar(255,0,255), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -210,8 +203,6 @@ string AlprImpl::toJson(const vector< AlprResult > results)
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cJSON* AlprImpl::createJsonObj(const AlprResult* result)
|
cJSON* AlprImpl::createJsonObj(const AlprResult* result)
|
||||||
{
|
{
|
||||||
cJSON *root, *coords, *candidates;
|
cJSON *root, *coords, *candidates;
|
||||||
@@ -238,7 +229,6 @@ cJSON* AlprImpl::createJsonObj(const AlprResult* result)
|
|||||||
cJSON_AddItemToArray(coords, coords_object);
|
cJSON_AddItemToArray(coords, coords_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cJSON_AddItemToObject(root, "candidates", candidates=cJSON_CreateArray());
|
cJSON_AddItemToObject(root, "candidates", candidates=cJSON_CreateArray());
|
||||||
for (int i = 0; i < result->topNPlates.size(); i++)
|
for (int i = 0; i < result->topNPlates.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -254,7 +244,6 @@ cJSON* AlprImpl::createJsonObj(const AlprResult* result)
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AlprImpl::setDetectRegion(bool detectRegion)
|
void AlprImpl::setDetectRegion(bool detectRegion)
|
||||||
{
|
{
|
||||||
this->detectRegion = detectRegion;
|
this->detectRegion = detectRegion;
|
||||||
|
@@ -33,14 +33,13 @@
|
|||||||
|
|
||||||
#include "binarize_wolf.h"
|
#include "binarize_wolf.h"
|
||||||
|
|
||||||
|
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
// glide a window across the image and
|
// glide a window across the image and
|
||||||
// create two maps: mean and standard deviation.
|
// create two maps: mean and standard deviation.
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
|
|
||||||
|
float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy)
|
||||||
float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy) {
|
{
|
||||||
|
|
||||||
float m,s,max_s;
|
float m,s,max_s;
|
||||||
long sum, sum_sq;
|
long sum, sum_sq;
|
||||||
@@ -52,14 +51,14 @@ float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy) {
|
|||||||
int y_firstth= wyh;
|
int y_firstth= wyh;
|
||||||
float winarea = winx*winy;
|
float winarea = winx*winy;
|
||||||
|
|
||||||
|
|
||||||
max_s = 0;
|
max_s = 0;
|
||||||
for (int j = y_firstth ; j<=y_lastth; j++)
|
for (int j = y_firstth ; j<=y_lastth; j++)
|
||||||
{
|
{
|
||||||
// Calculate the initial window at the beginning of the line
|
// Calculate the initial window at the beginning of the line
|
||||||
sum = sum_sq = 0;
|
sum = sum_sq = 0;
|
||||||
for (int wy=0 ; wy<winy; wy++)
|
for (int wy=0 ; wy<winy; wy++)
|
||||||
for (int wx=0 ; wx<winx; wx++) {
|
for (int wx=0 ; wx<winx; wx++)
|
||||||
|
{
|
||||||
foo = im.uget(wx,j-wyh+wy);
|
foo = im.uget(wx,j-wyh+wy);
|
||||||
sum += foo;
|
sum += foo;
|
||||||
sum_sq += foo*foo;
|
sum_sq += foo*foo;
|
||||||
@@ -72,10 +71,12 @@ float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy) {
|
|||||||
map_s.fset(x_firstth, j, s);
|
map_s.fset(x_firstth, j, s);
|
||||||
|
|
||||||
// Shift the window, add and remove new/old values to the histogram
|
// Shift the window, add and remove new/old values to the histogram
|
||||||
for (int i=1 ; i <= im.cols-winx; i++) {
|
for (int i=1 ; i <= im.cols-winx; i++)
|
||||||
|
{
|
||||||
|
|
||||||
// Remove the left old column and add the right new column
|
// Remove the left old column and add the right new column
|
||||||
for (int wy=0; wy<winy; ++wy) {
|
for (int wy=0; wy<winy; ++wy)
|
||||||
|
{
|
||||||
foo = im.uget(i-1,j-wyh+wy);
|
foo = im.uget(i-1,j-wyh+wy);
|
||||||
sum -= foo;
|
sum -= foo;
|
||||||
sum_sq -= foo*foo;
|
sum_sq -= foo*foo;
|
||||||
@@ -95,14 +96,13 @@ float calcLocalStats (Mat &im, Mat &map_m, Mat &map_s, int winx, int winy) {
|
|||||||
return max_s;
|
return max_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************
|
/**********************************************************
|
||||||
* The binarization routine
|
* The binarization routine
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
|
|
||||||
|
|
||||||
void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
|
void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
|
||||||
int winx, int winy, float k) {
|
int winx, int winy, float k)
|
||||||
|
{
|
||||||
|
|
||||||
float dR = BINARIZEWOLF_DEFAULTDR;
|
float dR = BINARIZEWOLF_DEFAULTDR;
|
||||||
|
|
||||||
@@ -129,16 +129,19 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
|
|||||||
// Create the threshold surface, including border processing
|
// Create the threshold surface, including border processing
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
|
|
||||||
for (int j = y_firstth ; j<=y_lastth; j++) {
|
for (int j = y_firstth ; j<=y_lastth; j++)
|
||||||
|
{
|
||||||
|
|
||||||
// NORMAL, NON-BORDER AREA IN THE MIDDLE OF THE WINDOW:
|
// NORMAL, NON-BORDER AREA IN THE MIDDLE OF THE WINDOW:
|
||||||
for (int i=0 ; i <= im.cols-winx; i++) {
|
for (int i=0 ; i <= im.cols-winx; i++)
|
||||||
|
{
|
||||||
|
|
||||||
m = map_m.fget(i+wxh, j);
|
m = map_m.fget(i+wxh, j);
|
||||||
s = map_s.fget(i+wxh, j);
|
s = map_s.fget(i+wxh, j);
|
||||||
|
|
||||||
// Calculate the threshold
|
// Calculate the threshold
|
||||||
switch (version) {
|
switch (version)
|
||||||
|
{
|
||||||
|
|
||||||
case NIBLACK:
|
case NIBLACK:
|
||||||
th = m + k*s;
|
th = m + k*s;
|
||||||
@@ -159,7 +162,8 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
|
|||||||
|
|
||||||
thsurf.fset(i+wxh,j,th);
|
thsurf.fset(i+wxh,j,th);
|
||||||
|
|
||||||
if (i==0) {
|
if (i==0)
|
||||||
|
{
|
||||||
// LEFT BORDER
|
// LEFT BORDER
|
||||||
for (int i=0; i<=x_firstth; ++i)
|
for (int i=0; i<=x_firstth; ++i)
|
||||||
thsurf.fset(i,j,th);
|
thsurf.fset(i,j,th);
|
||||||
@@ -205,8 +209,6 @@ void NiblackSauvolaWolfJolion (Mat im, Mat output, NiblackVersion version,
|
|||||||
thsurf.fset(i,u,th);
|
thsurf.fset(i,u,th);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (int y=0; y<im.rows; ++y)
|
for (int y=0; y<im.rows; ++y)
|
||||||
for (int x=0; x<im.cols; ++x)
|
for (int x=0; x<im.cols; ++x)
|
||||||
{
|
{
|
||||||
|
@@ -29,7 +29,6 @@ CharacterAnalysis::CharacterAnalysis(Mat img, Config* config)
|
|||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
cout << "Starting CharacterAnalysis identification" << endl;
|
cout << "Starting CharacterAnalysis identification" << endl;
|
||||||
|
|
||||||
|
|
||||||
if (img.type() != CV_8U)
|
if (img.type() != CV_8U)
|
||||||
cvtColor( img, this->img_gray, CV_BGR2GRAY );
|
cvtColor( img, this->img_gray, CV_BGR2GRAY );
|
||||||
else
|
else
|
||||||
@@ -49,15 +48,11 @@ CharacterAnalysis::~CharacterAnalysis()
|
|||||||
thresholds.clear();
|
thresholds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CharacterAnalysis::analyze()
|
void CharacterAnalysis::analyze()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
thresholds = produceThresholds(img_gray, config);
|
thresholds = produceThresholds(img_gray, config);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Morph Close the gray image to make it easier to detect blobs
|
// Morph Close the gray image to make it easier to detect blobs
|
||||||
int morph_elem = 1;
|
int morph_elem = 1;
|
||||||
@@ -73,11 +68,9 @@ void CharacterAnalysis::analyze()
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < thresholds.size(); i++)
|
for (int i = 0; i < thresholds.size(); i++)
|
||||||
{
|
{
|
||||||
vector<vector<Point> > contours;
|
vector<vector<Point> > contours;
|
||||||
@@ -95,9 +88,6 @@ void CharacterAnalysis::analyze()
|
|||||||
allHierarchy.push_back(hierarchy);
|
allHierarchy.push_back(hierarchy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -106,7 +96,6 @@ void CharacterAnalysis::analyze()
|
|||||||
}
|
}
|
||||||
//Mat img_equalized = equalizeBrightness(img_gray);
|
//Mat img_equalized = equalizeBrightness(img_gray);
|
||||||
|
|
||||||
|
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
for (int i = 0; i < thresholds.size(); i++)
|
for (int i = 0; i < thresholds.size(); i++)
|
||||||
@@ -125,8 +114,6 @@ void CharacterAnalysis::analyze()
|
|||||||
cout << " -- Character Analysis Filter Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
cout << " -- Character Analysis Filter Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->plateMask = findOuterBoxMask();
|
this->plateMask = findOuterBoxMask();
|
||||||
|
|
||||||
if (hasPlateMask)
|
if (hasPlateMask)
|
||||||
@@ -138,7 +125,6 @@ void CharacterAnalysis::analyze()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int bestFitScore = -1;
|
int bestFitScore = -1;
|
||||||
int bestFitIndex = -1;
|
int bestFitIndex = -1;
|
||||||
for (int i = 0; i < thresholds.size(); i++)
|
for (int i = 0; i < thresholds.size(); i++)
|
||||||
@@ -149,7 +135,6 @@ void CharacterAnalysis::analyze()
|
|||||||
|
|
||||||
int segmentCount = getGoodIndicesCount(charSegments[i]);
|
int segmentCount = getGoodIndicesCount(charSegments[i]);
|
||||||
|
|
||||||
|
|
||||||
if (segmentCount > bestFitScore)
|
if (segmentCount > bestFitScore)
|
||||||
{
|
{
|
||||||
bestFitScore = segmentCount;
|
bestFitScore = segmentCount;
|
||||||
@@ -165,11 +150,9 @@ void CharacterAnalysis::analyze()
|
|||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
cout << "Best fit score: " << bestFitScore << " Index: " << bestFitIndex << endl;
|
cout << "Best fit score: " << bestFitScore << " Index: " << bestFitIndex << endl;
|
||||||
|
|
||||||
|
|
||||||
if (bestFitScore <= 1)
|
if (bestFitScore <= 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
//getColorMask(img, allContours, allHierarchy, charSegments);
|
//getColorMask(img, allContours, allHierarchy, charSegments);
|
||||||
|
|
||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
@@ -196,15 +179,11 @@ void CharacterAnalysis::analyze()
|
|||||||
cv::Scalar(0,255,0), // in green
|
cv::Scalar(0,255,0), // in green
|
||||||
1); // with a thickness of 1
|
1); // with a thickness of 1
|
||||||
|
|
||||||
|
|
||||||
displayImage(config, "Matching Contours", img_contours);
|
displayImage(config, "Matching Contours", img_contours);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP));
|
//charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->linePolygon = getBestVotedLines(img_gray, bestContours, bestCharSegments);
|
this->linePolygon = getBestVotedLines(img_gray, bestContours, bestCharSegments);
|
||||||
|
|
||||||
if (this->linePolygon.size() > 0)
|
if (this->linePolygon.size() > 0)
|
||||||
@@ -223,14 +202,11 @@ void CharacterAnalysis::analyze()
|
|||||||
this->charBoxLeft = LineSegment(this->charArea[3].x, this->charArea[3].y, this->charArea[0].x, this->charArea[0].y);
|
this->charBoxLeft = LineSegment(this->charArea[3].x, this->charArea[3].y, this->charArea[0].x, this->charArea[0].y);
|
||||||
this->charBoxRight = LineSegment(this->charArea[2].x, this->charArea[2].y, this->charArea[1].x, this->charArea[1].y);
|
this->charBoxRight = LineSegment(this->charArea[2].x, this->charArea[2].y, this->charArea[1].x, this->charArea[1].y);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->thresholdsInverted = isPlateInverted();
|
this->thresholdsInverted = isPlateInverted();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CharacterAnalysis::getGoodIndicesCount(vector<bool> goodIndices)
|
int CharacterAnalysis::getGoodIndicesCount(vector<bool> goodIndices)
|
||||||
@@ -245,8 +221,6 @@ int CharacterAnalysis::getGoodIndicesCount(vector<bool> goodIndices)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mat CharacterAnalysis::findOuterBoxMask()
|
Mat CharacterAnalysis::findOuterBoxMask()
|
||||||
{
|
{
|
||||||
double min_parent_area = config->templateHeightPx * config->templateWidthPx * 0.10; // Needs to be at least 10% of the plate area to be considered.
|
double min_parent_area = config->templateHeightPx * config->templateWidthPx * 0.10; // Needs to be at least 10% of the plate area to be considered.
|
||||||
@@ -256,7 +230,6 @@ Mat CharacterAnalysis::findOuterBoxMask()
|
|||||||
int bestCharCount = 0;
|
int bestCharCount = 0;
|
||||||
double lowestArea = 99999999999999;
|
double lowestArea = 99999999999999;
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
cout << "CharacterAnalysis::findOuterBoxMask" << endl;
|
cout << "CharacterAnalysis::findOuterBoxMask" << endl;
|
||||||
|
|
||||||
@@ -297,15 +270,11 @@ Mat CharacterAnalysis::findOuterBoxMask()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
cout << "Winning image index is: " << winningIndex << endl;
|
cout << "Winning image index is: " << winningIndex << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (winningIndex != -1 && bestCharCount >= 3)
|
if (winningIndex != -1 && bestCharCount >= 3)
|
||||||
{
|
{
|
||||||
int longestChildIndex = -1;
|
int longestChildIndex = -1;
|
||||||
@@ -327,10 +296,6 @@ Mat CharacterAnalysis::findOuterBoxMask()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mat mask = Mat::zeros(thresholds[winningIndex].size(), CV_8U);
|
Mat mask = Mat::zeros(thresholds[winningIndex].size(), CV_8U);
|
||||||
|
|
||||||
// get rid of the outline by drawing a 1 pixel width black line
|
// get rid of the outline by drawing a 1 pixel width black line
|
||||||
@@ -343,7 +308,6 @@ Mat CharacterAnalysis::findOuterBoxMask()
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Morph Open the mask to get rid of any little connectors to non-plate portions
|
// Morph Open the mask to get rid of any little connectors to non-plate portions
|
||||||
int morph_elem = 2;
|
int morph_elem = 2;
|
||||||
int morph_size = 3;
|
int morph_size = 3;
|
||||||
@@ -356,7 +320,6 @@ Mat CharacterAnalysis::findOuterBoxMask()
|
|||||||
//element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
//element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
||||||
//dilate(mask, mask, element);
|
//dilate(mask, mask, element);
|
||||||
|
|
||||||
|
|
||||||
// Drawing the edge black effectively erodes the image. This may clip off some extra junk from the edges.
|
// Drawing the edge black effectively erodes the image. This may clip off some extra junk from the edges.
|
||||||
// We'll want to do the contour again and find the larges one so that we remove the clipped portion.
|
// We'll want to do the contour again and find the larges one so that we remove the clipped portion.
|
||||||
|
|
||||||
@@ -394,8 +357,6 @@ Mat CharacterAnalysis::findOuterBoxMask()
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
@@ -422,11 +383,8 @@ Mat CharacterAnalysis::findOuterBoxMask()
|
|||||||
bitwise_not(fullMask, fullMask);
|
bitwise_not(fullMask, fullMask);
|
||||||
return fullMask;
|
return fullMask;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mat CharacterAnalysis::getCharacterMask()
|
Mat CharacterAnalysis::getCharacterMask()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -437,7 +395,6 @@ Mat CharacterAnalysis::getCharacterMask()
|
|||||||
if (bestCharSegments[i] == false)
|
if (bestCharSegments[i] == false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
drawContours(charMask, bestContours,
|
drawContours(charMask, bestContours,
|
||||||
i, // draw this contour
|
i, // draw this contour
|
||||||
cv::Scalar(255,255,255), // in
|
cv::Scalar(255,255,255), // in
|
||||||
@@ -458,12 +415,9 @@ Mat CharacterAnalysis::getCharacterMask()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return charMask;
|
return charMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Returns a polygon "stripe" across the width of the character region. The lines are voted and the polygon starts at 0 and extends to image width
|
// Returns a polygon "stripe" across the width of the character region. The lines are voted and the polygon starts at 0 and extends to image width
|
||||||
vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices)
|
vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point> > contours, vector<bool> goodIndices)
|
||||||
{
|
{
|
||||||
@@ -481,7 +435,6 @@ vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point>
|
|||||||
charRegions.push_back(boundingRect(contours[i]));
|
charRegions.push_back(boundingRect(contours[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Find the best fit line segment that is parallel with the most char segments
|
// Find the best fit line segment that is parallel with the most char segments
|
||||||
if (charRegions.size() <= 1)
|
if (charRegions.size() <= 1)
|
||||||
{
|
{
|
||||||
@@ -499,7 +452,6 @@ vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point>
|
|||||||
//Mat tempImg;
|
//Mat tempImg;
|
||||||
//result.copyTo(tempImg);
|
//result.copyTo(tempImg);
|
||||||
|
|
||||||
|
|
||||||
Rect* leftRect;
|
Rect* leftRect;
|
||||||
Rect* rightRect;
|
Rect* rightRect;
|
||||||
if (charRegions[i].x < charRegions[k].x)
|
if (charRegions[i].x < charRegions[k].x)
|
||||||
@@ -534,7 +486,6 @@ vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point>
|
|||||||
//cv::line(tempImg, Point(x1, y1), Point(x2, y2), Scalar(0, 0, 255));
|
//cv::line(tempImg, Point(x1, y1), Point(x2, y2), Scalar(0, 0, 255));
|
||||||
topLines.push_back(LineSegment(x1, y1, x2, y2));
|
topLines.push_back(LineSegment(x1, y1, x2, y2));
|
||||||
|
|
||||||
|
|
||||||
if (leftRect->y > rightRect->y) // Rising line, use the bottom right corner of the rect
|
if (leftRect->y > rightRect->y) // Rising line, use the bottom right corner of the rect
|
||||||
{
|
{
|
||||||
x1 = leftRect->x + leftRect->width;
|
x1 = leftRect->x + leftRect->width;
|
||||||
@@ -565,7 +516,6 @@ vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point>
|
|||||||
float SCORING_MIN_THRESHOLD = 0.97;
|
float SCORING_MIN_THRESHOLD = 0.97;
|
||||||
float SCORING_MAX_THRESHOLD = 1.03;
|
float SCORING_MAX_THRESHOLD = 1.03;
|
||||||
|
|
||||||
|
|
||||||
int curScore = 0;
|
int curScore = 0;
|
||||||
for (int charidx = 0; charidx < charRegions.size(); charidx++)
|
for (int charidx = 0; charidx < charRegions.size(); charidx++)
|
||||||
{
|
{
|
||||||
@@ -588,7 +538,6 @@ vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tie goes to the one with longer line segments
|
// Tie goes to the one with longer line segments
|
||||||
if ((curScore > bestScore) ||
|
if ((curScore > bestScore) ||
|
||||||
(curScore == bestScore && topLines[i].length > bestScoreDistance))
|
(curScore == bestScore && topLines[i].length > bestScoreDistance))
|
||||||
@@ -600,7 +549,6 @@ vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
{
|
{
|
||||||
cout << "The winning score is: " << bestScore << endl;
|
cout << "The winning score is: " << bestScore << endl;
|
||||||
@@ -621,21 +569,16 @@ vector<Point> CharacterAnalysis::getBestVotedLines(Mat img, vector<vector<Point>
|
|||||||
Point bottomRight = Point(img.cols, bottomLines[bestScoreIndex].getPointAt(img.cols));
|
Point bottomRight = Point(img.cols, bottomLines[bestScoreIndex].getPointAt(img.cols));
|
||||||
Point bottomLeft = Point(0, bottomLines[bestScoreIndex].getPointAt(0));
|
Point bottomLeft = Point(0, bottomLines[bestScoreIndex].getPointAt(0));
|
||||||
|
|
||||||
|
|
||||||
bestStripe.push_back(topLeft);
|
bestStripe.push_back(topLeft);
|
||||||
bestStripe.push_back(topRight);
|
bestStripe.push_back(topRight);
|
||||||
bestStripe.push_back(bottomRight);
|
bestStripe.push_back(bottomRight);
|
||||||
bestStripe.push_back(bottomLeft);
|
bestStripe.push_back(bottomLeft);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return bestStripe;
|
return bestStripe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vector<bool> CharacterAnalysis::filter(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy)
|
vector<bool> CharacterAnalysis::filter(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy)
|
||||||
{
|
{
|
||||||
static int STARTING_MIN_HEIGHT = round (((float) img.rows) * config->charAnalysisMinPercent);
|
static int STARTING_MIN_HEIGHT = round (((float) img.rows) * config->charAnalysisMinPercent);
|
||||||
@@ -643,7 +586,6 @@ vector<bool> CharacterAnalysis::filter(Mat img, vector<vector<Point> > contours,
|
|||||||
static int HEIGHT_STEP = round (((float) img.rows) * config->charAnalysisHeightStepSize);
|
static int HEIGHT_STEP = round (((float) img.rows) * config->charAnalysisHeightStepSize);
|
||||||
static int NUM_STEPS = config->charAnalysisNumSteps;
|
static int NUM_STEPS = config->charAnalysisNumSteps;
|
||||||
|
|
||||||
|
|
||||||
vector<bool> charSegments;
|
vector<bool> charSegments;
|
||||||
int bestFitScore = -1;
|
int bestFitScore = -1;
|
||||||
for (int i = 0; i < NUM_STEPS; i++)
|
for (int i = 0; i < NUM_STEPS; i++)
|
||||||
@@ -655,7 +597,6 @@ vector<bool> CharacterAnalysis::filter(Mat img, vector<vector<Point> > contours,
|
|||||||
|
|
||||||
goodIndices = this->filterByBoxSize(contours, goodIndices, STARTING_MIN_HEIGHT + (i * HEIGHT_STEP), STARTING_MAX_HEIGHT + (i * HEIGHT_STEP));
|
goodIndices = this->filterByBoxSize(contours, goodIndices, STARTING_MIN_HEIGHT + (i * HEIGHT_STEP), STARTING_MAX_HEIGHT + (i * HEIGHT_STEP));
|
||||||
|
|
||||||
|
|
||||||
goodIndicesCount = getGoodIndicesCount(goodIndices);
|
goodIndicesCount = getGoodIndicesCount(goodIndices);
|
||||||
if ( goodIndicesCount > 0 && goodIndicesCount <= bestFitScore) // Don't bother doing more filtering if we already lost...
|
if ( goodIndicesCount > 0 && goodIndicesCount <= bestFitScore) // Don't bother doing more filtering if we already lost...
|
||||||
continue;
|
continue;
|
||||||
@@ -668,7 +609,6 @@ vector<bool> CharacterAnalysis::filter(Mat img, vector<vector<Point> > contours,
|
|||||||
vector<Point> lines = getBestVotedLines(img, contours, goodIndices);
|
vector<Point> lines = getBestVotedLines(img, contours, goodIndices);
|
||||||
goodIndices = this->filterBetweenLines(img, contours, hierarchy, lines, goodIndices);
|
goodIndices = this->filterBetweenLines(img, contours, hierarchy, lines, goodIndices);
|
||||||
|
|
||||||
|
|
||||||
int segmentCount = getGoodIndicesCount(goodIndices);
|
int segmentCount = getGoodIndicesCount(goodIndices);
|
||||||
|
|
||||||
if (segmentCount > bestFitScore)
|
if (segmentCount > bestFitScore)
|
||||||
@@ -678,11 +618,9 @@ vector<bool> CharacterAnalysis::filter(Mat img, vector<vector<Point> > contours,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return charSegments;
|
return charSegments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Goes through the contours for the plate and picks out possible char segments based on min/max height
|
// Goes through the contours for the plate and picks out possible char segments based on min/max height
|
||||||
vector<bool> CharacterAnalysis::filterByBoxSize(vector< vector< Point> > contours, vector<bool> goodIndices, int minHeightPx, int maxHeightPx)
|
vector<bool> CharacterAnalysis::filterByBoxSize(vector< vector< Point> > contours, vector<bool> goodIndices, int minHeightPx, int maxHeightPx)
|
||||||
{
|
{
|
||||||
@@ -690,7 +628,6 @@ vector<bool> CharacterAnalysis::filterByBoxSize(vector< vector< Point> > contour
|
|||||||
float idealAspect=config->charWidthMM / config->charHeightMM;
|
float idealAspect=config->charWidthMM / config->charHeightMM;
|
||||||
float aspecttolerance=0.25;
|
float aspecttolerance=0.25;
|
||||||
|
|
||||||
|
|
||||||
vector<bool> includedIndices(contours.size());
|
vector<bool> includedIndices(contours.size());
|
||||||
for (int j = 0; j < contours.size(); j++)
|
for (int j = 0; j < contours.size(); j++)
|
||||||
includedIndices.push_back(false);
|
includedIndices.push_back(false);
|
||||||
@@ -706,7 +643,8 @@ vector<bool> CharacterAnalysis::filterByBoxSize(vector< vector< Point> > contour
|
|||||||
float minWidth = mr.height * 0.2;
|
float minWidth = mr.height * 0.2;
|
||||||
//Crop image
|
//Crop image
|
||||||
//Mat auxRoi(img, mr);
|
//Mat auxRoi(img, mr);
|
||||||
if(mr.height >= minHeightPx && mr.height <= maxHeightPx && mr.width > minWidth){
|
if(mr.height >= minHeightPx && mr.height <= maxHeightPx && mr.width > minWidth)
|
||||||
|
{
|
||||||
|
|
||||||
float charAspect= (float)mr.width/(float)mr.height;
|
float charAspect= (float)mr.width/(float)mr.height;
|
||||||
|
|
||||||
@@ -719,8 +657,6 @@ vector<bool> CharacterAnalysis::filterByBoxSize(vector< vector< Point> > contour
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vector< bool > CharacterAnalysis::filterContourHoles(vector< vector< Point > > contours, vector< Vec4i > hierarchy, vector< bool > goodIndices)
|
vector< bool > CharacterAnalysis::filterContourHoles(vector< vector< Point > > contours, vector< Vec4i > hierarchy, vector< bool > goodIndices)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -752,7 +688,6 @@ vector< bool > CharacterAnalysis::filterContourHoles(vector< vector< Point > > c
|
|||||||
return includedIndices;
|
return includedIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Goes through the contours for the plate and picks out possible char segments based on min/max height
|
// Goes through the contours for the plate and picks out possible char segments based on min/max height
|
||||||
// returns a vector of indices corresponding to valid contours
|
// returns a vector of indices corresponding to valid contours
|
||||||
vector<bool> CharacterAnalysis::filterByParentContour( vector< vector< Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices)
|
vector<bool> CharacterAnalysis::filterByParentContour( vector< vector< Point> > contours, vector<Vec4i> hierarchy, vector<bool> goodIndices)
|
||||||
@@ -826,7 +761,6 @@ vector<bool> CharacterAnalysis::filterByParentContour( vector< vector< Point> >
|
|||||||
return includedIndices;
|
return includedIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vector<bool> CharacterAnalysis::filterBetweenLines(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<Point> outerPolygon, vector<bool> goodIndices)
|
vector<bool> CharacterAnalysis::filterBetweenLines(Mat img, vector<vector<Point> > contours, vector<Vec4i> hierarchy, vector<Point> outerPolygon, vector<bool> goodIndices)
|
||||||
{
|
{
|
||||||
static float MIN_AREA_PERCENT_WITHIN_LINES = 0.88;
|
static float MIN_AREA_PERCENT_WITHIN_LINES = 0.88;
|
||||||
@@ -835,7 +769,6 @@ vector<bool> CharacterAnalysis::filterBetweenLines(Mat img, vector<vector<Point>
|
|||||||
for (int j = 0; j < contours.size(); j++)
|
for (int j = 0; j < contours.size(); j++)
|
||||||
includedIndices[j] = false;
|
includedIndices[j] = false;
|
||||||
|
|
||||||
|
|
||||||
if (outerPolygon.size() == 0)
|
if (outerPolygon.size() == 0)
|
||||||
return includedIndices;
|
return includedIndices;
|
||||||
|
|
||||||
@@ -855,7 +788,6 @@ vector<bool> CharacterAnalysis::filterBetweenLines(Mat img, vector<vector<Point>
|
|||||||
Mat innerArea = Mat::zeros(img.size(), CV_8U);
|
Mat innerArea = Mat::zeros(img.size(), CV_8U);
|
||||||
fillConvexPoly(outerMask, outerPolygon.data(), outerPolygon.size(), Scalar(255,255,255));
|
fillConvexPoly(outerMask, outerPolygon.data(), outerPolygon.size(), Scalar(255,255,255));
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < contours.size(); i++)
|
for (int i = 0; i < contours.size(); i++)
|
||||||
{
|
{
|
||||||
if (goodIndices[i] == false)
|
if (goodIndices[i] == false)
|
||||||
@@ -871,10 +803,8 @@ vector<bool> CharacterAnalysis::filterBetweenLines(Mat img, vector<vector<Point>
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
bitwise_and(innerArea, outerMask, innerArea);
|
bitwise_and(innerArea, outerMask, innerArea);
|
||||||
|
|
||||||
|
|
||||||
vector<vector<Point> > tempContours;
|
vector<vector<Point> > tempContours;
|
||||||
findContours(innerArea, tempContours,
|
findContours(innerArea, tempContours,
|
||||||
CV_RETR_EXTERNAL, // retrieve the external contours
|
CV_RETR_EXTERNAL, // retrieve the external contours
|
||||||
@@ -889,7 +819,6 @@ vector<bool> CharacterAnalysis::filterBetweenLines(Mat img, vector<vector<Point>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (areaBetweenLines / totalArea >= MIN_AREA_PERCENT_WITHIN_LINES)
|
if (areaBetweenLines / totalArea >= MIN_AREA_PERCENT_WITHIN_LINES)
|
||||||
{
|
{
|
||||||
includedIndices[i] = true;
|
includedIndices[i] = true;
|
||||||
@@ -909,7 +838,6 @@ std::vector< bool > CharacterAnalysis::filterByOuterMask(vector< vector< Point >
|
|||||||
if (hasPlateMask == false)
|
if (hasPlateMask == false)
|
||||||
return goodIndices;
|
return goodIndices;
|
||||||
|
|
||||||
|
|
||||||
vector<bool> passingIndices;
|
vector<bool> passingIndices;
|
||||||
for (int i = 0; i < goodIndices.size(); i++)
|
for (int i = 0; i < goodIndices.size(); i++)
|
||||||
passingIndices.push_back(false);
|
passingIndices.push_back(false);
|
||||||
@@ -952,8 +880,6 @@ std::vector< bool > CharacterAnalysis::filterByOuterMask(vector< vector< Point >
|
|||||||
return passingIndices;
|
return passingIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool CharacterAnalysis::isPlateInverted()
|
bool CharacterAnalysis::isPlateInverted()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -964,14 +890,12 @@ bool CharacterAnalysis::isPlateInverted()
|
|||||||
if (this->config->debugCharAnalysis)
|
if (this->config->debugCharAnalysis)
|
||||||
cout << "CharacterAnalysis, plate inverted: MEAN: " << meanVal << " : " << bestThreshold.type() << endl;
|
cout << "CharacterAnalysis, plate inverted: MEAN: " << meanVal << " : " << bestThreshold.type() << endl;
|
||||||
|
|
||||||
|
|
||||||
if (meanVal[0] < 100) // Half would be 122.5. Give it a little extra oomf before saying it needs inversion. Most states aren't inverted.
|
if (meanVal[0] < 100) // Half would be 122.5. Give it a little extra oomf before saying it needs inversion. Most states aren't inverted.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CharacterAnalysis::verifySize(Mat r, float minHeightPx, float maxHeightPx)
|
bool CharacterAnalysis::verifySize(Mat r, float minHeightPx, float maxHeightPx)
|
||||||
{
|
{
|
||||||
//Char sizes 45x90
|
//Char sizes 45x90
|
||||||
@@ -999,7 +923,6 @@ bool CharacterAnalysis::verifySize(Mat r, float minHeightPx, float maxHeightPx)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vector<Point> CharacterAnalysis::getCharArea()
|
vector<Point> CharacterAnalysis::getCharArea()
|
||||||
{
|
{
|
||||||
const int MAX = 100000;
|
const int MAX = 100000;
|
||||||
|
@@ -28,19 +28,15 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
|||||||
|
|
||||||
this->confidence = 0;
|
this->confidence = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (this->debug)
|
if (this->debug)
|
||||||
cout << "Starting CharacterRegion identification" << endl;
|
cout << "Starting CharacterRegion identification" << endl;
|
||||||
|
|
||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
charAnalysis = new CharacterAnalysis(img, config);
|
charAnalysis = new CharacterAnalysis(img, config);
|
||||||
charAnalysis->analyze();
|
charAnalysis->analyze();
|
||||||
|
|
||||||
|
|
||||||
if (this->debug)
|
if (this->debug)
|
||||||
{
|
{
|
||||||
vector<Mat> tempDash;
|
vector<Mat> tempDash;
|
||||||
@@ -53,7 +49,6 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
|||||||
tempDash.push_back(tmp);
|
tempDash.push_back(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mat bestVal(charAnalysis->bestThreshold.size(), charAnalysis->bestThreshold.type());
|
Mat bestVal(charAnalysis->bestThreshold.size(), charAnalysis->bestThreshold.type());
|
||||||
charAnalysis->bestThreshold.copyTo(bestVal);
|
charAnalysis->bestThreshold.copyTo(bestVal);
|
||||||
cvtColor(bestVal, bestVal, CV_GRAY2BGR);
|
cvtColor(bestVal, bestVal, CV_GRAY2BGR);
|
||||||
@@ -69,8 +64,6 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
|||||||
displayImage(config, "Character Region Step 1 Thresholds", drawImageDashboard(tempDash, bestVal.type(), 3));
|
displayImage(config, "Character Region Step 1 Thresholds", drawImageDashboard(tempDash, bestVal.type(), 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (this->debug)
|
if (this->debug)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -95,15 +88,12 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
|||||||
cv::Scalar(0,255,0), // in green
|
cv::Scalar(0,255,0), // in green
|
||||||
1); // with a thickness of 1
|
1); // with a thickness of 1
|
||||||
|
|
||||||
|
|
||||||
displayImage(config, "Matching Contours", img_contours);
|
displayImage(config, "Matching Contours", img_contours);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP));
|
//charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP));
|
||||||
|
|
||||||
|
|
||||||
if (charAnalysis->linePolygon.size() > 0)
|
if (charAnalysis->linePolygon.size() > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -120,7 +110,6 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
|||||||
else if (absangle > 1)
|
else if (absangle > 1)
|
||||||
confidenceDrainers += (10 - absangle) * 5;
|
confidenceDrainers += (10 - absangle) * 5;
|
||||||
|
|
||||||
|
|
||||||
if (confidenceDrainers >= 100)
|
if (confidenceDrainers >= 100)
|
||||||
this->confidence=1;
|
this->confidence=1;
|
||||||
else
|
else
|
||||||
@@ -128,8 +117,6 @@ CharacterRegion::CharacterRegion(Mat img, Config* config)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -144,8 +131,6 @@ CharacterRegion::~CharacterRegion()
|
|||||||
delete(charAnalysis);
|
delete(charAnalysis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mat CharacterRegion::getPlateMask()
|
Mat CharacterRegion::getPlateMask()
|
||||||
{
|
{
|
||||||
return charAnalysis->plateMask;
|
return charAnalysis->plateMask;
|
||||||
|
@@ -34,7 +34,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
Mat img_gray(img.size(), CV_8U);
|
Mat img_gray(img.size(), CV_8U);
|
||||||
cvtColor( img, img_gray, CV_BGR2GRAY );
|
cvtColor( img, img_gray, CV_BGR2GRAY );
|
||||||
|
|
||||||
@@ -43,22 +42,14 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
if (invertedColors)
|
if (invertedColors)
|
||||||
bitwise_not(img_gray, img_gray);
|
bitwise_not(img_gray, img_gray);
|
||||||
|
|
||||||
|
|
||||||
charAnalysis = new CharacterAnalysis(img_gray, config);
|
charAnalysis = new CharacterAnalysis(img_gray, config);
|
||||||
charAnalysis->analyze();
|
charAnalysis->analyze();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
{
|
{
|
||||||
displayImage(config, "CharacterSegmenter Thresholds", drawImageDashboard(charAnalysis->thresholds, CV_8U, 3));
|
displayImage(config, "CharacterSegmenter Thresholds", drawImageDashboard(charAnalysis->thresholds, CV_8U, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -93,8 +84,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
imgDbgGeneral.push_back(bordered);
|
imgDbgGeneral.push_back(bordered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (charAnalysis->linePolygon.size() > 0)
|
if (charAnalysis->linePolygon.size() > 0)
|
||||||
{
|
{
|
||||||
this->top = LineSegment(charAnalysis->linePolygon[0].x, charAnalysis->linePolygon[0].y, charAnalysis->linePolygon[1].x, charAnalysis->linePolygon[1].y);
|
this->top = LineSegment(charAnalysis->linePolygon[0].x, charAnalysis->linePolygon[0].y, charAnalysis->linePolygon[1].x, charAnalysis->linePolygon[1].y);
|
||||||
@@ -108,7 +97,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
if (charAnalysis->bestCharSegments[i] == false)
|
if (charAnalysis->bestCharSegments[i] == false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
Rect mr = boundingRect(charAnalysis->bestContours[i]);
|
Rect mr = boundingRect(charAnalysis->bestContours[i]);
|
||||||
|
|
||||||
charWidths.push_back(mr.width);
|
charWidths.push_back(mr.width);
|
||||||
@@ -122,26 +110,21 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
|
|
||||||
// Do the histogram analysis to figure out char regions
|
// Do the histogram analysis to figure out char regions
|
||||||
|
|
||||||
|
|
||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
vector<Mat> allHistograms;
|
vector<Mat> allHistograms;
|
||||||
|
|
||||||
vector<Rect> allBoxes;
|
vector<Rect> allBoxes;
|
||||||
for (int i = 0; i < charAnalysis->allContours.size(); i++)
|
for (int i = 0; i < charAnalysis->allContours.size(); i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
Mat histogramMask = Mat::zeros(charAnalysis->thresholds[i].size(), CV_8U);
|
Mat histogramMask = Mat::zeros(charAnalysis->thresholds[i].size(), CV_8U);
|
||||||
|
|
||||||
fillConvexPoly(histogramMask, charAnalysis->linePolygon.data(), charAnalysis->linePolygon.size(), Scalar(255,255,255));
|
fillConvexPoly(histogramMask, charAnalysis->linePolygon.data(), charAnalysis->linePolygon.size(), Scalar(255,255,255));
|
||||||
|
|
||||||
|
|
||||||
VerticalHistogram vertHistogram(charAnalysis->thresholds[i], histogramMask);
|
VerticalHistogram vertHistogram(charAnalysis->thresholds[i], histogramMask);
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
{
|
{
|
||||||
Mat histoCopy(vertHistogram.histoImg.size(), vertHistogram.histoImg.type());
|
Mat histoCopy(vertHistogram.histoImg.size(), vertHistogram.histoImg.type());
|
||||||
@@ -154,7 +137,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
float score = 0;
|
float score = 0;
|
||||||
vector<Rect> charBoxes = getHistogramBoxes(vertHistogram, avgCharWidth, avgCharHeight, &score);
|
vector<Rect> charBoxes = getHistogramBoxes(vertHistogram, avgCharWidth, avgCharHeight, &score);
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
{
|
{
|
||||||
for (int cboxIdx = 0; cboxIdx < charBoxes.size(); cboxIdx++)
|
for (int cboxIdx = 0; cboxIdx < charBoxes.size(); cboxIdx++)
|
||||||
@@ -171,7 +153,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
//drawAndWait(&histogramMask);
|
//drawAndWait(&histogramMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float medianCharWidth = avgCharWidth;
|
float medianCharWidth = avgCharWidth;
|
||||||
vector<int> widthValues;
|
vector<int> widthValues;
|
||||||
// Compute largest char width
|
// Compute largest char width
|
||||||
@@ -182,7 +163,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
|
|
||||||
medianCharWidth = median(widthValues.data(), widthValues.size());
|
medianCharWidth = median(widthValues.data(), widthValues.size());
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -193,7 +173,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
//ColorFilter colorFilter(img, charAnalysis->getCharacterMask());
|
//ColorFilter colorFilter(img, charAnalysis->getCharacterMask());
|
||||||
vector<Rect> candidateBoxes = getBestCharBoxes(charAnalysis->thresholds[0], allBoxes, medianCharWidth);
|
vector<Rect> candidateBoxes = getBestCharBoxes(charAnalysis->thresholds[0], allBoxes, medianCharWidth);
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
{
|
{
|
||||||
// Setup the dashboard images to show the cleaning filters
|
// Setup the dashboard images to show the cleaning filters
|
||||||
@@ -211,7 +190,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
filterEdgeBoxes(charAnalysis->thresholds, candidateBoxes, medianCharWidth, avgCharHeight);
|
filterEdgeBoxes(charAnalysis->thresholds, candidateBoxes, medianCharWidth, avgCharHeight);
|
||||||
@@ -238,7 +216,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
Mat imgDash = drawImageDashboard(charAnalysis->thresholds, CV_8U, 3);
|
Mat imgDash = drawImageDashboard(charAnalysis->thresholds, CV_8U, 3);
|
||||||
displayImage(config, "Segmentation after cleaning", imgDash);
|
displayImage(config, "Segmentation after cleaning", imgDash);
|
||||||
|
|
||||||
@@ -250,11 +227,6 @@ CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -268,11 +240,6 @@ CharacterSegmenter::~CharacterSegmenter()
|
|||||||
delete charAnalysis;
|
delete charAnalysis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Given a histogram and the horizontal line boundaries, respond with an array of boxes where the characters are
|
// Given a histogram and the horizontal line boundaries, respond with an array of boxes where the characters are
|
||||||
// Scores the histogram quality as well based on num chars, char volume, and even separation
|
// Scores the histogram quality as well based on num chars, char volume, and even separation
|
||||||
vector<Rect> CharacterSegmenter::getHistogramBoxes(VerticalHistogram histogram, float avgCharWidth, float avgCharHeight, float* score)
|
vector<Rect> CharacterSegmenter::getHistogramBoxes(VerticalHistogram histogram, float avgCharWidth, float avgCharHeight, float* score)
|
||||||
@@ -328,15 +295,12 @@ vector<Rect> CharacterSegmenter::getHistogramBoxes(VerticalHistogram histogram,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return charBoxes;
|
return charBoxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxes, float avgCharWidth)
|
vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxes, float avgCharWidth)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
float MAX_SEGMENT_WIDTH = avgCharWidth * 1.55;
|
float MAX_SEGMENT_WIDTH = avgCharWidth * 1.55;
|
||||||
|
|
||||||
// This histogram is based on how many char boxes (from ALL of the many thresholded images) are covering each column
|
// This histogram is based on how many char boxes (from ALL of the many thresholded images) are covering each column
|
||||||
@@ -344,7 +308,6 @@ vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxe
|
|||||||
|
|
||||||
Mat histoImg = Mat::zeros(Size(img.cols, img.rows), CV_8U);
|
Mat histoImg = Mat::zeros(Size(img.cols, img.rows), CV_8U);
|
||||||
|
|
||||||
|
|
||||||
int columnCount;
|
int columnCount;
|
||||||
|
|
||||||
for (int col = 0; col < img.cols; col++)
|
for (int col = 0; col < img.cols; col++)
|
||||||
@@ -370,7 +333,6 @@ vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxe
|
|||||||
float bestRowScore = 0;
|
float bestRowScore = 0;
|
||||||
vector<Rect> bestBoxes;
|
vector<Rect> bestBoxes;
|
||||||
|
|
||||||
|
|
||||||
for (int row = 0; row < histoImg.rows; row++)
|
for (int row = 0; row < histoImg.rows; row++)
|
||||||
{
|
{
|
||||||
vector<Rect> validBoxes;
|
vector<Rect> validBoxes;
|
||||||
@@ -427,8 +389,6 @@ vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (rowScore > bestRowScore)
|
if (rowScore > bestRowScore)
|
||||||
{
|
{
|
||||||
bestRowScore = rowScore;
|
bestRowScore = rowScore;
|
||||||
@@ -437,8 +397,6 @@ vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
{
|
{
|
||||||
cvtColor(histoImg, histoImg, CV_GRAY2BGR);
|
cvtColor(histoImg, histoImg, CV_GRAY2BGR);
|
||||||
@@ -455,7 +413,6 @@ vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxe
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return bestBoxes;
|
return bestBoxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,11 +446,9 @@ vector<Rect> CharacterSegmenter::get1DHits(Mat img, int yOffset)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return hits;
|
return hits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CharacterSegmenter::removeSmallContours(vector<Mat> thresholds, vector<vector<vector<Point > > > allContours, float avgCharWidth, float avgCharHeight)
|
void CharacterSegmenter::removeSmallContours(vector<Mat> thresholds, vector<vector<vector<Point > > > allContours, float avgCharWidth, float avgCharHeight)
|
||||||
{
|
{
|
||||||
//const float MIN_CHAR_AREA = 0.02 * avgCharWidth * avgCharHeight; // To clear out the tiny specks
|
//const float MIN_CHAR_AREA = 0.02 * avgCharWidth * avgCharHeight; // To clear out the tiny specks
|
||||||
@@ -559,8 +514,6 @@ vector<Rect> CharacterSegmenter::combineCloseBoxes( vector<Rect> charBoxes, floa
|
|||||||
newCharBoxes.push_back(charBoxes[i]);
|
newCharBoxes.push_back(charBoxes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newCharBoxes;
|
return newCharBoxes;
|
||||||
@@ -575,7 +528,6 @@ void CharacterSegmenter::cleanCharRegions(vector<Mat> thresholds, vector<Rect> c
|
|||||||
|
|
||||||
Mat mask = getCharBoxMask(thresholds[0], charRegions);
|
Mat mask = getCharBoxMask(thresholds[0], charRegions);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < thresholds.size(); i++)
|
for (int i = 0; i < thresholds.size(); i++)
|
||||||
{
|
{
|
||||||
bitwise_and(thresholds[i], mask, thresholds[i]);
|
bitwise_and(thresholds[i], mask, thresholds[i]);
|
||||||
@@ -598,7 +550,6 @@ void CharacterSegmenter::cleanCharRegions(vector<Mat> thresholds, vector<Rect> c
|
|||||||
const float MIN_SPECKLE_HEIGHT = ((float)charRegions[j].height) * MIN_SPECKLE_HEIGHT_PERCENT;
|
const float MIN_SPECKLE_HEIGHT = ((float)charRegions[j].height) * MIN_SPECKLE_HEIGHT_PERCENT;
|
||||||
const float MIN_CONTOUR_AREA = ((float)charRegions[j].area()) * MIN_CONTOUR_AREA_PERCENT;
|
const float MIN_CONTOUR_AREA = ((float)charRegions[j].area()) * MIN_CONTOUR_AREA_PERCENT;
|
||||||
|
|
||||||
|
|
||||||
int tallestContourHeight = 0;
|
int tallestContourHeight = 0;
|
||||||
float totalArea = 0;
|
float totalArea = 0;
|
||||||
for (int c = 0; c < contours.size(); c++)
|
for (int c = 0; c < contours.size(); c++)
|
||||||
@@ -608,8 +559,6 @@ void CharacterSegmenter::cleanCharRegions(vector<Mat> thresholds, vector<Rect> c
|
|||||||
if (charRegions[j].contains(contours[c][0]) == false)
|
if (charRegions[j].contains(contours[c][0]) == false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Rect r = boundingRect(contours[c]);
|
Rect r = boundingRect(contours[c]);
|
||||||
|
|
||||||
if (r.height <= MIN_SPECKLE_HEIGHT || r.width <= MIN_SPECKLE_WIDTH_PX)
|
if (r.height <= MIN_SPECKLE_HEIGHT || r.width <= MIN_SPECKLE_WIDTH_PX)
|
||||||
@@ -629,7 +578,6 @@ void CharacterSegmenter::cleanCharRegions(vector<Mat> thresholds, vector<Rect> c
|
|||||||
|
|
||||||
totalArea += contourArea(contours[c]);
|
totalArea += contourArea(contours[c]);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//else if (r.height > tallestContourHeight)
|
//else if (r.height > tallestContourHeight)
|
||||||
//{
|
//{
|
||||||
@@ -639,8 +587,6 @@ void CharacterSegmenter::cleanCharRegions(vector<Mat> thresholds, vector<Rect> c
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (totalArea < MIN_CONTOUR_AREA)
|
if (totalArea < MIN_CONTOUR_AREA)
|
||||||
{
|
{
|
||||||
// Character is not voluminous enough. Erase it.
|
// Character is not voluminous enough. Erase it.
|
||||||
@@ -652,7 +598,6 @@ void CharacterSegmenter::cleanCharRegions(vector<Mat> thresholds, vector<Rect> c
|
|||||||
rectangle(imgDbgCleanStages[i], boxTop, COLOR_DEBUG_MIN_AREA, -1);
|
rectangle(imgDbgCleanStages[i], boxTop, COLOR_DEBUG_MIN_AREA, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rectangle(thresholds[i], charRegions[j], Scalar(0, 0, 0), -1);
|
rectangle(thresholds[i], charRegions[j], Scalar(0, 0, 0), -1);
|
||||||
}
|
}
|
||||||
else if (tallestContourHeight < ((float) charRegions[j].height * MIN_CONTOUR_HEIGHT_PERCENT))
|
else if (tallestContourHeight < ((float) charRegions[j].height * MIN_CONTOUR_HEIGHT_PERCENT))
|
||||||
@@ -670,7 +615,6 @@ void CharacterSegmenter::cleanCharRegions(vector<Mat> thresholds, vector<Rect> c
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mat closureElement = getStructuringElement( 1,
|
Mat closureElement = getStructuringElement( 1,
|
||||||
Size( 2 + 1, 2+1 ),
|
Size( 2 + 1, 2+1 ),
|
||||||
Point( 1, 1 ) );
|
Point( 1, 1 ) );
|
||||||
@@ -692,7 +636,6 @@ void CharacterSegmenter::cleanCharRegions(vector<Mat> thresholds, vector<Rect> c
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CharacterSegmenter::cleanBasedOnColor(vector<Mat> thresholds, Mat colorMask, vector<Rect> charRegions)
|
void CharacterSegmenter::cleanBasedOnColor(vector<Mat> thresholds, Mat colorMask, vector<Rect> charRegions)
|
||||||
{
|
{
|
||||||
// If I knock out x% of the contour area from this thing (after applying the color filter)
|
// If I knock out x% of the contour area from this thing (after applying the color filter)
|
||||||
@@ -710,8 +653,6 @@ void CharacterSegmenter::cleanBasedOnColor(vector<Mat> thresholds, Mat colorMask
|
|||||||
|
|
||||||
bitwise_and(thresholds[i], boxChar, boxChar);
|
bitwise_and(thresholds[i], boxChar, boxChar);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float meanBefore = mean(boxChar, boxChar)[0];
|
float meanBefore = mean(boxChar, boxChar)[0];
|
||||||
|
|
||||||
Mat thresholdCopy(thresholds[i].size(), CV_8U);
|
Mat thresholdCopy(thresholds[i].size(), CV_8U);
|
||||||
@@ -738,7 +679,6 @@ void CharacterSegmenter::cleanBasedOnColor(vector<Mat> thresholds, Mat colorMask
|
|||||||
// Mat tmpx = drawImageDashboard(tmpDebug, tmpytmp.type(), 1);
|
// Mat tmpx = drawImageDashboard(tmpDebug, tmpytmp.type(), 1);
|
||||||
//drawAndWait( &tmpx );
|
//drawAndWait( &tmpx );
|
||||||
|
|
||||||
|
|
||||||
cout << "Segmentation Filter Clean by Color: Removed Threshold " << i << " charregion " << j << endl;
|
cout << "Segmentation Filter Clean by Color: Removed Threshold " << i << " charregion " << j << endl;
|
||||||
cout << "Segmentation Filter Clean by Color: before=" << meanBefore << " after=" << meanAfter << endl;
|
cout << "Segmentation Filter Clean by Color: before=" << meanBefore << " after=" << meanAfter << endl;
|
||||||
|
|
||||||
@@ -751,7 +691,6 @@ void CharacterSegmenter::cleanBasedOnColor(vector<Mat> thresholds, Mat colorMask
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CharacterSegmenter::cleanMostlyFullBoxes(vector<Mat> thresholds, const vector<Rect> charRegions)
|
void CharacterSegmenter::cleanMostlyFullBoxes(vector<Mat> thresholds, const vector<Rect> charRegions)
|
||||||
{
|
{
|
||||||
float MAX_FILLED = 0.95 * 255;
|
float MAX_FILLED = 0.95 * 255;
|
||||||
@@ -825,7 +764,6 @@ vector<Rect> CharacterSegmenter::filterMostlyEmptyBoxes(vector<Mat> thresholds,
|
|||||||
height = boundingRect(allPointsInBox).height;
|
height = boundingRect(allPointsInBox).height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (height >= ((float) charRegions[j].height * MIN_CONTOUR_HEIGHT_PERCENT))
|
if (height >= ((float) charRegions[j].height * MIN_CONTOUR_HEIGHT_PERCENT))
|
||||||
{
|
{
|
||||||
boxScores[j] = boxScores[j] + 1;
|
boxScores[j] = boxScores[j] + 1;
|
||||||
@@ -835,7 +773,6 @@ vector<Rect> CharacterSegmenter::filterMostlyEmptyBoxes(vector<Mat> thresholds,
|
|||||||
drawX(imgDbgCleanStages[i], charRegions[j], COLOR_DEBUG_EMPTYFILTER, 3);
|
drawX(imgDbgCleanStages[i], charRegions[j], COLOR_DEBUG_EMPTYFILTER, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -902,7 +839,6 @@ void CharacterSegmenter::filterEdgeBoxes(vector<Mat> thresholds, const vector<Re
|
|||||||
//while (charBoxes.size() > 0 && charBoxes[0].width < MIN_SEGMENT_WIDTH_EDGES)
|
//while (charBoxes.size() > 0 && charBoxes[0].width < MIN_SEGMENT_WIDTH_EDGES)
|
||||||
// charBoxes.erase(charBoxes.begin() + 0);
|
// charBoxes.erase(charBoxes.begin() + 0);
|
||||||
|
|
||||||
|
|
||||||
// TECHNIQUE #1
|
// TECHNIQUE #1
|
||||||
// Check for long vertical lines. Once the line is too long, mask the whole region
|
// Check for long vertical lines. Once the line is too long, mask the whole region
|
||||||
|
|
||||||
@@ -969,7 +905,6 @@ void CharacterSegmenter::filterEdgeBoxes(vector<Mat> thresholds, const vector<Re
|
|||||||
col++;
|
col++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (leftEdgeX != 0)
|
if (leftEdgeX != 0)
|
||||||
leftEdges.push_back(leftEdgeX);
|
leftEdges.push_back(leftEdgeX);
|
||||||
if (rightEdgeX != thresholds[i].cols)
|
if (rightEdgeX != thresholds[i].cols)
|
||||||
@@ -1007,7 +942,6 @@ void CharacterSegmenter::filterEdgeBoxes(vector<Mat> thresholds, const vector<Re
|
|||||||
warpAffine( mask, mask, rot_mat, mask.size() );
|
warpAffine( mask, mask, rot_mat, mask.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// If our edge mask covers more than x% of the char region, mask the whole thing...
|
// If our edge mask covers more than x% of the char region, mask the whole thing...
|
||||||
const float MAX_COVERAGE_PERCENT = 0.6;
|
const float MAX_COVERAGE_PERCENT = 0.6;
|
||||||
int leftCoveragePx = leftEdge - charRegions[0].x;
|
int leftCoveragePx = leftEdge - charRegions[0].x;
|
||||||
@@ -1034,7 +968,6 @@ void CharacterSegmenter::filterEdgeBoxes(vector<Mat> thresholds, const vector<Re
|
|||||||
bitwise_and(thresholds[i], mask, thresholds[i]);
|
bitwise_and(thresholds[i], mask, thresholds[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugCharSegmenter)
|
if (this->config->debugCharSegmenter)
|
||||||
{
|
{
|
||||||
cout << "Edge Filter: left=" << leftEdge << " right=" << rightEdge << endl;
|
cout << "Edge Filter: left=" << leftEdge << " right=" << rightEdge << endl;
|
||||||
@@ -1163,7 +1096,6 @@ int CharacterSegmenter::getLongestBlobLengthBetweenLines(Mat img, int col)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return longestBlobLength;
|
return longestBlobLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1183,7 +1115,6 @@ int CharacterSegmenter::isSkinnyLineInsideBox(Mat threshold, Rect box, vector<ve
|
|||||||
Mat boxMask = Mat::zeros(threshold.size(), CV_8U);
|
Mat boxMask = Mat::zeros(threshold.size(), CV_8U);
|
||||||
rectangle(boxMask, slightlySmallerBox, Scalar(255, 255, 255), -1);
|
rectangle(boxMask, slightlySmallerBox, Scalar(255, 255, 255), -1);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < contours.size(); i++)
|
for (int i = 0; i < contours.size(); i++)
|
||||||
{
|
{
|
||||||
// Only bother with the big boxes
|
// Only bother with the big boxes
|
||||||
@@ -1215,7 +1146,6 @@ int CharacterSegmenter::isSkinnyLineInsideBox(Mat threshold, Rect box, vector<ve
|
|||||||
if (tallestContourIdx != -1)
|
if (tallestContourIdx != -1)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//cout << "Edge Filter: " << tallestContourHeight << " -- " << avgCharHeight << endl;
|
//cout << "Edge Filter: " << tallestContourHeight << " -- " << avgCharHeight << endl;
|
||||||
if (tallestContourHeight >= avgCharHeight * 0.9 &&
|
if (tallestContourHeight >= avgCharHeight * 0.9 &&
|
||||||
((tallestContourWidth < config->segmentationMinBoxWidthPx) || (tallestContourArea < avgCharWidth * avgCharHeight * 0.1)))
|
((tallestContourWidth < config->segmentationMinBoxWidthPx) || (tallestContourArea < avgCharWidth * avgCharHeight * 0.1)))
|
||||||
@@ -1230,8 +1160,6 @@ int CharacterSegmenter::isSkinnyLineInsideBox(Mat threshold, Rect box, vector<ve
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mat CharacterSegmenter::getCharBoxMask(Mat img_threshold, vector<Rect> charBoxes)
|
Mat CharacterSegmenter::getCharBoxMask(Mat img_threshold, vector<Rect> charBoxes)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@@ -24,8 +24,7 @@
|
|||||||
#define cJSON__h
|
#define cJSON__h
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* cJSON Types: */
|
/* cJSON Types: */
|
||||||
@@ -40,7 +39,8 @@ extern "C"
|
|||||||
#define cJSON_IsReference 256
|
#define cJSON_IsReference 256
|
||||||
|
|
||||||
/* The cJSON structure: */
|
/* The cJSON structure: */
|
||||||
typedef struct cJSON {
|
typedef struct cJSON
|
||||||
|
{
|
||||||
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||||
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||||
|
|
||||||
@@ -53,7 +53,8 @@ typedef struct cJSON {
|
|||||||
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||||
} cJSON;
|
} cJSON;
|
||||||
|
|
||||||
typedef struct cJSON_Hooks {
|
typedef struct cJSON_Hooks
|
||||||
|
{
|
||||||
void *(*malloc_fn)(size_t sz);
|
void *(*malloc_fn)(size_t sz);
|
||||||
void (*free_fn)(void *ptr);
|
void (*free_fn)(void *ptr);
|
||||||
} cJSON_Hooks;
|
} cJSON_Hooks;
|
||||||
|
@@ -17,11 +17,8 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "colorfilter.h"
|
#include "colorfilter.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ColorFilter::ColorFilter(Mat image, Mat characterMask, Config* config)
|
ColorFilter::ColorFilter(Mat image, Mat characterMask, Config* config)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -32,7 +29,6 @@ ColorFilter::ColorFilter(Mat image, Mat characterMask, Config* config)
|
|||||||
|
|
||||||
this->debug = config->debugColorFiler;
|
this->debug = config->debugColorFiler;
|
||||||
|
|
||||||
|
|
||||||
this->grayscale = imageIsGrayscale(image);
|
this->grayscale = imageIsGrayscale(image);
|
||||||
|
|
||||||
if (this->debug)
|
if (this->debug)
|
||||||
@@ -48,7 +44,6 @@ ColorFilter::ColorFilter(Mat image, Mat characterMask, Config* config)
|
|||||||
|
|
||||||
findCharColors();
|
findCharColors();
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -120,8 +115,6 @@ void ColorFilter::findCharColors()
|
|||||||
vector<Vec4i> hierarchy;
|
vector<Vec4i> hierarchy;
|
||||||
findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
|
findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vector<float> hMeans, sMeans, vMeans;
|
vector<float> hMeans, sMeans, vMeans;
|
||||||
vector<float> hStdDevs, sStdDevs, vStdDevs;
|
vector<float> hStdDevs, sStdDevs, vStdDevs;
|
||||||
|
|
||||||
@@ -149,9 +142,6 @@ void ColorFilter::findCharColors()
|
|||||||
hierarchy
|
hierarchy
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//drawAndWait(&singleCharMask);
|
//drawAndWait(&singleCharMask);
|
||||||
|
|
||||||
Scalar mean;
|
Scalar mean;
|
||||||
@@ -174,7 +164,6 @@ void ColorFilter::findCharColors()
|
|||||||
sStdDevs.push_back(stddev[1]);
|
sStdDevs.push_back(stddev[1]);
|
||||||
vStdDevs.push_back(stddev[2]);
|
vStdDevs.push_back(stddev[2]);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hMeans.size() == 0)
|
if (hMeans.size() == 0)
|
||||||
@@ -184,11 +173,9 @@ void ColorFilter::findCharColors()
|
|||||||
int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35);
|
int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35);
|
||||||
int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30);
|
int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30);
|
||||||
|
|
||||||
|
|
||||||
if (sMeans[bestSatIndex] < MINIMUM_SATURATION)
|
if (sMeans[bestSatIndex] < MINIMUM_SATURATION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
bool doHueFilter = false, doSatFilter = false, doValFilter = false;
|
bool doHueFilter = false, doSatFilter = false, doValFilter = false;
|
||||||
float hueMin, hueMax;
|
float hueMin, hueMax;
|
||||||
float satMin, satMax;
|
float satMin, satMax;
|
||||||
@@ -259,8 +246,6 @@ void ColorFilter::findCharColors()
|
|||||||
cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax << endl;
|
cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type());
|
Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type());
|
||||||
Mat imgDebug = Mat::zeros(hsv.size(), hsv.type());
|
Mat imgDebug = Mat::zeros(hsv.size(), hsv.type());
|
||||||
Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U);
|
Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U);
|
||||||
@@ -318,7 +303,6 @@ void ColorFilter::findCharColors()
|
|||||||
else
|
else
|
||||||
this->colorMask.at<uchar>(row, col) = 0;
|
this->colorMask.at<uchar>(row, col) = 0;
|
||||||
|
|
||||||
|
|
||||||
if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses))
|
if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses))
|
||||||
{
|
{
|
||||||
vDistance = pow(vDistance, 0.9);
|
vDistance = pow(vDistance, 0.9);
|
||||||
@@ -333,8 +317,6 @@ void ColorFilter::findCharColors()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vector<Mat> debugImagesSet;
|
vector<Mat> debugImagesSet;
|
||||||
|
|
||||||
if (this->debug)
|
if (this->debug)
|
||||||
@@ -346,7 +328,6 @@ void ColorFilter::findCharColors()
|
|||||||
debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before"));
|
debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mat bigElement = getStructuringElement( 1,
|
Mat bigElement = getStructuringElement( 1,
|
||||||
Size( 3 + 1, 3+1 ),
|
Size( 3 + 1, 3+1 ),
|
||||||
Point( 1, 1 ) );
|
Point( 1, 1 ) );
|
||||||
@@ -378,15 +359,12 @@ void ColorFilter::findCharColors()
|
|||||||
|
|
||||||
debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off"));
|
debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off"));
|
||||||
|
|
||||||
|
|
||||||
Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3);
|
Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3);
|
||||||
displayImage(config, "Color Filter Images", dashboard);
|
displayImage(config, "Color Filter Images", dashboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Goes through an array of values, picks the winner based on the highest percentage of other values that are within the maxValDifference
|
// Goes through an array of values, picks the winner based on the highest percentage of other values that are within the maxValDifference
|
||||||
// Return -1 if it fails.
|
// Return -1 if it fails.
|
||||||
int ColorFilter::getMajorityOpinion(vector<float> values, float minPercentAgreement, float maxValDifference)
|
int ColorFilter::getMajorityOpinion(vector<float> values, float minPercentAgreement, float maxValDifference)
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
Config::Config(const std::string country, const std::string runtimeBaseDir)
|
Config::Config(const std::string country, const std::string runtimeBaseDir)
|
||||||
{
|
{
|
||||||
this->runtimeBaseDir = runtimeBaseDir;
|
this->runtimeBaseDir = runtimeBaseDir;
|
||||||
@@ -93,12 +92,10 @@ void Config::loadValues(string country)
|
|||||||
ocrImageWidthPx = round(((float) templateWidthPx) * ocrImagePercent);
|
ocrImageWidthPx = round(((float) templateWidthPx) * ocrImagePercent);
|
||||||
ocrImageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
|
ocrImageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
|
||||||
|
|
||||||
|
|
||||||
float stateIdImagePercent = getFloat("common", "state_id_img_size_percent", 100);
|
float stateIdImagePercent = getFloat("common", "state_id_img_size_percent", 100);
|
||||||
stateIdImageWidthPx = round(((float)templateWidthPx) * ocrImagePercent);
|
stateIdImageWidthPx = round(((float)templateWidthPx) * ocrImagePercent);
|
||||||
stateIdimageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
|
stateIdimageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
|
||||||
|
|
||||||
|
|
||||||
charAnalysisMinPercent = getFloat(country, "char_analysis_min_pct", 0);
|
charAnalysisMinPercent = getFloat(country, "char_analysis_min_pct", 0);
|
||||||
charAnalysisHeightRange = getFloat(country, "char_analysis_height_range", 0);
|
charAnalysisHeightRange = getFloat(country, "char_analysis_height_range", 0);
|
||||||
charAnalysisHeightStepSize = getFloat(country, "char_analysis_height_step_size", 0);
|
charAnalysisHeightStepSize = getFloat(country, "char_analysis_height_step_size", 0);
|
||||||
@@ -150,7 +147,6 @@ void Config::debugOff()
|
|||||||
debugPostProcess = false;
|
debugPostProcess = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string Config::getCascadeRuntimeDir()
|
string Config::getCascadeRuntimeDir()
|
||||||
{
|
{
|
||||||
return this->runtimeBaseDir + CASCADE_DIR;
|
return this->runtimeBaseDir + CASCADE_DIR;
|
||||||
@@ -168,9 +164,6 @@ string Config::getTessdataPrefix()
|
|||||||
return "TESSDATA_PREFIX=" + this->runtimeBaseDir + "/ocr/";
|
return "TESSDATA_PREFIX=" + this->runtimeBaseDir + "/ocr/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float Config::getFloat(string section, string key, float defaultValue)
|
float Config::getFloat(string section, string key, float defaultValue)
|
||||||
{
|
{
|
||||||
const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/);
|
const char * pszValue = ini->GetValue(section.c_str(), key.c_str(), NULL /*default*/);
|
||||||
|
@@ -17,15 +17,12 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "featurematcher.h"
|
#include "featurematcher.h"
|
||||||
|
|
||||||
|
|
||||||
//const int DEFAULT_QUERY_FEATURES = 305;
|
//const int DEFAULT_QUERY_FEATURES = 305;
|
||||||
//const int DEFAULT_TRAINING_FEATURES = 305;
|
//const int DEFAULT_TRAINING_FEATURES = 305;
|
||||||
const float MAX_DISTANCE_TO_MATCH = 100.0f;
|
const float MAX_DISTANCE_TO_MATCH = 100.0f;
|
||||||
|
|
||||||
|
|
||||||
FeatureMatcher::FeatureMatcher(Config* config)
|
FeatureMatcher::FeatureMatcher(Config* config)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = config;
|
||||||
@@ -35,7 +32,6 @@ FeatureMatcher::FeatureMatcher(Config* config)
|
|||||||
|
|
||||||
//this->descriptorMatcher = DescriptorMatcher::create( "FlannBased" );
|
//this->descriptorMatcher = DescriptorMatcher::create( "FlannBased" );
|
||||||
|
|
||||||
|
|
||||||
this->detector = new FastFeatureDetector(10, true);
|
this->detector = new FastFeatureDetector(10, true);
|
||||||
this->extractor = new BRISK(10, 1, 0.9);
|
this->extractor = new BRISK(10, 1, 0.9);
|
||||||
}
|
}
|
||||||
@@ -52,7 +48,6 @@ FeatureMatcher::~FeatureMatcher()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FeatureMatcher::isLoaded()
|
bool FeatureMatcher::isLoaded()
|
||||||
{
|
{
|
||||||
if( detector.empty() || extractor.empty() || descriptorMatcher.empty() )
|
if( detector.empty() || extractor.empty() || descriptorMatcher.empty() )
|
||||||
@@ -68,9 +63,6 @@ int FeatureMatcher::numTrainingElements()
|
|||||||
return billMapping.size();
|
return billMapping.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FeatureMatcher::surfStyleMatching( const Mat& queryDescriptors, vector<KeyPoint> queryKeypoints,
|
void FeatureMatcher::surfStyleMatching( const Mat& queryDescriptors, vector<KeyPoint> queryKeypoints,
|
||||||
vector<DMatch>& matches12 )
|
vector<DMatch>& matches12 )
|
||||||
{
|
{
|
||||||
@@ -78,15 +70,12 @@ void FeatureMatcher::surfStyleMatching( const Mat& queryDescriptors, vector<KeyP
|
|||||||
|
|
||||||
this->descriptorMatcher->radiusMatch(queryDescriptors, matchesKnn, MAX_DISTANCE_TO_MATCH);
|
this->descriptorMatcher->radiusMatch(queryDescriptors, matchesKnn, MAX_DISTANCE_TO_MATCH);
|
||||||
|
|
||||||
|
|
||||||
vector<DMatch> tempMatches;
|
vector<DMatch> tempMatches;
|
||||||
_surfStyleMatching(queryDescriptors, matchesKnn, tempMatches);
|
_surfStyleMatching(queryDescriptors, matchesKnn, tempMatches);
|
||||||
|
|
||||||
crisscrossFiltering(queryKeypoints, tempMatches, matches12);
|
crisscrossFiltering(queryKeypoints, tempMatches, matches12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FeatureMatcher::_surfStyleMatching(const Mat& queryDescriptors, vector<vector<DMatch> > matchesKnn, vector<DMatch>& matches12)
|
void FeatureMatcher::_surfStyleMatching(const Mat& queryDescriptors, vector<vector<DMatch> > matchesKnn, vector<DMatch>& matches12)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -138,7 +127,6 @@ void FeatureMatcher::_surfStyleMatching(const Mat& queryDescriptors, vector<vect
|
|||||||
matches12.push_back(matchesKnn[descInd][0]);
|
matches12.push_back(matchesKnn[descInd][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
else if (matchesKnn[descInd].size() == 1)
|
else if (matchesKnn[descInd].size() == 1)
|
||||||
@@ -156,11 +144,8 @@ void FeatureMatcher::_surfStyleMatching(const Mat& queryDescriptors, vector<vect
|
|||||||
//matches12.push_back(match);
|
//matches12.push_back(match);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares the matches keypoints for parallel lines. Removes matches that are criss-crossing too much
|
// Compares the matches keypoints for parallel lines. Removes matches that are criss-crossing too much
|
||||||
@@ -196,8 +181,6 @@ void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints,
|
|||||||
matchIdx.push_back(j);
|
matchIdx.push_back(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Iterate through each line (n^2) removing the one with the most criss-crosses until there are none left.
|
// Iterate through each line (n^2) removing the one with the most criss-crosses until there are none left.
|
||||||
int mostIntersections = 1;
|
int mostIntersections = 1;
|
||||||
while (mostIntersections > 0 && vlines.size() > 0)
|
while (mostIntersections > 0 && vlines.size() > 0)
|
||||||
@@ -251,7 +234,6 @@ void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns true if successful, false otherwise
|
// Returns true if successful, false otherwise
|
||||||
bool FeatureMatcher::loadRecognitionSet(string country)
|
bool FeatureMatcher::loadRecognitionSet(string country)
|
||||||
{
|
{
|
||||||
@@ -259,7 +241,6 @@ bool FeatureMatcher::loadRecognitionSet(string country)
|
|||||||
out << config->getKeypointsRuntimeDir() << "/" << country << "/";
|
out << config->getKeypointsRuntimeDir() << "/" << country << "/";
|
||||||
string country_dir = out.str();
|
string country_dir = out.str();
|
||||||
|
|
||||||
|
|
||||||
if (DirectoryExists(country_dir.c_str()))
|
if (DirectoryExists(country_dir.c_str()))
|
||||||
{
|
{
|
||||||
vector<Mat> trainImages;
|
vector<Mat> trainImages;
|
||||||
@@ -283,7 +264,6 @@ bool FeatureMatcher::loadRecognitionSet(string country)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mat descriptors;
|
Mat descriptors;
|
||||||
|
|
||||||
vector<KeyPoint> keypoints;
|
vector<KeyPoint> keypoints;
|
||||||
@@ -299,7 +279,6 @@ bool FeatureMatcher::loadRecognitionSet(string country)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this->descriptorMatcher->add(trainImages);
|
this->descriptorMatcher->add(trainImages);
|
||||||
this->descriptorMatcher->train();
|
this->descriptorMatcher->train();
|
||||||
|
|
||||||
@@ -310,8 +289,6 @@ bool FeatureMatcher::loadRecognitionSet(string country)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnImage, Mat* outputImage,
|
RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnImage, Mat* outputImage,
|
||||||
bool debug_on, vector<int> debug_matches_array
|
bool debug_on, vector<int> debug_matches_array
|
||||||
)
|
)
|
||||||
@@ -326,8 +303,6 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
|||||||
detector->detect( queryImg, queryKeypoints );
|
detector->detect( queryImg, queryKeypoints );
|
||||||
extractor->compute(queryImg, queryKeypoints, queryDescriptors);
|
extractor->compute(queryImg, queryKeypoints, queryDescriptors);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (queryKeypoints.size() <= 5)
|
if (queryKeypoints.size() <= 5)
|
||||||
{
|
{
|
||||||
// Cut it loose if there's less than 5 keypoints... nothing would ever match anyway and it could crash the matcher.
|
// Cut it loose if there's less than 5 keypoints... nothing would ever match anyway and it could crash the matcher.
|
||||||
@@ -338,17 +313,17 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vector<DMatch> filteredMatches;
|
vector<DMatch> filteredMatches;
|
||||||
|
|
||||||
surfStyleMatching( queryDescriptors, queryKeypoints, filteredMatches );
|
surfStyleMatching( queryDescriptors, queryKeypoints, filteredMatches );
|
||||||
|
|
||||||
|
|
||||||
// Create and initialize the counts to 0
|
// Create and initialize the counts to 0
|
||||||
std::vector<int> bill_match_counts( billMapping.size() );
|
std::vector<int> bill_match_counts( billMapping.size() );
|
||||||
|
|
||||||
for (int i = 0; i < billMapping.size(); i++) { bill_match_counts[i] = 0; }
|
for (int i = 0; i < billMapping.size(); i++)
|
||||||
|
{
|
||||||
|
bill_match_counts[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < filteredMatches.size(); i++)
|
for (int i = 0; i < filteredMatches.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -356,8 +331,6 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
|||||||
//if (filteredMatches[i].imgIdx
|
//if (filteredMatches[i].imgIdx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float max_count = 0; // represented as a percent (0 to 100)
|
float max_count = 0; // represented as a percent (0 to 100)
|
||||||
int secondmost_count = 0;
|
int secondmost_count = 0;
|
||||||
int maxcount_index = -1;
|
int maxcount_index = -1;
|
||||||
@@ -380,7 +353,6 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
|||||||
else if (score > 100)
|
else if (score > 100)
|
||||||
score = 100;
|
score = 100;
|
||||||
|
|
||||||
|
|
||||||
if (score > 0)
|
if (score > 0)
|
||||||
{
|
{
|
||||||
result.haswinner = true;
|
result.haswinner = true;
|
||||||
@@ -427,5 +399,4 @@ RecognitionResult FeatureMatcher::recognize( const Mat& queryImg, bool drawOnIma
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,8 @@ using namespace std;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct RecognitionResult {
|
struct RecognitionResult
|
||||||
|
{
|
||||||
bool haswinner;
|
bool haswinner;
|
||||||
string winner;
|
string winner;
|
||||||
int confidence;
|
int confidence;
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "licenseplatecandidate.h"
|
#include "licenseplatecandidate.h"
|
||||||
|
|
||||||
|
|
||||||
LicensePlateCandidate::LicensePlateCandidate(Mat frame, Rect regionOfInterest, Config* config)
|
LicensePlateCandidate::LicensePlateCandidate(Mat frame, Rect regionOfInterest, Config* config)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = config;
|
||||||
@@ -38,7 +37,6 @@ void LicensePlateCandidate::recognize()
|
|||||||
{
|
{
|
||||||
charSegmenter = NULL;
|
charSegmenter = NULL;
|
||||||
|
|
||||||
|
|
||||||
this->confidence = 0;
|
this->confidence = 0;
|
||||||
|
|
||||||
int expandX = round(this->plateRegion.width * 0.15);
|
int expandX = round(this->plateRegion.width * 0.15);
|
||||||
@@ -46,19 +44,14 @@ void LicensePlateCandidate::recognize()
|
|||||||
// expand box by 15% in all directions
|
// expand box by 15% in all directions
|
||||||
Rect expandedRegion = expandRect( this->plateRegion, expandX, expandY, frame.cols, frame.rows) ;
|
Rect expandedRegion = expandRect( this->plateRegion, expandX, expandY, frame.cols, frame.rows) ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mat plate_bgr = Mat(frame, expandedRegion);
|
Mat plate_bgr = Mat(frame, expandedRegion);
|
||||||
resize(plate_bgr, plate_bgr, Size(config->templateWidthPx, config->templateHeightPx));
|
resize(plate_bgr, plate_bgr, Size(config->templateWidthPx, config->templateHeightPx));
|
||||||
|
|
||||||
Mat plate_bgr_cleaned = Mat(plate_bgr.size(), plate_bgr.type());
|
Mat plate_bgr_cleaned = Mat(plate_bgr.size(), plate_bgr.type());
|
||||||
this->cleanupColors(plate_bgr, plate_bgr_cleaned);
|
this->cleanupColors(plate_bgr, plate_bgr_cleaned);
|
||||||
|
|
||||||
|
|
||||||
CharacterRegion charRegion(plate_bgr, config);
|
CharacterRegion charRegion(plate_bgr, config);
|
||||||
|
|
||||||
|
|
||||||
if (charRegion.confidence > 10)
|
if (charRegion.confidence > 10)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -75,13 +68,10 @@ void LicensePlateCandidate::recognize()
|
|||||||
{
|
{
|
||||||
this->plateCorners = transformPointsToOriginalImage(frame, plate_bgr, expandedRegion, smallPlateCorners);
|
this->plateCorners = transformPointsToOriginalImage(frame, plate_bgr, expandedRegion, smallPlateCorners);
|
||||||
|
|
||||||
|
|
||||||
this->deskewed = deSkewPlate(frame, this->plateCorners);
|
this->deskewed = deSkewPlate(frame, this->plateCorners);
|
||||||
|
|
||||||
|
|
||||||
charSegmenter = new CharacterSegmenter(deskewed, charRegion.thresholdsInverted(), config);
|
charSegmenter = new CharacterSegmenter(deskewed, charRegion.thresholdsInverted(), config);
|
||||||
|
|
||||||
|
|
||||||
//this->recognizedText = ocr->recognizedText;
|
//this->recognizedText = ocr->recognizedText;
|
||||||
//strcpy(this->recognizedText, ocr.recognizedText);
|
//strcpy(this->recognizedText, ocr.recognizedText);
|
||||||
|
|
||||||
@@ -91,13 +81,8 @@ void LicensePlateCandidate::recognize()
|
|||||||
charRegion.confidence = 0;
|
charRegion.confidence = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Re-maps the coordinates from the smallImage to the coordinate space of the bigImage.
|
// Re-maps the coordinates from the smallImage to the coordinate space of the bigImage.
|
||||||
vector<Point2f> LicensePlateCandidate::transformPointsToOriginalImage(Mat bigImage, Mat smallImage, Rect region, vector<Point> corners)
|
vector<Point2f> LicensePlateCandidate::transformPointsToOriginalImage(Mat bigImage, Mat smallImage, Rect region, vector<Point> corners)
|
||||||
{
|
{
|
||||||
@@ -116,7 +101,6 @@ vector<Point2f> LicensePlateCandidate::transformPointsToOriginalImage(Mat bigIma
|
|||||||
return cornerPoints;
|
return cornerPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners)
|
Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -159,7 +143,6 @@ Mat LicensePlateCandidate::deSkewPlate(Mat inputImage, vector<Point2f> corners)
|
|||||||
return deskewed;
|
return deskewed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LicensePlateCandidate::cleanupColors(Mat inputImage, Mat outputImage)
|
void LicensePlateCandidate::cleanupColors(Mat inputImage, Mat outputImage)
|
||||||
{
|
{
|
||||||
if (this->config->debugGeneral)
|
if (this->config->debugGeneral)
|
||||||
@@ -190,10 +173,8 @@ void LicensePlateCandidate::cleanupColors(Mat inputImage, Mat outputImage)
|
|||||||
//ycrcb.release();
|
//ycrcb.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bilateralFilter(intermediate, outputImage, 3, 25, 35);
|
bilateralFilter(intermediate, outputImage, 3, 25, 35);
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugGeneral)
|
if (this->config->debugGeneral)
|
||||||
{
|
{
|
||||||
displayImage(config, "After cleanup", outputImage);
|
displayImage(config, "After cleanup", outputImage);
|
||||||
|
@@ -17,9 +17,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "ocr.h"
|
#include "ocr.h"
|
||||||
|
|
||||||
OCR::OCR(Config* config)
|
OCR::OCR(Config* config)
|
||||||
@@ -36,7 +33,6 @@ OCR::OCR(Config* config)
|
|||||||
strcpy(tessdataPrefix.data(), config->getTessdataPrefix().c_str());
|
strcpy(tessdataPrefix.data(), config->getTessdataPrefix().c_str());
|
||||||
putenv(tessdataPrefix.data());
|
putenv(tessdataPrefix.data());
|
||||||
|
|
||||||
|
|
||||||
tesseract->Init("", config->ocrLanguage.c_str() );
|
tesseract->Init("", config->ocrLanguage.c_str() );
|
||||||
tesseract->SetVariable("save_blob_choices", "T");
|
tesseract->SetVariable("save_blob_choices", "T");
|
||||||
//tesseract->SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNPQRSTUVWXYZ1234567890");
|
//tesseract->SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNPQRSTUVWXYZ1234567890");
|
||||||
@@ -50,18 +46,14 @@ OCR::~OCR()
|
|||||||
delete tesseract;
|
delete tesseract;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
postProcessor->clear();
|
postProcessor->clear();
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < thresholds.size(); i++)
|
for (int i = 0; i < thresholds.size(); i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -69,7 +61,6 @@ void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
|||||||
bitwise_not(thresholds[i], thresholds[i]);
|
bitwise_not(thresholds[i], thresholds[i]);
|
||||||
tesseract->SetImage((uchar*) thresholds[i].data, thresholds[i].size().width, thresholds[i].size().height, thresholds[i].channels(), thresholds[i].step1());
|
tesseract->SetImage((uchar*) thresholds[i].data, thresholds[i].size().width, thresholds[i].size().height, thresholds[i].channels(), thresholds[i].step1());
|
||||||
|
|
||||||
|
|
||||||
for (int j = 0; j < charRegions.size(); j++)
|
for (int j = 0; j < charRegions.size(); j++)
|
||||||
{
|
{
|
||||||
Rect expandedRegion = expandRect( charRegions[j], 2, 2, thresholds[i].cols, thresholds[i].rows) ;
|
Rect expandedRegion = expandRect( charRegions[j], 2, 2, thresholds[i].cols, thresholds[i].rows) ;
|
||||||
@@ -79,7 +70,8 @@ void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
|||||||
|
|
||||||
tesseract::ResultIterator* ri = tesseract->GetIterator();
|
tesseract::ResultIterator* ri = tesseract->GetIterator();
|
||||||
tesseract::PageIteratorLevel level = tesseract::RIL_SYMBOL;
|
tesseract::PageIteratorLevel level = tesseract::RIL_SYMBOL;
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
const char* symbol = ri->GetUTF8Text(level);
|
const char* symbol = ri->GetUTF8Text(level);
|
||||||
float conf = ri->Confidence(level);
|
float conf = ri->Confidence(level);
|
||||||
|
|
||||||
@@ -88,21 +80,21 @@ void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
|||||||
int pointsize = 0;
|
int pointsize = 0;
|
||||||
const char* fontName = ri->WordFontAttributes(&dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &pointsize, &fontindex);
|
const char* fontName = ri->WordFontAttributes(&dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &dontcare, &pointsize, &fontindex);
|
||||||
|
|
||||||
if(symbol != 0 && pointsize >= config->ocrMinFontSize) {
|
if(symbol != 0 && pointsize >= config->ocrMinFontSize)
|
||||||
|
{
|
||||||
postProcessor->addLetter(*symbol, j, conf);
|
postProcessor->addLetter(*symbol, j, conf);
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugOcr)
|
if (this->config->debugOcr)
|
||||||
printf("charpos%d: threshold %d: symbol %s, conf: %f font: %s (index %d) size %dpx", j, i, symbol, conf, fontName, fontindex, pointsize);
|
printf("charpos%d: threshold %d: symbol %s, conf: %f font: %s (index %d) size %dpx", j, i, symbol, conf, fontName, fontindex, pointsize);
|
||||||
|
|
||||||
bool indent = false;
|
bool indent = false;
|
||||||
tesseract::ChoiceIterator ci(*ri);
|
tesseract::ChoiceIterator ci(*ri);
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
const char* choice = ci.GetUTF8Text();
|
const char* choice = ci.GetUTF8Text();
|
||||||
|
|
||||||
postProcessor->addLetter(*choice, j, ci.Confidence());
|
postProcessor->addLetter(*choice, j, ci.Confidence());
|
||||||
|
|
||||||
|
|
||||||
//letterScores.addScore(*choice, j, ci.Confidence() - MIN_CONFIDENCE);
|
//letterScores.addScore(*choice, j, ci.Confidence() - MIN_CONFIDENCE);
|
||||||
if (this->config->debugOcr)
|
if (this->config->debugOcr)
|
||||||
{
|
{
|
||||||
@@ -112,19 +104,20 @@ void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
|||||||
}
|
}
|
||||||
|
|
||||||
indent = true;
|
indent = true;
|
||||||
} while(ci.Next());
|
}
|
||||||
|
while(ci.Next());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->config->debugOcr)
|
if (this->config->debugOcr)
|
||||||
printf("---------------------------------------------\n");
|
printf("---------------------------------------------\n");
|
||||||
|
|
||||||
delete[] symbol;
|
delete[] symbol;
|
||||||
} while((ri->Next(level)));
|
}
|
||||||
|
while((ri->Next(level)));
|
||||||
|
|
||||||
delete ri;
|
delete ri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
@@ -134,7 +127,4 @@ void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
|
|||||||
cout << "OCR Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
cout << "OCR Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "platecorners.h"
|
#include "platecorners.h"
|
||||||
|
|
||||||
PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegion* charRegion, Config* config)
|
PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegion* charRegion, Config* config)
|
||||||
@@ -27,8 +26,6 @@ PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegi
|
|||||||
if (this->config->debugPlateCorners)
|
if (this->config->debugPlateCorners)
|
||||||
cout << "PlateCorners constructor" << endl;
|
cout << "PlateCorners constructor" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->inputImage = inputImage;
|
this->inputImage = inputImage;
|
||||||
this->plateLines = plateLines;
|
this->plateLines = plateLines;
|
||||||
this->charRegion = charRegion;
|
this->charRegion = charRegion;
|
||||||
@@ -36,7 +33,6 @@ PlateCorners::PlateCorners(Mat inputImage, PlateLines* plateLines, CharacterRegi
|
|||||||
this->bestHorizontalScore = 9999999999999;
|
this->bestHorizontalScore = 9999999999999;
|
||||||
this->bestVerticalScore = 9999999999999;
|
this->bestVerticalScore = 9999999999999;
|
||||||
|
|
||||||
|
|
||||||
Point topPoint = charRegion->getTopLine().midpoint();
|
Point topPoint = charRegion->getTopLine().midpoint();
|
||||||
Point bottomPoint = charRegion->getBottomLine().closestPointOnSegmentTo(topPoint);
|
Point bottomPoint = charRegion->getBottomLine().closestPointOnSegmentTo(topPoint);
|
||||||
this->charHeight = distanceBetweenPoints(topPoint, bottomPoint);
|
this->charHeight = distanceBetweenPoints(topPoint, bottomPoint);
|
||||||
@@ -65,7 +61,6 @@ vector<Point> PlateCorners::findPlateCorners()
|
|||||||
int horizontalLines = this->plateLines->horizontalLines.size();
|
int horizontalLines = this->plateLines->horizontalLines.size();
|
||||||
int verticalLines = this->plateLines->verticalLines.size();
|
int verticalLines = this->plateLines->verticalLines.size();
|
||||||
|
|
||||||
|
|
||||||
// layout horizontal lines
|
// layout horizontal lines
|
||||||
for (int h1 = NO_LINE; h1 < horizontalLines; h1++)
|
for (int h1 = NO_LINE; h1 < horizontalLines; h1++)
|
||||||
{
|
{
|
||||||
@@ -89,7 +84,6 @@ vector<Point> PlateCorners::findPlateCorners()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugPlateCorners)
|
if (this->config->debugPlateCorners)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -100,15 +94,11 @@ vector<Point> PlateCorners::findPlateCorners()
|
|||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
circle(imgCorners, charRegion->getCharArea()[i], 2, Scalar(0, 0, 0));
|
circle(imgCorners, charRegion->getCharArea()[i], 2, Scalar(0, 0, 0));
|
||||||
|
|
||||||
|
|
||||||
line(imgCorners, this->bestTop.p1, this->bestTop.p2, Scalar(255, 0, 0), 1, CV_AA);
|
line(imgCorners, this->bestTop.p1, this->bestTop.p2, Scalar(255, 0, 0), 1, CV_AA);
|
||||||
line(imgCorners, this->bestRight.p1, this->bestRight.p2, Scalar(0, 0, 255), 1, CV_AA);
|
line(imgCorners, this->bestRight.p1, this->bestRight.p2, Scalar(0, 0, 255), 1, CV_AA);
|
||||||
line(imgCorners, this->bestBottom.p1, this->bestBottom.p2, Scalar(0, 0, 255), 1, CV_AA);
|
line(imgCorners, this->bestBottom.p1, this->bestBottom.p2, Scalar(0, 0, 255), 1, CV_AA);
|
||||||
line(imgCorners, this->bestLeft.p1, this->bestLeft.p2, Scalar(255, 0, 0), 1, CV_AA);
|
line(imgCorners, this->bestLeft.p1, this->bestLeft.p2, Scalar(255, 0, 0), 1, CV_AA);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
displayImage(config, "Winning top/bottom Boundaries", imgCorners);
|
displayImage(config, "Winning top/bottom Boundaries", imgCorners);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -127,8 +117,6 @@ vector<Point> PlateCorners::findPlateCorners()
|
|||||||
corners.push_back(bestBottom.intersection(bestRight));
|
corners.push_back(bestBottom.intersection(bestRight));
|
||||||
corners.push_back(bestBottom.intersection(bestLeft));
|
corners.push_back(bestBottom.intersection(bestLeft));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -139,7 +127,6 @@ vector<Point> PlateCorners::findPlateCorners()
|
|||||||
return corners;
|
return corners;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PlateCorners::scoreVerticals(int v1, int v2)
|
void PlateCorners::scoreVerticals(int v1, int v2)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -148,8 +135,6 @@ void PlateCorners::scoreVerticals(int v1, int v2)
|
|||||||
LineSegment left;
|
LineSegment left;
|
||||||
LineSegment right;
|
LineSegment right;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float charHeightToPlateWidthRatio = config->plateWidthMM / config->charHeightMM;
|
float charHeightToPlateWidthRatio = config->plateWidthMM / config->charHeightMM;
|
||||||
float idealPixelWidth = this->charHeight * (charHeightToPlateWidthRatio * 1.05); // Add 10% so we don't clip any characters
|
float idealPixelWidth = this->charHeight * (charHeightToPlateWidthRatio * 1.05); // Add 10% so we don't clip any characters
|
||||||
|
|
||||||
@@ -183,8 +168,6 @@ void PlateCorners::scoreVerticals(int v1, int v2)
|
|||||||
score += SCORING_MISSING_SEGMENT_PENALTY_VERTICAL;
|
score += SCORING_MISSING_SEGMENT_PENALTY_VERTICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Make sure this line is to the left of our license plate letters
|
// Make sure this line is to the left of our license plate letters
|
||||||
if (left.isPointBelowLine(charRegion->getCharBoxLeft().midpoint()) == false)
|
if (left.isPointBelowLine(charRegion->getCharBoxLeft().midpoint()) == false)
|
||||||
return;
|
return;
|
||||||
@@ -193,7 +176,6 @@ void PlateCorners::scoreVerticals(int v1, int v2)
|
|||||||
if (right.isPointBelowLine(charRegion->getCharBoxRight().midpoint()))
|
if (right.isPointBelowLine(charRegion->getCharBoxRight().midpoint()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// Score "Distance from the edge...
|
// Score "Distance from the edge...
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
@@ -204,7 +186,6 @@ void PlateCorners::scoreVerticals(int v1, int v2)
|
|||||||
float distanceFromEdge = leftDistanceFromEdge + rightDistanceFromEdge;
|
float distanceFromEdge = leftDistanceFromEdge + rightDistanceFromEdge;
|
||||||
score += distanceFromEdge * SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT;
|
score += distanceFromEdge * SCORING_VERTICALDISTANCE_FROMEDGE_WEIGHT;
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// Score "Boxiness" of the 4 lines. How close is it to a parallelogram?
|
// Score "Boxiness" of the 4 lines. How close is it to a parallelogram?
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
@@ -213,12 +194,10 @@ void PlateCorners::scoreVerticals(int v1, int v2)
|
|||||||
|
|
||||||
score += (verticalAngleDiff) * SCORING_BOXINESS_WEIGHT;
|
score += (verticalAngleDiff) * SCORING_BOXINESS_WEIGHT;
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// SCORE the shape wrt character position and height relative to position
|
// SCORE the shape wrt character position and height relative to position
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
Point leftMidLinePoint = left.closestPointOnSegmentTo(charRegion->getCharBoxLeft().midpoint());
|
Point leftMidLinePoint = left.closestPointOnSegmentTo(charRegion->getCharBoxLeft().midpoint());
|
||||||
Point rightMidLinePoint = right.closestPointOnSegmentTo(charRegion->getCharBoxRight().midpoint());
|
Point rightMidLinePoint = right.closestPointOnSegmentTo(charRegion->getCharBoxRight().midpoint());
|
||||||
|
|
||||||
@@ -230,7 +209,6 @@ void PlateCorners::scoreVerticals(int v1, int v2)
|
|||||||
{
|
{
|
||||||
float scorecomponent;
|
float scorecomponent;
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugPlateCorners)
|
if (this->config->debugPlateCorners)
|
||||||
{
|
{
|
||||||
cout << "xx xx Score: charHeight " << this->charHeight << endl;
|
cout << "xx xx Score: charHeight " << this->charHeight << endl;
|
||||||
@@ -277,7 +255,6 @@ void PlateCorners::scoreHorizontals(int h1, int h2)
|
|||||||
float charHeightToPlateHeightRatio = config->plateHeightMM / config->charHeightMM;
|
float charHeightToPlateHeightRatio = config->plateHeightMM / config->charHeightMM;
|
||||||
float idealPixelHeight = this->charHeight * charHeightToPlateHeightRatio;
|
float idealPixelHeight = this->charHeight * charHeightToPlateHeightRatio;
|
||||||
|
|
||||||
|
|
||||||
if (h1 == NO_LINE && h2 == NO_LINE)
|
if (h1 == NO_LINE && h2 == NO_LINE)
|
||||||
{
|
{
|
||||||
// return;
|
// return;
|
||||||
@@ -308,39 +285,26 @@ void PlateCorners::scoreHorizontals(int h1, int h2)
|
|||||||
score += SCORING_MISSING_SEGMENT_PENALTY_HORIZONTAL;
|
score += SCORING_MISSING_SEGMENT_PENALTY_HORIZONTAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Make sure this line is above our license plate letters
|
// Make sure this line is above our license plate letters
|
||||||
if (top.isPointBelowLine(charRegion->getCharBoxTop().midpoint()) == false)
|
if (top.isPointBelowLine(charRegion->getCharBoxTop().midpoint()) == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
// Make sure this line is below our license plate letters
|
// Make sure this line is below our license plate letters
|
||||||
if (bottom.isPointBelowLine(charRegion->getCharBoxBottom().midpoint()))
|
if (bottom.isPointBelowLine(charRegion->getCharBoxBottom().midpoint()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// We now have 4 possible lines. Let's put them to the test and score them...
|
// We now have 4 possible lines. Let's put them to the test and score them...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// Score "Boxiness" of the 4 lines. How close is it to a parallelogram?
|
// Score "Boxiness" of the 4 lines. How close is it to a parallelogram?
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
float horizontalAngleDiff = abs(top.angle - bottom.angle);
|
float horizontalAngleDiff = abs(top.angle - bottom.angle);
|
||||||
|
|
||||||
|
|
||||||
score += (horizontalAngleDiff) * SCORING_BOXINESS_WEIGHT;
|
score += (horizontalAngleDiff) * SCORING_BOXINESS_WEIGHT;
|
||||||
// if (this->debug)
|
// if (this->debug)
|
||||||
// cout << "PlateCorners boxiness score: " << (horizontalAngleDiff + verticalAngleDiff) * SCORING_BOXINESS_WEIGHT << endl;
|
// cout << "PlateCorners boxiness score: " << (horizontalAngleDiff + verticalAngleDiff) * SCORING_BOXINESS_WEIGHT << endl;
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// SCORE the shape wrt character position and height relative to position
|
// SCORE the shape wrt character position and height relative to position
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -351,7 +315,6 @@ void PlateCorners::scoreHorizontals(int h1, int h2)
|
|||||||
|
|
||||||
// Get the height difference
|
// Get the height difference
|
||||||
|
|
||||||
|
|
||||||
float heightRatio = charHeight / plateHeightPx;
|
float heightRatio = charHeight / plateHeightPx;
|
||||||
float idealHeightRatio = (config->charHeightMM / config->plateHeightMM);
|
float idealHeightRatio = (config->charHeightMM / config->plateHeightMM);
|
||||||
//if (leftRatio < MIN_CHAR_HEIGHT_RATIO || leftRatio > MAX_CHAR_HEIGHT_RATIO || rightRatio < MIN_CHAR_HEIGHT_RATIO || rightRatio > MAX_CHAR_HEIGHT_RATIO)
|
//if (leftRatio < MIN_CHAR_HEIGHT_RATIO || leftRatio > MAX_CHAR_HEIGHT_RATIO || rightRatio < MIN_CHAR_HEIGHT_RATIO || rightRatio > MAX_CHAR_HEIGHT_RATIO)
|
||||||
@@ -367,7 +330,6 @@ void PlateCorners::scoreHorizontals(int h1, int h2)
|
|||||||
// float idealBottomDistance = charHeight * (BOTTOM_WHITESPACE_HEIGHT_MM / CHARACTER_HEIGHT_MM);
|
// float idealBottomDistance = charHeight * (BOTTOM_WHITESPACE_HEIGHT_MM / CHARACTER_HEIGHT_MM);
|
||||||
// float distScore = abs(topDistance - idealTopDistance) + abs(bottomDistance - idealBottomDistance);
|
// float distScore = abs(topDistance - idealTopDistance) + abs(bottomDistance - idealBottomDistance);
|
||||||
|
|
||||||
|
|
||||||
score += heightRatioDiff * SCORING_PLATEHEIGHT_WEIGHT;
|
score += heightRatioDiff * SCORING_PLATEHEIGHT_WEIGHT;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -398,14 +360,11 @@ void PlateCorners::scoreHorizontals(int h1, int h2)
|
|||||||
|
|
||||||
float charanglediff = abs(charAngle - top.angle) + abs(charAngle - bottom.angle);
|
float charanglediff = abs(charAngle - top.angle) + abs(charAngle - bottom.angle);
|
||||||
|
|
||||||
|
|
||||||
score += charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT;
|
score += charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT;
|
||||||
|
|
||||||
// if (this->debug)
|
// if (this->debug)
|
||||||
// cout << "PlateCorners boxiness score: " << charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT << endl;
|
// cout << "PlateCorners boxiness score: " << charanglediff * SCORING_ANGLE_MATCHES_LPCHARS_WEIGHT << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (score < this->bestHorizontalScore)
|
if (score < this->bestHorizontalScore)
|
||||||
{
|
{
|
||||||
float scorecomponent;
|
float scorecomponent;
|
||||||
@@ -442,6 +401,4 @@ void PlateCorners::scoreHorizontals(int h1, int h2)
|
|||||||
bestBottom = LineSegment(bottom.p1.x, bottom.p1.y, bottom.p2.x, bottom.p2.y);
|
bestBottom = LineSegment(bottom.p1.x, bottom.p1.y, bottom.p2.x, bottom.p2.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "platelines.h"
|
#include "platelines.h"
|
||||||
|
|
||||||
|
|
||||||
PlateLines::PlateLines(Config* config)
|
PlateLines::PlateLines(Config* config)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = config;
|
||||||
@@ -28,7 +27,6 @@ PlateLines::PlateLines(Config* config)
|
|||||||
if (debug)
|
if (debug)
|
||||||
cout << "PlateLines constructor" << endl;
|
cout << "PlateLines constructor" << endl;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlateLines::~PlateLines()
|
PlateLines::~PlateLines()
|
||||||
@@ -36,18 +34,14 @@ PlateLines::~PlateLines()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PlateLines::processImage(Mat inputImage, float sensitivity)
|
void PlateLines::processImage(Mat inputImage, float sensitivity)
|
||||||
{
|
{
|
||||||
if (this->debug)
|
if (this->debug)
|
||||||
cout << "PlateLines findLines" << endl;
|
cout << "PlateLines findLines" << endl;
|
||||||
|
|
||||||
|
|
||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
Mat smoothed(inputImage.size(), inputImage.type());
|
Mat smoothed(inputImage.size(), inputImage.type());
|
||||||
inputImage.copyTo(smoothed);
|
inputImage.copyTo(smoothed);
|
||||||
int morph_elem = 2;
|
int morph_elem = 2;
|
||||||
@@ -65,12 +59,9 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
|
|||||||
element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
||||||
morphologyEx( smoothed, smoothed, MORPH_OPEN, element );
|
morphologyEx( smoothed, smoothed, MORPH_OPEN, element );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mat edges(inputImage.size(), inputImage.type());
|
Mat edges(inputImage.size(), inputImage.type());
|
||||||
Canny(smoothed, edges, 66, 133);
|
Canny(smoothed, edges, 66, 133);
|
||||||
|
|
||||||
|
|
||||||
vector<LineSegment> hlines = this->getLines(edges, sensitivity, false);
|
vector<LineSegment> hlines = this->getLines(edges, sensitivity, false);
|
||||||
vector<LineSegment> vlines = this->getLines(edges, sensitivity, true);
|
vector<LineSegment> vlines = this->getLines(edges, sensitivity, true);
|
||||||
for (int i = 0; i < hlines.size(); i++)
|
for (int i = 0; i < hlines.size(); i++)
|
||||||
@@ -78,9 +69,6 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
|
|||||||
for (int i = 0; i < vlines.size(); i++)
|
for (int i = 0; i < vlines.size(); i++)
|
||||||
this->verticalLines.push_back(vlines[i]);
|
this->verticalLines.push_back(vlines[i]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if debug is enabled, draw the image
|
// if debug is enabled, draw the image
|
||||||
if (this->debug)
|
if (this->debug)
|
||||||
{
|
{
|
||||||
@@ -109,8 +97,6 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
|
|||||||
displayImage(config, "Hough Lines", dashboard);
|
displayImage(config, "Hough Lines", dashboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -119,7 +105,6 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
|
|||||||
}
|
}
|
||||||
//smoothed.release();
|
//smoothed.release();
|
||||||
|
|
||||||
|
|
||||||
//////////////// METHOD2!!!!!!!////////////////////
|
//////////////// METHOD2!!!!!!!////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -127,18 +112,13 @@ void PlateLines::processImage(Mat inputImage, float sensitivity)
|
|||||||
Mat imgCanny;
|
Mat imgCanny;
|
||||||
GaussianBlur(inputImage, imgBlur, Size(9, 9), 1, 1);
|
GaussianBlur(inputImage, imgBlur, Size(9, 9), 1, 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Canny(imgBlur, imgCanny, 10, 30, 3);
|
Canny(imgBlur, imgCanny, 10, 30, 3);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//int morph_elem = 2;
|
//int morph_elem = 2;
|
||||||
//int morph_size = 1;
|
//int morph_size = 1;
|
||||||
//Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
//Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
|
||||||
morphologyEx( imgCanny, imgCanny, MORPH_CLOSE, element );
|
morphologyEx( imgCanny, imgCanny, MORPH_CLOSE, element );
|
||||||
|
|
||||||
|
|
||||||
Mat imgShaped;
|
Mat imgShaped;
|
||||||
imgCanny.copyTo(imgShaped);
|
imgCanny.copyTo(imgShaped);
|
||||||
//Find contours of possibles characters
|
//Find contours of possibles characters
|
||||||
@@ -187,7 +167,6 @@ vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical)
|
|||||||
vector<double> errors;
|
vector<double> errors;
|
||||||
lswms.run(edges, lsegs, errors);
|
lswms.run(edges, lsegs, errors);
|
||||||
|
|
||||||
|
|
||||||
for( size_t i = 0; i < lsegs.size(); i++ )
|
for( size_t i = 0; i < lsegs.size(); i++ )
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -247,7 +226,6 @@ vector<LineSegment> PlateLines::getLines(Mat edges, bool vertical)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
vector<LineSegment> PlateLines::getLines(Mat edges, float sensitivityMultiplier, bool vertical)
|
vector<LineSegment> PlateLines::getLines(Mat edges, float sensitivityMultiplier, bool vertical)
|
||||||
{
|
{
|
||||||
if (this->debug)
|
if (this->debug)
|
||||||
@@ -267,7 +245,6 @@ vector<LineSegment> PlateLines::getLines(Mat edges, float sensitivityMultiplier,
|
|||||||
|
|
||||||
HoughLines( edges, allLines, 1, CV_PI/180, sensitivity, 0, 0 );
|
HoughLines( edges, allLines, 1, CV_PI/180, sensitivity, 0, 0 );
|
||||||
|
|
||||||
|
|
||||||
for( size_t i = 0; i < allLines.size(); i++ )
|
for( size_t i = 0; i < allLines.size(); i++ )
|
||||||
{
|
{
|
||||||
float rho = allLines[i][0], theta = allLines[i][1];
|
float rho = allLines[i][0], theta = allLines[i][1];
|
||||||
@@ -325,20 +302,14 @@ vector<LineSegment> PlateLines::getLines(Mat edges, float sensitivityMultiplier,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return filteredLines;
|
return filteredLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mat PlateLines::customGrayscaleConversion(Mat src)
|
Mat PlateLines::customGrayscaleConversion(Mat src)
|
||||||
{
|
{
|
||||||
Mat img_hsv;
|
Mat img_hsv;
|
||||||
cvtColor(src,img_hsv,CV_BGR2HSV);
|
cvtColor(src,img_hsv,CV_BGR2HSV);
|
||||||
|
|
||||||
|
|
||||||
Mat grayscale = Mat(img_hsv.size(), CV_8U );
|
Mat grayscale = Mat(img_hsv.size(), CV_8U );
|
||||||
Mat hue(img_hsv.size(), CV_8U );
|
Mat hue(img_hsv.size(), CV_8U );
|
||||||
|
|
||||||
@@ -352,7 +323,6 @@ Mat PlateLines::customGrayscaleConversion(Mat src)
|
|||||||
|
|
||||||
int pixval = pow(v, 1.05);
|
int pixval = pow(v, 1.05);
|
||||||
|
|
||||||
|
|
||||||
if (pixval > 255)
|
if (pixval > 255)
|
||||||
pixval = 255;
|
pixval = 255;
|
||||||
grayscale.at<uchar>(row, col) = pixval;
|
grayscale.at<uchar>(row, col) = pixval;
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "postprocess.h"
|
#include "postprocess.h"
|
||||||
|
|
||||||
|
|
||||||
PostProcess::PostProcess(Config* config)
|
PostProcess::PostProcess(Config* config)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = config;
|
||||||
@@ -29,7 +28,6 @@ PostProcess::PostProcess(Config* config)
|
|||||||
|
|
||||||
std::ifstream infile(filename.str().c_str());
|
std::ifstream infile(filename.str().c_str());
|
||||||
|
|
||||||
|
|
||||||
string region, pattern;
|
string region, pattern;
|
||||||
while (infile >> region >> pattern)
|
while (infile >> region >> pattern)
|
||||||
{
|
{
|
||||||
@@ -61,7 +59,8 @@ PostProcess::~PostProcess()
|
|||||||
// TODO: Delete all entries in rules vector
|
// TODO: Delete all entries in rules vector
|
||||||
map<string, vector<RegexRule*> >::iterator iter;
|
map<string, vector<RegexRule*> >::iterator iter;
|
||||||
|
|
||||||
for (iter = rules.begin(); iter != rules.end(); ++iter) {
|
for (iter = rules.begin(); iter != rules.end(); ++iter)
|
||||||
|
{
|
||||||
for (int i = 0; i < iter->second.size(); i++)
|
for (int i = 0; i < iter->second.size(); i++)
|
||||||
{
|
{
|
||||||
delete iter->second[i];
|
delete iter->second[i];
|
||||||
@@ -70,7 +69,6 @@ PostProcess::~PostProcess()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PostProcess::addLetter(char letter, int charposition, float score)
|
void PostProcess::addLetter(char letter, int charposition, float score)
|
||||||
{
|
{
|
||||||
if (score < config->postProcessMinConfidence)
|
if (score < config->postProcessMinConfidence)
|
||||||
@@ -96,7 +94,6 @@ void PostProcess::insertLetter(char letter, int charposition, float score)
|
|||||||
|
|
||||||
score = score - config->postProcessMinConfidence;
|
score = score - config->postProcessMinConfidence;
|
||||||
|
|
||||||
|
|
||||||
int existingIndex = -1;
|
int existingIndex = -1;
|
||||||
if (letters.size() < charposition + 1)
|
if (letters.size() < charposition + 1)
|
||||||
{
|
{
|
||||||
@@ -134,7 +131,6 @@ void PostProcess::insertLetter(char letter, int charposition, float score)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PostProcess::clear()
|
void PostProcess::clear()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < letters.size(); i++)
|
for (int i = 0; i < letters.size(); i++)
|
||||||
@@ -157,8 +153,6 @@ void PostProcess::analyze(string templateregion, int topn)
|
|||||||
timespec startTime;
|
timespec startTime;
|
||||||
getTime(&startTime);
|
getTime(&startTime);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Get a list of missing positions
|
// Get a list of missing positions
|
||||||
for (int i = letters.size() -1; i >= 0; i--)
|
for (int i = letters.size() -1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
@@ -168,11 +162,9 @@ void PostProcess::analyze(string templateregion, int topn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (letters.size() == 0)
|
if (letters.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
// Sort the letters as they are
|
// Sort the letters as they are
|
||||||
for (int i = 0; i < letters.size(); i++)
|
for (int i = 0; i < letters.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -180,8 +172,6 @@ void PostProcess::analyze(string templateregion, int topn)
|
|||||||
sort(letters[i].begin(), letters[i].end(), letterCompare);
|
sort(letters[i].begin(), letters[i].end(), letterCompare);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugPostProcess)
|
if (this->config->debugPostProcess)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -211,7 +201,6 @@ void PostProcess::analyze(string templateregion, int topn)
|
|||||||
vector<Letter> tmp;
|
vector<Letter> tmp;
|
||||||
findAllPermutations(tmp, 0, config->postProcessMaxSubstitutions);
|
findAllPermutations(tmp, 0, config->postProcessMaxSubstitutions);
|
||||||
|
|
||||||
|
|
||||||
timespec sortStartTime;
|
timespec sortStartTime;
|
||||||
getTime(&sortStartTime);
|
getTime(&sortStartTime);
|
||||||
|
|
||||||
@@ -228,11 +217,8 @@ void PostProcess::analyze(string templateregion, int topn)
|
|||||||
cout << " -- PostProcess Sort Time: " << diffclock(sortStartTime, sortEndTime) << "ms." << endl;
|
cout << " -- PostProcess Sort Time: " << diffclock(sortStartTime, sortEndTime) << "ms." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
matchesTemplate = false;
|
matchesTemplate = false;
|
||||||
|
|
||||||
|
|
||||||
if (templateregion != "")
|
if (templateregion != "")
|
||||||
{
|
{
|
||||||
vector<RegexRule*> regionRules = rules[templateregion];
|
vector<RegexRule*> regionRules = rules[templateregion];
|
||||||
@@ -251,8 +237,6 @@ void PostProcess::analyze(string templateregion, int topn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (i >= topn - 1)
|
if (i >= topn - 1)
|
||||||
break;
|
break;
|
||||||
//if (matchesTemplate || i >= TOP_N - 1)
|
//if (matchesTemplate || i >= TOP_N - 1)
|
||||||
@@ -289,12 +273,9 @@ void PostProcess::analyze(string templateregion, int topn)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (this->config->debugPostProcess)
|
if (this->config->debugPostProcess)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// Print top words
|
// Print top words
|
||||||
for (int i = 0; i < allPossibilities.size(); i++)
|
for (int i = 0; i < allPossibilities.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -309,8 +290,6 @@ void PostProcess::analyze(string templateregion, int topn)
|
|||||||
cout << allPossibilities.size() << " total permutations" << endl;
|
cout << allPossibilities.size() << " total permutations" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -372,7 +351,6 @@ vector<int> PostProcess::getMaxDepth(int topn)
|
|||||||
nextLeastDropCharPos = getNextLeastDrop(depth);
|
nextLeastDropCharPos = getNextLeastDrop(depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,14 +443,10 @@ void PostProcess::findAllPermutations(vector<Letter> prevletters, int charPos, i
|
|||||||
findAllPermutations(prevletters, charPos + 1, substitutionsLeft);
|
findAllPermutations(prevletters, charPos + 1, substitutionsLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wordCompare( const PPResult &left, const PPResult &right )
|
||||||
|
{
|
||||||
|
|
||||||
bool wordCompare( const PPResult &left, const PPResult &right ){
|
|
||||||
if (left.totalscore < right.totalscore)
|
if (left.totalscore < right.totalscore)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
@@ -486,7 +460,6 @@ bool letterCompare( const Letter &left, const Letter &right )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RegexRule::RegexRule(string region, string pattern)
|
RegexRule::RegexRule(string region, string pattern)
|
||||||
{
|
{
|
||||||
this->original = pattern;
|
this->original = pattern;
|
||||||
@@ -529,7 +502,6 @@ RegexRule::RegexRule(string region, string pattern)
|
|||||||
// cout << "AA Skip position: " << skipPositions[z] << endl;
|
// cout << "AA Skip position: " << skipPositions[z] << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool RegexRule::match(string text)
|
bool RegexRule::match(string text)
|
||||||
{
|
{
|
||||||
if (text.length() != numchars)
|
if (text.length() != numchars)
|
||||||
|
@@ -17,11 +17,8 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "regiondetector.h"
|
#include "regiondetector.h"
|
||||||
|
|
||||||
|
|
||||||
RegionDetector::RegionDetector(Config* config)
|
RegionDetector::RegionDetector(Config* config)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = config;
|
||||||
@@ -38,7 +35,6 @@ RegionDetector::RegionDetector(Config* config)
|
|||||||
this->plate_cascade = new CascadeClassifier();
|
this->plate_cascade = new CascadeClassifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if( this->plate_cascade->load( config->getCascadeRuntimeDir() + config->country + ".xml" ) )
|
if( this->plate_cascade->load( config->getCascadeRuntimeDir() + config->country + ".xml" ) )
|
||||||
{
|
{
|
||||||
this->loaded = true;
|
this->loaded = true;
|
||||||
@@ -49,8 +45,6 @@ RegionDetector::RegionDetector(Config* config)
|
|||||||
printf("--(!)Error loading classifier\n");
|
printf("--(!)Error loading classifier\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionDetector::~RegionDetector()
|
RegionDetector::~RegionDetector()
|
||||||
@@ -58,14 +52,11 @@ RegionDetector::~RegionDetector()
|
|||||||
delete this->plate_cascade;
|
delete this->plate_cascade;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool RegionDetector::isLoaded()
|
bool RegionDetector::isLoaded()
|
||||||
{
|
{
|
||||||
return this->loaded;
|
return this->loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vector<Rect> RegionDetector::detect(Mat frame)
|
vector<Rect> RegionDetector::detect(Mat frame)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -77,7 +68,6 @@ vector<Rect> RegionDetector::detect(Mat frame)
|
|||||||
return regionsOfInterest;
|
return regionsOfInterest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @function detectAndDisplay */
|
/** @function detectAndDisplay */
|
||||||
vector<Rect> RegionDetector::doCascade(Mat frame)
|
vector<Rect> RegionDetector::doCascade(Mat frame)
|
||||||
{
|
{
|
||||||
@@ -111,7 +101,6 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
|
|||||||
minSize, maxSize );
|
minSize, maxSize );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -119,8 +108,6 @@ vector<Rect> RegionDetector::doCascade(Mat frame)
|
|||||||
cout << "LBP Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
cout << "LBP Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for( int i = 0; i < plates.size(); i++ )
|
for( int i = 0; i < plates.size(); i++ )
|
||||||
{
|
{
|
||||||
plates[i].x = plates[i].x / scale_factor;
|
plates[i].x = plates[i].x / scale_factor;
|
||||||
|
@@ -99,14 +99,16 @@ typedef unsigned char Boolean; /* 0 or 1 */
|
|||||||
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
|
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
|
||||||
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
|
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
conversionOK, /* conversion successful */
|
conversionOK, /* conversion successful */
|
||||||
sourceExhausted, /* partial character in source, but hit end */
|
sourceExhausted, /* partial character in source, but hit end */
|
||||||
targetExhausted, /* insuff. room in target for conversion */
|
targetExhausted, /* insuff. room in target for conversion */
|
||||||
sourceIllegal /* source sequence is illegal/malformed */
|
sourceIllegal /* source sequence is illegal/malformed */
|
||||||
} ConversionResult;
|
} ConversionResult;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
strictConversion = 0,
|
strictConversion = 0,
|
||||||
lenientConversion
|
lenientConversion
|
||||||
} ConversionFlags;
|
} ConversionFlags;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -74,7 +74,8 @@ snippets(
|
|||||||
|
|
||||||
// output all of the items
|
// output all of the items
|
||||||
CSimpleIniA::TNamesDepend::const_iterator i;
|
CSimpleIniA::TNamesDepend::const_iterator i;
|
||||||
for (i = values.begin(); i != values.end(); ++i) {
|
for (i = values.begin(); i != values.end(); ++i)
|
||||||
|
{
|
||||||
printf("key-name = '%s'\n", i->pItem);
|
printf("key-name = '%s'\n", i->pItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "stateidentifier.h"
|
#include "stateidentifier.h"
|
||||||
|
|
||||||
|
|
||||||
StateIdentifier::StateIdentifier(Config* config)
|
StateIdentifier::StateIdentifier(Config* config)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = config;
|
||||||
@@ -66,19 +65,16 @@ int StateIdentifier::recognize(Mat img, char* stateCode)
|
|||||||
plateImg.copyTo(debugImg);
|
plateImg.copyTo(debugImg);
|
||||||
vector<int> matchesArray(featureMatcher->numTrainingElements());
|
vector<int> matchesArray(featureMatcher->numTrainingElements());
|
||||||
|
|
||||||
|
|
||||||
RecognitionResult result = featureMatcher->recognize(plateImg, true, &debugImg, true, matchesArray );
|
RecognitionResult result = featureMatcher->recognize(plateImg, true, &debugImg, true, matchesArray );
|
||||||
|
|
||||||
if (this->config->debugStateId)
|
if (this->config->debugStateId)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
displayImage(config, "State Identifier1", plateImg);
|
displayImage(config, "State Identifier1", plateImg);
|
||||||
displayImage(config, "State Identifier", debugImg);
|
displayImage(config, "State Identifier", debugImg);
|
||||||
cout << result.haswinner << " : " << result.confidence << " : " << result.winner << endl;
|
cout << result.haswinner << " : " << result.confidence << " : " << result.winner << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -86,12 +82,10 @@ int StateIdentifier::recognize(Mat img, char* stateCode)
|
|||||||
cout << "State Identification Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
cout << "State Identification Time: " << diffclock(startTime, endTime) << "ms." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (result.haswinner == false)
|
if (result.haswinner == false)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
strcpy(stateCode, result.winner.c_str());
|
strcpy(stateCode, result.winner.c_str());
|
||||||
|
|
||||||
|
|
||||||
return result.confidence;
|
return result.confidence;
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool hasEnding (std::string const &fullString, std::string const &ending)
|
bool hasEnding (std::string const &fullString, std::string const &ending)
|
||||||
{
|
{
|
||||||
if (fullString.length() >= ending.length()) {
|
if (fullString.length() >= ending.length())
|
||||||
|
{
|
||||||
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
|
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,14 +48,18 @@ std::vector<std::string> getFilesInDir(const char* dirPath)
|
|||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
|
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
if ((dir = opendir (dirPath)) != NULL) {
|
if ((dir = opendir (dirPath)) != NULL)
|
||||||
|
{
|
||||||
/* print all the files and directories within directory */
|
/* print all the files and directories within directory */
|
||||||
while ((ent = readdir (dir)) != NULL) {
|
while ((ent = readdir (dir)) != NULL)
|
||||||
|
{
|
||||||
if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0)
|
if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0)
|
||||||
files.push_back(ent->d_name);
|
files.push_back(ent->d_name);
|
||||||
}
|
}
|
||||||
closedir (dir);
|
closedir (dir);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* could not open directory */
|
/* could not open directory */
|
||||||
perror ("");
|
perror ("");
|
||||||
return files;
|
return files;
|
||||||
@@ -63,8 +68,8 @@ std::vector<std::string> getFilesInDir(const char* dirPath)
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool stringCompare( const std::string &left, const std::string &right )
|
||||||
bool stringCompare( const std::string &left, const std::string &right ){
|
{
|
||||||
for( std::string::const_iterator lit = left.begin(), rit = right.begin(); lit != left.end() && rit != right.end(); ++lit, ++rit )
|
for( std::string::const_iterator lit = left.begin(), rit = right.begin(); lit != left.end() && rit != right.end(); ++lit, ++rit )
|
||||||
if( tolower( *lit ) < tolower( *rit ) )
|
if( tolower( *lit ) < tolower( *rit ) )
|
||||||
return true;
|
return true;
|
||||||
|
@@ -1,9 +1,7 @@
|
|||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
|
|
||||||
|
|
||||||
timespec diff(timespec start, timespec end);
|
timespec diff(timespec start, timespec end);
|
||||||
|
|
||||||
|
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
|
|
||||||
// Windows timing code
|
// Windows timing code
|
||||||
@@ -37,20 +35,25 @@ int clock_gettime(int X, timespec *tv)
|
|||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
static BOOL usePerformanceCounter = 0;
|
static BOOL usePerformanceCounter = 0;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized)
|
||||||
|
{
|
||||||
LARGE_INTEGER performanceFrequency;
|
LARGE_INTEGER performanceFrequency;
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
|
usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
|
||||||
if (usePerformanceCounter) {
|
if (usePerformanceCounter)
|
||||||
|
{
|
||||||
QueryPerformanceCounter(&offset);
|
QueryPerformanceCounter(&offset);
|
||||||
frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
|
frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
offset = getFILETIMEoffset();
|
offset = getFILETIMEoffset();
|
||||||
frequencyToMicroseconds = 10.;
|
frequencyToMicroseconds = 10.;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (usePerformanceCounter) QueryPerformanceCounter(&t);
|
if (usePerformanceCounter) QueryPerformanceCounter(&t);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
GetSystemTimeAsFileTime(&f);
|
GetSystemTimeAsFileTime(&f);
|
||||||
t.QuadPart = f.dwHighDateTime;
|
t.QuadPart = f.dwHighDateTime;
|
||||||
t.QuadPart <<= 32;
|
t.QuadPart <<= 32;
|
||||||
@@ -65,8 +68,6 @@ int clock_gettime(int X, timespec *tv)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void getTime(timespec* time)
|
void getTime(timespec* time)
|
||||||
{
|
{
|
||||||
clock_gettime(0, time);
|
clock_gettime(0, time);
|
||||||
@@ -77,17 +78,19 @@ double diffclock(timespec time1,timespec time2)
|
|||||||
timespec delta = diff(time1,time2);
|
timespec delta = diff(time1,time2);
|
||||||
double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_usec) / 1000.0);
|
double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_usec) / 1000.0);
|
||||||
|
|
||||||
|
|
||||||
return milliseconds;
|
return milliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
timespec diff(timespec start, timespec end)
|
timespec diff(timespec start, timespec end)
|
||||||
{
|
{
|
||||||
timespec temp;
|
timespec temp;
|
||||||
if ((end.tv_usec-start.tv_usec)<0) {
|
if ((end.tv_usec-start.tv_usec)<0)
|
||||||
|
{
|
||||||
temp.tv_sec = end.tv_sec-start.tv_sec-1;
|
temp.tv_sec = end.tv_sec-start.tv_sec-1;
|
||||||
temp.tv_usec = 1000000+end.tv_usec-start.tv_usec;
|
temp.tv_usec = 1000000+end.tv_usec-start.tv_usec;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
temp.tv_sec = end.tv_sec-start.tv_sec;
|
temp.tv_sec = end.tv_sec-start.tv_sec;
|
||||||
temp.tv_usec = end.tv_usec-start.tv_usec;
|
temp.tv_usec = end.tv_usec-start.tv_usec;
|
||||||
}
|
}
|
||||||
@@ -96,8 +99,6 @@ timespec diff(timespec start, timespec end)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void getTime(timespec* time)
|
void getTime(timespec* time)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -120,24 +121,24 @@ double diffclock(timespec time1,timespec time2)
|
|||||||
timespec delta = diff(time1,time2);
|
timespec delta = diff(time1,time2);
|
||||||
double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_nsec) / 1000000.0);
|
double milliseconds = (delta.tv_sec * 1000) + (((double) delta.tv_nsec) / 1000000.0);
|
||||||
|
|
||||||
|
|
||||||
return milliseconds;
|
return milliseconds;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
timespec diff(timespec start, timespec end)
|
timespec diff(timespec start, timespec end)
|
||||||
{
|
{
|
||||||
timespec temp;
|
timespec temp;
|
||||||
if ((end.tv_nsec-start.tv_nsec)<0) {
|
if ((end.tv_nsec-start.tv_nsec)<0)
|
||||||
|
{
|
||||||
temp.tv_sec = end.tv_sec-start.tv_sec-1;
|
temp.tv_sec = end.tv_sec-start.tv_sec-1;
|
||||||
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
|
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
temp.tv_sec = end.tv_sec-start.tv_sec;
|
temp.tv_sec = end.tv_sec-start.tv_sec;
|
||||||
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
|
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
|
||||||
}
|
}
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -126,7 +126,6 @@ int tinydir_open(tinydir_dir *dir, const char *path)
|
|||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialise dir */
|
/* initialise dir */
|
||||||
dir->_files = NULL;
|
dir->_files = NULL;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -135,7 +134,6 @@ int tinydir_open(tinydir_dir *dir, const char *path)
|
|||||||
dir->_d = NULL;
|
dir->_d = NULL;
|
||||||
#endif
|
#endif
|
||||||
tinydir_close(dir);
|
tinydir_close(dir);
|
||||||
|
|
||||||
strcpy(dir->path, path);
|
strcpy(dir->path, path);
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
strcat(dir->path, "\\*");
|
strcat(dir->path, "\\*");
|
||||||
@@ -150,7 +148,6 @@ int tinydir_open(tinydir_dir *dir, const char *path)
|
|||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read first file */
|
/* read first file */
|
||||||
dir->has_next = 1;
|
dir->has_next = 1;
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
@@ -160,9 +157,7 @@ int tinydir_open(tinydir_dir *dir, const char *path)
|
|||||||
dir->has_next = 0;
|
dir->has_next = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
tinydir_close(dir);
|
tinydir_close(dir);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -175,7 +170,6 @@ int tinydir_open_sorted(tinydir_dir *dir, const char *path)
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir->n_files = 0;
|
dir->n_files = 0;
|
||||||
while (dir->has_next)
|
while (dir->has_next)
|
||||||
{
|
{
|
||||||
@@ -187,23 +181,18 @@ int tinydir_open_sorted(tinydir_dir *dir, const char *path)
|
|||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_file = &dir->_files[dir->n_files - 1];
|
p_file = &dir->_files[dir->n_files - 1];
|
||||||
if (tinydir_readfile(dir, p_file) == -1)
|
if (tinydir_readfile(dir, p_file) == -1)
|
||||||
{
|
{
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tinydir_next(dir) == -1)
|
if (tinydir_next(dir) == -1)
|
||||||
{
|
{
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp);
|
qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
tinydir_close(dir);
|
tinydir_close(dir);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -216,7 +205,6 @@ void tinydir_close(tinydir_dir *dir)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(dir->path, 0, sizeof(dir->path));
|
memset(dir->path, 0, sizeof(dir->path));
|
||||||
dir->has_next = 0;
|
dir->has_next = 0;
|
||||||
dir->n_files = -1;
|
dir->n_files = -1;
|
||||||
@@ -254,7 +242,6 @@ int tinydir_next(tinydir_dir *dir)
|
|||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
if (FindNextFile(dir->_h, &dir->_f) == 0)
|
if (FindNextFile(dir->_h, &dir->_f) == 0)
|
||||||
#else
|
#else
|
||||||
@@ -273,7 +260,6 @@ int tinydir_next(tinydir_dir *dir)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +305,6 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
|
|||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(file->path, dir->path);
|
strcpy(file->path, dir->path);
|
||||||
strcat(file->path, "/");
|
strcat(file->path, "/");
|
||||||
strcpy(file->name,
|
strcpy(file->name,
|
||||||
@@ -360,7 +345,6 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
|
|||||||
#else
|
#else
|
||||||
S_ISREG(file->_s.st_mode);
|
S_ISREG(file->_s.st_mode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,9 +361,7 @@ int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, int i)
|
|||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(file, &dir->_files[i], sizeof(tinydir_file));
|
memcpy(file, &dir->_files[i], sizeof(tinydir_file));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,14 +379,12 @@ int tinydir_open_subdir_n(tinydir_dir *dir, int i)
|
|||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(path, dir->_files[i].path);
|
strcpy(path, dir->_files[i].path);
|
||||||
tinydir_close(dir);
|
tinydir_close(dir);
|
||||||
if (tinydir_open_sorted(dir, path) == -1)
|
if (tinydir_open_sorted(dir, path) == -1)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -219,7 +219,8 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
/* Wide-character version */
|
/* Wide-character version */
|
||||||
struct _wdirent {
|
struct _wdirent
|
||||||
|
{
|
||||||
long d_ino; /* Always zero */
|
long d_ino; /* Always zero */
|
||||||
unsigned short d_reclen; /* Structure size */
|
unsigned short d_reclen; /* Structure size */
|
||||||
size_t d_namlen; /* Length of name without \0 */
|
size_t d_namlen; /* Length of name without \0 */
|
||||||
@@ -228,7 +229,8 @@ struct _wdirent {
|
|||||||
};
|
};
|
||||||
typedef struct _wdirent _wdirent;
|
typedef struct _wdirent _wdirent;
|
||||||
|
|
||||||
struct _WDIR {
|
struct _WDIR
|
||||||
|
{
|
||||||
struct _wdirent ent; /* Current directory entry */
|
struct _wdirent ent; /* Current directory entry */
|
||||||
WIN32_FIND_DATAW data; /* Private file data */
|
WIN32_FIND_DATAW data; /* Private file data */
|
||||||
int cached; /* True if data is valid */
|
int cached; /* True if data is valid */
|
||||||
@@ -253,7 +255,8 @@ static void _wrewinddir (_WDIR* dirp);
|
|||||||
|
|
||||||
|
|
||||||
/* Multi-byte character versions */
|
/* Multi-byte character versions */
|
||||||
struct dirent {
|
struct dirent
|
||||||
|
{
|
||||||
long d_ino; /* Always zero */
|
long d_ino; /* Always zero */
|
||||||
unsigned short d_reclen; /* Structure size */
|
unsigned short d_reclen; /* Structure size */
|
||||||
size_t d_namlen; /* Length of name without \0 */
|
size_t d_namlen; /* Length of name without \0 */
|
||||||
@@ -262,7 +265,8 @@ struct dirent {
|
|||||||
};
|
};
|
||||||
typedef struct dirent dirent;
|
typedef struct dirent dirent;
|
||||||
|
|
||||||
struct DIR {
|
struct DIR
|
||||||
|
{
|
||||||
struct dirent ent;
|
struct dirent ent;
|
||||||
struct _WDIR *wdirp;
|
struct _WDIR *wdirp;
|
||||||
};
|
};
|
||||||
@@ -305,50 +309,49 @@ _wopendir(
|
|||||||
{
|
{
|
||||||
_WDIR *dirp = NULL;
|
_WDIR *dirp = NULL;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* Must have directory name */
|
/* Must have directory name */
|
||||||
if (dirname == NULL || dirname[0] == '\0') {
|
if (dirname == NULL || dirname[0] == '\0')
|
||||||
|
{
|
||||||
dirent_set_errno (ENOENT);
|
dirent_set_errno (ENOENT);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate new _WDIR structure */
|
/* Allocate new _WDIR structure */
|
||||||
dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
|
dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
|
||||||
if (dirp != NULL) {
|
if (dirp != NULL)
|
||||||
|
{
|
||||||
DWORD n;
|
DWORD n;
|
||||||
|
|
||||||
/* Reset _WDIR structure */
|
/* Reset _WDIR structure */
|
||||||
dirp->handle = INVALID_HANDLE_VALUE;
|
dirp->handle = INVALID_HANDLE_VALUE;
|
||||||
dirp->patt = NULL;
|
dirp->patt = NULL;
|
||||||
dirp->cached = 0;
|
dirp->cached = 0;
|
||||||
|
|
||||||
/* Compute the length of full path plus zero terminator */
|
/* Compute the length of full path plus zero terminator */
|
||||||
n = GetFullPathNameW (dirname, 0, NULL, NULL);
|
n = GetFullPathNameW (dirname, 0, NULL, NULL);
|
||||||
|
|
||||||
/* Allocate room for absolute directory name and search pattern */
|
/* Allocate room for absolute directory name and search pattern */
|
||||||
dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
|
dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
|
||||||
if (dirp->patt) {
|
if (dirp->patt)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Convert relative directory name to an absolute one. This
|
* Convert relative directory name to an absolute one. This
|
||||||
* allows rewinddir() to function correctly even when current
|
* allows rewinddir() to function correctly even when current
|
||||||
* working directory is changed between opendir() and rewinddir().
|
* working directory is changed between opendir() and rewinddir().
|
||||||
*/
|
*/
|
||||||
n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
|
n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
|
||||||
if (n > 0) {
|
if (n > 0)
|
||||||
|
{
|
||||||
wchar_t *p;
|
wchar_t *p;
|
||||||
|
|
||||||
/* Append search pattern \* to the directory name */
|
/* Append search pattern \* to the directory name */
|
||||||
p = dirp->patt + n;
|
p = dirp->patt + n;
|
||||||
if (dirp->patt < p) {
|
if (dirp->patt < p)
|
||||||
switch (p[-1]) {
|
{
|
||||||
|
switch (p[-1])
|
||||||
|
{
|
||||||
case '\\':
|
case '\\':
|
||||||
case '/':
|
case '/':
|
||||||
case ':':
|
case ':':
|
||||||
/* Directory ends in path separator, e.g. c:\temp\ */
|
/* Directory ends in path separator, e.g. c:\temp\ */
|
||||||
/*NOP*/;
|
/*NOP*/
|
||||||
|
;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Directory name doesn't end in path separator */
|
/* Directory name doesn't end in path separator */
|
||||||
*p++ = '\\';
|
*p++ = '\\';
|
||||||
@@ -356,39 +359,43 @@ _wopendir(
|
|||||||
}
|
}
|
||||||
*p++ = '*';
|
*p++ = '*';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
/* Open directory stream and retrieve the first entry */
|
/* Open directory stream and retrieve the first entry */
|
||||||
if (dirent_first (dirp)) {
|
if (dirent_first (dirp))
|
||||||
|
{
|
||||||
/* Directory stream opened successfully */
|
/* Directory stream opened successfully */
|
||||||
error = 0;
|
error = 0;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Cannot retrieve first entry */
|
/* Cannot retrieve first entry */
|
||||||
error = 1;
|
error = 1;
|
||||||
dirent_set_errno (ENOENT);
|
dirent_set_errno (ENOENT);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Cannot retrieve full path name */
|
/* Cannot retrieve full path name */
|
||||||
dirent_set_errno (ENOENT);
|
dirent_set_errno (ENOENT);
|
||||||
error = 1;
|
error = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Cannot allocate memory for search pattern */
|
/* Cannot allocate memory for search pattern */
|
||||||
error = 1;
|
error = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Cannot allocate _WDIR structure */
|
/* Cannot allocate _WDIR structure */
|
||||||
error = 1;
|
error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up in case of error */
|
/* Clean up in case of error */
|
||||||
if (error && dirp) {
|
if (error && dirp)
|
||||||
|
{
|
||||||
_wclosedir (dirp);
|
_wclosedir (dirp);
|
||||||
dirp = NULL;
|
dirp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dirp;
|
return dirp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,47 +414,48 @@ _wreaddir(
|
|||||||
|
|
||||||
/* Read next directory entry */
|
/* Read next directory entry */
|
||||||
datap = dirent_next (dirp);
|
datap = dirent_next (dirp);
|
||||||
if (datap) {
|
if (datap)
|
||||||
|
{
|
||||||
size_t n;
|
size_t n;
|
||||||
DWORD attr;
|
DWORD attr;
|
||||||
|
|
||||||
/* Pointer to directory entry to return */
|
/* Pointer to directory entry to return */
|
||||||
entp = &dirp->ent;
|
entp = &dirp->ent;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy file name as wide-character string. If the file name is too
|
* Copy file name as wide-character string. If the file name is too
|
||||||
* long to fit in to the destination buffer, then truncate file name
|
* long to fit in to the destination buffer, then truncate file name
|
||||||
* to PATH_MAX characters and zero-terminate the buffer.
|
* to PATH_MAX characters and zero-terminate the buffer.
|
||||||
*/
|
*/
|
||||||
n = 0;
|
n = 0;
|
||||||
while (n < PATH_MAX && datap->cFileName[n] != 0) {
|
while (n < PATH_MAX && datap->cFileName[n] != 0)
|
||||||
|
{
|
||||||
entp->d_name[n] = datap->cFileName[n];
|
entp->d_name[n] = datap->cFileName[n];
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
dirp->ent.d_name[n] = 0;
|
dirp->ent.d_name[n] = 0;
|
||||||
|
|
||||||
/* Length of file name excluding zero terminator */
|
/* Length of file name excluding zero terminator */
|
||||||
entp->d_namlen = n;
|
entp->d_namlen = n;
|
||||||
|
|
||||||
/* File type */
|
/* File type */
|
||||||
attr = datap->dwFileAttributes;
|
attr = datap->dwFileAttributes;
|
||||||
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
|
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0)
|
||||||
|
{
|
||||||
entp->d_type = DT_CHR;
|
entp->d_type = DT_CHR;
|
||||||
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
}
|
||||||
|
else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||||
|
{
|
||||||
entp->d_type = DT_DIR;
|
entp->d_type = DT_DIR;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
entp->d_type = DT_REG;
|
entp->d_type = DT_REG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset dummy fields */
|
/* Reset dummy fields */
|
||||||
entp->d_ino = 0;
|
entp->d_ino = 0;
|
||||||
entp->d_reclen = sizeof (struct _wdirent);
|
entp->d_reclen = sizeof (struct _wdirent);
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Last directory entry read */
|
/* Last directory entry read */
|
||||||
entp = NULL;
|
entp = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return entp;
|
return entp;
|
||||||
@@ -463,25 +471,26 @@ _wclosedir(
|
|||||||
_WDIR *dirp)
|
_WDIR *dirp)
|
||||||
{
|
{
|
||||||
int ok;
|
int ok;
|
||||||
if (dirp) {
|
if (dirp)
|
||||||
|
{
|
||||||
/* Release search handle */
|
/* Release search handle */
|
||||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
if (dirp->handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
FindClose (dirp->handle);
|
FindClose (dirp->handle);
|
||||||
dirp->handle = INVALID_HANDLE_VALUE;
|
dirp->handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release search pattern */
|
/* Release search pattern */
|
||||||
if (dirp->patt) {
|
if (dirp->patt)
|
||||||
|
{
|
||||||
free (dirp->patt);
|
free (dirp->patt);
|
||||||
dirp->patt = NULL;
|
dirp->patt = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release directory structure */
|
/* Release directory structure */
|
||||||
free (dirp);
|
free (dirp);
|
||||||
ok = /*success*/0;
|
ok = /*success*/0;
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Invalid directory stream */
|
/* Invalid directory stream */
|
||||||
dirent_set_errno (EBADF);
|
dirent_set_errno (EBADF);
|
||||||
ok = /*failure*/-1;
|
ok = /*failure*/-1;
|
||||||
@@ -497,12 +506,13 @@ static void
|
|||||||
_wrewinddir(
|
_wrewinddir(
|
||||||
_WDIR* dirp)
|
_WDIR* dirp)
|
||||||
{
|
{
|
||||||
if (dirp) {
|
if (dirp)
|
||||||
|
{
|
||||||
/* Release existing search handle */
|
/* Release existing search handle */
|
||||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
if (dirp->handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
FindClose (dirp->handle);
|
FindClose (dirp->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open new search handle */
|
/* Open new search handle */
|
||||||
dirent_first (dirp);
|
dirent_first (dirp);
|
||||||
}
|
}
|
||||||
@@ -514,21 +524,19 @@ dirent_first(
|
|||||||
_WDIR *dirp)
|
_WDIR *dirp)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATAW *datap;
|
WIN32_FIND_DATAW *datap;
|
||||||
|
|
||||||
/* Open directory and retrieve the first entry */
|
/* Open directory and retrieve the first entry */
|
||||||
dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
|
dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
|
||||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
if (dirp->handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
/* a directory entry is now waiting in memory */
|
/* a directory entry is now waiting in memory */
|
||||||
datap = &dirp->data;
|
datap = &dirp->data;
|
||||||
dirp->cached = 1;
|
dirp->cached = 1;
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Failed to re-open directory: no directory entry in memory */
|
/* Failed to re-open directory: no directory entry in memory */
|
||||||
dirp->cached = 0;
|
dirp->cached = 0;
|
||||||
datap = NULL;
|
datap = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
return datap;
|
return datap;
|
||||||
}
|
}
|
||||||
@@ -539,34 +547,34 @@ dirent_next(
|
|||||||
_WDIR *dirp)
|
_WDIR *dirp)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATAW *p;
|
WIN32_FIND_DATAW *p;
|
||||||
|
|
||||||
/* Get next directory entry */
|
/* Get next directory entry */
|
||||||
if (dirp->cached != 0) {
|
if (dirp->cached != 0)
|
||||||
|
{
|
||||||
/* A valid directory entry already in memory */
|
/* A valid directory entry already in memory */
|
||||||
p = &dirp->data;
|
p = &dirp->data;
|
||||||
dirp->cached = 0;
|
dirp->cached = 0;
|
||||||
|
}
|
||||||
} else if (dirp->handle != INVALID_HANDLE_VALUE) {
|
else if (dirp->handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
/* Get the next directory entry from stream */
|
/* Get the next directory entry from stream */
|
||||||
if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
|
if (FindNextFileW (dirp->handle, &dirp->data) != FALSE)
|
||||||
|
{
|
||||||
/* Got a file */
|
/* Got a file */
|
||||||
p = &dirp->data;
|
p = &dirp->data;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* The very last entry has been processed or an error occured */
|
/* The very last entry has been processed or an error occured */
|
||||||
FindClose (dirp->handle);
|
FindClose (dirp->handle);
|
||||||
dirp->handle = INVALID_HANDLE_VALUE;
|
dirp->handle = INVALID_HANDLE_VALUE;
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* End of directory stream reached */
|
/* End of directory stream reached */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,35 +587,38 @@ opendir(
|
|||||||
{
|
{
|
||||||
struct DIR *dirp;
|
struct DIR *dirp;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* Must have directory name */
|
/* Must have directory name */
|
||||||
if (dirname == NULL || dirname[0] == '\0') {
|
if (dirname == NULL || dirname[0] == '\0')
|
||||||
|
{
|
||||||
dirent_set_errno (ENOENT);
|
dirent_set_errno (ENOENT);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory for DIR structure */
|
/* Allocate memory for DIR structure */
|
||||||
dirp = (DIR*) malloc (sizeof (struct DIR));
|
dirp = (DIR*) malloc (sizeof (struct DIR));
|
||||||
if (dirp) {
|
if (dirp)
|
||||||
|
{
|
||||||
wchar_t wname[PATH_MAX + 1];
|
wchar_t wname[PATH_MAX + 1];
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
/* Convert directory name to wide-character string */
|
/* Convert directory name to wide-character string */
|
||||||
error = dirent_mbstowcs_s(
|
error = dirent_mbstowcs_s(
|
||||||
&n, wname, PATH_MAX + 1, dirname, PATH_MAX);
|
&n, wname, PATH_MAX + 1, dirname, PATH_MAX);
|
||||||
if (!error) {
|
if (!error)
|
||||||
|
{
|
||||||
/* Open directory stream using wide-character name */
|
/* Open directory stream using wide-character name */
|
||||||
dirp->wdirp = _wopendir (wname);
|
dirp->wdirp = _wopendir (wname);
|
||||||
if (dirp->wdirp) {
|
if (dirp->wdirp)
|
||||||
|
{
|
||||||
/* Directory stream opened */
|
/* Directory stream opened */
|
||||||
error = 0;
|
error = 0;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Failed to open directory stream */
|
/* Failed to open directory stream */
|
||||||
error = 1;
|
error = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Cannot convert file name to wide-character string. This
|
* Cannot convert file name to wide-character string. This
|
||||||
* occurs if the string contains invalid multi-byte sequences or
|
* occurs if the string contains invalid multi-byte sequences or
|
||||||
@@ -616,18 +627,18 @@ opendir(
|
|||||||
*/
|
*/
|
||||||
error = 1;
|
error = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Cannot allocate DIR structure */
|
/* Cannot allocate DIR structure */
|
||||||
error = 1;
|
error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up in case of error */
|
/* Clean up in case of error */
|
||||||
if (error && dirp) {
|
if (error && dirp)
|
||||||
|
{
|
||||||
free (dirp);
|
free (dirp);
|
||||||
dirp = NULL;
|
dirp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dirp;
|
return dirp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,14 +664,13 @@ readdir(
|
|||||||
|
|
||||||
/* Read next directory entry */
|
/* Read next directory entry */
|
||||||
datap = dirent_next (dirp->wdirp);
|
datap = dirent_next (dirp->wdirp);
|
||||||
if (datap) {
|
if (datap)
|
||||||
|
{
|
||||||
size_t n;
|
size_t n;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* Attempt to convert file name to multi-byte string */
|
/* Attempt to convert file name to multi-byte string */
|
||||||
error = dirent_wcstombs_s(
|
error = dirent_wcstombs_s(
|
||||||
&n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
|
&n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the file name cannot be represented by a multi-byte string,
|
* If the file name cannot be represented by a multi-byte string,
|
||||||
* then attempt to use old 8+3 file name. This allows traditional
|
* then attempt to use old 8+3 file name. This allows traditional
|
||||||
@@ -671,37 +681,40 @@ readdir(
|
|||||||
* name unless the file system provides one. At least
|
* name unless the file system provides one. At least
|
||||||
* VirtualBox shared folders fail to do this.
|
* VirtualBox shared folders fail to do this.
|
||||||
*/
|
*/
|
||||||
if (error && datap->cAlternateFileName[0] != '\0') {
|
if (error && datap->cAlternateFileName[0] != '\0')
|
||||||
|
{
|
||||||
error = dirent_wcstombs_s(
|
error = dirent_wcstombs_s(
|
||||||
&n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
|
&n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
|
||||||
sizeof (datap->cAlternateFileName) /
|
sizeof (datap->cAlternateFileName) /
|
||||||
sizeof (datap->cAlternateFileName[0]));
|
sizeof (datap->cAlternateFileName[0]));
|
||||||
}
|
}
|
||||||
|
if (!error)
|
||||||
if (!error) {
|
{
|
||||||
DWORD attr;
|
DWORD attr;
|
||||||
|
|
||||||
/* Initialize directory entry for return */
|
/* Initialize directory entry for return */
|
||||||
entp = &dirp->ent;
|
entp = &dirp->ent;
|
||||||
|
|
||||||
/* Length of file name excluding zero terminator */
|
/* Length of file name excluding zero terminator */
|
||||||
entp->d_namlen = n - 1;
|
entp->d_namlen = n - 1;
|
||||||
|
|
||||||
/* File attributes */
|
/* File attributes */
|
||||||
attr = datap->dwFileAttributes;
|
attr = datap->dwFileAttributes;
|
||||||
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
|
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0)
|
||||||
|
{
|
||||||
entp->d_type = DT_CHR;
|
entp->d_type = DT_CHR;
|
||||||
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
}
|
||||||
|
else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||||
|
{
|
||||||
entp->d_type = DT_DIR;
|
entp->d_type = DT_DIR;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
entp->d_type = DT_REG;
|
entp->d_type = DT_REG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset dummy fields */
|
/* Reset dummy fields */
|
||||||
entp->d_ino = 0;
|
entp->d_ino = 0;
|
||||||
entp->d_reclen = sizeof (struct dirent);
|
entp->d_reclen = sizeof (struct dirent);
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Cannot convert file name to multi-byte string so construct
|
* Cannot convert file name to multi-byte string so construct
|
||||||
* an errornous directory entry and return that. Note that
|
* an errornous directory entry and return that. Note that
|
||||||
@@ -716,8 +729,9 @@ readdir(
|
|||||||
entp->d_ino = 0;
|
entp->d_ino = 0;
|
||||||
entp->d_reclen = 0;
|
entp->d_reclen = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* No more directory entries */
|
/* No more directory entries */
|
||||||
entp = NULL;
|
entp = NULL;
|
||||||
}
|
}
|
||||||
@@ -733,21 +747,19 @@ closedir(
|
|||||||
DIR *dirp)
|
DIR *dirp)
|
||||||
{
|
{
|
||||||
int ok;
|
int ok;
|
||||||
if (dirp) {
|
if (dirp)
|
||||||
|
{
|
||||||
/* Close wide-character directory stream */
|
/* Close wide-character directory stream */
|
||||||
ok = _wclosedir (dirp->wdirp);
|
ok = _wclosedir (dirp->wdirp);
|
||||||
dirp->wdirp = NULL;
|
dirp->wdirp = NULL;
|
||||||
|
|
||||||
/* Release multi-byte character version */
|
/* Release multi-byte character version */
|
||||||
free (dirp);
|
free (dirp);
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Invalid directory stream */
|
/* Invalid directory stream */
|
||||||
dirent_set_errno (EBADF);
|
dirent_set_errno (EBADF);
|
||||||
ok = /*failure*/-1;
|
ok = /*failure*/-1;
|
||||||
|
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -773,43 +785,35 @@ dirent_mbstowcs_s(
|
|||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
|
|
||||||
/* Microsoft Visual Studio 2005 or later */
|
/* Microsoft Visual Studio 2005 or later */
|
||||||
error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
|
error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Older Visual Studio or non-Microsoft compiler */
|
/* Older Visual Studio or non-Microsoft compiler */
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
/* Convert to wide-character string */
|
/* Convert to wide-character string */
|
||||||
n = mbstowcs (wcstr, mbstr, count);
|
n = mbstowcs (wcstr, mbstr, count);
|
||||||
if (n < sizeInWords) {
|
if (n < sizeInWords)
|
||||||
|
{
|
||||||
/* Zero-terminate output buffer */
|
/* Zero-terminate output buffer */
|
||||||
if (wcstr) {
|
if (wcstr)
|
||||||
|
{
|
||||||
wcstr[n] = 0;
|
wcstr[n] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Length of resuting multi-byte string WITH zero terminator */
|
/* Length of resuting multi-byte string WITH zero terminator */
|
||||||
if (pReturnValue) {
|
if (pReturnValue)
|
||||||
|
{
|
||||||
*pReturnValue = n + 1;
|
*pReturnValue = n + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
error = 0;
|
error = 0;
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Could not convert string */
|
/* Could not convert string */
|
||||||
error = 1;
|
error = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,43 +827,35 @@ dirent_wcstombs_s(
|
|||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
|
|
||||||
/* Microsoft Visual Studio 2005 or later */
|
/* Microsoft Visual Studio 2005 or later */
|
||||||
error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
|
error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Older Visual Studio or non-Microsoft compiler */
|
/* Older Visual Studio or non-Microsoft compiler */
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
/* Convert to multi-byte string */
|
/* Convert to multi-byte string */
|
||||||
n = wcstombs (mbstr, wcstr, count);
|
n = wcstombs (mbstr, wcstr, count);
|
||||||
if (n < sizeInBytes) {
|
if (n < sizeInBytes)
|
||||||
|
{
|
||||||
/* Zero-terminate output buffer */
|
/* Zero-terminate output buffer */
|
||||||
if (mbstr) {
|
if (mbstr)
|
||||||
|
{
|
||||||
mbstr[n] = '\0';
|
mbstr[n] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lenght of resulting multi-bytes string WITH zero-terminator */
|
/* Lenght of resulting multi-bytes string WITH zero-terminator */
|
||||||
if (pReturnValue) {
|
if (pReturnValue)
|
||||||
|
{
|
||||||
*pReturnValue = n + 1;
|
*pReturnValue = n + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
error = 0;
|
error = 0;
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
/* Cannot convert string */
|
/* Cannot convert string */
|
||||||
error = 1;
|
error = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,15 +865,11 @@ dirent_set_errno(
|
|||||||
int error)
|
int error)
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
|
||||||
/* Microsoft Visual Studio */
|
/* Microsoft Visual Studio */
|
||||||
_set_errno (error);
|
_set_errno (error);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Non-Microsoft compiler */
|
/* Non-Microsoft compiler */
|
||||||
errno = error;
|
errno = error;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -51,7 +51,8 @@
|
|||||||
typedef unsigned int TRexBool;
|
typedef unsigned int TRexBool;
|
||||||
typedef struct TRex TRex;
|
typedef struct TRex TRex;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
const TRexChar *begin;
|
const TRexChar *begin;
|
||||||
int len;
|
int len;
|
||||||
} TRexMatch;
|
} TRexMatch;
|
||||||
|
@@ -17,12 +17,8 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
|
||||||
Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, int maxY)
|
Rect expandRect(Rect original, int expandXPixels, int expandYPixels, int maxX, int maxY)
|
||||||
{
|
{
|
||||||
Rect expandedRegion = Rect(original);
|
Rect expandedRegion = Rect(original);
|
||||||
@@ -90,8 +86,6 @@ Mat addLabel(Mat input, string label)
|
|||||||
return newImage;
|
return newImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void drawAndWait(cv::Mat* frame)
|
void drawAndWait(cv::Mat* frame)
|
||||||
{
|
{
|
||||||
cv::imshow("Temp Window", *frame);
|
cv::imshow("Temp Window", *frame);
|
||||||
@@ -137,7 +131,8 @@ vector<Mat> produceThresholds(const Mat img_gray, Config* config)
|
|||||||
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
||||||
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
||||||
|
|
||||||
k = 1; win = 22;
|
k = 1;
|
||||||
|
win = 22;
|
||||||
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
||||||
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
||||||
//NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
//NiblackSauvolaWolfJolion (img_gray, thresholds[i++], WOLFJOLION, win, win, 0.05 + (k * 0.35));
|
||||||
@@ -151,11 +146,6 @@ vector<Mat> produceThresholds(const Mat img_gray, Config* config)
|
|||||||
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], SAUVOLA, 12, 12, 0.18 * k);
|
NiblackSauvolaWolfJolion (img_gray, thresholds[i++], SAUVOLA, 12, 12, 0.18 * k);
|
||||||
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
bitwise_not(thresholds[i-1], thresholds[i-1]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (config->debugTiming)
|
if (config->debugTiming)
|
||||||
{
|
{
|
||||||
timespec endTime;
|
timespec endTime;
|
||||||
@@ -180,7 +170,6 @@ double median(int array[], int arraySize)
|
|||||||
return arraySize % 2 ? array[arraySize / 2] : (array[arraySize / 2 - 1] + array[arraySize / 2]) / 2;
|
return arraySize % 2 ? array[arraySize / 2] : (array[arraySize / 2 - 1] + array[arraySize / 2]) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mat equalizeBrightness(Mat img)
|
Mat equalizeBrightness(Mat img)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -194,7 +183,6 @@ Mat equalizeBrightness(Mat img)
|
|||||||
normalize(img, img, 0, 255, NORM_MINMAX);
|
normalize(img, img, 0, 255, NORM_MINMAX);
|
||||||
img.convertTo(img, CV_8U); // convert back to unsigned int
|
img.convertTo(img, CV_8U); // convert back to unsigned int
|
||||||
|
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +217,6 @@ void fillMask(Mat img, const Mat mask, Scalar color)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void drawX(Mat img, Rect rect, Scalar color, int thickness)
|
void drawX(Mat img, Rect rect, Scalar color, int thickness)
|
||||||
{
|
{
|
||||||
Point tl(rect.x, rect.y);
|
Point tl(rect.x, rect.y);
|
||||||
@@ -257,7 +244,6 @@ float angleBetweenPoints(Point p1, Point p2)
|
|||||||
return atan2((float) deltaY, (float) deltaX) * (180 / CV_PI);
|
return atan2((float) deltaY, (float) deltaX) * (180 / CV_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Size getSizeMaintainingAspect(Mat inputImg, int maxWidth, int maxHeight)
|
Size getSizeMaintainingAspect(Mat inputImg, int maxWidth, int maxHeight)
|
||||||
{
|
{
|
||||||
float aspect = ((float) inputImg.cols) / ((float) inputImg.rows);
|
float aspect = ((float) inputImg.cols) / ((float) inputImg.rows);
|
||||||
@@ -272,7 +258,6 @@ Size getSizeMaintainingAspect(Mat inputImg, int maxWidth, int maxHeight)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LineSegment::LineSegment()
|
LineSegment::LineSegment()
|
||||||
{
|
{
|
||||||
init(0, 0, 0, 0);
|
init(0, 0, 0, 0);
|
||||||
@@ -302,7 +287,8 @@ void LineSegment::init(int x1, int y1, int x2, int y2)
|
|||||||
this->angle = angleBetweenPoints(p1, p2);
|
this->angle = angleBetweenPoints(p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LineSegment::isPointBelowLine( Point tp ){
|
bool LineSegment::isPointBelowLine( Point tp )
|
||||||
|
{
|
||||||
return ((p2.x - p1.x)*(tp.y - p1.y) - (p2.y - p1.y)*(tp.x - p1.x)) > 0;
|
return ((p2.x - p1.x)*(tp.y - p1.y) - (p2.y - p1.y)*(tp.x - p1.x)) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +317,6 @@ Point LineSegment::intersection(LineSegment line)
|
|||||||
float c1, c2;
|
float c1, c2;
|
||||||
float intersection_X = -1, intersection_Y= -1;
|
float intersection_X = -1, intersection_Y= -1;
|
||||||
|
|
||||||
|
|
||||||
c1 = p1.y - slope * p1.x; // which is same as y2 - slope * x2
|
c1 = p1.y - slope * p1.x; // which is same as y2 - slope * x2
|
||||||
|
|
||||||
c2 = line.p2.y - line.slope * line.p2.x; // which is same as y2 - slope * x2
|
c2 = line.p2.y - line.slope * line.p2.x; // which is same as y2 - slope * x2
|
||||||
@@ -361,8 +346,6 @@ Point LineSegment::intersection(LineSegment line)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Point LineSegment::midpoint()
|
Point LineSegment::midpoint()
|
||||||
{
|
{
|
||||||
// Handle the case where the line is vertical
|
// Handle the case where the line is vertical
|
||||||
|
@@ -23,8 +23,6 @@ VerticalHistogram::VerticalHistogram(Mat inputImage, Mat mask)
|
|||||||
{
|
{
|
||||||
analyzeImage(inputImage, mask);
|
analyzeImage(inputImage, mask);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VerticalHistogram::~VerticalHistogram()
|
VerticalHistogram::~VerticalHistogram()
|
||||||
@@ -33,13 +31,11 @@ VerticalHistogram::~VerticalHistogram()
|
|||||||
colHeights.clear();
|
colHeights.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VerticalHistogram::analyzeImage(Mat inputImage, Mat mask)
|
void VerticalHistogram::analyzeImage(Mat inputImage, Mat mask)
|
||||||
{
|
{
|
||||||
highestPeak = 0;
|
highestPeak = 0;
|
||||||
lowestValley = inputImage.rows;
|
lowestValley = inputImage.rows;
|
||||||
|
|
||||||
|
|
||||||
histoImg = Mat::zeros(inputImage.size(), CV_8U);
|
histoImg = Mat::zeros(inputImage.size(), CV_8U);
|
||||||
|
|
||||||
int columnCount;
|
int columnCount;
|
||||||
@@ -55,7 +51,6 @@ void VerticalHistogram::analyzeImage(Mat inputImage, Mat mask)
|
|||||||
columnCount++;
|
columnCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this->colHeights.push_back(columnCount);
|
this->colHeights.push_back(columnCount);
|
||||||
|
|
||||||
if (columnCount < lowestValley)
|
if (columnCount < lowestValley)
|
||||||
@@ -63,7 +58,6 @@ void VerticalHistogram::analyzeImage(Mat inputImage, Mat mask)
|
|||||||
if (columnCount > highestPeak)
|
if (columnCount > highestPeak)
|
||||||
highestPeak = columnCount;
|
highestPeak = columnCount;
|
||||||
|
|
||||||
|
|
||||||
for (; columnCount > 0; columnCount--)
|
for (; columnCount > 0; columnCount--)
|
||||||
histoImg.at<uchar>(inputImage.rows - columnCount, col) = 255;
|
histoImg.at<uchar>(inputImage.rows - columnCount, col) = 255;
|
||||||
|
|
||||||
@@ -132,7 +126,6 @@ void VerticalHistogram::findValleys()
|
|||||||
if (colHeights[i] > relativePeakHeight)
|
if (colHeights[i] > relativePeakHeight)
|
||||||
relativePeakHeight = colHeights[i];
|
relativePeakHeight = colHeights[i];
|
||||||
|
|
||||||
|
|
||||||
prevDirection = FLAT;
|
prevDirection = FLAT;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -181,7 +174,6 @@ HistogramDirection VerticalHistogram::getHistogramDirection(int index)
|
|||||||
}
|
}
|
||||||
forwardAverage = forwardAverage / ((float) (1 + forwardEndIndex - index));
|
forwardAverage = forwardAverage / ((float) (1 + forwardEndIndex - index));
|
||||||
|
|
||||||
|
|
||||||
float diff = forwardAverage - trailingAverage;
|
float diff = forwardAverage - trailingAverage;
|
||||||
float minDiff = ((float) (highestPeak - lowestValley)) * 0.10;
|
float minDiff = ((float) (highestPeak - lowestValley)) * 0.10;
|
||||||
|
|
||||||
|
116
src/tclap/Arg.h
116
src/tclap/Arg.h
@@ -54,7 +54,8 @@ typedef std::istrstream istringstream;
|
|||||||
#include "ArgTraits.h"
|
#include "ArgTraits.h"
|
||||||
#include "StandardTraits.h"
|
#include "StandardTraits.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A virtual base class that defines the essential data for all arguments.
|
* A virtual base class that defines the essential data for all arguments.
|
||||||
@@ -77,13 +78,21 @@ class Arg
|
|||||||
/**
|
/**
|
||||||
* Indicates whether the rest of the arguments should be ignored.
|
* Indicates whether the rest of the arguments should be ignored.
|
||||||
*/
|
*/
|
||||||
static bool& ignoreRestRef() { static bool ign = false; return ign; }
|
static bool& ignoreRestRef()
|
||||||
|
{
|
||||||
|
static bool ign = false;
|
||||||
|
return ign;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The delimiter that separates an argument flag/name from the
|
* The delimiter that separates an argument flag/name from the
|
||||||
* value.
|
* value.
|
||||||
*/
|
*/
|
||||||
static char& delimiterRef() { static char delim = ' '; return delim; }
|
static char& delimiterRef()
|
||||||
|
{
|
||||||
|
static char delim = ' ';
|
||||||
|
return delim;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@@ -197,24 +206,36 @@ class Arg
|
|||||||
/**
|
/**
|
||||||
* Begin ignoring arguments since the "--" argument was specified.
|
* Begin ignoring arguments since the "--" argument was specified.
|
||||||
*/
|
*/
|
||||||
static void beginIgnoring() { ignoreRestRef() = true; }
|
static void beginIgnoring()
|
||||||
|
{
|
||||||
|
ignoreRestRef() = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to ignore the rest.
|
* Whether to ignore the rest.
|
||||||
*/
|
*/
|
||||||
static bool ignoreRest() { return ignoreRestRef(); }
|
static bool ignoreRest()
|
||||||
|
{
|
||||||
|
return ignoreRestRef();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The delimiter that separates an argument flag/name from the
|
* The delimiter that separates an argument flag/name from the
|
||||||
* value.
|
* value.
|
||||||
*/
|
*/
|
||||||
static char delimiter() { return delimiterRef(); }
|
static char delimiter()
|
||||||
|
{
|
||||||
|
return delimiterRef();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The char used as a place holder when SwitchArgs are combined.
|
* The char used as a place holder when SwitchArgs are combined.
|
||||||
* Currently set to the bell char (ASCII 7).
|
* Currently set to the bell char (ASCII 7).
|
||||||
*/
|
*/
|
||||||
static char blankChar() { return (char)7; }
|
static char blankChar()
|
||||||
|
{
|
||||||
|
return (char)7;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The char that indicates the beginning of a flag. Defaults to '-', but
|
* The char that indicates the beginning of a flag. Defaults to '-', but
|
||||||
@@ -223,7 +244,10 @@ class Arg
|
|||||||
#ifndef TCLAP_FLAGSTARTCHAR
|
#ifndef TCLAP_FLAGSTARTCHAR
|
||||||
#define TCLAP_FLAGSTARTCHAR '-'
|
#define TCLAP_FLAGSTARTCHAR '-'
|
||||||
#endif
|
#endif
|
||||||
static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; }
|
static char flagStartChar()
|
||||||
|
{
|
||||||
|
return TCLAP_FLAGSTARTCHAR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sting that indicates the beginning of a flag. Defaults to "-", but
|
* The sting that indicates the beginning of a flag. Defaults to "-", but
|
||||||
@@ -233,7 +257,10 @@ class Arg
|
|||||||
#ifndef TCLAP_FLAGSTARTSTRING
|
#ifndef TCLAP_FLAGSTARTSTRING
|
||||||
#define TCLAP_FLAGSTARTSTRING "-"
|
#define TCLAP_FLAGSTARTSTRING "-"
|
||||||
#endif
|
#endif
|
||||||
static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; }
|
static const std::string flagStartString()
|
||||||
|
{
|
||||||
|
return TCLAP_FLAGSTARTSTRING;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sting that indicates the beginning of a name. Defaults to "--", but
|
* The sting that indicates the beginning of a name. Defaults to "--", but
|
||||||
@@ -242,18 +269,27 @@ class Arg
|
|||||||
#ifndef TCLAP_NAMESTARTSTRING
|
#ifndef TCLAP_NAMESTARTSTRING
|
||||||
#define TCLAP_NAMESTARTSTRING "--"
|
#define TCLAP_NAMESTARTSTRING "--"
|
||||||
#endif
|
#endif
|
||||||
static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; }
|
static const std::string nameStartString()
|
||||||
|
{
|
||||||
|
return TCLAP_NAMESTARTSTRING;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name used to identify the ignore rest argument.
|
* The name used to identify the ignore rest argument.
|
||||||
*/
|
*/
|
||||||
static const std::string ignoreNameString() { return "ignore_rest"; }
|
static const std::string ignoreNameString()
|
||||||
|
{
|
||||||
|
return "ignore_rest";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the delimiter for all arguments.
|
* Sets the delimiter for all arguments.
|
||||||
* \param c - The character that delimits flags/names from values.
|
* \param c - The character that delimits flags/names from values.
|
||||||
*/
|
*/
|
||||||
static void setDelimiter( char c ) { delimiterRef() = c; }
|
static void setDelimiter( char c )
|
||||||
|
{
|
||||||
|
delimiterRef() = c;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure virtual method meant to handle the parsing and value assignment
|
* Pure virtual method meant to handle the parsing and value assignment
|
||||||
@@ -416,9 +452,9 @@ ExtractValue(T &destVal, const std::string& strVal, ValueLike vl)
|
|||||||
{
|
{
|
||||||
static_cast<void>(vl); // Avoid warning about unused vl
|
static_cast<void>(vl); // Avoid warning about unused vl
|
||||||
std::istringstream is(strVal);
|
std::istringstream is(strVal);
|
||||||
|
|
||||||
int valuesRead = 0;
|
int valuesRead = 0;
|
||||||
while ( is.good() ) {
|
while ( is.good() )
|
||||||
|
{
|
||||||
if ( is.peek() != EOF )
|
if ( is.peek() != EOF )
|
||||||
#ifdef TCLAP_SETBASE_ZERO
|
#ifdef TCLAP_SETBASE_ZERO
|
||||||
is >> std::setbase(0) >> destVal;
|
is >> std::setbase(0) >> destVal;
|
||||||
@@ -427,19 +463,14 @@ ExtractValue(T &destVal, const std::string& strVal, ValueLike vl)
|
|||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
valuesRead++;
|
valuesRead++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( is.fail() )
|
if ( is.fail() )
|
||||||
throw( ArgParseException("Couldn't read argument value "
|
throw( ArgParseException("Couldn't read argument value "
|
||||||
"from string '" + strVal + "'"));
|
"from string '" + strVal + "'"));
|
||||||
|
|
||||||
|
|
||||||
if ( valuesRead > 1 )
|
if ( valuesRead > 1 )
|
||||||
throw( ArgParseException("More than one valid value parsed from "
|
throw( ArgParseException("More than one valid value parsed from "
|
||||||
"string '" + strVal + "'"));
|
"string '" + strVal + "'"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -480,7 +511,6 @@ inline Arg::Arg(const std::string& flag,
|
|||||||
if ( _flag.length() > 1 )
|
if ( _flag.length() > 1 )
|
||||||
throw(SpecificationException(
|
throw(SpecificationException(
|
||||||
"Argument flag can only be one character long", toString() ) );
|
"Argument flag can only be one character long", toString() ) );
|
||||||
|
|
||||||
if ( _name != ignoreNameString() &&
|
if ( _name != ignoreNameString() &&
|
||||||
( _flag == Arg::flagStartString() ||
|
( _flag == Arg::flagStartString() ||
|
||||||
_flag == Arg::nameStartString() ||
|
_flag == Arg::nameStartString() ||
|
||||||
@@ -489,7 +519,6 @@ inline Arg::Arg(const std::string& flag,
|
|||||||
Arg::flagStartString() + "' or '" +
|
Arg::flagStartString() + "' or '" +
|
||||||
Arg::nameStartString() + "' or a space.",
|
Arg::nameStartString() + "' or a space.",
|
||||||
toString() ) );
|
toString() ) );
|
||||||
|
|
||||||
if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) ||
|
if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) ||
|
||||||
( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) ||
|
( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) ||
|
||||||
( _name.find( " ", 0 ) != std::string::npos ) )
|
( _name.find( " ", 0 ) != std::string::npos ) )
|
||||||
@@ -497,7 +526,6 @@ inline Arg::Arg(const std::string& flag,
|
|||||||
Arg::flagStartString() + "' or '" +
|
Arg::flagStartString() + "' or '" +
|
||||||
Arg::nameStartString() + "' or space.",
|
Arg::nameStartString() + "' or space.",
|
||||||
toString() ) );
|
toString() ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Arg::~Arg() { }
|
inline Arg::~Arg() { }
|
||||||
@@ -505,42 +533,31 @@ inline Arg::~Arg() { }
|
|||||||
inline std::string Arg::shortID( const std::string& valueId ) const
|
inline std::string Arg::shortID( const std::string& valueId ) const
|
||||||
{
|
{
|
||||||
std::string id = "";
|
std::string id = "";
|
||||||
|
|
||||||
if ( _flag != "" )
|
if ( _flag != "" )
|
||||||
id = Arg::flagStartString() + _flag;
|
id = Arg::flagStartString() + _flag;
|
||||||
else
|
else
|
||||||
id = Arg::nameStartString() + _name;
|
id = Arg::nameStartString() + _name;
|
||||||
|
|
||||||
if ( _valueRequired )
|
if ( _valueRequired )
|
||||||
id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
|
id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
|
||||||
|
|
||||||
if ( !_required )
|
if ( !_required )
|
||||||
id = "[" + id + "]";
|
id = "[" + id + "]";
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string Arg::longID( const std::string& valueId ) const
|
inline std::string Arg::longID( const std::string& valueId ) const
|
||||||
{
|
{
|
||||||
std::string id = "";
|
std::string id = "";
|
||||||
|
|
||||||
if ( _flag != "" )
|
if ( _flag != "" )
|
||||||
{
|
{
|
||||||
id += Arg::flagStartString() + _flag;
|
id += Arg::flagStartString() + _flag;
|
||||||
|
|
||||||
if ( _valueRequired )
|
if ( _valueRequired )
|
||||||
id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
|
id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
|
||||||
|
|
||||||
id += ", ";
|
id += ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
id += Arg::nameStartString() + _name;
|
id += Arg::nameStartString() + _name;
|
||||||
|
|
||||||
if ( _valueRequired )
|
if ( _valueRequired )
|
||||||
id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
|
id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Arg::operator==(const Arg& a) const
|
inline bool Arg::operator==(const Arg& a) const
|
||||||
@@ -556,21 +573,31 @@ inline std::string Arg::getDescription() const
|
|||||||
std::string desc = "";
|
std::string desc = "";
|
||||||
if ( _required )
|
if ( _required )
|
||||||
desc = "(" + _requireLabel + ") ";
|
desc = "(" + _requireLabel + ") ";
|
||||||
|
|
||||||
// if ( _valueRequired )
|
// if ( _valueRequired )
|
||||||
// desc += "(value required) ";
|
// desc += "(value required) ";
|
||||||
|
|
||||||
desc += _description;
|
desc += _description;
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::string& Arg::getFlag() const { return _flag; }
|
inline const std::string& Arg::getFlag() const
|
||||||
|
{
|
||||||
|
return _flag;
|
||||||
|
}
|
||||||
|
|
||||||
inline const std::string& Arg::getName() const { return _name; }
|
inline const std::string& Arg::getName() const
|
||||||
|
{
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Arg::isRequired() const { return _required; }
|
inline bool Arg::isRequired() const
|
||||||
|
{
|
||||||
|
return _required;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Arg::isValueRequired() const { return _valueRequired; }
|
inline bool Arg::isValueRequired() const
|
||||||
|
{
|
||||||
|
return _valueRequired;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Arg::isSet() const
|
inline bool Arg::isSet() const
|
||||||
{
|
{
|
||||||
@@ -580,7 +607,10 @@ inline bool Arg::isSet() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Arg::isIgnoreable() const { return _ignoreable; }
|
inline bool Arg::isIgnoreable() const
|
||||||
|
{
|
||||||
|
return _ignoreable;
|
||||||
|
}
|
||||||
|
|
||||||
inline void Arg::setRequireLabel( const std::string& s)
|
inline void Arg::setRequireLabel( const std::string& s)
|
||||||
{
|
{
|
||||||
@@ -599,12 +629,9 @@ inline bool Arg::argMatches( const std::string& argFlag ) const
|
|||||||
inline std::string Arg::toString() const
|
inline std::string Arg::toString() const
|
||||||
{
|
{
|
||||||
std::string s = "";
|
std::string s = "";
|
||||||
|
|
||||||
if ( _flag != "" )
|
if ( _flag != "" )
|
||||||
s += Arg::flagStartString() + _flag + " ";
|
s += Arg::flagStartString() + _flag + " ";
|
||||||
|
|
||||||
s += "(" + Arg::nameStartString() + _name + ")";
|
s += "(" + Arg::nameStartString() + _name + ")";
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,13 +653,11 @@ inline void Arg::trimFlag(std::string& flag, std::string& value) const
|
|||||||
stop = i;
|
stop = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( stop > 1 )
|
if ( stop > 1 )
|
||||||
{
|
{
|
||||||
value = flag.substr(stop+1);
|
value = flag.substr(stop+1);
|
||||||
flag = flag.substr(0,stop);
|
flag = flag.substr(0,stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -643,7 +668,6 @@ inline bool Arg::_hasBlanks( const std::string& s ) const
|
|||||||
for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
|
for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
|
||||||
if ( s[i] == Arg::blankChar() )
|
if ( s[i] == Arg::blankChar() )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -27,7 +27,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple class that defines and argument exception. Should be caught
|
* A simple class that defines and argument exception. Should be caught
|
||||||
@@ -61,7 +62,10 @@ class ArgException : public std::exception
|
|||||||
/**
|
/**
|
||||||
* Returns the error text.
|
* Returns the error text.
|
||||||
*/
|
*/
|
||||||
std::string error() const { return ( _errorText ); }
|
std::string error() const
|
||||||
|
{
|
||||||
|
return ( _errorText );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the argument id.
|
* Returns the argument id.
|
||||||
@@ -184,11 +188,15 @@ class SpecificationException : public ArgException
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExitException {
|
class ExitException
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
ExitException(int estat) : _estat(estat) {}
|
ExitException(int estat) : _estat(estat) {}
|
||||||
|
|
||||||
int getExitStatus() const { return _estat; }
|
int getExitStatus() const
|
||||||
|
{
|
||||||
|
return _estat;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _estat;
|
int _estat;
|
||||||
|
@@ -26,7 +26,8 @@
|
|||||||
#ifndef TCLAP_ARGTRAITS_H
|
#ifndef TCLAP_ARGTRAITS_H
|
||||||
#define TCLAP_ARGTRAITS_H
|
#define TCLAP_ARGTRAITS_H
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
// We use two empty structs to get compile type specialization
|
// We use two empty structs to get compile type specialization
|
||||||
// function to work
|
// function to work
|
||||||
@@ -35,7 +36,8 @@ namespace TCLAP {
|
|||||||
* A value like argument value type is a value that can be set using
|
* A value like argument value type is a value that can be set using
|
||||||
* operator>>. This is the default value type.
|
* operator>>. This is the default value type.
|
||||||
*/
|
*/
|
||||||
struct ValueLike {
|
struct ValueLike
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
virtual ~ValueLike() {}
|
virtual ~ValueLike() {}
|
||||||
};
|
};
|
||||||
@@ -45,7 +47,8 @@ struct ValueLike {
|
|||||||
* operator=(string). Usefull if the value type contains spaces which
|
* operator=(string). Usefull if the value type contains spaces which
|
||||||
* will be broken up into individual tokens by operator>>.
|
* will be broken up into individual tokens by operator>>.
|
||||||
*/
|
*/
|
||||||
struct StringLike {
|
struct StringLike
|
||||||
|
{
|
||||||
virtual ~StringLike() {}
|
virtual ~StringLike() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,7 +57,8 @@ struct StringLike {
|
|||||||
* traits. This is a compile time thing and does not add any overhead
|
* traits. This is a compile time thing and does not add any overhead
|
||||||
* to the inherenting class.
|
* to the inherenting class.
|
||||||
*/
|
*/
|
||||||
struct StringLikeTrait {
|
struct StringLikeTrait
|
||||||
|
{
|
||||||
typedef StringLike ValueCategory;
|
typedef StringLike ValueCategory;
|
||||||
virtual ~StringLikeTrait() {}
|
virtual ~StringLikeTrait() {}
|
||||||
};
|
};
|
||||||
@@ -64,7 +68,8 @@ struct StringLikeTrait {
|
|||||||
* traits. This is a compile time thing and does not add any overhead
|
* traits. This is a compile time thing and does not add any overhead
|
||||||
* to the inherenting class.
|
* to the inherenting class.
|
||||||
*/
|
*/
|
||||||
struct ValueLikeTrait {
|
struct ValueLikeTrait
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
virtual ~ValueLikeTrait() {}
|
virtual ~ValueLikeTrait() {}
|
||||||
};
|
};
|
||||||
@@ -76,7 +81,8 @@ struct ValueLikeTrait {
|
|||||||
* supported types are StringLike and ValueLike.
|
* supported types are StringLike and ValueLike.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct ArgTraits {
|
struct ArgTraits
|
||||||
|
{
|
||||||
typedef typename T::ValueCategory ValueCategory;
|
typedef typename T::ValueCategory ValueCategory;
|
||||||
virtual ~ArgTraits() {}
|
virtual ~ArgTraits() {}
|
||||||
//typedef ValueLike ValueCategory;
|
//typedef ValueLike ValueCategory;
|
||||||
|
@@ -48,7 +48,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdlib.h> // Needed for exit(), which isn't defined in some envs.
|
#include <stdlib.h> // Needed for exit(), which isn't defined in some envs.
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
template<typename T> void DelPtr(T ptr)
|
template<typename T> void DelPtr(T ptr)
|
||||||
{
|
{
|
||||||
@@ -346,8 +347,8 @@ inline CmdLine::~CmdLine()
|
|||||||
{
|
{
|
||||||
ClearContainer(_argDeleteOnExitList);
|
ClearContainer(_argDeleteOnExitList);
|
||||||
ClearContainer(_visitorDeleteOnExitList);
|
ClearContainer(_visitorDeleteOnExitList);
|
||||||
|
if ( !_userSetOutput )
|
||||||
if ( !_userSetOutput ) {
|
{
|
||||||
delete _output;
|
delete _output;
|
||||||
_output = 0;
|
_output = 0;
|
||||||
}
|
}
|
||||||
@@ -356,11 +357,8 @@ inline CmdLine::~CmdLine()
|
|||||||
inline void CmdLine::_constructor()
|
inline void CmdLine::_constructor()
|
||||||
{
|
{
|
||||||
_output = new StdOutput;
|
_output = new StdOutput;
|
||||||
|
|
||||||
Arg::setDelimiter( _delimiter );
|
Arg::setDelimiter( _delimiter );
|
||||||
|
|
||||||
Visitor* v;
|
Visitor* v;
|
||||||
|
|
||||||
if ( _helpAndVersion )
|
if ( _helpAndVersion )
|
||||||
{
|
{
|
||||||
v = new HelpVisitor( this, &_output );
|
v = new HelpVisitor( this, &_output );
|
||||||
@@ -370,7 +368,6 @@ inline void CmdLine::_constructor()
|
|||||||
add( help );
|
add( help );
|
||||||
deleteOnExit(help);
|
deleteOnExit(help);
|
||||||
deleteOnExit(v);
|
deleteOnExit(v);
|
||||||
|
|
||||||
v = new VersionVisitor( this, &_output );
|
v = new VersionVisitor( this, &_output );
|
||||||
SwitchArg* vers = new SwitchArg("","version",
|
SwitchArg* vers = new SwitchArg("","version",
|
||||||
"Displays version information and exits.",
|
"Displays version information and exits.",
|
||||||
@@ -379,7 +376,6 @@ inline void CmdLine::_constructor()
|
|||||||
deleteOnExit(vers);
|
deleteOnExit(vers);
|
||||||
deleteOnExit(v);
|
deleteOnExit(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
v = new IgnoreRestVisitor();
|
v = new IgnoreRestVisitor();
|
||||||
SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
|
SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
|
||||||
Arg::ignoreNameString(),
|
Arg::ignoreNameString(),
|
||||||
@@ -393,7 +389,6 @@ inline void CmdLine::_constructor()
|
|||||||
inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
|
inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
|
||||||
{
|
{
|
||||||
_xorHandler.add( ors );
|
_xorHandler.add( ors );
|
||||||
|
|
||||||
for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
|
for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
|
||||||
{
|
{
|
||||||
(*it)->forceRequired();
|
(*it)->forceRequired();
|
||||||
@@ -422,9 +417,7 @@ inline void CmdLine::add( Arg* a )
|
|||||||
throw( SpecificationException(
|
throw( SpecificationException(
|
||||||
"Argument with same flag/name already exists!",
|
"Argument with same flag/name already exists!",
|
||||||
a->longID() ) );
|
a->longID() ) );
|
||||||
|
|
||||||
a->addToList( _argList );
|
a->addToList( _argList );
|
||||||
|
|
||||||
if ( a->isRequired() )
|
if ( a->isRequired() )
|
||||||
_numRequired++;
|
_numRequired++;
|
||||||
}
|
}
|
||||||
@@ -437,7 +430,6 @@ inline void CmdLine::parse(int argc, const char * const * argv)
|
|||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
args.push_back(argv[i]);
|
args.push_back(argv[i]);
|
||||||
|
|
||||||
parse(args);
|
parse(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,18 +437,17 @@ inline void CmdLine::parse(std::vector<std::string>& args)
|
|||||||
{
|
{
|
||||||
bool shouldExit = false;
|
bool shouldExit = false;
|
||||||
int estat = 0;
|
int estat = 0;
|
||||||
|
try
|
||||||
try {
|
{
|
||||||
_progName = args.front();
|
_progName = args.front();
|
||||||
args.erase(args.begin());
|
args.erase(args.begin());
|
||||||
|
|
||||||
int requiredCount = 0;
|
int requiredCount = 0;
|
||||||
|
|
||||||
for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
|
for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
|
||||||
{
|
{
|
||||||
bool matched = false;
|
bool matched = false;
|
||||||
for (ArgListIterator it = _argList.begin();
|
for (ArgListIterator it = _argList.begin();
|
||||||
it != _argList.end(); it++) {
|
it != _argList.end(); it++)
|
||||||
|
{
|
||||||
if ( (*it)->processArg( &i, args ) )
|
if ( (*it)->processArg( &i, args ) )
|
||||||
{
|
{
|
||||||
requiredCount += _xorHandler.check( *it );
|
requiredCount += _xorHandler.check( *it );
|
||||||
@@ -464,46 +455,47 @@ inline void CmdLine::parse(std::vector<std::string>& args)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks to see if the argument is an empty combined
|
// checks to see if the argument is an empty combined
|
||||||
// switch and if so, then we've actually matched it
|
// switch and if so, then we've actually matched it
|
||||||
if ( !matched && _emptyCombined( args[i] ) )
|
if ( !matched && _emptyCombined( args[i] ) )
|
||||||
matched = true;
|
matched = true;
|
||||||
|
|
||||||
if ( !matched && !Arg::ignoreRest() )
|
if ( !matched && !Arg::ignoreRest() )
|
||||||
throw(CmdLineParseException("Couldn't find match "
|
throw(CmdLineParseException("Couldn't find match "
|
||||||
"for argument",
|
"for argument",
|
||||||
args[i]));
|
args[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( requiredCount < _numRequired )
|
if ( requiredCount < _numRequired )
|
||||||
missingArgsException();
|
missingArgsException();
|
||||||
|
|
||||||
if ( requiredCount > _numRequired )
|
if ( requiredCount > _numRequired )
|
||||||
throw(CmdLineParseException("Too many arguments!"));
|
throw(CmdLineParseException("Too many arguments!"));
|
||||||
|
}
|
||||||
} catch ( ArgException& e ) {
|
catch ( ArgException& e )
|
||||||
|
{
|
||||||
// If we're not handling the exceptions, rethrow.
|
// If we're not handling the exceptions, rethrow.
|
||||||
if ( !_handleExceptions) {
|
if ( !_handleExceptions)
|
||||||
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
try
|
||||||
try {
|
{
|
||||||
_output->failure(*this,e);
|
_output->failure(*this,e);
|
||||||
} catch ( ExitException &ee ) {
|
}
|
||||||
|
catch ( ExitException &ee )
|
||||||
|
{
|
||||||
estat = ee.getExitStatus();
|
estat = ee.getExitStatus();
|
||||||
shouldExit = true;
|
shouldExit = true;
|
||||||
}
|
}
|
||||||
} catch (ExitException &ee) {
|
}
|
||||||
|
catch (ExitException &ee)
|
||||||
|
{
|
||||||
// If we're not handling the exceptions, rethrow.
|
// If we're not handling the exceptions, rethrow.
|
||||||
if ( !_handleExceptions) {
|
if ( !_handleExceptions)
|
||||||
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
estat = ee.getExitStatus();
|
estat = ee.getExitStatus();
|
||||||
shouldExit = true;
|
shouldExit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldExit)
|
if (shouldExit)
|
||||||
exit(estat);
|
exit(estat);
|
||||||
}
|
}
|
||||||
@@ -512,18 +504,15 @@ inline bool CmdLine::_emptyCombined(const std::string& s)
|
|||||||
{
|
{
|
||||||
if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
|
if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
|
for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
|
||||||
if ( s[i] != Arg::blankChar() )
|
if ( s[i] != Arg::blankChar() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CmdLine::missingArgsException()
|
inline void CmdLine::missingArgsException()
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
std::string missingArgList;
|
std::string missingArgList;
|
||||||
for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
|
for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
|
||||||
{
|
{
|
||||||
@@ -535,15 +524,12 @@ inline void CmdLine::missingArgsException()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
missingArgList = missingArgList.substr(0,missingArgList.length()-2);
|
missingArgList = missingArgList.substr(0,missingArgList.length()-2);
|
||||||
|
|
||||||
std::string msg;
|
std::string msg;
|
||||||
if ( count > 1 )
|
if ( count > 1 )
|
||||||
msg = "Required arguments missing: ";
|
msg = "Required arguments missing: ";
|
||||||
else
|
else
|
||||||
msg = "Required argument missing: ";
|
msg = "Required argument missing: ";
|
||||||
|
|
||||||
msg += missingArgList;
|
msg += missingArgList;
|
||||||
|
|
||||||
throw(CmdLineParseException(msg));
|
throw(CmdLineParseException(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,7 +605,6 @@ inline void CmdLine::reset()
|
|||||||
{
|
{
|
||||||
for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
|
for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
|
||||||
(*it)->reset();
|
(*it)->reset();
|
||||||
|
|
||||||
_progName.clear();
|
_progName.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,7 +30,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
class Arg;
|
class Arg;
|
||||||
class CmdLineOutput;
|
class CmdLineOutput;
|
||||||
|
@@ -30,7 +30,8 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
class CmdLineInterface;
|
class CmdLineInterface;
|
||||||
class ArgException;
|
class ArgException;
|
||||||
|
@@ -29,7 +29,8 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface that defines the interaction between the Arg and Constraint.
|
* The interface that defines the interaction between the Arg and Constraint.
|
||||||
@@ -61,7 +62,10 @@ class Constraint
|
|||||||
* Silences warnings about Constraint being a base class with virtual
|
* Silences warnings about Constraint being a base class with virtual
|
||||||
* functions but without a virtual destructor.
|
* functions but without a virtual destructor.
|
||||||
*/
|
*/
|
||||||
virtual ~Constraint() { ; }
|
virtual ~Constraint()
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace TCLAP
|
} //namespace TCLAP
|
||||||
|
@@ -34,7 +34,8 @@
|
|||||||
#include <tclap/XorHandler.h>
|
#include <tclap/XorHandler.h>
|
||||||
#include <tclap/Arg.h>
|
#include <tclap/Arg.h>
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that generates DocBook output for usage() method for the
|
* A class that generates DocBook output for usage() method for the
|
||||||
@@ -101,28 +102,21 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
|
|||||||
XorHandler xorHandler = _cmd.getXorHandler();
|
XorHandler xorHandler = _cmd.getXorHandler();
|
||||||
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
||||||
basename(progName);
|
basename(progName);
|
||||||
|
|
||||||
std::cout << "<?xml version='1.0'?>" << std::endl;
|
std::cout << "<?xml version='1.0'?>" << std::endl;
|
||||||
std::cout << "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"" << std::endl;
|
std::cout << "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"" << std::endl;
|
||||||
std::cout << "\t\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">" << std::endl << std::endl;
|
std::cout << "\t\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">" << std::endl << std::endl;
|
||||||
|
|
||||||
std::cout << "<refentry>" << std::endl;
|
std::cout << "<refentry>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<refmeta>" << std::endl;
|
std::cout << "<refmeta>" << std::endl;
|
||||||
std::cout << "<refentrytitle>" << progName << "</refentrytitle>" << std::endl;
|
std::cout << "<refentrytitle>" << progName << "</refentrytitle>" << std::endl;
|
||||||
std::cout << "<manvolnum>1</manvolnum>" << std::endl;
|
std::cout << "<manvolnum>1</manvolnum>" << std::endl;
|
||||||
std::cout << "</refmeta>" << std::endl;
|
std::cout << "</refmeta>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<refnamediv>" << std::endl;
|
std::cout << "<refnamediv>" << std::endl;
|
||||||
std::cout << "<refname>" << progName << "</refname>" << std::endl;
|
std::cout << "<refname>" << progName << "</refname>" << std::endl;
|
||||||
std::cout << "<refpurpose>" << _cmd.getMessage() << "</refpurpose>" << std::endl;
|
std::cout << "<refpurpose>" << _cmd.getMessage() << "</refpurpose>" << std::endl;
|
||||||
std::cout << "</refnamediv>" << std::endl;
|
std::cout << "</refnamediv>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<refsynopsisdiv>" << std::endl;
|
std::cout << "<refsynopsisdiv>" << std::endl;
|
||||||
std::cout << "<cmdsynopsis>" << std::endl;
|
std::cout << "<cmdsynopsis>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<command>" << progName << "</command>" << std::endl;
|
std::cout << "<command>" << progName << "</command>" << std::endl;
|
||||||
|
|
||||||
// xor
|
// xor
|
||||||
for ( int i = 0; (unsigned int)i < xorList.size(); i++ )
|
for ( int i = 0; (unsigned int)i < xorList.size(); i++ )
|
||||||
{
|
{
|
||||||
@@ -130,45 +124,34 @@ inline void DocBookOutput::usage(CmdLineInterface& _cmd )
|
|||||||
for ( ArgVectorIterator it = xorList[i].begin();
|
for ( ArgVectorIterator it = xorList[i].begin();
|
||||||
it != xorList[i].end(); it++ )
|
it != xorList[i].end(); it++ )
|
||||||
printShortArg((*it));
|
printShortArg((*it));
|
||||||
|
|
||||||
std::cout << "</group>" << std::endl;
|
std::cout << "</group>" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rest of args
|
// rest of args
|
||||||
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
||||||
if ( !xorHandler.contains( (*it) ) )
|
if ( !xorHandler.contains( (*it) ) )
|
||||||
printShortArg((*it));
|
printShortArg((*it));
|
||||||
|
|
||||||
std::cout << "</cmdsynopsis>" << std::endl;
|
std::cout << "</cmdsynopsis>" << std::endl;
|
||||||
std::cout << "</refsynopsisdiv>" << std::endl;
|
std::cout << "</refsynopsisdiv>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<refsect1>" << std::endl;
|
std::cout << "<refsect1>" << std::endl;
|
||||||
std::cout << "<title>Description</title>" << std::endl;
|
std::cout << "<title>Description</title>" << std::endl;
|
||||||
std::cout << "<para>" << std::endl;
|
std::cout << "<para>" << std::endl;
|
||||||
std::cout << _cmd.getMessage() << std::endl;
|
std::cout << _cmd.getMessage() << std::endl;
|
||||||
std::cout << "</para>" << std::endl;
|
std::cout << "</para>" << std::endl;
|
||||||
std::cout << "</refsect1>" << std::endl;
|
std::cout << "</refsect1>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<refsect1>" << std::endl;
|
std::cout << "<refsect1>" << std::endl;
|
||||||
std::cout << "<title>Options</title>" << std::endl;
|
std::cout << "<title>Options</title>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<variablelist>" << std::endl;
|
std::cout << "<variablelist>" << std::endl;
|
||||||
|
|
||||||
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
||||||
printLongArg((*it));
|
printLongArg((*it));
|
||||||
|
|
||||||
std::cout << "</variablelist>" << std::endl;
|
std::cout << "</variablelist>" << std::endl;
|
||||||
std::cout << "</refsect1>" << std::endl;
|
std::cout << "</refsect1>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<refsect1>" << std::endl;
|
std::cout << "<refsect1>" << std::endl;
|
||||||
std::cout << "<title>Version</title>" << std::endl;
|
std::cout << "<title>Version</title>" << std::endl;
|
||||||
std::cout << "<para>" << std::endl;
|
std::cout << "<para>" << std::endl;
|
||||||
std::cout << xversion << std::endl;
|
std::cout << xversion << std::endl;
|
||||||
std::cout << "</para>" << std::endl;
|
std::cout << "</para>" << std::endl;
|
||||||
std::cout << "</refsect1>" << std::endl;
|
std::cout << "</refsect1>" << std::endl;
|
||||||
|
|
||||||
std::cout << "</refentry>" << std::endl;
|
std::cout << "</refentry>" << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DocBookOutput::failure( CmdLineInterface& _cmd,
|
inline void DocBookOutput::failure( CmdLineInterface& _cmd,
|
||||||
@@ -213,22 +196,17 @@ inline void DocBookOutput::printShortArg(Arg* a)
|
|||||||
{
|
{
|
||||||
std::string lt = "<";
|
std::string lt = "<";
|
||||||
std::string gt = ">";
|
std::string gt = ">";
|
||||||
|
|
||||||
std::string id = a->shortID();
|
std::string id = a->shortID();
|
||||||
substituteSpecialChars(id,'<',lt);
|
substituteSpecialChars(id,'<',lt);
|
||||||
substituteSpecialChars(id,'>',gt);
|
substituteSpecialChars(id,'>',gt);
|
||||||
removeChar(id,'[');
|
removeChar(id,'[');
|
||||||
removeChar(id,']');
|
removeChar(id,']');
|
||||||
|
|
||||||
std::string choice = "opt";
|
std::string choice = "opt";
|
||||||
if ( a->isRequired() )
|
if ( a->isRequired() )
|
||||||
choice = "plain";
|
choice = "plain";
|
||||||
|
|
||||||
std::cout << "<arg choice='" << choice << '\'';
|
std::cout << "<arg choice='" << choice << '\'';
|
||||||
if ( a->acceptsMultipleValues() )
|
if ( a->acceptsMultipleValues() )
|
||||||
std::cout << " rep='repeat'";
|
std::cout << " rep='repeat'";
|
||||||
|
|
||||||
|
|
||||||
std::cout << '>';
|
std::cout << '>';
|
||||||
if ( !a->getFlag().empty() )
|
if ( !a->getFlag().empty() )
|
||||||
std::cout << a->flagStartChar() << a->getFlag();
|
std::cout << a->flagStartChar() << a->getFlag();
|
||||||
@@ -246,20 +224,16 @@ inline void DocBookOutput::printShortArg(Arg* a)
|
|||||||
std::cout << "<replaceable>" << arg << "</replaceable>";
|
std::cout << "<replaceable>" << arg << "</replaceable>";
|
||||||
}
|
}
|
||||||
std::cout << "</arg>" << std::endl;
|
std::cout << "</arg>" << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DocBookOutput::printLongArg(Arg* a)
|
inline void DocBookOutput::printLongArg(Arg* a)
|
||||||
{
|
{
|
||||||
std::string lt = "<";
|
std::string lt = "<";
|
||||||
std::string gt = ">";
|
std::string gt = ">";
|
||||||
|
|
||||||
std::string desc = a->getDescription();
|
std::string desc = a->getDescription();
|
||||||
substituteSpecialChars(desc,'<',lt);
|
substituteSpecialChars(desc,'<',lt);
|
||||||
substituteSpecialChars(desc,'>',gt);
|
substituteSpecialChars(desc,'>',gt);
|
||||||
|
|
||||||
std::cout << "<varlistentry>" << std::endl;
|
std::cout << "<varlistentry>" << std::endl;
|
||||||
|
|
||||||
if ( !a->getFlag().empty() )
|
if ( !a->getFlag().empty() )
|
||||||
{
|
{
|
||||||
std::cout << "<term>" << std::endl;
|
std::cout << "<term>" << std::endl;
|
||||||
@@ -268,7 +242,6 @@ inline void DocBookOutput::printLongArg(Arg* a)
|
|||||||
std::cout << "</option>" << std::endl;
|
std::cout << "</option>" << std::endl;
|
||||||
std::cout << "</term>" << std::endl;
|
std::cout << "</term>" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "<term>" << std::endl;
|
std::cout << "<term>" << std::endl;
|
||||||
std::cout << "<option>";
|
std::cout << "<option>";
|
||||||
std::cout << a->nameStartString() << a->getName();
|
std::cout << a->nameStartString() << a->getName();
|
||||||
@@ -285,13 +258,11 @@ inline void DocBookOutput::printLongArg(Arg* a)
|
|||||||
}
|
}
|
||||||
std::cout << "</option>" << std::endl;
|
std::cout << "</option>" << std::endl;
|
||||||
std::cout << "</term>" << std::endl;
|
std::cout << "</term>" << std::endl;
|
||||||
|
|
||||||
std::cout << "<listitem>" << std::endl;
|
std::cout << "<listitem>" << std::endl;
|
||||||
std::cout << "<para>" << std::endl;
|
std::cout << "<para>" << std::endl;
|
||||||
std::cout << desc << std::endl;
|
std::cout << desc << std::endl;
|
||||||
std::cout << "</para>" << std::endl;
|
std::cout << "</para>" << std::endl;
|
||||||
std::cout << "</listitem>" << std::endl;
|
std::cout << "</listitem>" << std::endl;
|
||||||
|
|
||||||
std::cout << "</varlistentry>" << std::endl;
|
std::cout << "</varlistentry>" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,8 @@
|
|||||||
#include "CmdLineOutput.h"
|
#include "CmdLineOutput.h"
|
||||||
#include "Visitor.h"
|
#include "Visitor.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Visitor object that calls the usage method of the given CmdLineOutput
|
* A Visitor object that calls the usage method of the given CmdLineOutput
|
||||||
@@ -67,7 +68,11 @@ class HelpVisitor: public Visitor
|
|||||||
* Calls the usage method of the CmdLineOutput for the
|
* Calls the usage method of the CmdLineOutput for the
|
||||||
* specified CmdLine.
|
* specified CmdLine.
|
||||||
*/
|
*/
|
||||||
void visit() { (*_out)->usage(*_cmd); throw ExitException(0); }
|
void visit()
|
||||||
|
{
|
||||||
|
(*_out)->usage(*_cmd);
|
||||||
|
throw ExitException(0);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -26,7 +26,8 @@
|
|||||||
#include "Visitor.h"
|
#include "Visitor.h"
|
||||||
#include "Arg.h"
|
#include "Arg.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Vistor that tells the CmdLine to begin ignoring arguments after
|
* A Vistor that tells the CmdLine to begin ignoring arguments after
|
||||||
@@ -44,7 +45,10 @@ class IgnoreRestVisitor: public Visitor
|
|||||||
/**
|
/**
|
||||||
* Sets Arg::_ignoreRest.
|
* Sets Arg::_ignoreRest.
|
||||||
*/
|
*/
|
||||||
void visit() { Arg::beginIgnoring(); }
|
void visit()
|
||||||
|
{
|
||||||
|
Arg::beginIgnoring();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,8 @@
|
|||||||
#include "Arg.h"
|
#include "Arg.h"
|
||||||
#include "Constraint.h"
|
#include "Constraint.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* An argument that allows multiple values of type T to be specified. Very
|
* An argument that allows multiple values of type T to be specified. Very
|
||||||
* similar to a ValueArg, except a vector of values will be returned
|
* similar to a ValueArg, except a vector of values will be returned
|
||||||
@@ -191,13 +192,19 @@ public:
|
|||||||
* Returns an iterator over the values parsed from the command
|
* Returns an iterator over the values parsed from the command
|
||||||
* line.
|
* line.
|
||||||
*/
|
*/
|
||||||
const_iterator begin() const { return _values.begin(); }
|
const_iterator begin() const
|
||||||
|
{
|
||||||
|
return _values.begin();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the end of the values parsed from the command
|
* Returns the end of the values parsed from the command
|
||||||
* line.
|
* line.
|
||||||
*/
|
*/
|
||||||
const_iterator end() const { return _values.end(); }
|
const_iterator end() const
|
||||||
|
{
|
||||||
|
return _values.end();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the a short id string. Used in the usage.
|
* Returns the a short id string. Used in the usage.
|
||||||
@@ -302,29 +309,27 @@ MultiArg<T>::MultiArg(const std::string& flag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
const std::vector<T>& MultiArg<T>::getValue() { return _values; }
|
const std::vector<T>& MultiArg<T>::getValue()
|
||||||
|
{
|
||||||
|
return _values;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
if ( _ignoreable && Arg::ignoreRest() )
|
if ( _ignoreable && Arg::ignoreRest() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( _hasBlanks( args[*i] ) )
|
if ( _hasBlanks( args[*i] ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string flag = args[*i];
|
std::string flag = args[*i];
|
||||||
std::string value = "";
|
std::string value = "";
|
||||||
|
|
||||||
trimFlag( flag, value );
|
trimFlag( flag, value );
|
||||||
|
|
||||||
if ( argMatches( flag ) )
|
if ( argMatches( flag ) )
|
||||||
{
|
{
|
||||||
if ( Arg::delimiter() != ' ' && value == "" )
|
if ( Arg::delimiter() != ' ' && value == "" )
|
||||||
throw( ArgParseException(
|
throw( ArgParseException(
|
||||||
"Couldn't find delimiter for this argument!",
|
"Couldn't find delimiter for this argument!",
|
||||||
toString() ) );
|
toString() ) );
|
||||||
|
|
||||||
// always take the first one, regardless of start string
|
// always take the first one, regardless of start string
|
||||||
if ( value == "" )
|
if ( value == "" )
|
||||||
{
|
{
|
||||||
@@ -337,7 +342,6 @@ bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
_extractValue( value );
|
_extractValue( value );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// continuing taking the args until we hit one with a start string
|
// continuing taking the args until we hit one with a start string
|
||||||
while ( (unsigned int)(*i)+1 < args.size() &&
|
while ( (unsigned int)(*i)+1 < args.size() &&
|
||||||
@@ -345,10 +349,8 @@ bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
|||||||
args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
|
args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
|
||||||
_extractValue( args[++(*i)] );
|
_extractValue( args[++(*i)] );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_alreadySet = true;
|
_alreadySet = true;
|
||||||
_checkWithVisitor();
|
_checkWithVisitor();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -391,20 +393,21 @@ bool MultiArg<T>::isRequired() const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void MultiArg<T>::_extractValue( const std::string& val )
|
void MultiArg<T>::_extractValue( const std::string& val )
|
||||||
{
|
{
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
T tmp;
|
T tmp;
|
||||||
ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory());
|
ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory());
|
||||||
_values.push_back(tmp);
|
_values.push_back(tmp);
|
||||||
} catch( ArgParseException &e) {
|
}
|
||||||
|
catch( ArgParseException &e)
|
||||||
|
{
|
||||||
throw ArgParseException(e.error(), toString());
|
throw ArgParseException(e.error(), toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _constraint != NULL )
|
if ( _constraint != NULL )
|
||||||
if ( ! _constraint->check( _values.back() ) )
|
if ( ! _constraint->check( _values.back() ) )
|
||||||
throw( CmdLineParseException( "Value '" + val +
|
throw( CmdLineParseException( "Value '" + val +
|
||||||
|
@@ -30,7 +30,8 @@
|
|||||||
|
|
||||||
#include "SwitchArg.h"
|
#include "SwitchArg.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A multiple switch argument. If the switch is set on the command line, then
|
* A multiple switch argument. If the switch is set on the command line, then
|
||||||
@@ -150,39 +151,34 @@ _default( init )
|
|||||||
parser.add( this );
|
parser.add( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int MultiSwitchArg::getValue() { return _value; }
|
inline int MultiSwitchArg::getValue()
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args)
|
inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
if ( _ignoreable && Arg::ignoreRest() )
|
if ( _ignoreable && Arg::ignoreRest() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( argMatches( args[*i] ))
|
if ( argMatches( args[*i] ))
|
||||||
{
|
{
|
||||||
// so the isSet() method will work
|
// so the isSet() method will work
|
||||||
_alreadySet = true;
|
_alreadySet = true;
|
||||||
|
|
||||||
// Matched argument: increment value.
|
// Matched argument: increment value.
|
||||||
++_value;
|
++_value;
|
||||||
|
|
||||||
_checkWithVisitor();
|
_checkWithVisitor();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if ( combinedSwitchesMatch( args[*i] ) )
|
else if ( combinedSwitchesMatch( args[*i] ) )
|
||||||
{
|
{
|
||||||
// so the isSet() method will work
|
// so the isSet() method will work
|
||||||
_alreadySet = true;
|
_alreadySet = true;
|
||||||
|
|
||||||
// Matched argument: increment value.
|
// Matched argument: increment value.
|
||||||
++_value;
|
++_value;
|
||||||
|
|
||||||
// Check for more in argument and increment value.
|
// Check for more in argument and increment value.
|
||||||
while ( combinedSwitchesMatch( args[*i] ) )
|
while ( combinedSwitchesMatch( args[*i] ) )
|
||||||
++_value;
|
++_value;
|
||||||
|
|
||||||
_checkWithVisitor();
|
_checkWithVisitor();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -26,7 +26,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
class OptionalUnlabeledTracker
|
class OptionalUnlabeledTracker
|
||||||
{
|
{
|
||||||
@@ -35,13 +36,23 @@ class OptionalUnlabeledTracker
|
|||||||
|
|
||||||
static void check( bool req, const std::string& argName );
|
static void check( bool req, const std::string& argName );
|
||||||
|
|
||||||
static void gotOptional() { alreadyOptionalRef() = true; }
|
static void gotOptional()
|
||||||
|
{
|
||||||
|
alreadyOptionalRef() = true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool& alreadyOptional() { return alreadyOptionalRef(); }
|
static bool& alreadyOptional()
|
||||||
|
{
|
||||||
|
return alreadyOptionalRef();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static bool& alreadyOptionalRef() { static bool ct = false; return ct; }
|
static bool& alreadyOptionalRef()
|
||||||
|
{
|
||||||
|
static bool ct = false;
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +62,6 @@ inline void OptionalUnlabeledTracker::check( bool req, const std::string& argNam
|
|||||||
throw( SpecificationException(
|
throw( SpecificationException(
|
||||||
"You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg",
|
"You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg",
|
||||||
argName ) );
|
argName ) );
|
||||||
|
|
||||||
if ( !req )
|
if ( !req )
|
||||||
OptionalUnlabeledTracker::gotOptional();
|
OptionalUnlabeledTracker::gotOptional();
|
||||||
}
|
}
|
||||||
|
@@ -39,7 +39,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
// Integer types
|
// Integer types
|
||||||
@@ -49,7 +50,8 @@ namespace TCLAP {
|
|||||||
* longs have value-like semantics.
|
* longs have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<long> {
|
struct ArgTraits<long>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,7 +59,8 @@ struct ArgTraits<long> {
|
|||||||
* ints have value-like semantics.
|
* ints have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<int> {
|
struct ArgTraits<int>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -65,7 +68,8 @@ struct ArgTraits<int> {
|
|||||||
* shorts have value-like semantics.
|
* shorts have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<short> {
|
struct ArgTraits<short>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,7 +77,8 @@ struct ArgTraits<short> {
|
|||||||
* chars have value-like semantics.
|
* chars have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<char> {
|
struct ArgTraits<char>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,7 +87,8 @@ struct ArgTraits<char> {
|
|||||||
* long longs have value-like semantics.
|
* long longs have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<long long> {
|
struct ArgTraits<long long>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -95,7 +101,8 @@ struct ArgTraits<long long> {
|
|||||||
* unsigned longs have value-like semantics.
|
* unsigned longs have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<unsigned long> {
|
struct ArgTraits<unsigned long>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -103,7 +110,8 @@ struct ArgTraits<unsigned long> {
|
|||||||
* unsigned ints have value-like semantics.
|
* unsigned ints have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<unsigned int> {
|
struct ArgTraits<unsigned int>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,7 +119,8 @@ struct ArgTraits<unsigned int> {
|
|||||||
* unsigned shorts have value-like semantics.
|
* unsigned shorts have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<unsigned short> {
|
struct ArgTraits<unsigned short>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -119,7 +128,8 @@ struct ArgTraits<unsigned short> {
|
|||||||
* unsigned chars have value-like semantics.
|
* unsigned chars have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<unsigned char> {
|
struct ArgTraits<unsigned char>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -129,7 +139,8 @@ struct ArgTraits<unsigned char> {
|
|||||||
* size_ts have value-like semantics.
|
* size_ts have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<size_t> {
|
struct ArgTraits<size_t>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -140,7 +151,8 @@ struct ArgTraits<size_t> {
|
|||||||
* unsigned long longs have value-like semantics.
|
* unsigned long longs have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<unsigned long long> {
|
struct ArgTraits<unsigned long long>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -153,7 +165,8 @@ struct ArgTraits<unsigned long long> {
|
|||||||
* floats have value-like semantics.
|
* floats have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<float> {
|
struct ArgTraits<float>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -161,7 +174,8 @@ struct ArgTraits<float> {
|
|||||||
* doubles have value-like semantics.
|
* doubles have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<double> {
|
struct ArgTraits<double>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -173,7 +187,8 @@ struct ArgTraits<double> {
|
|||||||
* bools have value-like semantics.
|
* bools have value-like semantics.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<bool> {
|
struct ArgTraits<bool>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -183,7 +198,8 @@ struct ArgTraits<bool> {
|
|||||||
*/
|
*/
|
||||||
#ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS
|
#ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<wchar_t> {
|
struct ArgTraits<wchar_t>
|
||||||
|
{
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -192,7 +208,8 @@ struct ArgTraits<wchar_t> {
|
|||||||
* Strings have string like argument traits.
|
* Strings have string like argument traits.
|
||||||
*/
|
*/
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<std::string> {
|
struct ArgTraits<std::string>
|
||||||
|
{
|
||||||
typedef StringLike ValueCategory;
|
typedef StringLike ValueCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -34,7 +34,8 @@
|
|||||||
#include "XorHandler.h"
|
#include "XorHandler.h"
|
||||||
#include "Arg.h"
|
#include "Arg.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that isolates any output from the CmdLine object so that it
|
* A class that isolates any output from the CmdLine object so that it
|
||||||
@@ -109,7 +110,6 @@ inline void StdOutput::version(CmdLineInterface& _cmd)
|
|||||||
{
|
{
|
||||||
std::string progName = _cmd.getProgramName();
|
std::string progName = _cmd.getProgramName();
|
||||||
std::string xversion = _cmd.getVersion();
|
std::string xversion = _cmd.getVersion();
|
||||||
|
|
||||||
std::cout << std::endl << progName << " version: "
|
std::cout << std::endl << progName << " version: "
|
||||||
<< xversion << std::endl << std::endl;
|
<< xversion << std::endl << std::endl;
|
||||||
}
|
}
|
||||||
@@ -117,38 +117,28 @@ inline void StdOutput::version(CmdLineInterface& _cmd)
|
|||||||
inline void StdOutput::usage(CmdLineInterface& _cmd )
|
inline void StdOutput::usage(CmdLineInterface& _cmd )
|
||||||
{
|
{
|
||||||
std::cout << std::endl << "USAGE: " << std::endl << std::endl;
|
std::cout << std::endl << "USAGE: " << std::endl << std::endl;
|
||||||
|
|
||||||
_shortUsage( _cmd, std::cout );
|
_shortUsage( _cmd, std::cout );
|
||||||
|
|
||||||
std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl;
|
std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl;
|
||||||
|
|
||||||
_longUsage( _cmd, std::cout );
|
_longUsage( _cmd, std::cout );
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void StdOutput::failure( CmdLineInterface& _cmd,
|
inline void StdOutput::failure( CmdLineInterface& _cmd,
|
||||||
ArgException& e )
|
ArgException& e )
|
||||||
{
|
{
|
||||||
std::string progName = _cmd.getProgramName();
|
std::string progName = _cmd.getProgramName();
|
||||||
|
|
||||||
std::cerr << "PARSE ERROR: " << e.argId() << std::endl
|
std::cerr << "PARSE ERROR: " << e.argId() << std::endl
|
||||||
<< " " << e.error() << std::endl << std::endl;
|
<< " " << e.error() << std::endl << std::endl;
|
||||||
|
|
||||||
if ( _cmd.hasHelpAndVersion() )
|
if ( _cmd.hasHelpAndVersion() )
|
||||||
{
|
{
|
||||||
std::cerr << "Brief USAGE: " << std::endl;
|
std::cerr << "Brief USAGE: " << std::endl;
|
||||||
|
|
||||||
_shortUsage( _cmd, std::cerr );
|
_shortUsage( _cmd, std::cerr );
|
||||||
|
|
||||||
std::cerr << std::endl << "For complete USAGE and HELP type: "
|
std::cerr << std::endl << "For complete USAGE and HELP type: "
|
||||||
<< std::endl << " " << progName << " --help"
|
<< std::endl << " " << progName << " --help"
|
||||||
<< std::endl << std::endl;
|
<< std::endl << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
usage(_cmd);
|
usage(_cmd);
|
||||||
|
|
||||||
throw ExitException(1);
|
throw ExitException(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,9 +150,7 @@ StdOutput::_shortUsage( CmdLineInterface& _cmd,
|
|||||||
std::string progName = _cmd.getProgramName();
|
std::string progName = _cmd.getProgramName();
|
||||||
XorHandler xorHandler = _cmd.getXorHandler();
|
XorHandler xorHandler = _cmd.getXorHandler();
|
||||||
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
||||||
|
|
||||||
std::string s = progName + " ";
|
std::string s = progName + " ";
|
||||||
|
|
||||||
// first the xor
|
// first the xor
|
||||||
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
|
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
|
||||||
{
|
{
|
||||||
@@ -170,20 +158,16 @@ StdOutput::_shortUsage( CmdLineInterface& _cmd,
|
|||||||
for ( ArgVectorIterator it = xorList[i].begin();
|
for ( ArgVectorIterator it = xorList[i].begin();
|
||||||
it != xorList[i].end(); it++ )
|
it != xorList[i].end(); it++ )
|
||||||
s += (*it)->shortID() + "|";
|
s += (*it)->shortID() + "|";
|
||||||
|
|
||||||
s[s.length()-1] = '}';
|
s[s.length()-1] = '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
// then the rest
|
// then the rest
|
||||||
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
||||||
if ( !xorHandler.contains( (*it) ) )
|
if ( !xorHandler.contains( (*it) ) )
|
||||||
s += " " + (*it)->shortID();
|
s += " " + (*it)->shortID();
|
||||||
|
|
||||||
// if the program name is too long, then adjust the second line offset
|
// if the program name is too long, then adjust the second line offset
|
||||||
int secondLineOffset = static_cast<int>(progName.length()) + 2;
|
int secondLineOffset = static_cast<int>(progName.length()) + 2;
|
||||||
if ( secondLineOffset > 75/2 )
|
if ( secondLineOffset > 75/2 )
|
||||||
secondLineOffset = static_cast<int>(75/2);
|
secondLineOffset = static_cast<int>(75/2);
|
||||||
|
|
||||||
spacePrint( os, s, 75, 3, secondLineOffset );
|
spacePrint( os, s, 75, 3, secondLineOffset );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +179,6 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
|
|||||||
std::string message = _cmd.getMessage();
|
std::string message = _cmd.getMessage();
|
||||||
XorHandler xorHandler = _cmd.getXorHandler();
|
XorHandler xorHandler = _cmd.getXorHandler();
|
||||||
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
||||||
|
|
||||||
// first the xor
|
// first the xor
|
||||||
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
|
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
|
||||||
{
|
{
|
||||||
@@ -205,13 +188,11 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
|
|||||||
{
|
{
|
||||||
spacePrint( os, (*it)->longID(), 75, 3, 3 );
|
spacePrint( os, (*it)->longID(), 75, 3, 3 );
|
||||||
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
|
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
|
||||||
|
|
||||||
if ( it+1 != xorList[i].end() )
|
if ( it+1 != xorList[i].end() )
|
||||||
spacePrint(os, "-- OR --", 75, 9, 0);
|
spacePrint(os, "-- OR --", 75, 9, 0);
|
||||||
}
|
}
|
||||||
os << std::endl << std::endl;
|
os << std::endl << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// then the rest
|
// then the rest
|
||||||
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
||||||
if ( !xorHandler.contains( (*it) ) )
|
if ( !xorHandler.contains( (*it) ) )
|
||||||
@@ -220,9 +201,7 @@ StdOutput::_longUsage( CmdLineInterface& _cmd,
|
|||||||
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
|
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
|
||||||
os << std::endl;
|
os << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
os << std::endl;
|
os << std::endl;
|
||||||
|
|
||||||
spacePrint( os, message, 75, 3, 0 );
|
spacePrint( os, message, 75, 3, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +212,6 @@ inline void StdOutput::spacePrint( std::ostream& os,
|
|||||||
int secondLineOffset ) const
|
int secondLineOffset ) const
|
||||||
{
|
{
|
||||||
int len = static_cast<int>(s.length());
|
int len = static_cast<int>(s.length());
|
||||||
|
|
||||||
if ( (len + indentSpaces > maxWidth) && maxWidth > 0 )
|
if ( (len + indentSpaces > maxWidth) && maxWidth > 0 )
|
||||||
{
|
{
|
||||||
int allowedLen = maxWidth - indentSpaces;
|
int allowedLen = maxWidth - indentSpaces;
|
||||||
@@ -245,7 +223,6 @@ inline void StdOutput::spacePrint( std::ostream& os,
|
|||||||
// doing it this way to support a VisualC++ 2005 bug
|
// doing it this way to support a VisualC++ 2005 bug
|
||||||
using namespace std;
|
using namespace std;
|
||||||
int stringLen = min<int>( len - start, allowedLen );
|
int stringLen = min<int>( len - start, allowedLen );
|
||||||
|
|
||||||
// trim the length so it doesn't end in middle of a word
|
// trim the length so it doesn't end in middle of a word
|
||||||
if ( stringLen == allowedLen )
|
if ( stringLen == allowedLen )
|
||||||
while ( stringLen >= 0 &&
|
while ( stringLen >= 0 &&
|
||||||
@@ -253,36 +230,28 @@ inline void StdOutput::spacePrint( std::ostream& os,
|
|||||||
s[stringLen+start] != ',' &&
|
s[stringLen+start] != ',' &&
|
||||||
s[stringLen+start] != '|' )
|
s[stringLen+start] != '|' )
|
||||||
stringLen--;
|
stringLen--;
|
||||||
|
|
||||||
// ok, the word is longer than the line, so just split
|
// ok, the word is longer than the line, so just split
|
||||||
// wherever the line ends
|
// wherever the line ends
|
||||||
if ( stringLen <= 0 )
|
if ( stringLen <= 0 )
|
||||||
stringLen = allowedLen;
|
stringLen = allowedLen;
|
||||||
|
|
||||||
// check for newlines
|
// check for newlines
|
||||||
for ( int i = 0; i < stringLen; i++ )
|
for ( int i = 0; i < stringLen; i++ )
|
||||||
if ( s[start+i] == '\n' )
|
if ( s[start+i] == '\n' )
|
||||||
stringLen = i+1;
|
stringLen = i+1;
|
||||||
|
|
||||||
// print the indent
|
// print the indent
|
||||||
for ( int i = 0; i < indentSpaces; i++ )
|
for ( int i = 0; i < indentSpaces; i++ )
|
||||||
os << " ";
|
os << " ";
|
||||||
|
|
||||||
if ( start == 0 )
|
if ( start == 0 )
|
||||||
{
|
{
|
||||||
// handle second line offsets
|
// handle second line offsets
|
||||||
indentSpaces += secondLineOffset;
|
indentSpaces += secondLineOffset;
|
||||||
|
|
||||||
// adjust allowed len
|
// adjust allowed len
|
||||||
allowedLen -= secondLineOffset;
|
allowedLen -= secondLineOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
os << s.substr(start,stringLen) << std::endl;
|
os << s.substr(start,stringLen) << std::endl;
|
||||||
|
|
||||||
// so we don't start a line with a space
|
// so we don't start a line with a space
|
||||||
while ( s[stringLen+start] == ' ' && start < len )
|
while ( s[stringLen+start] == ' ' && start < len )
|
||||||
start++;
|
start++;
|
||||||
|
|
||||||
start += stringLen;
|
start += stringLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,8 @@
|
|||||||
|
|
||||||
#include "Arg.h"
|
#include "Arg.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple switch argument. If the switch is set on the command line, then
|
* A simple switch argument. If the switch is set on the command line, then
|
||||||
@@ -155,14 +156,16 @@ inline SwitchArg::SwitchArg(const std::string& flag,
|
|||||||
parser.add( this );
|
parser.add( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool SwitchArg::getValue() { return _value; }
|
inline bool SwitchArg::getValue()
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool SwitchArg::lastCombined(std::string& combinedSwitches )
|
inline bool SwitchArg::lastCombined(std::string& combinedSwitches )
|
||||||
{
|
{
|
||||||
for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
|
for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
|
||||||
if ( combinedSwitches[i] != Arg::blankChar() )
|
if ( combinedSwitches[i] != Arg::blankChar() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,16 +175,13 @@ inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches )
|
|||||||
if ( combinedSwitches.length() > 0 &&
|
if ( combinedSwitches.length() > 0 &&
|
||||||
combinedSwitches[0] != Arg::flagStartString()[0] )
|
combinedSwitches[0] != Arg::flagStartString()[0] )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// make sure it isn't a long name
|
// make sure it isn't a long name
|
||||||
if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) ==
|
if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) ==
|
||||||
Arg::nameStartString() )
|
Arg::nameStartString() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// make sure the delimiter isn't in the string
|
// make sure the delimiter isn't in the string
|
||||||
if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos )
|
if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// ok, we're not specifying a ValueArg, so we know that we have
|
// ok, we're not specifying a ValueArg, so we know that we have
|
||||||
// a combined switch list.
|
// a combined switch list.
|
||||||
for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
|
for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
|
||||||
@@ -196,7 +196,6 @@ inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches )
|
|||||||
combinedSwitches[i] = Arg::blankChar();
|
combinedSwitches[i] = Arg::blankChar();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// none of the switches passed in the list match.
|
// none of the switches passed in the list match.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -206,17 +205,13 @@ inline void SwitchArg::commonProcessing()
|
|||||||
if ( _xorSet )
|
if ( _xorSet )
|
||||||
throw(CmdLineParseException(
|
throw(CmdLineParseException(
|
||||||
"Mutually exclusive argument already set!", toString()));
|
"Mutually exclusive argument already set!", toString()));
|
||||||
|
|
||||||
if ( _alreadySet )
|
if ( _alreadySet )
|
||||||
throw(CmdLineParseException("Argument already set!", toString()));
|
throw(CmdLineParseException("Argument already set!", toString()));
|
||||||
|
|
||||||
_alreadySet = true;
|
_alreadySet = true;
|
||||||
|
|
||||||
if ( _value == true )
|
if ( _value == true )
|
||||||
_value = false;
|
_value = false;
|
||||||
else
|
else
|
||||||
_value = true;
|
_value = true;
|
||||||
|
|
||||||
_checkWithVisitor();
|
_checkWithVisitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,12 +219,10 @@ inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args)
|
|||||||
{
|
{
|
||||||
if ( _ignoreable && Arg::ignoreRest() )
|
if ( _ignoreable && Arg::ignoreRest() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// if the whole string matches the flag or name string
|
// if the whole string matches the flag or name string
|
||||||
if ( argMatches( args[*i] ) )
|
if ( argMatches( args[*i] ) )
|
||||||
{
|
{
|
||||||
commonProcessing();
|
commonProcessing();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// if a substring matches the flag as part of a combination
|
// if a substring matches the flag as part of a combination
|
||||||
@@ -240,9 +233,7 @@ inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args)
|
|||||||
if ( combinedSwitchesMatch( args[*i] ) )
|
if ( combinedSwitchesMatch( args[*i] ) )
|
||||||
throw(CmdLineParseException("Argument already set!",
|
throw(CmdLineParseException("Argument already set!",
|
||||||
toString()));
|
toString()));
|
||||||
|
|
||||||
commonProcessing();
|
commonProcessing();
|
||||||
|
|
||||||
// We only want to return true if we've found the last combined
|
// We only want to return true if we've found the last combined
|
||||||
// match in the string, otherwise we return true so that other
|
// match in the string, otherwise we return true so that other
|
||||||
// switches in the combination will have a chance to match.
|
// switches in the combination will have a chance to match.
|
||||||
|
@@ -29,7 +29,8 @@
|
|||||||
#include "MultiArg.h"
|
#include "MultiArg.h"
|
||||||
#include "OptionalUnlabeledTracker.h"
|
#include "OptionalUnlabeledTracker.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just like a MultiArg, except that the arguments are unlabeled. Basically,
|
* Just like a MultiArg, except that the arguments are unlabeled. Basically,
|
||||||
@@ -244,16 +245,11 @@ UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
|
|||||||
template<class T>
|
template<class T>
|
||||||
bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( _hasBlanks( args[*i] ) )
|
if ( _hasBlanks( args[*i] ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// never ignore an unlabeled multi arg
|
// never ignore an unlabeled multi arg
|
||||||
|
|
||||||
|
|
||||||
// always take the first value, regardless of the start string
|
// always take the first value, regardless of the start string
|
||||||
_extractValue( args[(*i)] );
|
_extractValue( args[(*i)] );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// continue taking args until we hit the end or a start string
|
// continue taking args until we hit the end or a start string
|
||||||
while ( (unsigned int)(*i)+1 < args.size() &&
|
while ( (unsigned int)(*i)+1 < args.size() &&
|
||||||
@@ -261,9 +257,7 @@ bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args)
|
|||||||
args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
|
args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
|
||||||
_extractValue( args[++(*i)] );
|
_extractValue( args[++(*i)] );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_alreadySet = true;
|
_alreadySet = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,7 +31,8 @@
|
|||||||
#include "OptionalUnlabeledTracker.h"
|
#include "OptionalUnlabeledTracker.h"
|
||||||
|
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The basic unlabeled argument that parses a value.
|
* The basic unlabeled argument that parses a value.
|
||||||
@@ -220,9 +221,7 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
|||||||
: ValueArg<T>("", name, desc, req, val, typeDesc, v)
|
: ValueArg<T>("", name, desc, req, val, typeDesc, v)
|
||||||
{
|
{
|
||||||
_ignoreable = ignoreable;
|
_ignoreable = ignoreable;
|
||||||
|
|
||||||
OptionalUnlabeledTracker::check(req, toString());
|
OptionalUnlabeledTracker::check(req, toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@@ -280,15 +279,11 @@ UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
|
|||||||
template<class T>
|
template<class T>
|
||||||
bool UnlabeledValueArg<T>::processArg(int *i, std::vector<std::string>& args)
|
bool UnlabeledValueArg<T>::processArg(int *i, std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( _alreadySet )
|
if ( _alreadySet )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( _hasBlanks( args[*i] ) )
|
if ( _hasBlanks( args[*i] ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// never ignore an unlabeled arg
|
// never ignore an unlabeled arg
|
||||||
|
|
||||||
_extractValue( args[*i] );
|
_extractValue( args[*i] );
|
||||||
_alreadySet = true;
|
_alreadySet = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -311,7 +306,6 @@ template<class T>
|
|||||||
std::string UnlabeledValueArg<T>::longID(const std::string& val) const
|
std::string UnlabeledValueArg<T>::longID(const std::string& val) const
|
||||||
{
|
{
|
||||||
static_cast<void>(val); // Ignore input, don't warn
|
static_cast<void>(val); // Ignore input, don't warn
|
||||||
|
|
||||||
// Ideally we would like to be able to use RTTI to return the name
|
// Ideally we would like to be able to use RTTI to return the name
|
||||||
// of the type required for this argument. However, g++ at least,
|
// of the type required for this argument. However, g++ at least,
|
||||||
// doesn't appear to return terribly useful "names" of the types.
|
// doesn't appear to return terribly useful "names" of the types.
|
||||||
|
@@ -29,7 +29,8 @@
|
|||||||
#include "Arg.h"
|
#include "Arg.h"
|
||||||
#include "Constraint.h"
|
#include "Constraint.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The basic labeled argument that parses a value.
|
* The basic labeled argument that parses a value.
|
||||||
@@ -319,7 +320,10 @@ ValueArg<T>::ValueArg(const std::string& flag,
|
|||||||
* Implementation of getValue().
|
* Implementation of getValue().
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
T& ValueArg<T>::getValue() { return _value; }
|
T& ValueArg<T>::getValue()
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of processArg().
|
* Implementation of processArg().
|
||||||
@@ -329,15 +333,11 @@ bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
|
|||||||
{
|
{
|
||||||
if ( _ignoreable && Arg::ignoreRest() )
|
if ( _ignoreable && Arg::ignoreRest() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( _hasBlanks( args[*i] ) )
|
if ( _hasBlanks( args[*i] ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string flag = args[*i];
|
std::string flag = args[*i];
|
||||||
|
|
||||||
std::string value = "";
|
std::string value = "";
|
||||||
trimFlag( flag, value );
|
trimFlag( flag, value );
|
||||||
|
|
||||||
if ( argMatches( flag ) )
|
if ( argMatches( flag ) )
|
||||||
{
|
{
|
||||||
if ( _alreadySet )
|
if ( _alreadySet )
|
||||||
@@ -350,12 +350,10 @@ bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
|
|||||||
throw( CmdLineParseException("Argument already set!",
|
throw( CmdLineParseException("Argument already set!",
|
||||||
toString()) );
|
toString()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Arg::delimiter() != ' ' && value == "" )
|
if ( Arg::delimiter() != ' ' && value == "" )
|
||||||
throw( ArgParseException(
|
throw( ArgParseException(
|
||||||
"Couldn't find delimiter for this argument!",
|
"Couldn't find delimiter for this argument!",
|
||||||
toString() ) );
|
toString() ) );
|
||||||
|
|
||||||
if ( value == "" )
|
if ( value == "" )
|
||||||
{
|
{
|
||||||
(*i)++;
|
(*i)++;
|
||||||
@@ -367,7 +365,6 @@ bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
_extractValue( value );
|
_extractValue( value );
|
||||||
|
|
||||||
_alreadySet = true;
|
_alreadySet = true;
|
||||||
_checkWithVisitor();
|
_checkWithVisitor();
|
||||||
return true;
|
return true;
|
||||||
@@ -399,12 +396,14 @@ std::string ValueArg<T>::longID(const std::string& val) const
|
|||||||
template<class T>
|
template<class T>
|
||||||
void ValueArg<T>::_extractValue( const std::string& val )
|
void ValueArg<T>::_extractValue( const std::string& val )
|
||||||
{
|
{
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory());
|
ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory());
|
||||||
} catch( ArgParseException &e) {
|
}
|
||||||
|
catch( ArgParseException &e)
|
||||||
|
{
|
||||||
throw ArgParseException(e.error(), toString());
|
throw ArgParseException(e.error(), toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _constraint != NULL )
|
if ( _constraint != NULL )
|
||||||
if ( ! _constraint->check( _value ) )
|
if ( ! _constraint->check( _value ) )
|
||||||
throw( CmdLineParseException( "Value '" + val +
|
throw( CmdLineParseException( "Value '" + val +
|
||||||
|
@@ -41,7 +41,8 @@
|
|||||||
#error "Need a stringstream (sstream or strstream) to compile!"
|
#error "Need a stringstream (sstream or strstream) to compile!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Constraint that constrains the Arg to only those values specified
|
* A Constraint that constrains the Arg to only those values specified
|
||||||
@@ -102,7 +103,6 @@ ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed)
|
|||||||
{
|
{
|
||||||
for ( unsigned int i = 0; i < _allowed.size(); i++ )
|
for ( unsigned int i = 0; i < _allowed.size(); i++ )
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(HAVE_SSTREAM)
|
#if defined(HAVE_SSTREAM)
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
#elif defined(HAVE_STRSTREAM)
|
#elif defined(HAVE_STRSTREAM)
|
||||||
@@ -110,11 +110,8 @@ ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed)
|
|||||||
#else
|
#else
|
||||||
#error "Need a stringstream (sstream or strstream) to compile!"
|
#error "Need a stringstream (sstream or strstream) to compile!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
os << _allowed[i];
|
os << _allowed[i];
|
||||||
|
|
||||||
std::string temp( os.str() );
|
std::string temp( os.str() );
|
||||||
|
|
||||||
if ( i > 0 )
|
if ( i > 0 )
|
||||||
_typeDesc += "|";
|
_typeDesc += "|";
|
||||||
_typeDesc += temp;
|
_typeDesc += temp;
|
||||||
|
@@ -28,7 +28,8 @@
|
|||||||
#include "CmdLineOutput.h"
|
#include "CmdLineOutput.h"
|
||||||
#include "Visitor.h"
|
#include "Visitor.h"
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Vistor that will call the version method of the given CmdLineOutput
|
* A Vistor that will call the version method of the given CmdLineOutput
|
||||||
@@ -69,7 +70,8 @@ class VersionVisitor: public Visitor
|
|||||||
* Calls the version method of the output object using the
|
* Calls the version method of the output object using the
|
||||||
* specified CmdLine.
|
* specified CmdLine.
|
||||||
*/
|
*/
|
||||||
void visit() {
|
void visit()
|
||||||
|
{
|
||||||
(*_out)->version(*_cmd);
|
(*_out)->version(*_cmd);
|
||||||
throw ExitException(0);
|
throw ExitException(0);
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,8 @@
|
|||||||
#ifndef TCLAP_VISITOR_H
|
#ifndef TCLAP_VISITOR_H
|
||||||
#define TCLAP_VISITOR_H
|
#define TCLAP_VISITOR_H
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base class that defines the interface for visitors.
|
* A base class that defines the interface for visitors.
|
||||||
|
@@ -29,7 +29,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles lists of Arg's that are to be XOR'd on the command
|
* This class handles lists of Arg's that are to be XOR'd on the command
|
||||||
@@ -116,14 +117,12 @@ inline int XorHandler::check( const Arg* a )
|
|||||||
throw(CmdLineParseException(
|
throw(CmdLineParseException(
|
||||||
"Mutually exclusive argument already set!",
|
"Mutually exclusive argument already set!",
|
||||||
(*it)->toString()));
|
(*it)->toString()));
|
||||||
|
|
||||||
// go through and set each arg that is not a
|
// go through and set each arg that is not a
|
||||||
for ( ArgVectorIterator it = _orList[i].begin();
|
for ( ArgVectorIterator it = _orList[i].begin();
|
||||||
it != _orList[i].end();
|
it != _orList[i].end();
|
||||||
it++ )
|
it++ )
|
||||||
if ( a != (*it) )
|
if ( a != (*it) )
|
||||||
(*it)->xorSet();
|
(*it)->xorSet();
|
||||||
|
|
||||||
// return the number of required args that have now been set
|
// return the number of required args that have now been set
|
||||||
if ( (*ait)->allowMore() )
|
if ( (*ait)->allowMore() )
|
||||||
return 0;
|
return 0;
|
||||||
@@ -131,7 +130,6 @@ inline int XorHandler::check( const Arg* a )
|
|||||||
return static_cast<int>(_orList[i].size());
|
return static_cast<int>(_orList[i].size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( a->isRequired() )
|
if ( a->isRequired() )
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
@@ -146,7 +144,6 @@ inline bool XorHandler::contains( const Arg* a )
|
|||||||
it++ )
|
it++ )
|
||||||
if ( a == (*it) )
|
if ( a == (*it) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,7 +34,8 @@
|
|||||||
#include <tclap/XorHandler.h>
|
#include <tclap/XorHandler.h>
|
||||||
#include <tclap/Arg.h>
|
#include <tclap/Arg.h>
|
||||||
|
|
||||||
namespace TCLAP {
|
namespace TCLAP
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that generates a Zsh completion function as output from the usage()
|
* A class that generates a Zsh completion function as output from the usage()
|
||||||
@@ -110,11 +111,9 @@ inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd )
|
|||||||
std::string xversion = _cmd.getVersion();
|
std::string xversion = _cmd.getVersion();
|
||||||
theDelimiter = _cmd.getDelimiter();
|
theDelimiter = _cmd.getDelimiter();
|
||||||
basename(progName);
|
basename(progName);
|
||||||
|
|
||||||
std::cout << "#compdef " << progName << std::endl << std::endl <<
|
std::cout << "#compdef " << progName << std::endl << std::endl <<
|
||||||
"# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl <<
|
"# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl <<
|
||||||
"_arguments -s -S";
|
"_arguments -s -S";
|
||||||
|
|
||||||
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
||||||
{
|
{
|
||||||
if ( (*it)->shortID().at(0) == '<' )
|
if ( (*it)->shortID().at(0) == '<' )
|
||||||
@@ -122,7 +121,6 @@ inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd )
|
|||||||
else if ( (*it)->getFlag() != "-" )
|
else if ( (*it)->getFlag() != "-" )
|
||||||
printOption((*it), getMutexList(_cmd, *it));
|
printOption((*it), getMutexList(_cmd, *it));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +162,6 @@ inline void ZshCompletionOutput::basename( std::string& s )
|
|||||||
inline void ZshCompletionOutput::printArg(Arg* a)
|
inline void ZshCompletionOutput::printArg(Arg* a)
|
||||||
{
|
{
|
||||||
static int count = 1;
|
static int count = 1;
|
||||||
|
|
||||||
std::cout << " \\" << std::endl << " '";
|
std::cout << " \\" << std::endl << " '";
|
||||||
if ( a->acceptsMultipleValues() )
|
if ( a->acceptsMultipleValues() )
|
||||||
std::cout << '*';
|
std::cout << '*';
|
||||||
@@ -173,7 +170,6 @@ inline void ZshCompletionOutput::printArg(Arg* a)
|
|||||||
std::cout << ':';
|
std::cout << ':';
|
||||||
if ( !a->isRequired() )
|
if ( !a->isRequired() )
|
||||||
std::cout << ':';
|
std::cout << ':';
|
||||||
|
|
||||||
std::cout << a->getName() << ':';
|
std::cout << a->getName() << ':';
|
||||||
std::map<std::string, std::string>::iterator compArg = common.find(a->getName());
|
std::map<std::string, std::string>::iterator compArg = common.find(a->getName());
|
||||||
if ( compArg != common.end() )
|
if ( compArg != common.end() )
|
||||||
@@ -192,7 +188,6 @@ inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex)
|
|||||||
std::string flag = a->flagStartChar() + a->getFlag();
|
std::string flag = a->flagStartChar() + a->getFlag();
|
||||||
std::string name = a->nameStartString() + a->getName();
|
std::string name = a->nameStartString() + a->getName();
|
||||||
std::string desc = a->getDescription();
|
std::string desc = a->getDescription();
|
||||||
|
|
||||||
// remove full stop and capitalisation from description as
|
// remove full stop and capitalisation from description as
|
||||||
// this is the convention for zsh function
|
// this is the convention for zsh function
|
||||||
if (!desc.compare(0, 12, "(required) "))
|
if (!desc.compare(0, 12, "(required) "))
|
||||||
@@ -212,9 +207,7 @@ inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex)
|
|||||||
{
|
{
|
||||||
desc.replace(0, 1, 1, tolower(desc.at(0)));
|
desc.replace(0, 1, 1, tolower(desc.at(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << " \\" << std::endl << " '" << mutex;
|
std::cout << " \\" << std::endl << " '" << mutex;
|
||||||
|
|
||||||
if ( a->getFlag().empty() )
|
if ( a->getFlag().empty() )
|
||||||
{
|
{
|
||||||
std::cout << name;
|
std::cout << name;
|
||||||
@@ -227,7 +220,6 @@ inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex)
|
|||||||
std::cout << "=-";
|
std::cout << "=-";
|
||||||
quoteSpecialChars(desc);
|
quoteSpecialChars(desc);
|
||||||
std::cout << '[' << desc << ']';
|
std::cout << '[' << desc << ']';
|
||||||
|
|
||||||
if ( a->isValueRequired() )
|
if ( a->isValueRequired() )
|
||||||
{
|
{
|
||||||
std::string arg = a->shortID();
|
std::string arg = a->shortID();
|
||||||
@@ -264,7 +256,6 @@ inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << '\'';
|
std::cout << '\'';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,18 +263,15 @@ inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Ar
|
|||||||
{
|
{
|
||||||
XorHandler xorHandler = _cmd.getXorHandler();
|
XorHandler xorHandler = _cmd.getXorHandler();
|
||||||
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
||||||
|
|
||||||
if (a->getName() == "help" || a->getName() == "version")
|
if (a->getName() == "help" || a->getName() == "version")
|
||||||
{
|
{
|
||||||
return "(-)";
|
return "(-)";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream list;
|
std::ostringstream list;
|
||||||
if ( a->acceptsMultipleValues() )
|
if ( a->acceptsMultipleValues() )
|
||||||
{
|
{
|
||||||
list << '*';
|
list << '*';
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
|
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
|
||||||
{
|
{
|
||||||
for ( ArgVectorIterator it = xorList[i].begin();
|
for ( ArgVectorIterator it = xorList[i].begin();
|
||||||
@@ -309,13 +297,12 @@ inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Ar
|
|||||||
return list.str();
|
return list.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// wasn't found in xor list
|
// wasn't found in xor list
|
||||||
if (!a->getFlag().empty()) {
|
if (!a->getFlag().empty())
|
||||||
|
{
|
||||||
list << "(" << a->flagStartChar() << a->getFlag() << ' ' <<
|
list << "(" << a->flagStartChar() << a->getFlag() << ' ' <<
|
||||||
a->nameStartString() << a->getName() << ')';
|
a->nameStartString() << a->getName() << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
return list.str();
|
return list.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user