Repository for OpenCV's extra modules
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

352 lines
11 KiB

// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright Amir Hassan (kallaballa) <amir@viel-zu.org>
#ifndef SRC_OPENCV_V4D_UTIL_HPP_
#define SRC_OPENCV_V4D_UTIL_HPP_
#include "source.hpp"
#include "sink.hpp"
#include <filesystem>
#include <string>
#include <iostream>
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
#endif
#include <opencv2/core/ocl.hpp>
#include <opencv2/imgproc.hpp>
#ifdef __EMSCRIPTEN__
# include <emscripten.h>
# include <emscripten/bind.h>
# include <emscripten/threading.h>
# include <fstream>
#endif
#include <unistd.h>
#include <mutex>
#include <functional>
#include <iostream>
#include <cmath>
#include <thread>
namespace cv {
namespace v4d {
namespace detail {
using std::cout;
using std::endl;
inline uint64_t get_epoch_nanos() {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
static thread_local std::mutex mtx_;
static thread_local bool sync_run_ = false;
class CV_EXPORTS ThreadLocal {
public:
CV_EXPORTS static bool& sync_run() {
return sync_run_;
}
CV_EXPORTS static std::mutex& mutex() {
return mtx_;
}
};
class CV_EXPORTS Global {
inline static std::mutex mtx_;
inline static uint64_t frame_cnt_ = 0;
inline static uint64_t start_time_ = get_epoch_nanos();
inline static bool first_run_ = true;
inline static double fps_ = 0;
inline static const std::thread::id default_thread_id_;
inline static std::thread::id main_thread_id_;
public:
CV_EXPORTS static std::mutex& mutex() {
return mtx_;
}
CV_EXPORTS static uint64_t& frame_cnt() {
return frame_cnt_;
}
CV_EXPORTS static uint64_t& start_time() {
return start_time_;
}
CV_EXPORTS static bool& first_run() {
return first_run_;
}
CV_EXPORTS static double& fps() {
return fps_;
}
CV_EXPORTS static const std::thread::id& default_id() {
return default_thread_id_;
}
CV_EXPORTS static std::thread::id& main_id() {
return main_thread_id_;
}
CV_EXPORTS static bool is_main() {
return main_thread_id_ == default_thread_id_ || main_thread_id_ == std::this_thread::get_id();
}
};
//https://stackoverflow.com/a/27885283/1884837
template<class T>
struct function_traits : function_traits<decltype(&T::operator())> {
};
// partial specialization for function type
template<class R, class... Args>
struct function_traits<R(Args...)> {
using result_type = R;
using argument_types = std::tuple<std::remove_reference_t<Args>...>;
};
// partial specialization for function pointer
template<class R, class... Args>
struct function_traits<R (*)(Args...)> {
using result_type = R;
using argument_types = std::tuple<std::remove_reference_t<Args>...>;
};
// partial specialization for std::function
template<class R, class... Args>
struct function_traits<std::function<R(Args...)>> {
using result_type = R;
using argument_types = std::tuple<std::remove_reference_t<Args>...>;
};
// partial specialization for pointer-to-member-function (i.e., operator()'s)
template<class T, class R, class... Args>
struct function_traits<R (T::*)(Args...)> {
using result_type = R;
using argument_types = std::tuple<std::remove_reference_t<Args>...>;
};
template<class T, class R, class... Args>
struct function_traits<R (T::*)(Args...) const> {
using result_type = R;
using argument_types = std::tuple<std::remove_reference_t<Args>...>;
};
//https://stackoverflow.com/questions/281818/unmangling-the-result-of-stdtype-infoname
CV_EXPORTS std::string demangle(const char* name);
template <const size_t _UniqueId, typename _Res, typename... _ArgTypes>
struct fun_ptr_helper
{
public:
typedef std::function<_Res(_ArgTypes...)> function_type;
static void bind(function_type&& f)
{ instance().fn_.swap(f); }
static void bind(const function_type& f)
{ instance().fn_=f; }
static _Res invoke(_ArgTypes... args)
{ return instance().fn_(args...); }
typedef decltype(&fun_ptr_helper::invoke) pointer_type;
static pointer_type ptr()
{ return &invoke; }
private:
static fun_ptr_helper& instance()
{
static fun_ptr_helper inst_;
return inst_;
}
fun_ptr_helper() {}
function_type fn_;
};
template <const size_t _UniqueId, typename _Res, typename... _ArgTypes>
typename fun_ptr_helper<_UniqueId, _Res, _ArgTypes...>::pointer_type
get_fn_ptr(const std::function<_Res(_ArgTypes...)>& f)
{
fun_ptr_helper<_UniqueId, _Res, _ArgTypes...>::bind(f);
return fun_ptr_helper<_UniqueId, _Res, _ArgTypes...>::ptr();
}
template<typename T>
std::function<typename std::enable_if<std::is_function<T>::value, T>::type>
make_function(T *t)
{
return {t};
}
//https://stackoverflow.com/a/33047781/1884837
struct Lambda {
template<typename Tret, typename T>
static Tret lambda_ptr_exec() {
return (Tret) (*(T*)fn<T>());
}
template<typename Tret = void, typename Tfp = Tret(*)(), typename T>
static Tfp ptr(T& t) {
fn<T>(&t);
return (Tfp) lambda_ptr_exec<Tret, T>;
}
template<typename T>
static const void* fn(const void* new_fn = nullptr) {
CV_Assert(new_fn);
return new_fn;
}
};
template<std::size_t Tid>
void run_sync_on_main(std::function<void()> fn) {
std::unique_lock<std::mutex> lock(ThreadLocal::mutex());
CV_Assert(fn);
CV_Assert(!ThreadLocal::sync_run());
ThreadLocal::sync_run() = true;
#ifdef __EMSCRIPTEN__
emscripten_sync_run_in_main_runtime_thread(EM_FUNC_SIG_V, cv::v4d::detail::get_fn_ptr<Tid>(fn));
#else
fn();
#endif
ThreadLocal::sync_run() = false;
}
CV_EXPORTS size_t cnz(const cv::UMat& m);
}
using std::string;
class V4D;
/*!
* Convenience function to color convert from Scalar to Scalar
* @param src The scalar to color convert
* @param code The color converions code
* @return The color converted scalar
*/
CV_EXPORTS cv::Scalar colorConvert(const cv::Scalar& src, cv::ColorConversionCodes code);
#ifdef __EMSCRIPTEN__
CV_EXPORTS Mat read_embedded_image(const string &path);
#endif
/*!
* Convenience function to check for OpenGL errors. Should only be used via the macro #GL_CHECK.
* @param file The file path of the error.
* @param line The file line of the error.
* @param expression The expression that failed.
*/
CV_EXPORTS void gl_check_error(const std::filesystem::path& file, unsigned int line, const char* expression);
/*!
* Convenience macro to check for OpenGL errors.
*/
#ifndef NDEBUG
#define GL_CHECK(expr) \
expr; \
cv::v4d::gl_check_error(__FILE__, __LINE__, #expr);
#else
#define GL_CHECK(expr) \
expr;
#endif
CV_EXPORTS unsigned int initShader(const char* vShader, const char* fShader, const char* outputAttributeName);
/*!
* Returns the OpenGL vendor string
* @return a string object with the OpenGL vendor information
*/
CV_EXPORTS std::string getGlVendor();
/*!
* Returns the OpenGL Version information.
* @return a string object with the OpenGL version information
*/
CV_EXPORTS std::string getGlInfo();
/*!
* Returns the OpenCL Version information.
* @return a string object with the OpenCL version information
*/
CV_EXPORTS std::string getClInfo();
/*!
* Determines if Intel VAAPI is supported
* @return true if it is supported
*/
CV_EXPORTS bool isIntelVaSupported();
/*!
* Determines if cl_khr_gl_sharing is supported
* @return true if it is supported
*/
CV_EXPORTS bool isClGlSharingSupported();
/*!
* Tells the application if it's alright to keep on running.
* Note: If you use this mechanism signal handlers are installed
* @return true if the program should keep on running
*/
CV_EXPORTS bool keepRunning();
#ifndef __EMSCRIPTEN__
/*!
* Creates an Intel VAAPI enabled VideoWriter sink object to use in conjunction with #V4D::setSink().
* Usually you would call #makeWriterSink() and let it automatically decide if VAAPI is available.
* @param outputFilename The filename to write the video to.
* @param fourcc The fourcc code of the codec to use.
* @param fps The fps of the target video.
* @param frameSize The frame size of the target video.
* @param vaDeviceIndex The VAAPI device index to use.
* @return A VAAPI enabled sink object.
*/
CV_EXPORTS cv::Ptr<Sink> makeVaSink(cv::Ptr<V4D> window, const string& outputFilename, const int fourcc, const float fps,
const cv::Size& frameSize, const int vaDeviceIndex);
/*!
* Creates an Intel VAAPI enabled VideoCapture source object to use in conjunction with #V4D::setSource().
* Usually you would call #makeCaptureSource() and let it automatically decide if VAAPI is available.
* @param inputFilename The file to read from.
* @param vaDeviceIndex The VAAPI device index to use.
* @return A VAAPI enabled source object.
*/
CV_EXPORTS cv::Ptr<Source> makeVaSource(cv::Ptr<V4D> window, const string& inputFilename, const int vaDeviceIndex);
/*!
* Creates a VideoWriter sink object to use in conjunction with #V4D::setSink().
* This function automatically determines if Intel VAAPI is available and enables it if so.
* @param outputFilename The filename to write the video to.
* @param fourcc The fourcc code of the codec to use.
* @param fps The fps of the target video.
* @param frameSize The frame size of the target video.
* @return A (optionally VAAPI enabled) VideoWriter sink object.
*/
CV_EXPORTS cv::Ptr<Sink> makeWriterSink(cv::Ptr<V4D> window, const string& outputFilename, const float fps,
const cv::Size& frameSize);
CV_EXPORTS cv::Ptr<Sink> makeWriterSink(cv::Ptr<V4D> window, const string& outputFilename, const float fps,
const cv::Size& frameSize, const int fourcc);
/*!
* Creates a VideoCapture source object to use in conjunction with #V4D::setSource().
* This function automatically determines if Intel VAAPI is available and enables it if so.
* @param inputFilename The file to read from.
* @return A (optionally VAAPI enabled) VideoCapture enabled source object.
*/
CV_EXPORTS cv::Ptr<Source> makeCaptureSource(cv::Ptr<V4D> window, const string& inputFilename);
#else
/*!
* Creates a WebCam source object to use in conjunction with #V4D::setSource().
* @param width The frame width to capture (usually the initial width of the V4D object)
* @param height The frame height to capture (usually the initial height of the V4D object)
* @return A WebCam source object.
*/
CV_EXPORTS cv::Ptr<Source> makeCaptureSource(cv::Ptr<V4D> window);
#endif
void resizePreserveAspectRatio(const cv::UMat& src, cv::UMat& output, const cv::Size& dstSize, const cv::Scalar& bgcolor = {0,0,0,255});
}
}
#endif /* SRC_OPENCV_V4D_UTIL_HPP_ */