diff --git a/src/daemon.cpp b/src/daemon.cpp index a27f2f8..a994362 100644 --- a/src/daemon.cpp +++ b/src/daemon.cpp @@ -286,7 +286,7 @@ void streamRecognitionThread(void* arg) { timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); std::vector regionsOfInterest; regionsOfInterest.push_back(AlprRegionOfInterest(0,0, latestFrame.cols, latestFrame.rows)); @@ -294,7 +294,7 @@ void streamRecognitionThread(void* arg) AlprResults results = alpr.recognize(latestFrame.data, latestFrame.elemSize(), latestFrame.cols, latestFrame.rows, regionsOfInterest); timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); double totalProcessingTime = diffclock(startTime, endTime); if (tdata->clock_on) @@ -304,10 +304,9 @@ void streamRecognitionThread(void* arg) if (results.plates.size() > 0) { - long epoch_time = getEpochTime(); std::stringstream uuid_ss; - uuid_ss << tdata->site_id << "-cam" << tdata->camera_id << "-" << epoch_time; + uuid_ss << tdata->site_id << "-cam" << tdata->camera_id << "-" << getEpochTimeMs(); std::string uuid = uuid_ss.str(); // Save the image to disk (using the UUID) diff --git a/src/main.cpp b/src/main.cpp index 09b2fe4..5bd32a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -275,7 +275,7 @@ bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJso { timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); std::vector regionsOfInterest; regionsOfInterest.push_back(AlprRegionOfInterest(0,0, frame.cols, frame.rows)); @@ -283,7 +283,7 @@ bool detectandshow( Alpr* alpr, cv::Mat frame, std::string region, bool writeJso AlprResults results = alpr->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, regionsOfInterest ); timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); double totalProcessingTime = diffclock(startTime, endTime); if (measureProcessingTime) std::cout << "Total Time to process image: " << totalProcessingTime << "ms." << std::endl; diff --git a/src/misc_utilities/benchmarks/benchmark.cpp b/src/misc_utilities/benchmarks/benchmark.cpp index 4ece8c6..8db0256 100644 --- a/src/misc_utilities/benchmarks/benchmark.cpp +++ b/src/misc_utilities/benchmarks/benchmark.cpp @@ -187,18 +187,18 @@ int main( int argc, const char** argv ) string fullpath = inDir + "/" + files[i]; frame = imread( fullpath.c_str() ); - getTime(&startTime); + getTimeMonotonic(&startTime); vector regionsOfInterest; regionsOfInterest.push_back(Rect(0, 0, frame.cols, frame.rows)); alpr.recognize(frame, regionsOfInterest); - getTime(&endTime); + getTimeMonotonic(&endTime); double endToEndTime = diffclock(startTime, endTime); cout << " -- End to End recognition time: " << endToEndTime << "ms." << endl; endToEndTimes.push_back(endToEndTime); - getTime(&startTime); + getTimeMonotonic(&startTime); vector regions = plateDetector->detect(frame); - getTime(&endTime); + getTimeMonotonic(&endTime); double regionDetectionTime = diffclock(startTime, endTime); cout << " -- Region detection time: " << regionDetectionTime << "ms." << endl; @@ -209,18 +209,18 @@ int main( int argc, const char** argv ) PipelineData pipeline_data(frame, regions[z].rect, &config); - getTime(&startTime); + getTimeMonotonic(&startTime); stateIdentifier.recognize(&pipeline_data); - getTime(&endTime); + getTimeMonotonic(&endTime); double stateidTime = diffclock(startTime, endTime); cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl; stateIdTimes.push_back(stateidTime); - getTime(&startTime); + getTimeMonotonic(&startTime); LicensePlateCandidate lp(&pipeline_data); lp.recognize(); - getTime(&endTime); + getTimeMonotonic(&endTime); double analysisTime = diffclock(startTime, endTime); cout << "\tRegion " << z << ": Analysis time: " << analysisTime << "ms." << endl; @@ -228,16 +228,16 @@ int main( int argc, const char** argv ) { lpAnalysisPositiveTimes.push_back(analysisTime); - getTime(&startTime); + getTimeMonotonic(&startTime); ocr.performOCR(&pipeline_data); - getTime(&endTime); + getTimeMonotonic(&endTime); double ocrTime = diffclock(startTime, endTime); cout << "\tRegion " << z << ": OCR time: " << ocrTime << "ms." << endl; ocrTimes.push_back(ocrTime); - getTime(&startTime); + getTimeMonotonic(&startTime); ocr.postProcessor.analyze("", 25); - getTime(&endTime); + getTimeMonotonic(&endTime); double postProcessTime = diffclock(startTime, endTime); cout << "\tRegion " << z << ": PostProcess time: " << postProcessTime << "ms." << endl; postProcessTimes.push_back(postProcessTime); diff --git a/src/openalpr/alpr.cpp b/src/openalpr/alpr.cpp index 371ba00..ac1998b 100644 --- a/src/openalpr/alpr.cpp +++ b/src/openalpr/alpr.cpp @@ -55,7 +55,7 @@ namespace alpr { std::cerr << "file does not exist: " << filepath << std::endl; AlprResults emptyResults; - emptyResults.epoch_time = getEpochTime(); + emptyResults.epoch_time = getEpochTimeMs(); emptyResults.img_width = 0; emptyResults.img_height = 0; emptyResults.total_processing_time_ms = 0; diff --git a/src/openalpr/alpr_impl.cpp b/src/openalpr/alpr_impl.cpp index 3fd7830..56c1b1c 100644 --- a/src/openalpr/alpr_impl.cpp +++ b/src/openalpr/alpr_impl.cpp @@ -72,12 +72,12 @@ namespace alpr AlprFullDetails AlprImpl::recognizeFullDetails(cv::Mat img, std::vector regionsOfInterest) { timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); AlprFullDetails response; - response.results.epoch_time = getEpochTime(); + response.results.epoch_time = getEpochTimeMs(); response.results.img_width = img.cols; response.results.img_height = img.rows; @@ -126,7 +126,7 @@ namespace alpr PipelineData pipeline_data(img, plateRegion.rect, config); timespec platestarttime; - getTime(&platestarttime); + getTimeMonotonic(&platestarttime); LicensePlateCandidate lp(&pipeline_data); @@ -196,7 +196,7 @@ namespace alpr } timespec plateEndTime; - getTime(&plateEndTime); + getTimeMonotonic(&plateEndTime); plateResult.processing_time_ms = diffclock(platestarttime, plateEndTime); if (plateResult.topNPlates.size() > 0) @@ -222,7 +222,7 @@ namespace alpr } timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); response.results.total_processing_time_ms = diffclock(startTime, endTime); if (config->debugTiming) diff --git a/src/openalpr/colorfilter.cpp b/src/openalpr/colorfilter.cpp index 4598d96..d7add3a 100644 --- a/src/openalpr/colorfilter.cpp +++ b/src/openalpr/colorfilter.cpp @@ -29,7 +29,7 @@ namespace alpr ColorFilter::ColorFilter(Mat image, Mat characterMask, Config* config) { timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); this->config = config; @@ -53,7 +53,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << " -- ColorFilter Time: " << diffclock(startTime, endTime) << "ms." << endl; } } diff --git a/src/openalpr/detection/detectorcpu.cpp b/src/openalpr/detection/detectorcpu.cpp index 2775ab4..64a3a5e 100644 --- a/src/openalpr/detection/detectorcpu.cpp +++ b/src/openalpr/detection/detectorcpu.cpp @@ -102,7 +102,7 @@ namespace alpr //-- Detect plates timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); float maxWidth = ((float) w) * (config->maxPlateWidthPercent / 100.0f) * this->scale_factor; float maxHeight = ((float) h) * (config->maxPlateHeightPercent / 100.0f) * this->scale_factor; @@ -118,7 +118,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "LBP Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/openalpr/detection/detectorcuda.cpp b/src/openalpr/detection/detectorcuda.cpp index 65615c4..956c0d6 100644 --- a/src/openalpr/detection/detectorcuda.cpp +++ b/src/openalpr/detection/detectorcuda.cpp @@ -98,7 +98,7 @@ namespace alpr //-- Detect plates timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); float maxWidth = ((float) w) * (config->maxPlateWidthPercent / 100.0f) * this->scale_factor; float maxHeight = ((float) h) * (config->maxPlateHeightPercent / 100.0f) * this->scale_factor; @@ -121,7 +121,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "LBP Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/openalpr/edges/platecorners.cpp b/src/openalpr/edges/platecorners.cpp index b49b299..12be2cd 100644 --- a/src/openalpr/edges/platecorners.cpp +++ b/src/openalpr/edges/platecorners.cpp @@ -53,7 +53,7 @@ namespace alpr cout << "PlateCorners::findPlateCorners" << endl; timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); int horizontalLines = this->plateLines->horizontalLines.size(); int verticalLines = this->plateLines->verticalLines.size(); @@ -118,7 +118,7 @@ namespace alpr if (pipelineData->config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "Plate Corners Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/openalpr/edges/platelines.cpp b/src/openalpr/edges/platelines.cpp index 14956a2..ec7aa27 100644 --- a/src/openalpr/edges/platelines.cpp +++ b/src/openalpr/edges/platelines.cpp @@ -47,7 +47,7 @@ namespace alpr cout << "PlateLines findLines" << endl; timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); // Ignore input images that are pure white or pure black @@ -129,7 +129,7 @@ namespace alpr if (pipelineData->config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "Plate Lines Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/openalpr/licenseplatecandidate.cpp b/src/openalpr/licenseplatecandidate.cpp index 213daf1..22d6501 100644 --- a/src/openalpr/licenseplatecandidate.cpp +++ b/src/openalpr/licenseplatecandidate.cpp @@ -69,7 +69,7 @@ namespace alpr { timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); Mat originalCrop = pipeline_data->crop_gray; @@ -113,7 +113,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "deskew Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/openalpr/ocr.cpp b/src/openalpr/ocr.cpp index a379ff2..6be91d5 100644 --- a/src/openalpr/ocr.cpp +++ b/src/openalpr/ocr.cpp @@ -54,7 +54,7 @@ namespace alpr void OCR::performOCR(PipelineData* pipeline_data) { timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); postProcessor.clear(); @@ -131,7 +131,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "OCR Time: " << diffclock(startTime, endTime) << "ms." << endl; } } diff --git a/src/openalpr/postprocess.cpp b/src/openalpr/postprocess.cpp index f2194c9..e4375b0 100644 --- a/src/openalpr/postprocess.cpp +++ b/src/openalpr/postprocess.cpp @@ -152,7 +152,7 @@ namespace alpr void PostProcess::analyze(string templateregion, int topn) { timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); // Get a list of missing positions for (int i = letters.size() -1; i >= 0; i--) @@ -201,7 +201,7 @@ namespace alpr findAllPermutations(tmp, 0, config->postProcessMaxSubstitutions); timespec sortStartTime; - getTime(&sortStartTime); + getTimeMonotonic(&sortStartTime); int numelements = topn; if (allPossibilities.size() < topn) @@ -212,7 +212,7 @@ namespace alpr if (config->debugTiming) { timespec sortEndTime; - getTime(&sortEndTime); + getTimeMonotonic(&sortEndTime); cout << " -- PostProcess Sort Time: " << diffclock(sortStartTime, sortEndTime) << "ms." << endl; } @@ -290,7 +290,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "PostProcess Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/openalpr/segmentation/charactersegmenter.cpp b/src/openalpr/segmentation/charactersegmenter.cpp index b7309ba..c4b6644 100644 --- a/src/openalpr/segmentation/charactersegmenter.cpp +++ b/src/openalpr/segmentation/charactersegmenter.cpp @@ -40,7 +40,7 @@ namespace alpr //CharacterRegion charRegion(img, debug); timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); if (pipeline_data->plate_inverted) bitwise_not(pipeline_data->crop_gray, pipeline_data->crop_gray); @@ -110,7 +110,7 @@ namespace alpr // Do the histogram analysis to figure out char regions timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); vector allHistograms; @@ -166,7 +166,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << " -- Character Segmentation Create and Score Histograms Time: " << diffclock(startTime, endTime) << "ms." << endl; } @@ -189,7 +189,7 @@ namespace alpr } } - getTime(&startTime); + getTimeMonotonic(&startTime); filterEdgeBoxes(pipeline_data->thresholds, candidateBoxes, medianCharWidth, avgCharHeight); candidateBoxes = filterMostlyEmptyBoxes(pipeline_data->thresholds, candidateBoxes); @@ -204,7 +204,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << " -- Character Segmentation Box cleaning/filtering Time: " << diffclock(startTime, endTime) << "ms." << endl; } @@ -226,7 +226,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "Character Segmenter Time: " << diffclock(startTime, endTime) << "ms." << endl; } } diff --git a/src/openalpr/stateidentifier.cpp b/src/openalpr/stateidentifier.cpp index 49aa9ee..3757134 100644 --- a/src/openalpr/stateidentifier.cpp +++ b/src/openalpr/stateidentifier.cpp @@ -52,7 +52,7 @@ namespace alpr bool StateIdentifier::recognize(PipelineData* pipeline_data) { timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); Mat plateImg = Mat(pipeline_data->grayImg, pipeline_data->regionOfInterest); @@ -75,7 +75,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "State Identification Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/openalpr/support/timing.cpp b/src/openalpr/support/timing.cpp index f585076..b33e228 100644 --- a/src/openalpr/support/timing.cpp +++ b/src/openalpr/support/timing.cpp @@ -71,11 +71,24 @@ namespace alpr return (0); } - void getTime(timespec* time) + void getTimeMonotonic(timespec* time) { clock_gettime(0, time); } + + long getTimeMonotonicMs() + { + timespec time; + getTimeMonotonic(&time); + timespec time_start; + time_start.tv_sec = 0; + time_start.tv_nsec = 0; + + return diffclock(time_start, time); + } + + double diffclock(timespec time1,timespec time2) { timespec delta = diff(time1,time2); @@ -101,26 +114,48 @@ namespace alpr } - long getEpochTime() + long getEpochTimeMs() { return std::time(0) * 1000; } #else - void getTime(timespec* time) + void _getTime(bool realtime, timespec* time) { - #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - time->tv_sec = mts.tv_sec; - time->tv_nsec = mts.tv_nsec; - #else - clock_gettime(CLOCK_MONOTONIC, time); - #endif + #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + time->tv_sec = mts.tv_sec; + time->tv_nsec = mts.tv_nsec; + #else + if (realtime) + clock_gettime(CLOCK_REALTIME, time); + else + clock_gettime(CLOCK_MONOTONIC, time); + #endif + } + + // Returns a monotonic clock time unaffected by time changes (e.g., NTP) + // Useful for interval comparisons + void getTimeMonotonic(timespec* time) + { + _getTime(false, time); + } + + long getTimeMonotonicMs() + { + timespec time; + getTimeMonotonic(&time); + + timespec time_start; + time_start.tv_sec = 0; + time_start.tv_nsec = 0; + + return diffclock(time_start, time); } double diffclock(timespec time1,timespec time2) @@ -148,13 +183,18 @@ namespace alpr } - long getEpochTime() + // Returns wall clock time since Unix epoch (Jan 1, 1970) + long getEpochTimeMs() { - struct timeval tp; - gettimeofday(&tp, NULL); - long ms = tp.tv_sec * 1000 + tp.tv_usec / 1000; + timespec time; + _getTime(true, &time); + + timespec epoch_start; + epoch_start.tv_sec = 0; + epoch_start.tv_nsec = 0; + + return diffclock(epoch_start, time); - return ms; } #endif diff --git a/src/openalpr/support/timing.h b/src/openalpr/support/timing.h index a89bc64..542be0b 100644 --- a/src/openalpr/support/timing.h +++ b/src/openalpr/support/timing.h @@ -26,10 +26,12 @@ namespace alpr { - void getTime(timespec* time); + void getTimeMonotonic(timespec* time); + long getTimeMonotonicMs(); + double diffclock(timespec time1,timespec time2); - long getEpochTime(); + long getEpochTimeMs(); } diff --git a/src/openalpr/textdetection/characteranalysis.cpp b/src/openalpr/textdetection/characteranalysis.cpp index f9b52d2..4d13e4c 100644 --- a/src/openalpr/textdetection/characteranalysis.cpp +++ b/src/openalpr/textdetection/characteranalysis.cpp @@ -56,7 +56,7 @@ namespace alpr timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); pipeline_data->textLines.clear(); @@ -70,12 +70,12 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << " -- Character Analysis Find Contours Time: " << diffclock(startTime, endTime) << "ms." << endl; } //Mat img_equalized = equalizeBrightness(img_gray); - getTime(&startTime); + getTimeMonotonic(&startTime); for (unsigned int i = 0; i < pipeline_data->thresholds.size(); i++) { @@ -88,7 +88,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << " -- Character Analysis Filter Time: " << diffclock(startTime, endTime) << "ms." << endl; } @@ -206,7 +206,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << "Character Analysis Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/openalpr/utility.cpp b/src/openalpr/utility.cpp index 1e64ad5..9c4b7c9 100644 --- a/src/openalpr/utility.cpp +++ b/src/openalpr/utility.cpp @@ -121,7 +121,7 @@ namespace alpr //Mat img_equalized = equalizeBrightness(img_gray); timespec startTime; - getTime(&startTime); + getTimeMonotonic(&startTime); vector thresholds; @@ -160,7 +160,7 @@ namespace alpr if (config->debugTiming) { timespec endTime; - getTime(&endTime); + getTimeMonotonic(&endTime); cout << " -- Produce Threshold Time: " << diffclock(startTime, endTime) << "ms." << endl; } diff --git a/src/tests/test_api.cpp b/src/tests/test_api.cpp index a9441cd..fdf3939 100644 --- a/src/tests/test_api.cpp +++ b/src/tests/test_api.cpp @@ -20,7 +20,7 @@ using namespace alpr; TEST_CASE( "JSON Serialization/Deserialization", "[json]" ) { AlprResults origResults; - origResults.epoch_time = getEpochTime(); + origResults.epoch_time = getEpochTimeMs(); origResults.img_width = 640; origResults.img_height = 480; origResults.total_processing_time_ms = 100;