diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | cmake/opentrack-kinect.cmake | 45 | ||||
-rw-r--r-- | tracker-kinect-face/CMakeLists.txt | 49 | ||||
-rw-r--r-- | tracker-pt/module/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tracker-pt/module/camera_kinect_ir.cpp | 182 | ||||
-rw-r--r-- | tracker-pt/module/camera_kinect_ir.h | 70 | ||||
-rw-r--r-- | tracker-pt/module/module.cpp | 47 |
7 files changed, 351 insertions, 46 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 79ab0b5e..ceada462 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ include(opentrack-hier) include(opentrack-platform) include(opentrack-i18n) include(opentrack-boilerplate) - +include(opentrack-kinect) include(opentrack-qt) include(opentrack-version) include(opentrack-variant) diff --git a/cmake/opentrack-kinect.cmake b/cmake/opentrack-kinect.cmake new file mode 100644 index 00000000..a8b4243e --- /dev/null +++ b/cmake/opentrack-kinect.cmake @@ -0,0 +1,45 @@ +# Kinect SDK is Windows only +if (WIN32 AND opentrack-intel) + # Setup cache variable to Kinect SDK path + set(SDK_KINECT20 "$ENV{KINECTSDK20_DIR}" CACHE PATH "Kinect SDK path") +endif() + +# I'm guessing if we make this a function it's going to cause all sorts of problems and will need to be fixed in many ways +macro(otr_kinect_setup) + # If we have a valid SDK path, try build that tracker + if(SDK_KINECT20) + if(MSVC) + # workaround warning in SDK + target_compile_options(${self} PRIVATE "-wd4471") + endif() + + # Add include path to Kinect SDK + target_include_directories(${self} SYSTEM PRIVATE "${SDK_KINECT20}/inc") + + # Check processor architecture + if(opentrack-64bit) + # 64 bits + set(kinect-arch-dir "x64") + else() + # 32 bits + set(kinect-arch-dir "x86") + endif() + + # Link against Kinect SDK libraries + target_link_libraries(${self} "${SDK_KINECT20}/lib/${kinect-arch-dir}/Kinect20.lib" "${SDK_KINECT20}/lib/${kinect-arch-dir}/Kinect20.Face.lib") + # Link against video utilities, needed for video preview + #target_link_libraries(${self} opentrack-video) + + # Install Kinect Face DLL + install(FILES "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll" DESTINATION "${opentrack-hier-pfx}" PERMISSIONS ${opentrack-perms-exec}) + # Install Kinect Face Database + install(DIRECTORY "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/NuiDatabase" DESTINATION "${opentrack-hier-pfx}") + + set(redist-dir "${CMAKE_SOURCE_DIR}/redist/${kinect-arch-dir}") + install( + FILES "${redist-dir}/msvcp110.dll" "${redist-dir}/msvcr110.dll" + DESTINATION "${opentrack-hier-pfx}" + PERMISSIONS ${opentrack-perms-exec} + ) + endif() +endmacro() diff --git a/tracker-kinect-face/CMakeLists.txt b/tracker-kinect-face/CMakeLists.txt index 8eb064e7..5763567d 100644 --- a/tracker-kinect-face/CMakeLists.txt +++ b/tracker-kinect-face/CMakeLists.txt @@ -1,44 +1,11 @@ # Kinect SDK is Windows only -if (WIN32 AND opentrack-intel) - # Setup cache variable to Kinect SDK path - set(SDK_KINECT20 "$ENV{KINECTSDK20_DIR}" CACHE PATH "Kinect SDK path") - # If we have a valid SDK path, try build that tracker - if(SDK_KINECT20) - # Register our module - otr_module(tracker-kinect-face) +# If we have a valid SDK path, try build that tracker +if(SDK_KINECT20) + # Register our module + otr_module(tracker-kinect-face) + # Setup Kinect for this module + otr_kinect_setup() + # Link against video utilities, needed for video preview + target_link_libraries(${self} opentrack-video) - if(MSVC) - # workaround warning in SDK - target_compile_options(${self} PRIVATE "-wd4471") - endif() - - # Add include path to Kinect SDK - target_include_directories(${self} SYSTEM PRIVATE "${SDK_KINECT20}/inc") - - # Check processor architecture - if(opentrack-64bit) - # 64 bits - set(kinect-arch-dir "x64") - else() - # 32 bits - set(kinect-arch-dir "x86") - endif() - - # Link against Kinect SDK libraries - target_link_libraries(${self} "${SDK_KINECT20}/lib/${kinect-arch-dir}/Kinect20.lib" "${SDK_KINECT20}/lib/${kinect-arch-dir}/Kinect20.Face.lib") - # Link against video utilities, needed for video preview - target_link_libraries(${self} opentrack-video) - - # Install Kinect Face DLL - install(FILES "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll" DESTINATION "${opentrack-hier-pfx}" PERMISSIONS ${opentrack-perms-exec}) - # Install Kinect Face Database - install(DIRECTORY "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/NuiDatabase" DESTINATION "${opentrack-hier-pfx}") - - set(redist-dir "${CMAKE_SOURCE_DIR}/redist/${kinect-arch-dir}") - install( - FILES "${redist-dir}/msvcp110.dll" "${redist-dir}/msvcr110.dll" - DESTINATION "${opentrack-hier-pfx}" - PERMISSIONS ${opentrack-perms-exec} - ) - endif() endif() diff --git a/tracker-pt/module/CMakeLists.txt b/tracker-pt/module/CMakeLists.txt index 22b725c9..72d985c6 100644 --- a/tracker-pt/module/CMakeLists.txt +++ b/tracker-pt/module/CMakeLists.txt @@ -3,4 +3,6 @@ if(OpenCV_FOUND) otr_module(tracker-pt) target_link_libraries(${self} opentrack-tracker-pt-base) target_include_directories(${self} PUBLIC "${CMAKE_SOURCE_DIR}/tracker-pt") + # Add Kinect dependency if available + otr_kinect_setup() endif() diff --git a/tracker-pt/module/camera_kinect_ir.cpp b/tracker-pt/module/camera_kinect_ir.cpp new file mode 100644 index 00000000..ea5d2591 --- /dev/null +++ b/tracker-pt/module/camera_kinect_ir.cpp @@ -0,0 +1,182 @@ +/* Copyright (c) 2012 Patrick Ruoff + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "camera_kinect_ir.h" +#include "frame.hpp" + +#include "compat/sleep.hpp" +#include "compat/camera-names.hpp" +#include "compat/math-imports.hpp" + +#include <opencv2/imgproc.hpp> + +#include "cv/video-property-page.hpp" + +#include <cstdlib> + +namespace pt_module { + +CameraKinectIr::CameraKinectIr(const QString& module_name) : s { module_name } +{ +} + +QString CameraKinectIr::get_desired_name() const +{ + return desired_name; +} + +QString CameraKinectIr::get_active_name() const +{ + return active_name; +} + +void CameraKinectIr::show_camera_settings() +{ + const int idx = camera_name_to_index(s.camera_name); + + if (cap && cap->isOpened()) + video_property_page::show_from_capture(*cap, idx); + else + video_property_page::show(idx); +} + +CameraKinectIr::result CameraKinectIr::get_info() const +{ + if (cam_info.res_x == 0 || cam_info.res_y == 0) + return { false, pt_camera_info() }; + else + return { true, cam_info }; +} + +CameraKinectIr::result CameraKinectIr::get_frame(pt_frame& frame_) +{ + cv::Mat& frame = frame_.as<Frame>()->mat; + + const bool new_frame = get_frame_(frame); + + if (new_frame) + { + const f dt = (f)t.elapsed_seconds(); + t.start(); + + // measure fps of valid frames + constexpr f RC = f{1}/10; // seconds + const f alpha = dt/(dt + RC); + + if (dt_mean < dt_eps) + dt_mean = dt; + else + dt_mean = (1-alpha) * dt_mean + alpha * dt; + + cam_info.fps = dt_mean > dt_eps ? 1 / dt_mean : 0; + cam_info.res_x = frame.cols; + cam_info.res_y = frame.rows; + cam_info.fov = fov; + + return { true, cam_info }; + } + else + return { false, {} }; +} + +bool CameraKinectIr::start(int idx, int fps, int res_x, int res_y) +{ + + if (idx >= 0 && fps >= 0 && res_x >= 0 && res_y >= 0) + { + if (cam_desired.idx != idx || + (int)cam_desired.fps != fps || + cam_desired.res_x != res_x || + cam_desired.res_y != res_y || + !cap || !cap->isOpened() || !cap->grab()) + { + stop(); + + desired_name = get_camera_names().value(idx); + bool kinectIRSensor = false; + if (desired_name.compare(KKinectIRSensor) == 0) + { + kinectIRSensor = true; + } + cam_desired.idx = idx; + cam_desired.fps = fps; + cam_desired.res_x = res_x; + cam_desired.res_y = res_y; + cam_desired.fov = fov; + + cap = camera_ptr(new cv::VideoCapture(idx)); + + if (cam_desired.res_x > 0 && cam_desired.res_y > 0) + { + cap->set(cv::CAP_PROP_FRAME_WIDTH, res_x); + cap->set(cv::CAP_PROP_FRAME_HEIGHT, res_y); + } + + if (fps > 0) + cap->set(cv::CAP_PROP_FPS, fps); + + if (cap->isOpened()) + { + cam_info = pt_camera_info(); + cam_info.idx = idx; + dt_mean = 0; + active_name = desired_name; + + cv::Mat tmp; + + if (get_frame_(tmp)) + { + t.start(); + return true; + } + } + + cap = nullptr; + return false; + } + + return true; + } + + stop(); + return false; +} + +void CameraKinectIr::stop() +{ + cap = nullptr; + desired_name = QString{}; + active_name = QString{}; + cam_info = {}; + cam_desired = {}; +} + +bool CameraKinectIr::get_frame_(cv::Mat& frame) +{ + if (cap && cap->isOpened()) + { + for (unsigned i = 0; i < 10; i++) + { + if (cap->read(frame)) + return true; + portable::sleep(50); + } + } + return false; +} + +void CameraKinectIr::camera_deleter::operator()(cv::VideoCapture* cap) +{ + if (cap) + { + if (cap->isOpened()) + cap->release(); + delete cap; + } +} + +} // ns pt_module diff --git a/tracker-pt/module/camera_kinect_ir.h b/tracker-pt/module/camera_kinect_ir.h new file mode 100644 index 00000000..93c3d75b --- /dev/null +++ b/tracker-pt/module/camera_kinect_ir.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2012 Patrick Ruoff + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#pragma once + +#if __has_include(<Kinect.h>) + +#include "pt-api.hpp" +#include "compat/timer.hpp" + +#include <memory> + +#include <opencv2/core.hpp> +#include <opencv2/videoio.hpp> + +#include <QString> + +namespace pt_module { + +/// +/// Implement our camera interface using Kinect V2 SDK IR Sensor. +/// +struct CameraKinectIr final : pt_camera +{ + CameraKinectIr(const QString& module_name); + + bool start(int idx, int fps, int res_x, int res_y) override; + void stop() override; + + result get_frame(pt_frame& Frame) override; + result get_info() const override; + + pt_camera_info get_desired() const override { return cam_desired; } + QString get_desired_name() const override; + QString get_active_name() const override; + + void set_fov(f value) override { fov = value; } + void show_camera_settings() override; + +private: + [[nodiscard]] bool get_frame_(cv::Mat& frame); + + f dt_mean = 0, fov = 30; + Timer t; + pt_camera_info cam_info; + pt_camera_info cam_desired; + QString desired_name, active_name; + + struct camera_deleter final + { + void operator()(cv::VideoCapture* cap); + }; + + using camera_ptr = std::unique_ptr<cv::VideoCapture, camera_deleter>; + + camera_ptr cap; + + pt_settings s; + + static constexpr f dt_eps = f{1}/256; +}; + +} // ns pt_module + + +#endif diff --git a/tracker-pt/module/module.cpp b/tracker-pt/module/module.cpp index db3e8fac..c3b417a7 100644 --- a/tracker-pt/module/module.cpp +++ b/tracker-pt/module/module.cpp @@ -2,6 +2,7 @@ #include "module.hpp" #include "camera.h" +#include "camera_kinect_ir.h" #include "compat/camera-names.hpp" #include "frame.hpp" #include "point_extractor.h" @@ -19,7 +20,9 @@ static const QString module_name = "tracker-pt"; namespace pt_module { -// Traits for OpenCV VideoCapture camera +/// +/// Traits for OpenCV VideoCapture camera +/// struct pt_module_traits final : pt_runtime_traits { pointer<pt_camera> make_camera() const override @@ -48,6 +51,41 @@ struct pt_module_traits final : pt_runtime_traits } }; +#if __has_include(<Kinect.h>) +/// +/// Traits for Kinect V2 IR Sensor +/// +struct KinectIrTraits final : pt_runtime_traits +{ + pointer<pt_camera> make_camera() const override + { + return pointer<pt_camera>(new CameraKinectIr(module_name)); + } + + pointer<pt_point_extractor> make_point_extractor() const override + { + return pointer<pt_point_extractor>(new PointExtractor(module_name)); + } + + QString get_module_name() const override + { + return module_name; + } + + pointer<pt_frame> make_frame() const override + { + return pointer<pt_frame>(new Frame); + } + + pointer<pt_preview> make_preview(int w, int h) const override + { + return pointer<pt_preview>(new Preview(w, h)); + } +}; +#endif + + + struct tracker_pt : Tracker_PT { tracker_pt() : Tracker_PT(module_name) @@ -56,13 +94,14 @@ struct tracker_pt : Tracker_PT pointer<pt_runtime_traits> create_traits() override { - // Create different traits according to settings +#if __has_include(<Kinect.h>) + // Create Kinect traits according to settings if (s.camera_name().compare(KKinectIRSensor) == 0) { // Use Kinect IR trait - return pointer<pt_runtime_traits>(new pt_module_traits); + return pointer<pt_runtime_traits>(new KinectIrTraits); } - +#endif return pointer<pt_runtime_traits>(new pt_module_traits); } |