diff --git a/src/daemon.cpp b/src/daemon.cpp index b075d5e..675a49f 100644 --- a/src/daemon.cpp +++ b/src/daemon.cpp @@ -1,18 +1,30 @@ #include +#include +#include "tclap/CmdLine.h" #include "beanstalk.hpp" #include "alpr.h" #include "openalpr/simpleini/simpleini.h" +#include "openalpr/cjson.h" #include "support/tinythread.h" #include "videobuffer.h" +#include "uuid.h" + + // prototypes void streamRecognitionThread(void* arg); +bool writeToQueue(std::string jsonResult); struct ThreadData { std::string stream_url; + int camera_id; + + std::string config_file; + std::string country_code; + std::string output_image_folder; }; bool daemon_active; @@ -21,6 +33,59 @@ int main( int argc, const char** argv ) { daemon_active = true; + bool noDaemon = false; + std::string logFile; + int topn; + + std::string configFile; + std::string country; + + TCLAP::CmdLine cmd("OpenAlpr Daemon", ' ', Alpr::getVersion()); + + 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 configFileArg("","config","Path to the openalpr.conf file.",false, "" ,"config_file"); + TCLAP::ValueArg topNArg("n","topn","Max number of possible plate numbers to return. Default=10",false, 10 ,"topN"); + TCLAP::ValueArg logFileArg("l","log","Log file to write to. Default=/var/log/openalpr.log",false, "/var/log/openalpr.log" ,"topN"); + + TCLAP::SwitchArg daemonOffSwitch("f","foreground","Set this flag for debugging. Disables forking the process as a daemon and runs in the foreground. Default=off", cmd, false); + + try + { + + cmd.add( topNArg ); + cmd.add( configFileArg ); + cmd.add( logFileArg ); + + + if (cmd.parse( argc, argv ) == false) + { + // Error occured while parsing. Exit now. + return 1; + } + + country = countryCodeArg.getValue(); + configFile = configFileArg.getValue(); + logFile = logFileArg.getValue(); + topn = topNArg.getValue(); + noDaemon = daemonOffSwitch.getValue(); + } + catch (TCLAP::ArgException &e) // catch any exceptions + { + std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; + return 1; + } + + if (noDaemon == false) + { + // Fork off into a separate daemon + daemon(0, 0); + std::cout << "Running OpenALPR daemon in daemon mode." << std::endl; + } + else + { + std::cout << "Running OpenALPR daemon in the foreground" << std::endl; + } + CSimpleIniA ini; ini.SetMultiKey(); @@ -48,15 +113,27 @@ int main( int argc, const char** argv ) return 1; } + std::string imageFolder = ini.GetValue("daemon", "image_folder", "/tmp/"); + + std::cout << "Using: " << imageFolder << " for storing valid plate images" << std::endl; + for (int i = 0; i < stream_urls.size(); i++) { ThreadData* tdata = new ThreadData(); tdata->stream_url = stream_urls[i]; + tdata->camera_id = i + 1; + tdata->config_file = configFile; + tdata->output_image_folder = imageFolder; + tdata->country_code = country; + tthread::thread* t = new tthread::thread(streamRecognitionThread, (void*) tdata); } - + while (daemon_active) + { + usleep(30000); + } } @@ -65,7 +142,14 @@ void streamRecognitionThread(void* arg) { ThreadData* tdata = (ThreadData*) arg; - std::cout << "Stream: " << tdata->stream_url << std::endl; + std::cout << "country: " << tdata->country_code << " -- config file: " << tdata->config_file << std::endl; + std::cout << "Stream " << tdata->camera_id << ": " << tdata->stream_url << std::endl; + + Alpr alpr(tdata->country_code, tdata->config_file); + + + std::cout << "asdf" << std::endl; + int framenum = 0; @@ -75,19 +159,58 @@ void streamRecognitionThread(void* arg) cv::Mat latestFrame; - /* + std::vector buffer; + + std::cout << "Daemon active: " << daemon_active << std::endl; + while (daemon_active) { int response = videoBuffer.getLatestFrame(&latestFrame); if (response != -1) { - detectandshow( &alpr, latestFrame, "", outputJson); + cv::imencode(".bmp", latestFrame, buffer ); + std::vector results = alpr.recognize(buffer); + + if (results.size() > 0) + { + // Create a UUID for the image + std::string uuid = newUUID(); + + // Save the image to disk (using the UUID) + std::stringstream ss; + ss << tdata->output_image_folder << "/" << uuid << ".jpg"; + + cv::imwrite(ss.str(), latestFrame); + + // Update the JSON content to include UUID and camera ID + cJSON *root; + + root=cJSON_CreateObject(); + + std::string json = alpr.toJson(results); + + cJSON *array = cJSON_Parse(json.c_str()); + cJSON_AddStringToObject(root, "uuid", uuid.c_str()); + cJSON_AddNumberToObject(root, "camera_id", tdata->camera_id); + cJSON_AddItemToObject(root, "results", array); + + char *out; + out=cJSON_PrintUnformatted(root); + cJSON_Delete(root); + + std::string response(out); + + free(out); + + // Push the results to the Beanstalk queue + writeToQueue(response); + } } - //cv::waitKey(10); + usleep(10000); } - */ + videoBuffer.disconnect(); @@ -97,14 +220,14 @@ void streamRecognitionThread(void* arg) } -bool writeToQueue(AlprResult result) +bool writeToQueue(std::string jsonResult) { Beanstalk::Client client("127.0.0.1", 11300); client.use("test"); client.watch("test"); - int id = client.put("hello"); + int id = client.put(jsonResult); if (id <= 0) return 1; @@ -119,7 +242,7 @@ bool writeToQueue(AlprResult result) std::cout << "reserved job id: " << job.id() - << " with body {" << job.body() << "}" + << " with body: " << job.body() << "" << std::endl; client.del(job.id());