diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..06628d5
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,56 @@
+project(src)
+
+
+cmake_minimum_required (VERSION 2.6)
+
+IF (WIN32)
+ add_definitions( -DWINDOWS)
+ add_definitions( -DNOMINMAX)
+
+ SET(OpenCV_DIR "C:\\projects\\alpr\\libraries\\opencv")
+ SET(Tesseract_DIR "C:\\projects\\alpr\\libraries\\tesseract-3.02")
+
+ include_directories(
+ ${Tesseract_DIR}/include/tesseract
+
+ )
+ link_directories( ${Tesseract_DIR}/lib/ )
+ELSE()
+
+ SET(OpenCV_DIR "../libraries/opencv/")
+ SET(Tesseract_DIR "/home/mhill/projects/alpr/libraries/tesseract-ocr")
+
+ include_directories(
+ ${Tesseract_DIR}/api
+ ${Tesseract_DIR}/ccutil/
+ ${Tesseract_DIR}/ccstruct/
+ ${Tesseract_DIR}/ccmain/
+
+ )
+ link_directories( ${Tesseract_DIR}/api/.libs/ )
+ENDIF()
+
+
+# Opencv Package
+FIND_PACKAGE( OpenCV REQUIRED )
+IF (${OpenCV_VERSION} VERSION_LESS 2.3.0)
+ MESSAGE(FATAL_ERROR "OpenCV version is not compatible : ${OpenCV_VERSION}")
+ENDIF()
+
+
+include_directories(./openalpr )
+
+
+set(CMAKE_CSS_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall ")
+ADD_EXECUTABLE( alpr main.cpp )
+TARGET_LINK_LIBRARIES(alpr
+ openalpr
+ support
+ ${OpenCV_LIBS}
+ tesseract
+ )
+
+
+add_subdirectory(openalpr)
+add_subdirectory(misc_utilities)
+
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..0386964
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2013 New Designs Unlimited, LLC
+ * Opensource Automated License Plate Recognition [http://www.openalpr.com]
+ *
+ * This file is part of OpenAlpr.
+ *
+ * OpenAlpr is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License
+ * version 3 as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+*/
+
+
+
+ #include
+ #include
+ #include
+
+ #include "opencv2/highgui/highgui.hpp"
+ #include "opencv2/imgproc/imgproc.hpp"
+
+
+ #include "tclap/CmdLine.h"
+ #include "support/filesystem.h"
+ #include "support/timing.h"
+ #include "alpr.h"
+
+
+
+ const std::string MAIN_WINDOW_NAME = "ALPR main window";
+
+
+ const bool SAVE_LAST_VIDEO_STILL = false;
+ const std::string LAST_VIDEO_STILL_LOCATION = "/tmp/laststill.jpg";
+
+
+ /** Function Headers */
+ bool detectandshow(Alpr* alpr, cv::Mat frame, std::string region, bool writeJson);
+
+
+ bool measureProcessingTime = false;
+
+ int main( int argc, const char** argv )
+ {
+ std::string filename;
+ std::string runtimePath = "";
+ bool outputJson = false;
+ int seektoms = 0;
+ bool detectRegion = false;
+ std::string templateRegion;
+ std::string country;
+ int topn;
+
+ try {
+
+ TCLAP::CmdLine cmd("OpenAlpr Command Line Utility", ' ', OPENALPR_VERSION);
+
+ TCLAP::UnlabeledValueArg fileArg( "image_file", "Image containing license plates", true, "", "image_file_path" );
+
+ TCLAP::ValueArg countryCodeArg("c","country","Country code to identify (either us for USA or eu for Europe). Default=us",false, "us" ,"country_code");
+ TCLAP::ValueArg seekToMsArg("","seek","Seek to the specied millisecond in a video file. Default=0",false, 0 ,"integer_ms");
+ TCLAP::ValueArg runtimeDirArg("r","runtime_dir","Path to the OpenAlpr runtime data directory",false, "" ,"runtime_dir");
+ TCLAP::ValueArg templateRegionArg("t","template_region","Attempt to match the plate number against a region template (e.g., md for Maryland, ca for California)",false, "" ,"region code");
+ TCLAP::ValueArg topNArg("n","topn","Max number of possible plate numbers to return. Default=10",false, 10 ,"topN");
+
+ TCLAP::SwitchArg jsonSwitch("j","json","Output recognition results in JSON format. Default=off", cmd, false);
+ TCLAP::SwitchArg detectRegionSwitch("d","detect_region","Attempt to detect the region of the plate image. Default=off", cmd, false);
+ TCLAP::SwitchArg clockSwitch("","clock","Measure/print the total time to process image and all plates. Default=off", cmd, false);
+
+ cmd.add( fileArg );
+ cmd.add( countryCodeArg );
+ cmd.add( seekToMsArg );
+ cmd.add( topNArg );
+ cmd.add( runtimeDirArg );
+ cmd.add( templateRegionArg );
+
+ cmd.parse( argc, argv );
+
+ filename = fileArg.getValue();
+
+ country = countryCodeArg.getValue();
+ seektoms = seekToMsArg.getValue();
+ outputJson = jsonSwitch.getValue();
+ runtimePath = runtimeDirArg.getValue();
+ detectRegion = detectRegionSwitch.getValue();
+ templateRegion = templateRegionArg.getValue();
+ topn = topNArg.getValue();
+ measureProcessingTime = clockSwitch.getValue();
+
+ } catch (TCLAP::ArgException &e) // catch any exceptions
+ {
+ std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
+ return 1;
+ }
+
+ cv::Mat frame;
+
+
+ Alpr alpr(country, runtimePath);
+ alpr.setTopN(topn);
+
+ if (detectRegion)
+ alpr.setDetectRegion(detectRegion);
+
+ if (strcmp(templateRegion.c_str(), "") != 0)
+ {
+ alpr.setDefaultRegion(templateRegion);
+ }
+
+ if (alpr.isLoaded() == false)
+ {
+ std::cerr << "Error loading OpenAlpr" << std::endl;
+ return 1;
+ }
+
+ if (strcmp(filename.c_str(), "webcam") == 0)
+ {
+ int framenum = 0;
+ cv::VideoCapture cap(0);
+ if (!cap.isOpened())
+ {
+ std::cout << "Error opening webcam" << std::endl;
+ return 1;
+ }
+
+ while (cap.read(frame) == true)
+ {
+ detectandshow(&alpr, frame, "", outputJson);
+ cv::waitKey(1);
+ framenum++;
+ }
+ }
+ else if (hasEnding(filename, ".avi") || hasEnding(filename, ".mp4") || hasEnding(filename, ".webm") || hasEnding(filename, ".flv"))
+ {
+ int framenum = 0;
+
+ cv::VideoCapture cap=cv::VideoCapture();
+ cap.open(filename);
+ cap.set(CV_CAP_PROP_POS_MSEC, seektoms);
+
+ while (cap.read(frame) == true)
+ {
+ if (SAVE_LAST_VIDEO_STILL == true)
+ {
+ cv::imwrite(LAST_VIDEO_STILL_LOCATION, frame);
+ }
+ std::cout << "Frame: " << framenum << std::endl;
+
+ detectandshow( &alpr, frame, "", outputJson);
+ //create a 1ms delay
+ cv::waitKey(1);
+ framenum++;
+ }
+
+ }
+ else if (hasEnding(filename, ".png") || hasEnding(filename, ".jpg") || hasEnding(filename, ".gif"))
+ {
+ frame = cv::imread( filename );
+
+ detectandshow( &alpr, frame, "", outputJson);
+
+
+ }
+ else if (DirectoryExists(filename.c_str()))
+ {
+ std::vector files = getFilesInDir(filename.c_str());
+
+ std::sort( files.begin(), files.end(), stringCompare );
+
+ for (int i = 0; i< files.size(); i++)
+ {
+ if (hasEnding(files[i], ".jpg") || hasEnding(files[i], ".png"))
+ {
+ std::string fullpath = filename + "/" + files[i];
+ std::cout << fullpath << std::endl;
+ frame = cv::imread( fullpath.c_str() );
+ if (detectandshow( &alpr, frame, "", outputJson))
+ {
+ //while ((char) cv::waitKey(50) != 'c') { }
+ }
+ else
+ {
+ //cv::waitKey(50);
+ }
+ }
+
+ }
+ }
+ else
+ {
+ std::cerr << "Unknown file type" << std::endl;
+ return 1;
+ }
+
+
+
+ return 0;
+ }
+
+
+ bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJson)
+ {
+
+
+ std::vector buffer;
+ cv::imencode(".bmp", frame, buffer );
+
+
+ timespec startTime;
+ getTime(&startTime);
+
+
+ std::vector results = alpr->recognize(buffer);
+
+
+ if (writeJson)
+ {
+ std::cout << alpr->toJson(results) << std::endl;
+ }
+ else
+ {
+ for (int i = 0; i < results.size(); i++)
+ {
+ std::cout << "plate" << i << ": " << results[i].result_count << " results -- Processing Time = " << results[i].processing_time_ms << "ms." << std::endl;
+
+ for (int k = 0; k < results[i].topNPlates.size(); k++)
+ {
+ std::cout << " - " << results[i].topNPlates[k].characters << "\t confidence: " << results[i].topNPlates[k].overall_confidence << "\t template_match: " << results[i].topNPlates[k].matches_template << std::endl;
+ }
+
+ }
+ }
+
+ timespec endTime;
+ getTime(&endTime);
+ if (measureProcessingTime)
+ std::cout << "Total Time to process image: " << diffclock(startTime, endTime) << "ms." << std::endl;
+
+
+ if (results.size() > 0)
+ return true;
+ return false;
+
+ }
+
+
+
+