diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ee7c99..dacda6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,9 @@ option(BUILD_EXAMPLE_APP "Build Iris example console application" OFF) option(EXPORT_IRIS "Export and install library" ON) option(BUILD_SHARED_LIBS "Build iris as a shared library" OFF) option(BUILD_COVERAGE "Builds code coverage target" OFF) +option(PROFILER "Enable profiling" OFF) -if (NOT UNIX) +if (BUILD_COVERAGE AND NOT UNIX) set(BUILD_COVERAGE OFF) message("Code coverage can only be built in Linux systems") endif() @@ -32,6 +33,7 @@ set(PUBLIC_HEADERS "include/iris/Log.h" "include/iris/Result.h" "include/iris/TotalFlashIncidents.h" + "include/iris/ScopeProfiler.h" ) source_group("Public header files" FILES ${PUBLIC_HEADERS}) @@ -44,14 +46,12 @@ set(SOURCE_FILES "src/RedSaturation.h" "src/RedSaturation.cpp" "src/CDLuminance.cpp" - "src/TransitionEvaluator.cpp" "src/Configuration.cpp" "src/ConfigurationParams.h" "src/Flash.h" "src/RelativeLuminance.h" "src/CDLuminance.h" - "src/FrameRgbConverter.h" - "src/TransitionEvaluator.h" + "src/FrameRgbConverter.h" "src/FrameData.h" "src/FlashDetection.h" "src/FlashDetection.cpp" @@ -60,12 +60,19 @@ set(SOURCE_FILES "src/PatternDetection.h" "src/PatternDetection.cpp" "src/PhotosensitivityDetector.h" + "src/TransitionTracker.h" + "src/TransitionTrackerByFPS.h" + "src/TransitionTrackerByTime.h" + "src/TransitionTrackerByFPS.cpp" + "src/TransitionTrackerByTime.cpp" + "src/ScopeProfiler.cpp" ) source_group("Source files" FILES ${SOURCE_FILES}) # Dependencies find_package(OpenCV CONFIG REQUIRED) +find_package(FFMPEG REQUIRED) add_subdirectory ("utils") if(BUILD_SHARED_LIBS) @@ -115,6 +122,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC utils ${OpenCV_LIBS} + ${FFMPEG_LIBRARIES} ) # --------------------------------------------------------------------------------------- @@ -136,6 +144,14 @@ if(BUILD_TESTS) add_subdirectory("test/AddressSanitizer.Tests") endif() +# --------------------------------------------------------------------------------------- +# Profiler +# --------------------------------------------------------------------------------------- +if(PROFILER) + message("Profiler enabled") + target_compile_definitions(${PROJECT_NAME} PUBLIC -DPROFILING) +endif() + # --------------------------------------------------------------------------------------- # Install # --------------------------------------------------------------------------------------- @@ -192,4 +208,4 @@ export(EXPORT "${PROJECT_NAME}Targets" NAMESPACE ${namespace}:: ) -endif() \ No newline at end of file +endif() diff --git a/config/appsettings.json b/config/appsettings.json index ea4cee6..af3ccac 100644 --- a/config/appsettings.json +++ b/config/appsettings.json @@ -287,11 +287,12 @@ "MaxDataStored": 10 //max stored frame data in memory until persistence }, - "TransitionEvaluator": { + "TransitionTracker": { "MaxTransitions": 6, //max allowed transitions and max transitions to count for extended fail "MinTransitions": 4, //amount of min transitions to add to extended fail count "ExtendedFailSeconds": 4, //max seconds until the start of extended failure - "ExtendedFailWindow": 5 //seconds in extended fail count window + "ExtendedFailWindow": 5, //seconds in extended fail count window + "AnalyseByTime": false }, "FlashDetection": { @@ -559,7 +560,9 @@ "VideoAnalyser": { "LuminanceType": "RELATIVE", //CD || RELATIVE - "PatternDetectionEnabled": false + "PatternDetectionEnabled": false, + "FrameResizeEnabled": false, + "ResizeFrameProportion": 0.2 }, "Logging": { diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 81f5eb9..2caf50f 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -20,12 +20,18 @@ target_include_directories(${PROJECT_NAME} PUBLIC # Copy needed dll files into executable when building iris as dll if(BUILD_SHARED_LIBS) message("Copy dynamic libraries into IrisApp directory") - file(GLOB_RECURSE DLL_FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/*.dll) - file(COPY ${DLL_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - set(IRIS_DLL iris.dll) if (CMAKE_BUILD_TYPE STREQUAL "Debug") # set DEBUG_POSTFIX set(IRIS_DLL irisd.dll) + set(UTILS_DLL utilsd.dll) + file(GLOB_RECURSE DLL_DEBUG_FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug/bin/*.dll) + file(COPY ${DLL_DEBUG_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + + else() + file(GLOB_RECURSE DLL_FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/*.dll) + file(COPY ${DLL_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + set(IRIS_DLL iris.dll) + set(UTILS_DLL utils.dll) endif() add_custom_command(TARGET ${PROJECT_NAME} @@ -33,6 +39,12 @@ if(BUILD_SHARED_LIBS) COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/${IRIS_DLL} ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Copying Iris DLL to build directory" + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/utils/${UTILS_DLL} + ${CMAKE_CURRENT_BINARY_DIR} + + COMMENT "Copying Iris and utils DLL to build directory" ) + + endif() diff --git a/example/appsettings.json b/example/appsettings.json index d54f77a..2e3c3ef 100644 --- a/example/appsettings.json +++ b/example/appsettings.json @@ -286,11 +286,12 @@ "MaxDataStored": 10 //max stored frame data in memory until persistence }, - "TransitionEvaluator": { + "TransitionTracker": { "MaxTransitions": 6, //max allowed transitions and max transitions to count for extended fail "MinTransitions": 4, //amount of min transitions to add to extended fail count "ExtendedFailSeconds": 4, //max seconds until the start of extended failure - "ExtendedFailWindow": 5 //seconds in extended fail count window + "ExtendedFailWindow": 5, //seconds in extended fail count window + "AnalyseByTime": false }, "FlashDetection": { @@ -558,7 +559,9 @@ "VideoAnalyser": { "LuminanceType": "RELATIVE", //CD || RELATIVE - "PatternDetectionEnabled": false + "PatternDetectionEnabled": false, + "FrameResizeEnabled": false, + "ResizeFrameProportion": 0.2 }, "Logging": { diff --git a/example/main.cpp b/example/main.cpp index 76cab56..4e14335 100644 --- a/example/main.cpp +++ b/example/main.cpp @@ -116,6 +116,18 @@ int main(int argc, char* argv[]) configuration.SetPatternDetectionStatus(false); } } + if (cmdOptionExists(argv, argv + argc, "-r")) + { + std::string resize = getCmdOption(argv, argv + argc, "-r"); + if (resize == "true" || resize == "1") + { + configuration.SetFrameResizeEnabled(true); + } + else if (resize == "false" || resize == "0") + { + configuration.SetFrameResizeEnabled(false); + } + } if (cmdOptionExists(argv, argv + argc, "-a")) { @@ -126,7 +138,6 @@ int main(int argc, char* argv[]) //Run video analysis CreateResultsDir(configuration); - if (sourceVideo != nullptr) //Run specific video { iris::VideoAnalyser vA(&configuration); diff --git a/include/iris/Configuration.h b/include/iris/Configuration.h index b553f68..26c662d 100644 --- a/include/iris/Configuration.h +++ b/include/iris/Configuration.h @@ -11,7 +11,7 @@ namespace EA::EACC::Utils namespace iris { struct FlashParams; - struct TransitionEvaluatorParams; + struct TransitionTrackerParams; struct PatternDetectionParams; struct PatternAnalyserParams; struct StraightLineDetectorParams; @@ -42,11 +42,17 @@ namespace iris inline FlashParams* GetRedSaturationFlashParams() { return m_redSaturationFlashParams; } inline EA::EACC::Utils::FrameConverterParams* GetFrameSrgbConverterParams() { return m_frameSrgbConverterParams; } inline EA::EACC::Utils::FrameConverterParams* GetFrameCDLuminanceConverterParams() { return m_frameCDLuminanceConverterParams; } - inline TransitionEvaluatorParams* GetTransitionEvaluatorParams() { return m_transitionEvaluatorParams; } + inline TransitionTrackerParams* GetTransitionTrackerParams() { return m_transitionTrackerParams; } inline PatternDetectionParams* GetPatternDetectionParams() { return m_patternDetectionParams; } inline bool PatternDetectionEnabled() { return m_patternDetectionEnabled; } inline void SetPatternDetectionStatus(bool status) { m_patternDetectionEnabled = status; } + + inline bool FrameResizeEnabled() { return m_frameResizeEnabled; } + inline void SetFrameResizeEnabled(bool status) { m_frameResizeEnabled = status; } + + inline float GetFrameResizeProportion() { return m_frameResizeProportion; } + inline void SetFrameResizeProportion(float proportion) { m_frameResizeProportion = proportion; } void SetSafeArea(float areaProportion); @@ -58,11 +64,15 @@ namespace iris FlashParams* m_redSaturationFlashParams = nullptr; EA::EACC::Utils::FrameConverterParams* m_frameSrgbConverterParams = nullptr; EA::EACC::Utils::FrameConverterParams* m_frameCDLuminanceConverterParams = nullptr; - TransitionEvaluatorParams* m_transitionEvaluatorParams = nullptr; + TransitionTrackerParams* m_transitionTrackerParams = nullptr; PatternDetectionParams* m_patternDetectionParams = nullptr; LuminanceType m_luminanceType = LuminanceType::UN_SET; bool m_patternDetectionEnabled = true; + bool m_frameResizeEnabled = true; + + float m_frameResizeProportion = 1; + std::string m_resultsPath; }; -} \ No newline at end of file +} diff --git a/include/iris/FrameData.h b/include/iris/FrameData.h index 5043641..20ce321 100644 --- a/include/iris/FrameData.h +++ b/include/iris/FrameData.h @@ -26,7 +26,7 @@ namespace iris public: FrameData() {}; - FrameData(int frame, long timeMs) : Frame(frame) + FrameData(unsigned int frame, unsigned long timeMs) : Frame(frame) { TimeStampMs = msToTimeSpan(timeMs); }; @@ -108,7 +108,7 @@ namespace iris /// /// Frame index /// - int Frame = 0; + unsigned int Frame = 0; /// /// frame timestamp in milliseconds @@ -123,10 +123,10 @@ namespace iris float AverageRedDiff = 0; float AverageRedDiffAcc = 0; float PatternRisk = 0; - int LuminanceTransitions = 0; - int RedTransitions = 0; - int LuminanceExtendedFailCount = 0; - int RedExtendedFailCount = 0; + unsigned int LuminanceTransitions = 0; + unsigned int RedTransitions = 0; + unsigned int LuminanceExtendedFailCount = 0; + unsigned int RedExtendedFailCount = 0; FlashResult luminanceFrameResult = FlashResult::Pass; FlashResult redFrameResult = FlashResult::Pass; std::string patternArea = "0.00%"; @@ -161,7 +161,7 @@ namespace iris struct FrameDataJson { - void reserve(const int& size) + void reserve(const unsigned int& size) { frame.reserve(size); timeStampMs.reserve(size); @@ -190,7 +190,7 @@ namespace iris } - void reserveLineGraphData(const int& size) + void reserveLineGraphData(const unsigned int& size) { timeStampMs.reserve(size); luminanceTransitions.reserve(size); @@ -238,25 +238,25 @@ namespace iris patternFrameResult.push_back((int)data.patternFrameResult); } - std::vector frame; + std::vector frame; std::vector timeStampMs; std::vector luminanceFlashArea; std::vector luminanceAverage; std::vector averageLuminanceDiff; std::vector averageLuminanceDiffAcc; - std::vector redFlashArea; + std::vector < std::string> redFlashArea; std::vector redAverage; std::vector averageRedDiff; std::vector averageRedDiffAcc; - std::vector luminanceTransitions; - std::vector redTransitions; - std::vector luminanceExtendedFailCount; - std::vector redExtendedFailCount; - std::vector luminanceFrameResult; - std::vector redFrameResult; + std::vector luminanceTransitions; + std::vector redTransitions; + std::vector luminanceExtendedFailCount; + std::vector redExtendedFailCount; + std::vector luminanceFrameResult; + std::vector redFrameResult; std::vector patternArea; std::vector patternDetectedLines; - std::vector patternFrameResult; + std::vector patternFrameResult; }; //Serializes FrameData to Json object diff --git a/include/iris/Result.h b/include/iris/Result.h index ebf7226..5f064cd 100644 --- a/include/iris/Result.h +++ b/include/iris/Result.h @@ -45,15 +45,15 @@ namespace iris struct Result { - int VideoLen = 0; - int AnalysisTime = 0; - int TotalFrame = 0; - int patternFailFrames = 0; + float VideoLen = 0; + unsigned int AnalysisTime = 0; + unsigned int TotalFrame = 0; AnalysisResult OverallResult = AnalysisResult::Pass; std::vector Results; //total amount of frames that were counted that belonged to each incident type TotalFlashIncidents totalLuminanceIncidents; TotalFlashIncidents totalRedIncidents; + unsigned int patternFailFrames = 0; }; diff --git a/include/iris/ScopeProfiler.h b/include/iris/ScopeProfiler.h new file mode 100644 index 0000000..1069156 --- /dev/null +++ b/include/iris/ScopeProfiler.h @@ -0,0 +1,102 @@ +#pragma once + +#include +#include +#include +#include + +#ifdef IRIS_SHARED +#ifdef IRIS_EXPORT +#define IRIS_API __declspec(dllexport) +#else +#define IRIS_API __declspec(dllimport) +#endif +#else +#define IRIS_API +#endif + + +#ifdef PROFILING + +#define BEGIN_PROFILING() ScopeProfiler::GetInstance()->WriteHeader("","") +#define BEGIN_PROFILING_PATH(videoName) ScopeProfiler::GetInstance()->WriteHeader(videoName, "") +#define BEGIN_PROFILING_PATH_END(videoName, strEnd) ScopeProfiler::GetInstance()->WriteHeader(videoName, strEnd) + +#define PROFILING_IN(eventName) ScopeProfiler::GetInstance()->RegisterEvent(eventName) +#define PROFILING_OUT(eventName) ScopeProfiler::GetInstance()->FinishEvent(eventName) + +#define END_PROFILING() ScopeProfiler::GetInstance()->WriteFooter() + +#else +#define BEGIN_PROFILING() +#define BEGIN_PROFILING_PATH(videoName) +#define BEGIN_PROFILING_PATH_END(videoName, strEnd) + +#define PROFILING_IN(eventName) +#define PROFILING_OUT(eventName) + +#define END_PROFILING() +#endif + + +class ScopeProfiler { +public: + + //Singleton + inline static ScopeProfiler* GetInstance() { + if (!instance) { + instance = new ScopeProfiler(); + } + return instance; + } + + /// + /// Open file and Write the header in the .json file + /// + void WriteHeader(const std::string&, const std::string&); + + /// + /// Creates the event and stores it in m_Events + /// + void RegisterEvent(const std::string&); + + /// + /// Write event info on .json file + /// + void FinishEvent(const std::string&); + + /// + /// Write the Footer in the .json file + /// + void WriteFooter(); + + +private: + struct ProfileEvent { + std::string name; + std::string category = "function"; + long long startTime, endTime; + unsigned int processId; + unsigned int threadId; + std::chrono::time_point chrono_StartTime; + }; + + std::ofstream m_OutputStream; + + IRIS_API static ScopeProfiler* instance; + + std::map m_Events; + + const std::string filepath = "Results/"; + const std::string filepathMid = "ProfilingResults"; + const std::string filepathEnd = ".json"; + + ScopeProfiler(); + + /// + /// Write event info in the .json file + /// + void WriteProfile(const ProfileEvent&); + +}; + diff --git a/include/iris/VideoAnalyser.h b/include/iris/VideoAnalyser.h index 42da8c1..acb069b 100644 --- a/include/iris/VideoAnalyser.h +++ b/include/iris/VideoAnalyser.h @@ -49,7 +49,7 @@ namespace iris /// /// Initializes FlashDetection and PatternDetection /// - void Init(const short& fps, const cv::Size& size, const std::string& videoName, bool flagJson = false); + void Init(const std::string& videoName, bool flagJson = false); /// /// Release FlashDetection and PatternDection @@ -59,7 +59,7 @@ namespace iris /// /// Checks if the video file can be opened and read /// - bool VideoIsOpen(cv::VideoCapture& video, const char* videoName); + bool VideoIsOpen(const char* sourceVideo, cv::VideoCapture& video, const char* videoName); /// /// Anlyses video to check photosensitivity @@ -71,16 +71,39 @@ namespace iris /// /// Frame analysis for checking for photosensitivity for tracked issues (flashes/patterns) /// - void AnalyseFrame(cv::Mat& frame, int& frameIndex, FrameData& data); + void AnalyseFrame(cv::Mat& frame, unsigned int& frameIndex, FrameData& data); + /// + /// Set optimal number of threads depending on the frame resolution + /// + void SetOptimalCvThreads(cv::Size size); + + + struct VideoInfo + { + int fps; //video frames per second + int frameCount; //number of frames in video + float duration; //duration in seconds + cv::Size frameSize; //video resolution + }; + + inline VideoInfo GetVideoInfo() { return m_videoInfo; } + private: + /// + /// Obtains the avg_frame_rate of the video + /// + /// Video file path + /// frames per second in video + int GetVideoFps(const char* sourceVideo); + void SerializeResults(const Result& result, const FrameDataJson& lineGraphData, const FrameDataJson& nonPassData); /// /// Updates the current analysis progress /// - void UpdateProgress(int& numFrames, const long& totalFrames, int& lastPercentage); + void UpdateProgress(unsigned int& numFrames, const unsigned long& totalFrames, unsigned int& lastPercentage); Configuration* m_configuration = nullptr; FlashDetection* m_flashDetection = nullptr; @@ -91,5 +114,7 @@ namespace iris std::string m_resultJsonPath; std::string m_frameDataJsonPath; + + VideoInfo m_videoInfo; }; } \ No newline at end of file diff --git a/ports/aws-lambda-cpp/portfile.cmake b/ports/aws-lambda-cpp/portfile.cmake deleted file mode 100644 index 64e30ea..0000000 --- a/ports/aws-lambda-cpp/portfile.cmake +++ /dev/null @@ -1,25 +0,0 @@ -vcpkg_from_git( - OUT_SOURCE_PATH SOURCE_PATH - URL https://gitlab.ea.com/eacc-tech/aws-lambda-cpp - REF e4f4c092dc7cd57c5d22a95959987a3770ef57ff # v0.2.7 - HEAD_REF master -) - -vcpkg_cmake_configure( - SOURCE_PATH ${SOURCE_PATH} -) - -vcpkg_cmake_install() - -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) - -vcpkg_copy_pdbs() - -vcpkg_cmake_config_fixup(PACKAGE_NAME aws-lambda-runtime CONFIG_PATH lib/aws-lambda-runtime/cmake) - -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share") -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/aws-lambda-runtime") -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/lib/aws-lambda-runtime") - -# Handle copyright -file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) diff --git a/ports/aws-lambda-cpp/portfile.cmake.template b/ports/aws-lambda-cpp/portfile.cmake.template deleted file mode 100644 index 15dfdaf..0000000 --- a/ports/aws-lambda-cpp/portfile.cmake.template +++ /dev/null @@ -1,25 +0,0 @@ -vcpkg_from_git( - OUT_SOURCE_PATH SOURCE_PATH - URL https://lambda:TOKEN@gitlab.ea.com/eacc-tech/aws-lambda-cpp.git - REF e4f4c092dc7cd57c5d22a95959987a3770ef57ff # v0.2.7 - HEAD_REF master -) - -vcpkg_cmake_configure( - SOURCE_PATH ${SOURCE_PATH} -) - -vcpkg_cmake_install() - -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) - -vcpkg_copy_pdbs() - -vcpkg_cmake_config_fixup(PACKAGE_NAME aws-lambda-runtime CONFIG_PATH lib/aws-lambda-runtime/cmake) - -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share") -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/aws-lambda-runtime") -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/lib/aws-lambda-runtime") - -# Handle copyright -file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) diff --git a/ports/aws-lambda-cpp/vcpkg.json b/ports/aws-lambda-cpp/vcpkg.json deleted file mode 100644 index 72b7d99..0000000 --- a/ports/aws-lambda-cpp/vcpkg.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "aws-lambda-cpp", - "version": "0.2.7", - "port-version": 1, - "description": "EACC fork of C++ Runtime for AWS Lambda.", - "supports": "linux", - "dependencies": [ - "curl", - { - "name": "vcpkg-cmake", - "host": true - }, - { - "name": "vcpkg-cmake-config", - "host": true - } - ] -} diff --git a/ports/cpputils/portfile.cmake b/ports/cpputils/portfile.cmake deleted file mode 100644 index 46d352b..0000000 --- a/ports/cpputils/portfile.cmake +++ /dev/null @@ -1,24 +0,0 @@ -vcpkg_from_git( - OUT_SOURCE_PATH SOURCE_PATH - URL C:\\dev\\cpputils #https://gitlab.ea.com/eacc-tech/cpputils - REF c3c2276e60ea77c6c2abcfb2c73572ed3849f0c2 - HEAD_REF dev-blanca/cmake-refactor -) - -vcpkg_cmake_configure( - SOURCE_PATH "${SOURCE_PATH}" - OPTIONS - -DEXPORT_CPPUTILS=1 -) - -vcpkg_cmake_install() - -vcpkg_cmake_config_fixup( - CONFIG_PATH cmake/ -) - -vcpkg_copy_pdbs() - -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") - -vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/Copyright.txt" COMMENT "Install copyright") diff --git a/ports/cpputils/portfile.cmake.template b/ports/cpputils/portfile.cmake.template deleted file mode 100644 index 9655804..0000000 --- a/ports/cpputils/portfile.cmake.template +++ /dev/null @@ -1,19 +0,0 @@ -vcpkg_check_linkage(ONLY_STATIC_LIBRARY) - -vcpkg_from_git( - OUT_SOURCE_PATH SOURCE_PATH - URL https://cpputils:TOKEN@gitlab.ea.com/eacc-tech/cpputils.git - REF 4cf4008bcc1b0512e68166a78d3bb7e378e131cf - HEAD_REF main -) - -vcpkg_cmake_configure( - SOURCE_PATH "${SOURCE_PATH}" -) - -vcpkg_cmake_install() -vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/cpputils) -vcpkg_copy_pdbs() - -vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/Copyright.txt" COMMENT "Install copyright") -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") \ No newline at end of file diff --git a/ports/cpputils/usage b/ports/cpputils/usage deleted file mode 100644 index 006c71d..0000000 --- a/ports/cpputils/usage +++ /dev/null @@ -1,4 +0,0 @@ -The package CppUtils provides CMake targets - - find_package(cpputils CONFIG REQUIRED) - target_link_libraries(main PRIVATE cpputils::cpputils) \ No newline at end of file diff --git a/ports/cpputils/vcpkg.json b/ports/cpputils/vcpkg.json deleted file mode 100644 index b6ec239..0000000 --- a/ports/cpputils/vcpkg.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "cpputils", - "version-string": "1.0.0", - "description": "Library to share common C++ code", - "license": null, - "dependencies": [ - "nlohmann-json", - "spdlog", - "opencv", - { - "name": "vcpkg-cmake", - "host": true - }, - { - "name": "vcpkg-cmake-config", - "host": true - } - ] - } \ No newline at end of file diff --git a/src/CDLuminance.cpp b/src/CDLuminance.cpp index 2f789ab..e03765d 100644 --- a/src/CDLuminance.cpp +++ b/src/CDLuminance.cpp @@ -14,8 +14,8 @@ Abstract class for Flash detection namespace iris { - CDLuminance::CDLuminance(EA::EACC::Utils::FrameConverter *converter, const short& videoFPS,const cv::Size& frameSize, FlashParams* params) - : Flash(videoFPS, frameSize, params) + CDLuminance::CDLuminance(EA::EACC::Utils::FrameConverter *converter, const short& fps,const cv::Size& frameSize, FlashParams* params) + : Flash(fps, frameSize, params) { m_converter = converter; } diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 57a2270..8cfc521 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -34,9 +34,9 @@ namespace iris delete m_frameCDLuminanceConverterParams; m_frameCDLuminanceConverterParams = nullptr; } - if (m_transitionEvaluatorParams != nullptr) + if (m_transitionTrackerParams != nullptr) { - delete m_transitionEvaluatorParams; m_transitionEvaluatorParams = nullptr; + delete m_transitionTrackerParams; m_transitionTrackerParams = nullptr; } if (m_patternDetectionParams != nullptr) @@ -60,6 +60,9 @@ namespace iris } m_patternDetectionEnabled = jsonFile.GetParam("VideoAnalyser", "PatternDetectionEnabled"); + m_frameResizeEnabled = jsonFile.GetParam("VideoAnalyser", "FrameResizeEnabled"); + + m_frameResizeProportion = jsonFile.GetParam("VideoAnalyser", "ResizeFrameProportion"); //Luminance if (m_luminanceType == LuminanceType::CD) @@ -94,12 +97,13 @@ namespace iris jsonFile.GetVector("Luminance", "CdLuminanceValues")); } - //Transition Evaluetor Params - m_transitionEvaluatorParams = new TransitionEvaluatorParams( - jsonFile.GetParam("TransitionEvaluator", "MaxTransitions"), - jsonFile.GetParam("TransitionEvaluator", "MinTransitions"), - jsonFile.GetParam("TransitionEvaluator", "ExtendedFailSeconds"), - jsonFile.GetParam("TransitionEvaluator", "ExtendedFailWindow")); + //Transition Tracker Params + m_transitionTrackerParams = new TransitionTrackerParams( + jsonFile.GetParam("TransitionTracker", "MaxTransitions"), + jsonFile.GetParam("TransitionTracker", "MinTransitions"), + jsonFile.GetParam("TransitionTracker", "ExtendedFailSeconds"), + jsonFile.GetParam("TransitionTracker", "ExtendedFailWindow"), + jsonFile.GetParam("TransitionTracker", "AnalyseByTime")); //Pattern Detection int minStripes = jsonFile.GetParam("PatternDetection", "MinStripes"); diff --git a/src/ConfigurationParams.h b/src/ConfigurationParams.h index e3c17cf..9eb11f3 100644 --- a/src/ConfigurationParams.h +++ b/src/ConfigurationParams.h @@ -6,6 +6,8 @@ namespace iris { + using uint = unsigned int; + struct FlashParams { FlashParams(float flashThresh, float areaP, float darkThresh) : flashThreshold(flashThresh), areaProportion(areaP), darkThreshold(darkThresh) {}; @@ -23,15 +25,16 @@ namespace iris std::vector sRgbValues; //The input array containing the decimal values for the sRgb convertion }; - struct TransitionEvaluatorParams + struct TransitionTrackerParams { - TransitionEvaluatorParams(int maxTransition, int minTransitions, int extendedFailSeconds, int extendedFailWindow) - : maxTransitions(maxTransition), minTransitions(minTransitions), extendedFailSeconds(extendedFailSeconds), extendedFailWindow (extendedFailWindow) {}; - - int maxTransitions; //max allowed transitions and max transitions to count for extended fail - int minTransitions; //amount of min transitions to add to extended fail count - int extendedFailSeconds; //if extendedFailFramesIS reach this value, extended failure has occured - int extendedFailWindow; //seconds in extended fail count window + TransitionTrackerParams(uint maxTransition, uint minTransitions, uint extendedFailSeconds, uint extendedFailWindow, bool analyseByTime) + : maxTransitions(maxTransition), minTransitions(minTransitions), extendedFailSeconds(extendedFailSeconds), extendedFailWindow (extendedFailWindow), analyseByTime(analyseByTime) {}; + + uint maxTransitions; //max allowed transitions and max transitions to count for extended fail + uint minTransitions; //amount of min transitions to add to extended fail count + uint extendedFailSeconds; //if extendedFailFramesIS reach this value, extended failure has occured + uint extendedFailWindow; //seconds in extended fail count window + bool analyseByTime; //realise the flash analysis by time instead of FPS }; struct PatternDetectionParams diff --git a/src/Flash.cpp b/src/Flash.cpp index 635adae..831276f 100644 --- a/src/Flash.cpp +++ b/src/Flash.cpp @@ -17,14 +17,14 @@ namespace iris { short Flash::fps = 0; - Flash::Flash(short videoFPS, const cv::Size& frameSize, FlashParams* flashParams) + Flash::Flash(short fps, const cv::Size& frameSize, FlashParams* flashParams) { - Flash::fps = videoFPS; + Flash::fps = fps; m_params = flashParams; m_avgDiffInSecond.reserve(fps); m_avgDiffInSecond.emplace_back(0); //initial frame m_frameSize = frameSize.area(); - m_safeArea = (int)(frameSize.area() * m_params->areaProportion); + m_safeArea = frameSize.area() * m_params->areaProportion; LOG_CORE_INFO("Flash Area in pixels: {0}", m_safeArea); LOG_CORE_INFO("Number of pixels in frame: {0}", frameSize.area()); @@ -62,7 +62,7 @@ namespace iris float Flash::FrameMean() { - return (float)cv::mean(*currentFrame)[0]; + return cv::mean(*currentFrame)[0]; } void Flash::SetCurrentFrame(cv::Mat* flashValuesFrame) @@ -132,7 +132,7 @@ namespace iris return result; } - float Flash::roundoff(float value, char prec) + float Flash::roundoff(float value, unsigned char prec) { float pow_10 = std::pow(10.0f, (float)prec); return std::round(value * pow_10) / pow_10; diff --git a/src/Flash.h b/src/Flash.h index 1974cc7..45a77a0 100644 --- a/src/Flash.h +++ b/src/Flash.h @@ -91,7 +91,7 @@ namespace iris /// /// /// - static float roundoff(float value, char prec); + static float roundoff(float value, unsigned char prec); /// /// Calculates sRGB values in the log file to later diff --git a/src/FlashDetection.cpp b/src/FlashDetection.cpp index ccedae0..fb49a32 100644 --- a/src/FlashDetection.cpp +++ b/src/FlashDetection.cpp @@ -11,13 +11,23 @@ #include "IrisFrame.h" #include "iris/Log.h" #include "iris/Result.h" +#include "TransitionTrackerByFPS.h" +#include "TransitionTrackerByTime.h" namespace iris { FlashDetection::FlashDetection(Configuration* configuration, const short& fps, const cv::Size& frameSize) - : m_transitionEvaluator(fps, configuration->GetTransitionEvaluatorParams()), m_sRgbConverter(configuration->GetFrameSrgbConverterParams()), m_fps(fps) + : m_sRgbConverter(configuration->GetFrameSrgbConverterParams()), m_fps(fps) { + + if (configuration->GetTransitionTrackerParams()->analyseByTime) { + m_transitionTracker = new TransitionTrackerByTime(fps, configuration->GetTransitionTrackerParams()); + } + else { + m_transitionTracker = new TransitionTrackerByFPS(fps, configuration->GetTransitionTrackerParams()); + } + if (configuration->GetLuminanceType() == Configuration::LuminanceType::RELATIVE) { m_luminance = new RelativeLuminance(fps, frameSize, configuration->GetLuminanceFlashParams()); @@ -46,6 +56,10 @@ namespace iris { delete m_cdLuminanceConverter; m_cdLuminanceConverter = nullptr; } + if (m_transitionTracker != nullptr) + { + delete m_transitionTracker; + } } void FlashDetection::setLuminance(IrisFrame& irisFrame) @@ -64,15 +78,19 @@ namespace iris if (framePos != 0) //check difference between frame(n) and frame (n - 1) { - frameDifference(data); - m_transitionEvaluator.EvaluateSecond(framePos, m_fps, data); + frameDifference(framePos, data); + m_transitionTracker->EvaluateFrameMoment(framePos, m_fps, data); + } + else + { + m_transitionTracker->SetFirstFrame(data); } data.AverageLuminanceDiffAcc = m_lastAvgLumDiffAcc; data.AverageRedDiffAcc = m_lastAvgRedDiffAcc; } - void FlashDetection::frameDifference(FrameData& data) + void FlashDetection::frameDifference(const int& framePos, FrameData& data) { //Red Saturation difference cv::Mat* redSaturationDiff = m_redSaturation->FrameDifference(); @@ -90,7 +108,7 @@ namespace iris m_lastAvgLumDiffAcc = luminanceTransition.lastAvgDiffAcc; //Evaluate and count new transitions - m_transitionEvaluator.SetTransitions(luminanceTransition.checkResult, redTranstion.checkResult, data); + m_transitionTracker->SetTransitions(luminanceTransition.checkResult, redTranstion.checkResult, data); data.LuminanceFlashArea = data.proportionToPercentage(m_luminance->GetFlashArea()); data.RedFlashArea = data.proportionToPercentage(m_redSaturation->GetFlashArea()); @@ -104,17 +122,17 @@ namespace iris bool FlashDetection::isFail() { - if (m_transitionEvaluator.getFlashFail()) + if (m_transitionTracker->getFlashFail()) { LOG_CORE_INFO("Flash FAIL"); } - if (m_transitionEvaluator.getExtendedFailure()) + if (m_transitionTracker->getExtendedFailure()) { LOG_CORE_INFO("Extended Failure"); } - return m_transitionEvaluator.getFlashFail() || m_transitionEvaluator.getExtendedFailure(); + return m_transitionTracker->getFlashFail() || m_transitionTracker->getExtendedFailure(); } cv::Mat* FlashDetection::getLuminanceFrame() @@ -125,11 +143,11 @@ namespace iris void FlashDetection::setResult(Result& result) { //set incident counters - result.totalLuminanceIncidents = m_transitionEvaluator.getLuminanceIncidents(); - result.totalRedIncidents = m_transitionEvaluator.getRedIncidents(); + result.totalLuminanceIncidents = m_transitionTracker->getLuminanceIncidents(); + result.totalRedIncidents = m_transitionTracker->getRedIncidents(); //set overall result and results vector - if (m_transitionEvaluator.getLumFlashFail()) + if (m_transitionTracker->getLumFlashFail()) { result.OverallResult = AnalysisResult::Fail; result.Results.emplace_back(AnalysisResult::LuminanceFlashFailure); @@ -137,14 +155,14 @@ namespace iris LOG_CORE_INFO("Luminance Flash FAIL"); } - if (m_transitionEvaluator.getLumExtendedFailure()) + if (m_transitionTracker->getLumExtendedFailure()) { result.OverallResult = AnalysisResult::Fail; result.Results.emplace_back(AnalysisResult::LuminanceExtendedFlashFailure); LOG_CORE_INFO("Luminance Extended Failure"); } - if (m_transitionEvaluator.getRedFlashFail()) + if (m_transitionTracker->getRedFlashFail()) { result.OverallResult = AnalysisResult::Fail; result.Results.emplace_back(AnalysisResult::RedFlashFailure); @@ -152,14 +170,14 @@ namespace iris LOG_CORE_INFO("Red Flash FAIL"); } - if (m_transitionEvaluator.getRedExtendedFailure()) + if (m_transitionTracker->getRedExtendedFailure()) { result.OverallResult = AnalysisResult::Fail; result.Results.emplace_back(AnalysisResult::RedExtendedFlashFailure); LOG_CORE_INFO("Red Extended Failure"); } - if (result.OverallResult != AnalysisResult::Fail && ( m_transitionEvaluator.getLumPassWithWarning() || m_transitionEvaluator.getRedPassWithWarning() )) + if (result.OverallResult != AnalysisResult::Fail && ( m_transitionTracker->getLumPassWithWarning() || m_transitionTracker->getRedPassWithWarning() )) { result.OverallResult = AnalysisResult::PassWithWarning; LOG_CORE_INFO("Pass with Warning"); diff --git a/src/FlashDetection.h b/src/FlashDetection.h index 4d564d9..8c1c8af 100644 --- a/src/FlashDetection.h +++ b/src/FlashDetection.h @@ -9,7 +9,7 @@ ///////////////////////////////////////////////////////////////////////////// #pragma once -#include "TransitionEvaluator.h" +#include "TransitionTracker.h" #include "utils/FrameConverter.h" #include "opencv2/core/types.hpp" #include "iris/Configuration.h" @@ -66,9 +66,9 @@ namespace iris /// /// current frame position /// FrameData to persist - void frameDifference(FrameData& data); + void frameDifference(const int& framePos, FrameData& data); - TransitionEvaluator m_transitionEvaluator; + TransitionTracker* m_transitionTracker; Flash* m_luminance = nullptr; Flash* m_redSaturation = nullptr; EA::EACC::Utils::FrameConverter m_sRgbConverter; diff --git a/src/FrameData.h b/src/FrameData.h index f07e47f..f0d6702 100644 --- a/src/FrameData.h +++ b/src/FrameData.h @@ -10,9 +10,9 @@ namespace iris { static std::string msToTimeSpan(int ms) { - float seconds = fmodf((ms / 1000.0f), 60); - int minutes = (int)floor((ms / (1000 * 60)) % 60); - int hours = (int)floor((ms / (1000 * 60 * 60)) % 24); + float seconds = fmodf((ms / 1000.0), 60); + int minutes = floor((ms / (1000 * 60)) % 60); + int hours = floor((ms / (1000 * 60 * 60)) % 24); std::string h = (hours < 10) ? "0" + std::to_string(hours) : std::to_string(hours); std::string m = (minutes < 10) ? "0" + std::to_string(minutes) : std::to_string(minutes); @@ -26,8 +26,9 @@ namespace iris public: FrameData() {}; - FrameData(int frame, long timeMs) : Frame(frame) + FrameData(unsigned int frame, unsigned long timeMs) : Frame(frame) { + TimeStampVal = timeMs; TimeStampMs = msToTimeSpan(timeMs); }; @@ -54,11 +55,11 @@ namespace iris + ',' + std::to_string(RedTransitions) + ',' + std::to_string(LuminanceExtendedFailCount) + ',' + std::to_string(RedExtendedFailCount) - + ',' + std::to_string((short)luminanceFrameResult) - + ',' + std::to_string((short)redFrameResult) + + ',' + std::to_string((int)luminanceFrameResult) + + ',' + std::to_string((int)redFrameResult) + ',' + patternArea + ',' + std::to_string(patternDetectedLines) - + ',' + std::to_string((short)patternFrameResult) + '\0'; + + ',' + std::to_string((int)patternFrameResult) + '\0'; return csvOutput; } @@ -108,7 +109,7 @@ namespace iris /// /// Frame index /// - int Frame = 0; + unsigned int Frame = 0; /// /// frame timestamp in milliseconds @@ -123,15 +124,16 @@ namespace iris float AverageRedDiff = 0; float AverageRedDiffAcc = 0; float PatternRisk = 0; - int LuminanceTransitions = 0; - int RedTransitions = 0; - int LuminanceExtendedFailCount = 0; - int RedExtendedFailCount = 0; + unsigned int LuminanceTransitions = 0; + unsigned int RedTransitions = 0; + unsigned int LuminanceExtendedFailCount = 0; + unsigned int RedExtendedFailCount = 0; FlashResult luminanceFrameResult = FlashResult::Pass; FlashResult redFrameResult = FlashResult::Pass; std::string patternArea = "0.00%"; int patternDetectedLines = 0; PatternResult patternFrameResult = PatternResult::Pass; + unsigned long TimeStampVal = 0; }; //Serializes FrameData to Json object @@ -161,7 +163,7 @@ namespace iris struct FrameDataJson { - void reserve(const int& size) + void reserve(const unsigned int& size) { frame.reserve(size); timeStampMs.reserve(size); @@ -190,7 +192,7 @@ namespace iris } - void reserveLineGraphData(const int& size) + void reserveLineGraphData(const unsigned int& size) { timeStampMs.reserve(size); luminanceTransitions.reserve(size); @@ -220,12 +222,12 @@ namespace iris luminanceExtendedFailCount.push_back(data.LuminanceExtendedFailCount); redExtendedFailCount.push_back(data.RedExtendedFailCount); - luminanceFrameResult.push_back((short)data.luminanceFrameResult); - redFrameResult.push_back((short)data.redFrameResult); + luminanceFrameResult.push_back((int)data.luminanceFrameResult); + redFrameResult.push_back((int)data.redFrameResult); patternArea.push_back(data.patternArea); patternDetectedLines.push_back(data.patternDetectedLines); - patternFrameResult.push_back((short)data.patternFrameResult); + patternFrameResult.push_back((int)data.patternFrameResult); } void push_back_lineGraphData(const FrameData& data) @@ -233,12 +235,12 @@ namespace iris timeStampMs.push_back(data.TimeStampMs); luminanceTransitions.push_back(data.LuminanceTransitions); redTransitions.push_back(data.RedTransitions); - luminanceFrameResult.push_back((short)data.luminanceFrameResult); - redFrameResult.push_back((short)data.redFrameResult); - patternFrameResult.push_back((short)data.patternFrameResult); + luminanceFrameResult.push_back((int)data.luminanceFrameResult); + redFrameResult.push_back((int)data.redFrameResult); + patternFrameResult.push_back((int)data.patternFrameResult); } - std::vector frame; + std::vector frame; std::vector timeStampMs; std::vector luminanceFlashArea; std::vector luminanceAverage; @@ -248,15 +250,15 @@ namespace iris std::vector redAverage; std::vector averageRedDiff; std::vector averageRedDiffAcc; - std::vector luminanceTransitions; - std::vector redTransitions; - std::vector luminanceExtendedFailCount; - std::vector redExtendedFailCount; - std::vector luminanceFrameResult; - std::vector redFrameResult; + std::vector luminanceTransitions; + std::vector redTransitions; + std::vector luminanceExtendedFailCount; + std::vector redExtendedFailCount; + std::vector luminanceFrameResult; + std::vector redFrameResult; std::vector patternArea; std::vector patternDetectedLines; - std::vector patternFrameResult; + std::vector patternFrameResult; }; //Serializes FrameData to Json object diff --git a/src/PatternDetection.cpp b/src/PatternDetection.cpp index 9391749..92cefc2 100644 --- a/src/PatternDetection.cpp +++ b/src/PatternDetection.cpp @@ -39,10 +39,12 @@ PatternDetection::PatternDetection(Configuration* configuration, const short& fp scaleSize = frameSize; } - m_safeArea = (int)(scaleSize.area() * m_params->areaProportion); - m_thresholdArea = (int)(scaleSize.area() * 0.20f); //20% of the screen display - m_frameTimeThresh = (int)(fps * m_params->timeThreshold); - m_contourThreshArea = (int)(scaleSize.area() * 0.00155); + m_safeArea = scaleSize.area() * m_params->areaProportion; + m_thresholdArea = scaleSize.area() * 0.20; //20% of the screen display + m_diffThreshold = scaleSize.area() * 0.1; + + m_frameTimeThresh = fps * m_params->timeThreshold; + m_contourThreshArea = scaleSize.area() * 0.00155; m_frameSize = scaleSize.area(); m_patternFrameCount = {}; @@ -57,7 +59,7 @@ PatternDetection::PatternDetection(Configuration* configuration, const short& fp cv::Size(2 * dilation_size + 1, 2 * dilation_size + 1), cv::Point(dilation_size, dilation_size)); - int erosion_size = 2; + int erosion_size = 1; m_erosionElement = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1), cv::Point(erosion_size, erosion_size)); @@ -65,7 +67,7 @@ PatternDetection::PatternDetection(Configuration* configuration, const short& fp void PatternDetection::checkFrame(const IrisFrame& irisFrame, const int& framePos, FrameData& data) { - auto pattern = detectPattern(irisFrame); + auto pattern = detectPattern(irisFrame, framePos); #ifdef DEBUG_PATTERN_DETECTION cv::destroyAllWindows(); @@ -83,7 +85,7 @@ void PatternDetection::checkFrame(const IrisFrame& irisFrame, const int& framePo checkFrameCount(data); } -PatternDetection::Pattern PatternDetection::detectPattern(const IrisFrame& irisFrame) +PatternDetection::Pattern PatternDetection::detectPattern(const IrisFrame& irisFrame, const int& framePos) { cv::Mat luminance, luminance_8UC, iftThresh; cv::resize(*irisFrame.luminanceFrame, luminance, scaleSize); @@ -148,7 +150,7 @@ bool PatternDetection::hasPattern(const cv::Mat& luminanceFrame, cv::Mat& iftThr iftThresh = highlightPatternArea(ift, luminanceFrame); //if the area threshold has not been reached, no harmful pattern exists - if (cv::countNonZero(iftThresh) < m_thresholdArea) + if (cv::countNonZero(iftThresh) < m_diffThreshold) { return false; } @@ -173,7 +175,7 @@ cv::Mat PatternDetection::highlightPatternArea(cv::Mat& ift, const cv::Mat& lumi SHOW_IMG(absDiff, "Absolute Difference"); #endif // DEBUG_IFT cv::Mat thresh; - cv::threshold(absDiff, thresh, 60, 255, cv::ThresholdTypes::THRESH_BINARY); + cv::threshold(absDiff, thresh, 50, 255, cv::ThresholdTypes::THRESH_BINARY); #ifdef DEBUG_IFT SHOW_IMG(thresh, "IFT Abs Diff Binary Threshold"); #endif // DEBUG_IFT @@ -183,7 +185,8 @@ cv::Mat PatternDetection::highlightPatternArea(cv::Mat& ift, const cv::Mat& lumi std::tuple PatternDetection::getPatternRegion(cv::Mat& threshIFT, cv::Mat& luminanceFrame) { - cv::erode(threshIFT, threshIFT, m_erosionElement); + //cv::erode(threshIFT, threshIFT, m_erosionElement); + #ifdef DEBUG_PATTERN_REGION SHOW_IMG(threshIFT, "Erosion"); #endif // DEBUG_PATTERN_REGION @@ -191,7 +194,7 @@ std::tuple PatternDetection::getPatternRegion(cv::Mat& threshIFT, //remove elements that are not part of the pattern auto threshContours = getContours(threshIFT); #ifdef DEBUG_PATTERN_REGION - SHOW_IMG(threshIFT, "Erosion Contours"); + SHOW_CONTOURS(threshContours, threshIFT, "Erosion Contours"); #endif // DEBUG_PATTERN_REGION auto contoursMat = moveBiggerContours(threshContours, threshIFT); @@ -255,8 +258,8 @@ void PatternDetection::setPatternLuminance(Pattern& pattern, cv::Mat& patternReg cv::bitwise_not(lightComponents, darkComponents, patternRegion); SHOW_IMG(darkComponents, "Dark Components"); - pattern.avgLightLuminance = (float)cv::mean(luminanceFrame, lightComponents)[0]; - pattern.avgDarkLuminance = (float)cv::mean(luminanceFrame, darkComponents)[0]; + pattern.avgLightLuminance = cv::mean(luminanceFrame, lightComponents)[0]; + pattern.avgDarkLuminance = cv::mean(luminanceFrame, darkComponents)[0]; } std::vector> PatternDetection::getContours(const cv::Mat& src) @@ -446,7 +449,7 @@ cv::Mat FourierTransform::getPeaks(const cv::Mat& psd) //threshold peaks cv::Mat threshPSD; psd.convertTo(threshPSD, CV_8UC1); - cv::threshold(threshPSD, threshPSD, 7, 255, cv::ThresholdTypes::THRESH_OTSU); + double thresh = cv::threshold(threshPSD, threshPSD, 7, 255, cv::ThresholdTypes::THRESH_OTSU); #ifdef DEBUG_FFT fftShift(threshPSD); diff --git a/src/PatternDetection.h b/src/PatternDetection.h index 89c2c78..11c5397 100644 --- a/src/PatternDetection.h +++ b/src/PatternDetection.h @@ -56,7 +56,7 @@ class PatternDetection : public PhotosensitivityDetector void checkFrameCount(FrameData& data); //detects a pattern in a video frame and returns the pattern info - Pattern detectPattern(const IrisFrame& irisFrame); + Pattern detectPattern(const IrisFrame& irisFrame, const int& framePos); //determines whether a video frame has a pattern or not bool hasPattern(const cv::Mat& luminanceFrame, cv::Mat& ift); @@ -119,8 +119,8 @@ class PatternDetection : public PhotosensitivityDetector } std::vector count; - int passed = 0; - int current = 0; + int passed; + int current; }; PatternDetectionParams* m_params; @@ -129,14 +129,14 @@ class PatternDetection : public PhotosensitivityDetector Counter m_patternFrameCount; int m_frameTimeThresh; - int m_patternFailFrames; + unsigned int m_patternFailFrames; short m_fps; int m_safeArea; int m_frameSize; int m_thresholdArea; //20% of the frame size to check if there is a possible pattern + int m_diffThreshold; //number of pixels that must have changed to continue the pattern detection flow bool m_isFail; - int areaThresh; int m_contourThreshArea; cv::Mat m_dilationElement; diff --git a/src/RedSaturation.cpp b/src/RedSaturation.cpp index a4d9c4b..2f6a476 100644 --- a/src/RedSaturation.cpp +++ b/src/RedSaturation.cpp @@ -7,8 +7,8 @@ namespace iris { - RedSaturation::RedSaturation(short videoFPS, const cv::Size& frameSize, FlashParams* params) - : Flash(videoFPS, frameSize, params) + RedSaturation::RedSaturation(short fps, const cv::Size& frameSize, FlashParams* params) + : Flash(fps, frameSize, params) { } diff --git a/src/RedSaturation.h b/src/RedSaturation.h index d092628..e87086f 100644 --- a/src/RedSaturation.h +++ b/src/RedSaturation.h @@ -18,7 +18,7 @@ namespace iris { public: - RedSaturation(short videoFPS, const cv::Size& frameSize, FlashParams* params); + RedSaturation(short fps, const cv::Size& frameSize, FlashParams* params); ~RedSaturation(); void SetCurrentFrame(cv::Mat* sRgbFrame) override; diff --git a/src/RelativeLuminance.cpp b/src/RelativeLuminance.cpp index 65c53d8..30257b3 100644 --- a/src/RelativeLuminance.cpp +++ b/src/RelativeLuminance.cpp @@ -15,8 +15,8 @@ namespace iris { cv::Scalar RelativeLuminance::rgbValues(0.0722f, 0.7152f, 0.2126f); - RelativeLuminance::RelativeLuminance(short videoFPS, const cv::Size& frameSize, FlashParams* params) - : Flash(videoFPS, frameSize, params) + RelativeLuminance::RelativeLuminance(short fps, const cv::Size& frameSize, FlashParams* params) + : Flash(fps, frameSize, params) { } diff --git a/src/ScopeProfiler.cpp b/src/ScopeProfiler.cpp new file mode 100644 index 0000000..2e6cdc6 --- /dev/null +++ b/src/ScopeProfiler.cpp @@ -0,0 +1,67 @@ +#include "iris/ScopeProfiler.h" +#include "iris/Log.h" + +#include +#include + +ScopeProfiler* ScopeProfiler::instance = nullptr; + + +ScopeProfiler::ScopeProfiler() { +} + +void ScopeProfiler::WriteHeader(const std::string& videoName,const std::string& end) +{ + m_OutputStream.close(); + + std::string newFilepath = filepath + videoName + "/"+ filepathMid + end + filepathEnd; + if (videoName == "" && end == "") + { + newFilepath = filepath + filepathMid + filepathEnd; + } + LOG_CORE_INFO("JSON Profiler path: " + newFilepath); + m_OutputStream.open(newFilepath); + m_OutputStream << "{\"otherData\": {},\"traceEvents\":["; + m_OutputStream.flush(); +} + +void ScopeProfiler::RegisterEvent(const std::string& eventName) { + ProfileEvent newProfile; + newProfile.name = eventName; + newProfile.processId = 0; + newProfile.threadId = std::hash{}(std::this_thread::get_id()); + newProfile.chrono_StartTime = std::chrono::high_resolution_clock::now(); + m_Events[eventName] = newProfile; +} + +void ScopeProfiler::FinishEvent(const std::string& eventName) { + auto endTime = std::chrono::high_resolution_clock::now(); + m_Events[eventName].startTime = std::chrono::time_point_cast(m_Events[eventName].chrono_StartTime).time_since_epoch().count(); + m_Events[eventName].endTime = std::chrono::time_point_cast(endTime).time_since_epoch().count(); + + WriteProfile(m_Events[eventName]); +} + +void ScopeProfiler::WriteFooter() +{ + m_OutputStream.seekp(-1, std::ios::end); + m_OutputStream << "]}"; + m_OutputStream.flush(); + m_OutputStream.close(); +} + +void ScopeProfiler::WriteProfile(const ProfileEvent& eventName) +{ + m_OutputStream << "{"; + m_OutputStream << "\"cat\":\"function\","; + m_OutputStream << "\"dur\":" << (eventName.endTime - eventName.startTime) << ','; + m_OutputStream << "\"name\":\"" << eventName.name << "\","; + m_OutputStream << "\"ph\":\"X\","; + m_OutputStream << "\"pid\":0,"; + m_OutputStream << "\"tid\":" << eventName.threadId << ","; + m_OutputStream << "\"ts\":" << eventName.startTime; + m_OutputStream << "}"; + m_OutputStream << ","; + + m_OutputStream.flush(); +} diff --git a/src/TransitionEvaluator.cpp b/src/TransitionEvaluator.cpp index 78647a1..2f181aa 100644 --- a/src/TransitionEvaluator.cpp +++ b/src/TransitionEvaluator.cpp @@ -1,12 +1,13 @@ //Copyright (C) 2023 Electronic Arts, Inc. All rights reserved. +/* #include "TransitionEvaluator.h" #include "ConfigurationParams.h" #include "FrameData.h" namespace iris { - TransitionEvaluator::TransitionEvaluator(int fps, TransitionEvaluatorParams* params): + TransitionEvaluator::TransitionEvaluator(unsigned int fps, TransitionTrackerParams* params): m_params(params) { m_luminanceTransitionCount.count.reserve(fps); m_luminanceTransitionCount.count.emplace_back(0); @@ -90,3 +91,4 @@ namespace iris } } } +*/ \ No newline at end of file diff --git a/src/TransitionEvaluator.h b/src/TransitionEvaluator.h index c162309..131ae84 100644 --- a/src/TransitionEvaluator.h +++ b/src/TransitionEvaluator.h @@ -1,5 +1,6 @@ //Copyright (C) 2023 Electronic Arts, Inc. All rights reserved. +/* #pragma once #include #include "iris/TotalFlashIncidents.h" @@ -7,14 +8,14 @@ namespace iris { -struct TransitionEvaluatorParams; +struct TransitionTrackerParams; class FrameData; class TransitionEvaluator { public: - TransitionEvaluator(int fps, TransitionEvaluatorParams* params); + TransitionEvaluator(unsigned int fps, TransitionTrackerParams* params); ~TransitionEvaluator(); inline bool getLumPassWithWarning() { return m_luminanceResults.passWithWarning; }; @@ -105,7 +106,8 @@ class TransitionEvaluator TotalFlashIncidents m_luminanceIncidents; TotalFlashIncidents m_redIncidents; - TransitionEvaluatorParams* m_params = nullptr; + TransitionTrackerParams* m_params = nullptr; }; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/TransitionTracker.h b/src/TransitionTracker.h new file mode 100644 index 0000000..9f5805b --- /dev/null +++ b/src/TransitionTracker.h @@ -0,0 +1,119 @@ +//Copyright (C) 2023 Electronic Arts, Inc. All rights reserved. + +#pragma once +#include +#include "iris/TotalFlashIncidents.h" + +namespace iris +{ + + struct TransitionTrackerParams; + class FrameData; + + class TransitionTracker + { + + public: + + + inline bool getLumPassWithWarning() { return m_luminanceResults.passWithWarning; }; + inline bool getRedPassWithWarning() { return m_redResults.passWithWarning; }; + + + inline bool getFlashFail() { return m_luminanceResults.flashFail || m_redResults.flashFail; }; + inline bool getLumFlashFail() { return m_luminanceResults.flashFail; }; + inline bool getRedFlashFail() { return m_redResults.flashFail; }; + + inline bool getExtendedFailure() { return m_luminanceResults.extendedFail || m_redResults.extendedFail; }; + inline bool getLumExtendedFailure() { return m_luminanceResults.extendedFail; }; + inline bool getRedExtendedFailure() { return m_redResults.extendedFail; }; + + const TotalFlashIncidents& getLuminanceIncidents() { return m_luminanceIncidents; }; + const TotalFlashIncidents& getRedIncidents() { return m_redIncidents; }; + + /// + /// Updates the transition count, extended fail count and the transitions in the last second + /// from the current frame + /// + /// true if there is a new luminance transition + /// true if there is a new red transition + /// data to persist + virtual void SetTransitions(bool lumTransition, bool redTransition, FrameData& data)=0; + + /// + /// Checks if in the current frame (moment of the video) the video has failed the flash criteria + /// + /// current frame index + /// video frame rate + /// data to persist + virtual void EvaluateFrameMoment(int framePos, int fps,FrameData& data) = 0; + + /// + /// If AnalysisByTime is enabled, add the first frame to the FrameTimeStamps structs + /// + /// data to persist + virtual void SetFirstFrame(FrameData& data) {return;} + protected: + + struct Counter + { + std::vector count; //transition count that surpass the luminance/red threshold from the last second + //or frames count where the transitions where between 4 and 6 + int current = 0; //current luminance/red transitions from this moment up to one second before + //or current frame count for extended failure + int passed = 0; //amount of luminance/red transitions that have passed the 1s window + //or amount of frames that have passed the 5s window + + // Get current frame's luminance or red transitions from the last second and update the transition count vector + // or get the current frame's luminance or red extended failure count + // return new current + int updateCurrent(const bool& newTransition) + { + + + //update the new transition count + if (newTransition) + { + count.emplace_back(count.back() + 1); + } + else + { + count.emplace_back(count.back()); + } + + + current = count.back() - passed; //current transitions in second + return current; + } + + void updatePassed() + { + passed = count.front(); + count.erase(count.begin()); + } + }; + + struct FlashResults //possible flash results + { + bool passWithWarning = false; //flash pass with warning status + bool flashFail = false; //flash fail status + bool extendedFail = false; //extended flash failure status + }; + + Counter m_luminanceTransitionCount; + Counter m_redTransitionCount; + + Counter m_luminanceExtendedCount; + Counter m_redExtendedCount; + + FlashResults m_luminanceResults; + FlashResults m_redResults; + + TotalFlashIncidents m_luminanceIncidents; + TotalFlashIncidents m_redIncidents; + + TransitionTrackerParams* m_params = nullptr; + + }; + +} \ No newline at end of file diff --git a/src/TransitionTrackerByFPS.cpp b/src/TransitionTrackerByFPS.cpp new file mode 100644 index 0000000..d4e1fc8 --- /dev/null +++ b/src/TransitionTrackerByFPS.cpp @@ -0,0 +1,77 @@ +#include "TransitionTrackerByFPS.h" + +namespace iris +{ + TransitionTrackerByFPS::TransitionTrackerByFPS(unsigned int fps, TransitionTrackerParams* params) + { + m_params = params; + m_luminanceTransitionCount.count.reserve(fps); m_luminanceTransitionCount.count.emplace_back(0); + m_redTransitionCount.count.reserve(fps); m_redTransitionCount.count.emplace_back(0); + m_luminanceExtendedCount.count.reserve(m_params->extendedFailWindow * fps); m_luminanceExtendedCount.count.emplace_back(0); + m_redExtendedCount.count.reserve(m_params->extendedFailWindow * fps); m_redExtendedCount.count.emplace_back(0); + } + + void TransitionTrackerByFPS::SetTransitions(bool lumTransition, bool redTransition, FrameData& data) + { + data.LuminanceTransitions = m_luminanceTransitionCount.updateCurrent(lumTransition); + data.RedTransitions = m_redTransitionCount.updateCurrent(redTransition); + + data.LuminanceExtendedFailCount = m_luminanceExtendedCount.updateCurrent(m_luminanceTransitionCount.current <= m_params->maxTransitions && m_luminanceTransitionCount.current >= m_params->minTransitions); + data.RedExtendedFailCount = m_redExtendedCount.updateCurrent(m_redTransitionCount.current <= m_params->maxTransitions && m_redTransitionCount.current >= m_params->minTransitions); + } + + void TransitionTrackerByFPS::EvaluateFrameMoment(int framePos, int fps, FrameData& data) + { + if (m_luminanceTransitionCount.current > m_params->maxTransitions) //FAIL as max allowed transitions has been surpassed + { + m_luminanceResults.flashFail = true; + data.luminanceFrameResult = FlashResult::FlashFail; + m_luminanceIncidents.flashFailFrames += 1; + } + else if (m_luminanceExtendedCount.current >= m_params->extendedFailSeconds * fps && m_luminanceTransitionCount.current >= 4) //EXTENDED FAILURE + { + m_luminanceResults.extendedFail = true; + data.luminanceFrameResult = FlashResult::ExtendedFail; + m_luminanceIncidents.extendedFailFrames += 1; + } + else if (m_luminanceTransitionCount.current >= 4) + { + m_luminanceResults.passWithWarning = true; + data.luminanceFrameResult = FlashResult::PassWithWarning; + m_luminanceIncidents.passWithWarningFrames += 1; + } + + if (m_redTransitionCount.current > m_params->maxTransitions) //FAIL as max allowed transitions has been surpassed + { + m_redResults.flashFail = true; + data.redFrameResult = FlashResult::FlashFail; + m_redIncidents.flashFailFrames += 1; + } + else if (m_redExtendedCount.current >= m_params->extendedFailSeconds * fps && m_redTransitionCount.current >= 4) //EXTENDED FAILURE + { + m_redResults.extendedFail = true; + data.redFrameResult = FlashResult::ExtendedFail; + m_redIncidents.extendedFailFrames += 1; + } + else if (m_redTransitionCount.current >= 4) + { + m_redResults.passWithWarning = true; + data.redFrameResult = FlashResult::PassWithWarning; + m_redIncidents.passWithWarningFrames += 1; + } + + //update transition lists as 1s has passed + if (framePos >= fps - 1) + { + m_luminanceTransitionCount.updatePassed(); + m_redTransitionCount.updatePassed(); + + // update extended failure as 5s have passed + if (framePos >= m_params->extendedFailWindow * fps - 1) + { + m_luminanceExtendedCount.updatePassed(); + m_redExtendedCount.updatePassed(); + } + } + } +} \ No newline at end of file diff --git a/src/TransitionTrackerByFPS.h b/src/TransitionTrackerByFPS.h new file mode 100644 index 0000000..d53950e --- /dev/null +++ b/src/TransitionTrackerByFPS.h @@ -0,0 +1,27 @@ +//Copyright (C) 2023 Electronic Arts, Inc. All rights reserved. + +#pragma once +#include "TransitionTracker.h" +#include "ConfigurationParams.h" +#include "FrameData.h" +#include + +namespace iris +{ + class TransitionTrackerByFPS :public TransitionTracker { + + public: + TransitionTrackerByFPS(unsigned int fps, TransitionTrackerParams* params); + + void SetTransitions(bool lumTransition, bool redTransition, FrameData& data) override; + + /// + /// Checks if in the current frame (moment of the video) the video has + /// failed the flash criteria + /// + /// current frame index + /// video frame rate + /// data to persist + void EvaluateFrameMoment(int framePos, int fps, FrameData& data) override; + }; +} \ No newline at end of file diff --git a/src/TransitionTrackerByTime.cpp b/src/TransitionTrackerByTime.cpp new file mode 100644 index 0000000..cb0a2d4 --- /dev/null +++ b/src/TransitionTrackerByTime.cpp @@ -0,0 +1,105 @@ +#include "TransitionTrackerByTime.h" + +namespace iris +{ + TransitionTrackerByTime::TransitionTrackerByTime(unsigned int starterFpsReserve, TransitionTrackerParams* params) + { + m_params = params; + m_luminanceTransitionCount.count.reserve(starterFpsReserve); m_luminanceTransitionCount.count.emplace_back(0); + m_redTransitionCount.count.reserve(starterFpsReserve); m_redTransitionCount.count.emplace_back(0); + m_luminanceExtendedCount.count.reserve(m_params->extendedFailWindow * starterFpsReserve); m_luminanceExtendedCount.count.emplace_back(0); + m_redExtendedCount.count.reserve(m_params->extendedFailWindow * starterFpsReserve); m_redExtendedCount.count.emplace_back(0); + + m_oneSecondTimeStamps.frameTimeStamp.reserve(starterFpsReserve + 1); + m_oneSecondTimeStamps.timesBetweenPairOfFrames.reserve(starterFpsReserve); + + m_fiveSecondTimeStamps.frameTimeStamp.reserve(m_params->extendedFailSeconds * starterFpsReserve + 1); + m_fiveSecondTimeStamps.timesBetweenPairOfFrames.reserve(m_params->extendedFailWindow * starterFpsReserve); + + m_fourSecondTimeStamps.frameTimeStamp.reserve(m_params->extendedFailSeconds * starterFpsReserve + 1); + m_fourSecondTimeStamps.timesBetweenPairOfFrames.reserve(m_params->extendedFailWindow * starterFpsReserve); + + m_oneSecondTimeStamps.SetTimeBarrier(1); + m_fiveSecondTimeStamps.SetTimeBarrier(m_params->extendedFailWindow); + m_fourSecondTimeStamps.SetTimeBarrier(m_params->extendedFailSeconds); + + } + + void TransitionTrackerByTime::SetFirstFrame(FrameData& data) + { + m_oneSecondTimeStamps.AddNewFrame(data.TimeStampVal, 0); + m_fiveSecondTimeStamps.AddNewFrame(data.TimeStampVal, 0); + m_fourSecondTimeStamps.AddNewFrame(data.TimeStampVal, 0); + } + + void TransitionTrackerByTime::SetTransitions(bool lumTransition, bool redTransition, FrameData& data) + { + m_oneSecondFramesToRemove = m_oneSecondTimeStamps.GetFrameNumToRemove(data.TimeStampVal); + m_fiveSecondFramesToRemove = m_fiveSecondTimeStamps.GetFrameNumToRemove(data.TimeStampVal); + m_fourSecondTimeStamps.GetFrameNumToRemove(data.TimeStampVal); + + //update transition lists as 1s has passed + for (m_oneSecondFramesToRemove; m_oneSecondFramesToRemove > 0; m_oneSecondFramesToRemove--) + { + m_luminanceTransitionCount.updatePassed(); + m_redTransitionCount.updatePassed(); + } + //update extended failure as 5s have passed + for (m_fiveSecondFramesToRemove; m_fiveSecondFramesToRemove > 0; m_fiveSecondFramesToRemove--) + { + m_luminanceExtendedCount.updatePassed(); + m_redExtendedCount.updatePassed(); + } + + + data.LuminanceTransitions = m_luminanceTransitionCount.updateCurrent(lumTransition); + data.RedTransitions = m_redTransitionCount.updateCurrent(redTransition); + + data.LuminanceExtendedFailCount = m_luminanceExtendedCount.updateCurrent(m_luminanceTransitionCount.current <= m_params->maxTransitions && m_luminanceTransitionCount.current >= m_params->minTransitions); + data.RedExtendedFailCount = m_redExtendedCount.updateCurrent(m_redTransitionCount.current <= m_params->maxTransitions && m_redTransitionCount.current >= m_params->minTransitions); + + } + + void TransitionTrackerByTime::EvaluateFrameMoment(int framePos, int fps, FrameData& data) + { + int framesInFourSeconds = m_oneSecondTimeStamps.timesBetweenPairOfFrames.size() * m_params->extendedFailSeconds; //only works on videos, must found a solution to get the exact number of frames in the last 4 seconds + + if (m_luminanceTransitionCount.current > m_params->maxTransitions) //FAIL as max allowed transitions has been surpassed + { + m_luminanceResults.flashFail = true; + data.luminanceFrameResult = FlashResult::FlashFail; + m_luminanceIncidents.flashFailFrames += 1; + } + else if (m_luminanceExtendedCount.current >= framesInFourSeconds && m_luminanceTransitionCount.current >= 4) //EXTENDED FAILURE + { + m_luminanceResults.extendedFail = true; + data.luminanceFrameResult = FlashResult::ExtendedFail; + m_luminanceIncidents.extendedFailFrames += 1; + } + else if (m_luminanceTransitionCount.current >= 4) + { + m_luminanceResults.passWithWarning = true; + data.luminanceFrameResult = FlashResult::PassWithWarning; + m_luminanceIncidents.passWithWarningFrames += 1; + } + + if (m_redTransitionCount.current > m_params->maxTransitions) //FAIL as max allowed transitions has been surpassed + { + m_redResults.flashFail = true; + data.redFrameResult = FlashResult::FlashFail; + m_redIncidents.flashFailFrames += 1; + } + else if (m_redExtendedCount.current >= framesInFourSeconds && m_redTransitionCount.current >= 4) //EXTENDED FAILURE + { + m_redResults.extendedFail = true; + data.redFrameResult = FlashResult::ExtendedFail; + m_redIncidents.extendedFailFrames += 1; + } + else if (m_redTransitionCount.current >= 4) + { + m_redResults.passWithWarning = true; + data.redFrameResult = FlashResult::PassWithWarning; + m_redIncidents.passWithWarningFrames += 1; + } + } +} \ No newline at end of file diff --git a/src/TransitionTrackerByTime.h b/src/TransitionTrackerByTime.h new file mode 100644 index 0000000..c7ad2d6 --- /dev/null +++ b/src/TransitionTrackerByTime.h @@ -0,0 +1,120 @@ +//Copyright (C) 2023 Electronic Arts, Inc. All rights reserved. + +#pragma once +#include "TransitionTracker.h" +#include "ConfigurationParams.h" +#include "FrameData.h" +#include +#include +#include "iris/Log.h" + +namespace iris +{ + class TransitionTrackerByTime :public TransitionTracker { + public: + TransitionTrackerByTime(unsigned int starterFpsReserve, TransitionTrackerParams* params); + + + void SetTransitions(bool lumTransition, bool redTransition, FrameData& data) override; + + /// + /// Checks if in the current frame (moment of the video) the video has + /// failed the flash criteria + /// + /// current frame index + /// video frame rate + /// data to persist + void EvaluateFrameMoment(int framePos, int fps, FrameData& data) override; + + /// + /// Add the first frame to the FrameTimeStamps structs + /// + /// data to persist + void SetFirstFrame(FrameData& data)override; + + private: + + struct FrameTimeStamps + { + std::vector frameTimeStamp; //vector of current frame entry times frames in the window + + std::vector timesBetweenPairOfFrames; //vector of current times between frames in the window + + float timesSum = 0; //total sum of times between each pair of Frames + + /// + /// Set time barrier in milliseconds + /// + /// time barrier in seconds + void SetTimeBarrier(int seconds) { + timeBarrier = seconds * 1000; + } + + /// + /// Check if when adding a new frame it is needed to update frameTimeStamp and timesBetweenPairOfFrames vectors (timeBarrier has been surpassed), + /// then add newFrameTime to frameTimeStamp and timesBetweenPairOfFrames vectors. + /// This function returns an integer (number of frames to remove from the count vectors) + /// + /// new frame MS + int GetFrameNumToRemove(const unsigned long & newFrameTime) + { + int framesToRemove = 0; //number of frames to that are no longer inside the time window + long newTimeBetFrames = 0;//time between frame to add and last recorded frame time stamp + + if (frameTimeStamp.size() > 0) + { + newTimeBetFrames= newFrameTime - frameTimeStamp[frameTimeStamp.size() - 1]; + + if (timesSum + newTimeBetFrames == timeBarrier) + { + framesToRemove++; + } + //Remove frames until new frame fits inside the window + while (timesSum + newTimeBetFrames > timeBarrier) + { + timesSum -= timesBetweenPairOfFrames[0]; + frameTimeStamp.erase(frameTimeStamp.begin()); + timesBetweenPairOfFrames.erase(timesBetweenPairOfFrames.begin()); + + framesToRemove++; + } + } + AddNewFrame(newFrameTime, newTimeBetFrames); + + return framesToRemove; + } + + /// + /// add the new frame time in the frameTimeStamp and the timesBetweenPairOfFrames vectors + /// also update the timesSum (times between frames) variable + /// + /// new frame MS + /// time between frame to add and last recorded frame time stamp + void AddNewFrame(const unsigned long & newFrameTime, const unsigned long& newTimeBetFrames) + { + if (frameTimeStamp.size() > 0) + { + timesSum += newTimeBetFrames; + timesBetweenPairOfFrames.emplace_back(newTimeBetFrames); + } + frameTimeStamp.emplace_back(newFrameTime); + } + private: + //Time barrier measured in seconds + //Used to know when timesBetweenPairOfFrames vector sum has surpased the desired second window and vectors needs to be updated + int timeBarrier; + }; + + + FrameTimeStamps m_oneSecondTimeStamps; //1 second window + + FrameTimeStamps m_fiveSecondTimeStamps; //5 second window + + FrameTimeStamps m_fourSecondTimeStamps; //4 second window + + int m_oneSecondFramesToRemove=0 , m_fiveSecondFramesToRemove = 0; //Number of frames to be removed from the count vector of the Counter structs + + + }; + +} diff --git a/src/VideoAnalyser.cpp b/src/VideoAnalyser.cpp index b39a200..85c0d0e 100644 --- a/src/VideoAnalyser.cpp +++ b/src/VideoAnalyser.cpp @@ -17,6 +17,13 @@ #include "iris/Result.h" #include #include "utils/JsonWrapper.h" +#include + +extern "C" { +#include +#include +} + namespace iris { @@ -35,12 +42,20 @@ namespace iris { } - void VideoAnalyser::Init(const short& fps, const cv::Size& size, const std::string& videoName, bool flagJson) + void VideoAnalyser::Init(const std::string& videoName, bool flagJson) { - m_flashDetection = new FlashDetection(m_configuration, fps, size); + if (m_configuration->FrameResizeEnabled()) + { + float resizedFrameProportion; + resizedFrameProportion = m_configuration->GetFrameResizeProportion(); + LOG_CORE_INFO("Resizing frames at: {0}%", resizedFrameProportion * 100); + m_videoInfo.frameSize = cv::Size(m_videoInfo.frameSize.width * resizedFrameProportion, m_videoInfo.frameSize.height * resizedFrameProportion); + } + + m_flashDetection = new FlashDetection(m_configuration, m_videoInfo.fps, m_videoInfo.frameSize); m_photosensitivityDetector.push_back(m_flashDetection); m_frameSrgbConverter = new EA::EACC::Utils::FrameConverter(m_configuration->GetFrameSrgbConverterParams()); - m_patternDetection = new PatternDetection(m_configuration, fps, size); + m_patternDetection = new PatternDetection(m_configuration, m_videoInfo.fps, m_videoInfo.frameSize); if (m_configuration->PatternDetectionEnabled()) { @@ -56,12 +71,12 @@ namespace iris m_frameDataJsonPath = m_configuration->GetResultsPath() + videoName + "/" + "frameData" + ".json"; } - LOG_CORE_INFO("Video analysis FPS: {}", fps); - const char* luminanceType = m_configuration->GetLuminanceType() == Configuration::LuminanceType::CD ? "CD" : "RELATIVE"; LOG_CORE_INFO("Luminance Type: {0}", luminanceType); LOG_CORE_INFO("Pattern Detection: {0}", m_configuration->PatternDetectionEnabled()); + + LOG_CORE_INFO("Frame Resize: {0}", m_configuration->FrameResizeEnabled()); LOG_CORE_INFO("Safe Area Proportion: {0}", m_configuration->GetSafeAreaProportion()); @@ -91,14 +106,15 @@ namespace iris cv::VideoCapture video(sourceVideo); std::string videoName = std::filesystem::path(sourceVideo).filename().string(); - if (VideoIsOpen(video, videoName.c_str())) + if (VideoIsOpen(sourceVideo, video, videoName.c_str())) { - Init((short)round(video.get(cv::CAP_PROP_FPS)), cv::Size(video.get(cv::CAP_PROP_FRAME_WIDTH), video.get(cv::CAP_PROP_FRAME_HEIGHT)), videoName, flagJson); + Init(videoName, flagJson); + SetOptimalCvThreads(m_videoInfo.frameSize); cv::Mat frame; video.read(frame); - int numFrames = 0; - int lastPercentage = 0; + unsigned int numFrames = 0; + unsigned int lastPercentage = 0; LOG_DATA_INFO(FrameData().CsvColumns()); LOG_CORE_INFO("Video analysis started"); @@ -110,18 +126,22 @@ namespace iris if (flagJson) { - lineGraphData.reserveLineGraphData((int)video.get(cv::CAP_PROP_FRAME_COUNT)); - nonPassData.reserve((int)(video.get(cv::CAP_PROP_FRAME_COUNT) * 0.25)); //reserve at least one quarter of frames + lineGraphData.reserveLineGraphData(m_videoInfo.frameCount); + nonPassData.reserve(m_videoInfo.frameCount * 0.25); //reserve at least one quarter of frames } while (!frame.empty()) { - FrameData data(numFrames + 1, 1000.0 * (double)numFrames / video.get(cv::CAP_PROP_FPS)); + FrameData data(numFrames + 1, 1000.0 * (double)numFrames / m_videoInfo.fps); + if (m_configuration->FrameResizeEnabled()) + { + cv::resize(frame, frame, m_videoInfo.frameSize); + } AnalyseFrame(frame, numFrames, data); video.read(frame); //obtain new frame - UpdateProgress(numFrames, video.get(cv::CAP_PROP_FRAME_COUNT), lastPercentage); + UpdateProgress(numFrames, m_videoInfo.frameCount, lastPercentage); numFrames++; LOG_DATA_INFO(data.ToCSV()); @@ -139,7 +159,7 @@ namespace iris auto end = std::chrono::steady_clock::now(); LOG_CORE_INFO("Video analysis ended"); - int elapsedTime = std::chrono::duration_cast(end - start).count(); + unsigned int elapsedTime = std::chrono::duration_cast(end - start).count(); LOG_CORE_INFO("Elapsed time: {0} ms", elapsedTime); if (m_flashDetection->isFail() || m_patternDetection->isFail()) @@ -156,9 +176,9 @@ namespace iris Result result; m_flashDetection->setResult(result); if (m_patternDetection != nullptr) { m_patternDetection->setResult(result); } - result.VideoLen = (int)(video.get(cv::CAP_PROP_FRAME_COUNT) / video.get(cv::CAP_PROP_FPS) * 1000); + result.VideoLen = m_videoInfo.duration * 1000; result.AnalysisTime = elapsedTime; - result.TotalFrame = (int)video.get(cv::CAP_PROP_FRAME_COUNT); + result.TotalFrame = m_videoInfo.frameCount; SerializeResults(result, lineGraphData, nonPassData); } @@ -168,7 +188,7 @@ namespace iris video.release(); } - void VideoAnalyser::AnalyseFrame(cv::Mat& frame, int& frameIndex, FrameData& data) + void VideoAnalyser::AnalyseFrame(cv::Mat& frame, unsigned int& frameIndex, FrameData& data) { IrisFrame irisFrame(&(frame), m_frameSrgbConverter->Convert(frame), data); @@ -181,15 +201,52 @@ namespace iris irisFrame.Release(); } - bool VideoAnalyser::VideoIsOpen(cv::VideoCapture& video, const char* videoName) + void VideoAnalyser::SetOptimalCvThreads(cv::Size size) + { + int num_threads = 1; + + //Detection of max num of threads available + int max_num_threads = std::thread::hardware_concurrency(); + + //Depending of the size of the frame, different number of threads will be used + //If the resolution is less or more than 1080, 6 threads will be used + //If not more than 6 threads will be used with higher resolutions like 2K. + //The research concluded that the optimal number of threads for a 1080p resolution + //is 6 and for a 4K resolution is 10. + //The operation (1 / 270) * (size.height - 1080) + 6 is a rule of three that + //ensures these results. + num_threads = std::round(size.height <= 1080) + ? 6 : (1 / 270) * (size.height - 1080) + 6; + + //If the PC does not have the num of threads that the program requires, + //we will take the max num of threads that are available in the machine. + int threads_used = max_num_threads < num_threads && max_num_threads != 0 ? max_num_threads : num_threads; + + //Setting number of used threads + cv::setNumThreads(threads_used); + LOG_CORE_INFO("Number of threads used: {0}", threads_used); + } + + bool VideoAnalyser::VideoIsOpen(const char* sourceVideo, cv::VideoCapture& video, const char* videoName) { if (video.isOpened()) { + m_videoInfo.fps = GetVideoFps(sourceVideo); + if (m_videoInfo.fps == -1) + { + LOG_CORE_ERROR("Video FPS extraction with FFmpeg failed, attempting with OpenCV"); + m_videoInfo.fps = video.get(cv::CAP_PROP_FPS); + } + + m_videoInfo.frameCount = video.get(cv::CAP_PROP_FRAME_COUNT); + m_videoInfo.frameSize = cv::Size(video.get(cv::CAP_PROP_FRAME_WIDTH), video.get(cv::CAP_PROP_FRAME_HEIGHT)); + m_videoInfo.duration = m_videoInfo.frameCount / (float)m_videoInfo.fps; + LOG_CORE_INFO("Video: {0} opened successful", videoName); - LOG_CORE_INFO("Total frames: {0}", video.get(cv::CAP_PROP_FRAME_COUNT)); - LOG_CORE_INFO("FPS: {0}", video.get(cv::CAP_PROP_FPS)); - LOG_CORE_INFO("Duration: {0}s", video.get(cv::CAP_PROP_FRAME_COUNT) / video.get(cv::CAP_PROP_FPS)); - LOG_CORE_INFO("Video resolution: {0}x{1}", video.get(cv::CAP_PROP_FRAME_WIDTH), video.get(cv::CAP_PROP_FRAME_HEIGHT)); + LOG_CORE_INFO("Video FPS: {}", m_videoInfo.fps); + LOG_CORE_INFO("Total frames: {0}", m_videoInfo.frameCount); + LOG_CORE_INFO("Video resolution: {0}x{1}", m_videoInfo.frameSize.width, m_videoInfo.frameSize.height); + LOG_CORE_INFO("Duration: {0}s", m_videoInfo.duration); return true; } @@ -198,9 +255,9 @@ namespace iris return false; } - void VideoAnalyser::UpdateProgress(int& numFrames, const long& totalFrames, int& lastPercentage) + void VideoAnalyser::UpdateProgress(unsigned int& numFrames, const unsigned long& totalFrames, unsigned int& lastPercentage) { - int progress = numFrames / (float)totalFrames * 100.0f; + unsigned int progress = numFrames / (float)totalFrames * 100.0f; if (progress != 0 && progress % 10 == 0 && lastPercentage != progress) //display progress { @@ -209,6 +266,50 @@ namespace iris } } + int VideoAnalyser::GetVideoFps(const char* filePath) + { + AVFormatContext* pFormatContext = avformat_alloc_context(); + + if (avformat_open_input(&pFormatContext, filePath, NULL, NULL) != 0) { + LOG_CORE_ERROR("Unable to open file {}", filePath); + return -1; + } + + // Retrieve stream information + if (avformat_find_stream_info(pFormatContext, NULL) < 0) { + LOG_CORE_ERROR("Failed to retrieve stream info"); + return -1; + } + + // Get the first video stream + int videoStreamIndex = -1; + for (int i = 0; i < pFormatContext->nb_streams; i++) { + if (pFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoStreamIndex = i; + break; + } + } + + if (videoStreamIndex == -1) { + LOG_CORE_ERROR("No video stream found"); + return -1; + } + + // Get the frame rates + AVRational r_frame_rate = pFormatContext->streams[videoStreamIndex]->r_frame_rate; + AVRational avg_frame_rate = pFormatContext->streams[videoStreamIndex]->avg_frame_rate; + + LOG_CORE_DEBUG("r_frame_rate: {}/{}", r_frame_rate.num, r_frame_rate.den); + LOG_CORE_DEBUG("avg_frame_rate: {}/{}", avg_frame_rate.num, avg_frame_rate.den); + + int fps = round(avg_frame_rate.num / (float)avg_frame_rate.den); + + // Close the video file + avformat_close_input(&pFormatContext); + avformat_free_context(pFormatContext); + return fps; + } + void VideoAnalyser::SerializeResults(const Result& result, const FrameDataJson& lineGraphData, const FrameDataJson& nonPassData) { EA::EACC::Utils::JsonWrapper resultJson; @@ -217,8 +318,8 @@ namespace iris resultJson.SetParam("FrameDataResult", "FrameResultJsonRepositoryKey", "00000000-0000-0000-0000-000000000000"); resultJson.SetParam("FrameDataResult", "FrameDataJsonRepositoryKey", "00000000-0000-0000-0000-000000000000"); resultJson.SetParam("TotalFrame", result.TotalFrame); - resultJson.SetParam("AnalyzeTimeString", msToTimeSpan(result.AnalysisTime)); - resultJson.SetParam("VideoLenString", msToTimeSpan(result.VideoLen)); + resultJson.SetParam("AnalyzeTime", msToTimeSpan(result.AnalysisTime)); + resultJson.SetParam("VideoLen", msToTimeSpan(result.VideoLen)); resultJson.SetParam("OverallResult", result.OverallResult); resultJson.SetParam("Results", result.Results); resultJson.SetParam("TotalLuminanceIncidents", result.totalLuminanceIncidents); @@ -235,4 +336,4 @@ namespace iris frameDataJson.WriteFile(m_frameDataJsonPath.c_str()); LOG_CORE_INFO("Non Pass Json written to {}", m_frameDataJsonPath); } -} \ No newline at end of file +} diff --git a/test/Iris.Tests/CMakeLists.txt b/test/Iris.Tests/CMakeLists.txt index db05d15..9a350bf 100644 --- a/test/Iris.Tests/CMakeLists.txt +++ b/test/Iris.Tests/CMakeLists.txt @@ -13,10 +13,11 @@ set(SOURCE_FILES "src/RedSaturationTests.cpp" "src/RelativeLuminanceTest.cpp" "src/CDLuminanceTest.cpp" - "src/TransitionEvaluatorTest.cpp" "src/FlashDetectionTests.cpp" "src/PatternDetectionTests.cpp" "src/VideoAnalysisTests.cpp" + "src/TransitionTrackerByFPSTests.cpp" + "src/TransitionTrackerByTimeTests.cpp" ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/test/Iris.Tests/appsettings.json b/test/Iris.Tests/appsettings.json index 2f37dd3..0f644ca 100644 --- a/test/Iris.Tests/appsettings.json +++ b/test/Iris.Tests/appsettings.json @@ -532,13 +532,14 @@ 0.9822506, 0.9911022, 1 - ] + ] }, - "TransitionEvaluator": { + "TransitionTracker": { "MaxTransitions": 6, "MinTransitions": 4, "ExtendedFailSeconds": 4, - "ExtendedFailWindow": 5 + "ExtendedFailWindow": 5, + "AnalyseByTime": false }, "PatternDetection": { "MinStripes": 6, //min stripes for harmful patterns @@ -551,6 +552,8 @@ "VideoAnalyser": { "ScreenShotsPath": "ScreenShots", "LuminanceType": "RELATIVE", //CD || RELATIVE - "PatternDetectionEnabled": false + "PatternDetectionEnabled": false, + "FrameResizeEnabled": false, + "ResizeFrameProportion": 0.2 } } \ No newline at end of file diff --git a/test/Iris.Tests/include/IrisLibTest.h b/test/Iris.Tests/include/IrisLibTest.h index ed7e10a..bafdea9 100644 --- a/test/Iris.Tests/include/IrisLibTest.h +++ b/test/Iris.Tests/include/IrisLibTest.h @@ -65,13 +65,11 @@ namespace iris::Tests return canny; } - - static bool CompareFloat(const float& a, const float& b) + static bool CompareFloat(const float& a, const float& b, const float& errorMargin = 0.0001f) { - return fabs(a - b) < 0.0001f; + return fabs(a - b) <= errorMargin; } - class IrisLibTest : public ::testing::Test { protected: Configuration configuration; diff --git a/test/Iris.Tests/src/TransitionEvaluatorTest.cpp b/test/Iris.Tests/src/TransitionEvaluatorTest.cpp index 0af6203..b0911e3 100644 --- a/test/Iris.Tests/src/TransitionEvaluatorTest.cpp +++ b/test/Iris.Tests/src/TransitionEvaluatorTest.cpp @@ -1,5 +1,5 @@ //Copyright (C) 2023 Electronic Arts, Inc. All rights reserved. - +/* #include "IrisLibTest.h" #include #include "TransitionEvaluator.h" @@ -16,7 +16,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionTrackerParams()); transitionEvaluator.SetTransitions(true, false, testData); transitionEvaluator.SetTransitions(true, false, testData); @@ -34,7 +34,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionTrackerParams()); transitionEvaluator.SetTransitions(false, false, testData); transitionEvaluator.SetTransitions(false, true, testData); @@ -52,7 +52,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionTrackerParams()); transitionEvaluator.SetTransitions(false, false, testData); transitionEvaluator.SetTransitions(true, true, testData); @@ -70,7 +70,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionTrackerParams()); for (int i = 0; i < 8; i++) { @@ -87,7 +87,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionTrackerParams()); for (int i = 0; i < 8; i++) { @@ -105,7 +105,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(10, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(10, configuration.GetTransitionTrackerParams()); for (int i = 0; i < 2; i++) //add 2 luminance and red transitions { @@ -135,7 +135,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionTrackerParams()); for (int i = 0; i < 3; i++) //add 3 luminance transitions { @@ -156,7 +156,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionTrackerParams()); for (int i = 0; i < 3; i++) //add 3 red transitions { @@ -177,7 +177,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(8, configuration.GetTransitionTrackerParams()); for (int i = 0; i < 3; i++) //add 3 luminance and red transitions { @@ -198,7 +198,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData; - TransitionEvaluator transitionEvaluator(5, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(5, configuration.GetTransitionTrackerParams()); for (int i = 0; i < 23; i++) //add luminance and red transitions { @@ -223,7 +223,7 @@ namespace iris::Tests { //Only luminance transitions FrameData testData = FrameData(); - TransitionEvaluator transitionEvaluator(4, configuration.GetTransitionEvaluatorParams()); + TransitionEvaluator transitionEvaluator(4, configuration.GetTransitionTrackerParams()); for (int i = 0; i < 5; i++) //add 5 luminance and red transitions { @@ -245,4 +245,4 @@ namespace iris::Tests EXPECT_EQ(9, testData.LuminanceTransitions); EXPECT_EQ(11, testData.RedTransitions); } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/test/Iris.Tests/src/TransitionTrackerByFPSTests.cpp b/test/Iris.Tests/src/TransitionTrackerByFPSTests.cpp new file mode 100644 index 0000000..21feb52 --- /dev/null +++ b/test/Iris.Tests/src/TransitionTrackerByFPSTests.cpp @@ -0,0 +1,247 @@ +//Copyright (C) 2023 Electronic Arts, Inc. All rights reserved. + +#include "IrisLibTest.h" +#include +#include "TransitionTrackerByFPS.h" +#include "FrameData.h" + +namespace iris::Tests +{ + class TransitionTrackerByFPSTest : public IrisLibTest { + protected: + }; + + TEST_F(TransitionTrackerByFPSTest, Transition_WhenOnlyLuminance_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(8, configuration.GetTransitionTrackerParams()); + + transitionTracker.SetTransitions(true, false, testData); + transitionTracker.SetTransitions(true, false, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(true, false, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(true, false, testData); + + EXPECT_EQ(4, testData.LuminanceTransitions); + EXPECT_EQ(0, testData.RedTransitions); + } + + TEST_F(TransitionTrackerByFPSTest, Transition_WhenOnlyRed_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(8, configuration.GetTransitionTrackerParams()); + + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(false, true, testData); + + EXPECT_EQ(0, testData.LuminanceTransitions); + EXPECT_EQ(4, testData.RedTransitions); + } + + TEST_F(TransitionTrackerByFPSTest, Transition_WhenLuminanceAndRed_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(8, configuration.GetTransitionTrackerParams()); + + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(true, true, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(true, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(true, true, testData); + + EXPECT_EQ(3, testData.LuminanceTransitions); + EXPECT_EQ(4, testData.RedTransitions); + } + + TEST_F(TransitionTrackerByFPSTest, EvaluateFrameMoment_WhenLuminanceFlashFail_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 8; i++) + { + transitionTracker.SetTransitions(true, false, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_TRUE(transitionTracker.getFlashFail()); + EXPECT_TRUE(transitionTracker.getLumFlashFail()); + EXPECT_EQ(FlashResult::FlashFail, testData.luminanceFrameResult); + EXPECT_EQ(1, transitionTracker.getLuminanceIncidents().flashFailFrames); + } + + TEST_F(TransitionTrackerByFPSTest, EvaluateFrameMoment_WhenRedFlashFail_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 8; i++) + { + transitionTracker.SetTransitions(false, true, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_TRUE(transitionTracker.getFlashFail()); + EXPECT_TRUE(transitionTracker.getRedFlashFail()); + EXPECT_EQ(FlashResult::FlashFail, testData.redFrameResult); + EXPECT_EQ(1, transitionTracker.getRedIncidents().flashFailFrames); + + } + + TEST_F(TransitionTrackerByFPSTest, EvaluateFrameMoment_WhenLuminanceAndRedFlashFail_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(10, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 2; i++) //add 2 luminance and red transitions + { + transitionTracker.SetTransitions(true, true, testData); + } + for (int i = 0; i < 3; i++) //add 3 red transitions + { + transitionTracker.SetTransitions(false, true, testData); + } + for (int i = 0; i < 5; i++) //add 5 luminance transitions + { + transitionTracker.SetTransitions(true, false, testData); + } + transitionTracker.EvaluateFrameMoment(10, 10, testData); + EXPECT_TRUE(transitionTracker.getFlashFail()); + EXPECT_TRUE(transitionTracker.getLumFlashFail()); + EXPECT_FALSE(transitionTracker.getRedFlashFail()); + + EXPECT_EQ(FlashResult::FlashFail, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::PassWithWarning, testData.redFrameResult); + EXPECT_EQ(1, transitionTracker.getLuminanceIncidents().flashFailFrames); + EXPECT_EQ(1, transitionTracker.getRedIncidents().passWithWarningFrames); + + } + + TEST_F(TransitionTrackerByFPSTest, EvaluateFrameMoment_WhenLuminanceFlashPass_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 3; i++) //add 3 luminance transitions + { + transitionTracker.SetTransitions(true, false, testData); + } + + for (int i = 0; i < 5; i++) //add 5 frames, no transitions + { + transitionTracker.SetTransitions(false, false, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_FALSE(transitionTracker.getFlashFail()); + EXPECT_EQ(FlashResult::Pass, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::Pass, testData.redFrameResult); + } + + TEST_F(TransitionTrackerByFPSTest, EvaluateFrameMoment_WhenRedFlashPass_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 3; i++) //add 3 red transitions + { + transitionTracker.SetTransitions(false, true, testData); + } + + for (int i = 0; i < 5; i++) //add 5 frames, no transitions + { + transitionTracker.SetTransitions(false, false, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_FALSE(transitionTracker.getFlashFail()); + EXPECT_EQ(FlashResult::Pass, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::Pass, testData.redFrameResult); + } + + TEST_F(TransitionTrackerByFPSTest, EvaluateFrameMoment_WhenLuminanceAndRedFlashPass_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 3; i++) //add 3 luminance and red transitions + { + transitionTracker.SetTransitions(true, true, testData); + } + + for (int i = 0; i < 5; i++) //add 5 frames, no transitions + { + transitionTracker.SetTransitions(false, false, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_FALSE(transitionTracker.getFlashFail()); + EXPECT_EQ(FlashResult::Pass, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::Pass, testData.redFrameResult); + } + + TEST_F(TransitionTrackerByFPSTest, EvaluateFrameMoment_WhenExtendedFailure_Test) + { + //Only luminance transitions + FrameData testData; + TransitionTrackerByFPS transitionTracker(5, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 23; i++) //add luminance and red transitions + { + transitionTracker.SetTransitions(true, true, testData); + transitionTracker.EvaluateFrameMoment(i, 5, testData); + } + EXPECT_TRUE(transitionTracker.getExtendedFailure()); + EXPECT_TRUE(transitionTracker.getLumExtendedFailure()); + EXPECT_TRUE(transitionTracker.getRedExtendedFailure()); + EXPECT_EQ(FlashResult::ExtendedFail, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::ExtendedFail, testData.redFrameResult); + + EXPECT_EQ(0, transitionTracker.getLuminanceIncidents().flashFailFrames); + EXPECT_EQ(1, transitionTracker.getLuminanceIncidents().extendedFailFrames); + EXPECT_EQ(19, transitionTracker.getLuminanceIncidents().passWithWarningFrames); + EXPECT_EQ(0, transitionTracker.getRedIncidents().flashFailFrames); + EXPECT_EQ(1, transitionTracker.getRedIncidents().extendedFailFrames); + EXPECT_EQ(19, transitionTracker.getRedIncidents().passWithWarningFrames); + } + + TEST_F(TransitionTrackerByFPSTest, TotalTransictionCount_WhenLuminanceAndRed_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByFPS transitionTracker(4, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 5; i++) //add 5 luminance and red transitions + { + transitionTracker.SetTransitions(true, true, testData); + } + for (int i = 0; i < 3; i++) //add 3 frames, no transitions + { + transitionTracker.SetTransitions(false, false, testData); + } + for (int i = 0; i < 4; i++) //add 4 luminance transitions + { + transitionTracker.SetTransitions(true, false, testData); + } + for (int i = 0; i < 6; i++) //add 6 red transitions + { + transitionTracker.SetTransitions(false, true, testData); + } + + EXPECT_EQ(9, testData.LuminanceTransitions); + EXPECT_EQ(11, testData.RedTransitions); + } +} \ No newline at end of file diff --git a/test/Iris.Tests/src/TransitionTrackerByTimeTests.cpp b/test/Iris.Tests/src/TransitionTrackerByTimeTests.cpp new file mode 100644 index 0000000..724421b --- /dev/null +++ b/test/Iris.Tests/src/TransitionTrackerByTimeTests.cpp @@ -0,0 +1,369 @@ +//Copyright (C) 2023 Electronic Arts, Inc. All rights reserved + +#include "IrisLibTest.h" +#include +#include "TransitionTrackerByTime.h" +#include "FrameData.h" + +namespace iris::Tests +{ + class TransitionTrackerByTimeTest : public IrisLibTest { + protected: + }; + + TEST_F(TransitionTrackerByTimeTest, Transition_WhenOnlyLuminance_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(8, configuration.GetTransitionTrackerParams()); + + transitionTracker.SetTransitions(true, false, testData); + transitionTracker.SetTransitions(true, false, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(true, false, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(true, false, testData); + + EXPECT_EQ(4, testData.LuminanceTransitions); + EXPECT_EQ(0, testData.RedTransitions); + } + + TEST_F(TransitionTrackerByTimeTest, Transition_WhenOnlyRed_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(8, configuration.GetTransitionTrackerParams()); + + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(false, true, testData); + + EXPECT_EQ(0, testData.LuminanceTransitions); + EXPECT_EQ(4, testData.RedTransitions); + } + + TEST_F(TransitionTrackerByTimeTest, Transition_WhenLuminanceAndRed_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(8, configuration.GetTransitionTrackerParams()); + + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(true, true, testData); + transitionTracker.SetTransitions(false, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(true, false, testData); + transitionTracker.SetTransitions(false, true, testData); + transitionTracker.SetTransitions(true, true, testData); + + EXPECT_EQ(3, testData.LuminanceTransitions); + EXPECT_EQ(4, testData.RedTransitions); + } + + TEST_F(TransitionTrackerByTimeTest, EvaluateFrameMoment_WhenLuminanceFlashFail_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 8; i++) + { + transitionTracker.SetTransitions(true, false, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_TRUE(transitionTracker.getFlashFail()); + EXPECT_TRUE(transitionTracker.getLumFlashFail()); + EXPECT_EQ(FlashResult::FlashFail, testData.luminanceFrameResult); + EXPECT_EQ(1, transitionTracker.getLuminanceIncidents().flashFailFrames); + } + + TEST_F(TransitionTrackerByTimeTest, EvaluateFrameMoment_WhenRedFlashFail_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 8; i++) + { + transitionTracker.SetTransitions(false, true, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_TRUE(transitionTracker.getFlashFail()); + EXPECT_TRUE(transitionTracker.getRedFlashFail()); + EXPECT_EQ(FlashResult::FlashFail, testData.redFrameResult); + EXPECT_EQ(1, transitionTracker.getRedIncidents().flashFailFrames); + + } + + TEST_F(TransitionTrackerByTimeTest, EvaluateFrameMoment_WhenLuminanceAndRedFlashFail_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(10, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 2; i++) //add 2 luminance and red transitions + { + transitionTracker.SetTransitions(true, true, testData); + } + for (int i = 0; i < 3; i++) //add 3 red transitions + { + transitionTracker.SetTransitions(false, true, testData); + } + for (int i = 0; i < 5; i++) //add 5 luminance transitions + { + transitionTracker.SetTransitions(true, false, testData); + } + transitionTracker.EvaluateFrameMoment(10, 10, testData); + EXPECT_TRUE(transitionTracker.getFlashFail()); + EXPECT_TRUE(transitionTracker.getLumFlashFail()); + EXPECT_FALSE(transitionTracker.getRedFlashFail()); + + EXPECT_EQ(FlashResult::FlashFail, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::PassWithWarning, testData.redFrameResult); + EXPECT_EQ(1, transitionTracker.getLuminanceIncidents().flashFailFrames); + EXPECT_EQ(1, transitionTracker.getRedIncidents().passWithWarningFrames); + + } + + TEST_F(TransitionTrackerByTimeTest, EvaluateFrameMoment_WhenLuminanceFlashPass_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 3; i++) //add 3 luminance transitions + { + transitionTracker.SetTransitions(true, false, testData); + } + + for (int i = 0; i < 5; i++) //add 5 frames, no transitions + { + transitionTracker.SetTransitions(false, false, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_FALSE(transitionTracker.getFlashFail()); + EXPECT_EQ(FlashResult::Pass, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::Pass, testData.redFrameResult); + } + + TEST_F(TransitionTrackerByTimeTest, EvaluateFrameMoment_WhenRedFlashPass_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 3; i++) //add 3 red transitions + { + transitionTracker.SetTransitions(false, true, testData); + } + + for (int i = 0; i < 5; i++) //add 5 frames, no transitions + { + transitionTracker.SetTransitions(false, false, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_FALSE(transitionTracker.getFlashFail()); + EXPECT_EQ(FlashResult::Pass, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::Pass, testData.redFrameResult); + } + + TEST_F(TransitionTrackerByTimeTest, EvaluateFrameMoment_WhenLuminanceAndRedFlashPass_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(8, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 3; i++) //add 3 luminance and red transitions + { + transitionTracker.SetTransitions(true, true, testData); + } + + for (int i = 0; i < 5; i++) //add 5 frames, no transitions + { + transitionTracker.SetTransitions(false, false, testData); + } + transitionTracker.EvaluateFrameMoment(8, 8, testData); + EXPECT_FALSE(transitionTracker.getFlashFail()); + EXPECT_EQ(FlashResult::Pass, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::Pass, testData.redFrameResult); + } + + //TEST_F(TransitionTrackerByTimeTest, EvaluateFrameMoment_WhenExtendedFailure_Test) + //{ + // //Only luminance transitions + // FrameData testData; + // TransitionTrackerByTime transitionTracker(5, configuration.GetTransitionTrackerParams()); + + // for (int i = 0; i < 23; i++) //add luminance and red transitions + // { + // testData.TimeStampVal += 200; + // transitionTracker.SetTransitions(true, true, testData); + // transitionTracker.EvaluateFrameMoment(i, 5, testData); + // } + // EXPECT_TRUE(transitionTracker.getExtendedFailure()); + // EXPECT_TRUE(transitionTracker.getLumExtendedFailure()); + // EXPECT_TRUE(transitionTracker.getRedExtendedFailure()); + // EXPECT_EQ(FlashResult::ExtendedFail, testData.luminanceFrameResult); + // EXPECT_EQ(FlashResult::ExtendedFail, testData.redFrameResult); + + // EXPECT_EQ(0, transitionTracker.getLuminanceIncidents().flashFailFrames); + // EXPECT_EQ(1, transitionTracker.getLuminanceIncidents().extendedFailFrames); + // EXPECT_EQ(19, transitionTracker.getLuminanceIncidents().passWithWarningFrames); + // EXPECT_EQ(0, transitionTracker.getRedIncidents().flashFailFrames); + // EXPECT_EQ(1, transitionTracker.getRedIncidents().extendedFailFrames); + // EXPECT_EQ(19, transitionTracker.getRedIncidents().passWithWarningFrames); + //} + + TEST_F(TransitionTrackerByTimeTest, TotalTransictionCount_WhenLuminanceAndRed_Test) + { + //Only luminance transitions + FrameData testData = FrameData(); + TransitionTrackerByTime transitionTracker(4, configuration.GetTransitionTrackerParams()); + + for (int i = 0; i < 5; i++) //add 5 luminance and red transitions + { + transitionTracker.SetTransitions(true, true, testData); + } + for (int i = 0; i < 3; i++) //add 3 frames, no transitions + { + transitionTracker.SetTransitions(false, false, testData); + } + for (int i = 0; i < 4; i++) //add 4 luminance transitions + { + transitionTracker.SetTransitions(true, false, testData); + } + for (int i = 0; i < 6; i++) //add 6 red transitions + { + transitionTracker.SetTransitions(false, true, testData); + } + + EXPECT_EQ(9, testData.LuminanceTransitions); + EXPECT_EQ(11, testData.RedTransitions); + } + + /*TEST_F(TransitionTrackerByTimeTest, EvaluateSecond_WhenTimesBeteewnFramesNotEqual_Test) + { + //Only luminance transitions + FrameData testData; + TransitionTrackerByTime transitionTracker(5, configuration.GetTransitionTrackerParams()); + + int frameNum = 0; + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 0; + transitionTracker.EvaluateFrameMoment(frameNum, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 150; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 500; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 750; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 1000; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 1150; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 1350; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 1600; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 1950; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 2000; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 2200; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 2450; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 2800; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 2900; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 3000; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 3450; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 3800; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 3850; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 3950; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 4000; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 4250; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 4600; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + transitionTracker.SetTransitions(true, true, testData); + testData.TimeStampVal = 4850; + transitionTracker.EvaluateFrameMoment(frameNum++, 5, testData); + + + EXPECT_TRUE(transitionTracker.getExtendedFailure()); + EXPECT_TRUE(transitionTracker.getLumExtendedFailure()); + EXPECT_TRUE(transitionTracker.getRedExtendedFailure()); + EXPECT_EQ(FlashResult::ExtendedFail, testData.luminanceFrameResult); + EXPECT_EQ(FlashResult::ExtendedFail, testData.redFrameResult); + + EXPECT_EQ(0, transitionTracker.getLuminanceIncidents().flashFailFrames); + EXPECT_EQ(1, transitionTracker.getLuminanceIncidents().extendedFailFrames); + EXPECT_EQ(19, transitionTracker.getLuminanceIncidents().passWithWarningFrames); + EXPECT_EQ(0, transitionTracker.getRedIncidents().flashFailFrames); + EXPECT_EQ(1, transitionTracker.getRedIncidents().extendedFailFrames); + EXPECT_EQ(19, transitionTracker.getRedIncidents().passWithWarningFrames); + }*/ +} \ No newline at end of file diff --git a/test/Iris.Tests/src/VideoAnalysisTests.cpp b/test/Iris.Tests/src/VideoAnalysisTests.cpp index 49ab06f..dc9a3d6 100644 --- a/test/Iris.Tests/src/VideoAnalysisTests.cpp +++ b/test/Iris.Tests/src/VideoAnalysisTests.cpp @@ -1,7 +1,7 @@ //Copyright (C) 2023 Electronic Arts, Inc. All rights reserved. #include "IrisLibTest.h" -#include "VideoAnalyser.cpp" +#include "iris/VideoAnalyser.h" #include #include #include @@ -24,14 +24,15 @@ namespace iris::Tests std::string line; std::getline(logFile, line); //discard first line std::string testVideo = "testVideo"; - videoAnalyser.Init(video.get(cv::CAP_PROP_FPS), cv::Size(video.get(cv::CAP_PROP_FRAME_WIDTH), video.get(cv::CAP_PROP_FRAME_HEIGHT)), testVideo); + videoAnalyser.Init(testVideo); cv::Mat frame; video.read(frame); - int numFrames = 0; + unsigned int numFrames = 0; while (!frame.empty()) { - FrameData data(numFrames + 1, video.get(cv::CAP_PROP_FRAME_COUNT)); + FrameData data(numFrames + 1, 1000.0 * (double)numFrames / video.get(cv::CAP_PROP_FPS)); + //FrameData data(numFrames + 1, video.get(cv::CAP_PROP_FRAME_COUNT)); videoAnalyser.AnalyseFrame(frame, numFrames, data); video.read(frame); //obtain new frame @@ -90,7 +91,7 @@ namespace iris::Tests VideoAnalyser videoAnalyser(&configuration); cv::VideoCapture video(sourceVideo); - if (videoAnalyser.VideoIsOpen(video, nullptr)) + if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) { TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/2Hz_5s_RELATIVE.csv"); } @@ -102,7 +103,7 @@ namespace iris::Tests VideoAnalyser videoAnalyser(&configuration); cv::VideoCapture video(sourceVideo); - if (videoAnalyser.VideoIsOpen(video, nullptr)) + if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) { TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/2Hz_6s_RELATIVE.csv"); } @@ -114,7 +115,7 @@ namespace iris::Tests VideoAnalyser videoAnalyser(&configuration); cv::VideoCapture video(sourceVideo); - if (videoAnalyser.VideoIsOpen(video, nullptr)) + if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) { TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/3Hz_6s_RELATIVE.csv"); } @@ -126,7 +127,7 @@ namespace iris::Tests VideoAnalyser videoAnalyser(&configuration); cv::VideoCapture video(sourceVideo); - if (videoAnalyser.VideoIsOpen(video, nullptr)) + if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) { TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/extendedFLONG_RELATIVE.csv"); } @@ -138,7 +139,7 @@ namespace iris::Tests VideoAnalyser videoAnalyser(&configuration); cv::VideoCapture video(sourceVideo); - if (videoAnalyser.VideoIsOpen(video, nullptr)) + if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) { TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/GradualRedIncrease_RELATIVE.csv"); } @@ -150,7 +151,7 @@ namespace iris::Tests VideoAnalyser videoAnalyser(&configuration); cv::VideoCapture video(sourceVideo); - if (videoAnalyser.VideoIsOpen(video, nullptr)) + if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) { TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/gray_RELATIVE.csv"); } @@ -162,7 +163,7 @@ namespace iris::Tests VideoAnalyser videoAnalyser(&configuration); cv::VideoCapture video(sourceVideo); - if (videoAnalyser.VideoIsOpen(video, nullptr)) + if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) { TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/intermitentEF_RELATIVE.csv"); } @@ -174,7 +175,7 @@ namespace iris::Tests // VideoAnalyser videoAnalyser(&configuration); // cv::VideoCapture video(sourceVideo); - // if (videoAnalyser.VideoIsOpen(video, nullptr)) + // if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) // { // TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/Pattern - Circular 4_RELATIVE.csv"); // } @@ -186,7 +187,7 @@ namespace iris::Tests // VideoAnalyser videoAnalyser(&configuration); // cv::VideoCapture video(sourceVideo); - // if (videoAnalyser.VideoIsOpen(video, nullptr)) + // if (videoAnalyser.VideoIsOpen(sourceVideo, video, nullptr)) // { // TestVideoAnalysis(videoAnalyser, video, "data/ExpectedVideoLogFiles/Pattern - Circular 5_RELATIVE.csv"); // } diff --git a/utils/include/utils/BaseLog.h b/utils/include/utils/BaseLog.h index 47d7ff2..b7370ce 100644 --- a/utils/include/utils/BaseLog.h +++ b/utils/include/utils/BaseLog.h @@ -40,9 +40,9 @@ namespace EA::EACC::Utils RotatingFileSinkParams(const char* fileName) : fileName(fileName){} const char* fileName = nullptr; + std::size_t max_size = 1024 * 1024; std::size_t max_files = 5; bool rotate_on_open = true; - std::size_t max_size = 1024 * 1024; }; protected: