redisgned v4d-contexts to take variadic arguments instead of lamda-capturing.

pull/3471/head
kallaballa 2 years ago
parent 2d3e74da84
commit a9dfdbf8bc
  1. 42
      modules/v4d/include/opencv2/v4d/detail/framebuffercontext.hpp
  2. 4
      modules/v4d/include/opencv2/v4d/detail/glcontext.hpp
  3. 4
      modules/v4d/include/opencv2/v4d/detail/nanovgcontext.hpp
  4. 5
      modules/v4d/include/opencv2/v4d/detail/timetracker.hpp
  5. 10
      modules/v4d/include/opencv2/v4d/util.hpp
  6. 77
      modules/v4d/include/opencv2/v4d/v4d.hpp
  7. 24
      modules/v4d/samples/beauty-demo.cpp
  8. 2
      modules/v4d/samples/cube-demo.cpp
  9. 6
      modules/v4d/samples/custom_source_and_sink.cpp
  10. 8
      modules/v4d/samples/display_image_fb.cpp
  11. 20
      modules/v4d/samples/display_image_nvg.cpp
  12. 24
      modules/v4d/samples/font-demo.cpp
  13. 6
      modules/v4d/samples/font_rendering.cpp
  14. 10
      modules/v4d/samples/font_with_gui.cpp
  15. 10
      modules/v4d/samples/many_cubes-demo.cpp
  16. 6
      modules/v4d/samples/nanovg-demo.cpp
  17. 2
      modules/v4d/samples/optflow-demo.cpp
  18. 8
      modules/v4d/samples/pedestrian-demo.cpp
  19. 4
      modules/v4d/samples/shader-demo.cpp
  20. 2
      modules/v4d/samples/vector_graphics.cpp
  21. 2
      modules/v4d/samples/vector_graphics_and_fb.cpp
  22. 6
      modules/v4d/samples/video_editing.cpp
  23. 20
      modules/v4d/src/detail/framebuffercontext.cpp
  24. 8
      modules/v4d/src/detail/glcontext.cpp
  25. 6
      modules/v4d/src/detail/nanovgcontext.cpp
  26. 2
      modules/v4d/src/detail/timetracker.cpp
  27. 85
      modules/v4d/src/v4d.cpp

@ -12,10 +12,12 @@
//FIXME //FIXME
#include "opencv2/v4d/detail/cl.hpp" #include "opencv2/v4d/detail/cl.hpp"
#include <opencv2/core.hpp>
#include <opencv2/core/ocl.hpp> #include <opencv2/core/ocl.hpp>
#include "opencv2/v4d/util.hpp" #include "opencv2/v4d/util.hpp"
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <vector>
struct GLFWwindow; struct GLFWwindow;
typedef unsigned int GLenum; typedef unsigned int GLenum;
@ -24,6 +26,27 @@ typedef unsigned int GLenum;
namespace cv { namespace cv {
namespace v4d { namespace v4d {
class V4D; class V4D;
template <typename ... Args>
class V4DAndArgsInFunctor : public std::function<void(cv::Ptr<V4D>, Args ...)> {
public:
V4DAndArgsInFunctor(cv::Ptr<V4D> window, Args ... args) : std::function<void(cv::Ptr<V4D>, Args ...)>(window, args...) {
}
};
template <typename Tfn, typename ... Args>
class V4DAndFbAndArgsInFunctor : public std::function<void(cv::Ptr<V4D>, cv::UMat&, Args& ...)> {
public:
V4DAndFbAndArgsInFunctor(Tfn fn) : std::function<void(cv::Ptr<V4D>, cv::UMat&, Args& ...)>(fn) {
}
};
template <typename ... Args>
class V4DAndSizeTAndArgsInFunctor : public std::function<void(cv::Ptr<V4D>, size_t&, Args ...)> {
public:
V4DAndSizeTAndArgsInFunctor(std::function<void(cv::Ptr<V4D>, size_t&, Args ...)> fn) : std::function<void(cv::Ptr<V4D>, size_t&, Args ...)>(fn) {
}
};
namespace detail { namespace detail {
typedef cv::ocl::OpenCLExecutionContext CLExecContext_t; typedef cv::ocl::OpenCLExecutionContext CLExecContext_t;
class CLExecScope_t class CLExecScope_t
@ -217,7 +240,24 @@ public:
* directly on the framebuffer. * directly on the framebuffer.
* @param fn A function object that is passed the framebuffer to be read/manipulated. * @param fn A function object that is passed the framebuffer to be read/manipulated.
*/ */
void execute(std::function<void(cv::UMat&)> fn); template <typename Tfn, typename ... Args>
void execute(Tfn fn, Args& ... args) {
run_sync_on_main<2>([this, fn, &args...](){
#ifndef __EMSCRIPTEN__
if(!getCLExecContext().empty()) {
CLExecScope_t clExecScope(getCLExecContext());
FrameBufferContext::GLScope glScope(*this, GL_FRAMEBUFFER);
FrameBufferContext::FrameBufferScope fbScope(*this, framebuffer_);
fn(framebuffer_, args...);
} else
#endif
{
FrameBufferContext::GLScope glScope(*this, GL_FRAMEBUFFER);
FrameBufferContext::FrameBufferScope fbScope(*this, framebuffer_);
fn(framebuffer_, args...);
}
});
}
cv::Vec2f position(); cv::Vec2f position();
float pixelRatioX(); float pixelRatioX();
float pixelRatioY(); float pixelRatioY();

@ -19,7 +19,7 @@ namespace detail {
/*! /*!
* Used to setup a nanovg context * Used to setup a nanovg context
*/ */
class GLContext { class CV_EXPORTS GLContext {
FrameBufferContext& mainFbContext_; FrameBufferContext& mainFbContext_;
FrameBufferContext glFbContext_; FrameBufferContext glFbContext_;
public: public:
@ -34,7 +34,7 @@ public:
* @param fn A function that is passed the size of the framebuffer * @param fn A function that is passed the size of the framebuffer
* and performs drawing using opengl * and performs drawing using opengl
*/ */
void render(std::function<void(const cv::Size&)> fn); void render(std::function<void()> fn);
FrameBufferContext& fbCtx(); FrameBufferContext& fbCtx();
}; };

@ -19,7 +19,7 @@ namespace detail {
/*! /*!
* Used to setup a nanovg context * Used to setup a nanovg context
*/ */
class NanoVGContext { class CV_EXPORTS NanoVGContext {
FrameBufferContext& mainFbContext_; FrameBufferContext& mainFbContext_;
FrameBufferContext nvgFbContext_; FrameBufferContext nvgFbContext_;
NVGcontext* context_; NVGcontext* context_;
@ -61,7 +61,7 @@ public:
* @param fn A function that is passed the size of the framebuffer * @param fn A function that is passed the size of the framebuffer
* and performs drawing using cv::viz::nvg * and performs drawing using cv::viz::nvg
*/ */
void render(std::function<void(const cv::Size&)> fn); void render(std::function<void()> fn);
FrameBufferContext& fbCtx(); FrameBufferContext& fbCtx();
private: private:

@ -8,6 +8,7 @@
#include <ostream> #include <ostream>
#include <limits> #include <limits>
#include <mutex> #include <mutex>
#include <opencv2/core/cvdef.h>
using std::ostream; using std::ostream;
using std::stringstream; using std::stringstream;
@ -16,7 +17,7 @@ using std::map;
using std::chrono::microseconds; using std::chrono::microseconds;
using std::mutex; using std::mutex;
struct TimeInfo { struct CV_EXPORTS TimeInfo {
long totalCnt_ = 0; long totalCnt_ = 0;
long totalTime_ = 0; long totalTime_ = 0;
long iterCnt_ = 0; long iterCnt_ = 0;
@ -60,7 +61,7 @@ inline std::ostream& operator<<(ostream &os, TimeInfo &ti) {
return os; return os;
} }
class TimeTracker { class CV_EXPORTS TimeTracker {
private: private:
static TimeTracker *instance_; static TimeTracker *instance_;
mutex mapMtx_; mutex mapMtx_;

@ -78,14 +78,22 @@ make_function(T *t)
static thread_local bool sync_run = false; static thread_local bool sync_run = false;
template<std::size_t Tid> template<std::size_t Tid>
void run_sync_on_main(std::function<void()> fn) { void run_sync_on_main(std::function<void()> fn) {
CV_Assert(fn);
if(sync_run) if(sync_run)
throw std::runtime_error("Encountered nested run_sync_on_main"); throw std::runtime_error("Encountered nested run_sync_on_main");
sync_run = true; sync_run = true;
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
emscripten_sync_run_in_main_runtime_thread(EM_FUNC_SIG_V, cv::v4d::detail::get_fn_ptr<Tid>(fn)); typedef void* function_t( void* ) ;
function_t* ptr_fun = fn.target<function_t>() ;
//Check that the function object wrapped something callable
CV_Assert( ptr_fun != nullptr );
emscripten_sync_run_in_main_runtime_thread(EM_FUNC_SIG_V, ptr_fun);
#else #else
fn(); fn();
#endif #endif
sync_run = false; sync_run = false;
} }

@ -18,7 +18,11 @@
#include "detail/threadpool.hpp" #include "detail/threadpool.hpp"
#include "opencv2/v4d/detail/gl.hpp" #include "opencv2/v4d/detail/gl.hpp"
#include "opencv2/v4d/detail/framebuffercontext.hpp" #include "opencv2/v4d/detail/framebuffercontext.hpp"
#include "opencv2/v4d/detail/nanovgcontext.hpp"
#include "opencv2/v4d/detail/imguicontext.hpp" #include "opencv2/v4d/detail/imguicontext.hpp"
#include "opencv2/v4d/detail/timetracker.hpp"
#include "opencv2/v4d/detail/glcontext.hpp"
#include <iostream> #include <iostream>
#include <future> #include <future>
@ -26,6 +30,8 @@
#include <map> #include <map>
#include <string> #include <string>
#include <memory> #include <memory>
#include <vector>
#include <type_traits>
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp> #include <opencv2/imgproc.hpp>
@ -38,6 +44,7 @@ using std::string;
struct GLFWwindow; struct GLFWwindow;
/*! /*!
* OpenCV namespace * OpenCV namespace
*/ */
@ -57,6 +64,24 @@ enum AllocateFlags {
* Private namespace * Private namespace
*/ */
namespace detail { namespace detail {
//https://stackoverflow.com/questions/19961873/test-if-a-lambda-is-stateless#:~:text=As%20per%20the%20Standard%2C%20if,lambda%20is%20stateless%20or%20not.
template <typename T, typename U>
struct helper : helper<T, decltype(&U::operator())>
{};
template <typename T, typename C, typename R, typename... A>
struct helper<T, R(C::*)(A...) const>
{
static const bool value = std::is_convertible<T, R(*)(A...)>::value;
};
template<typename T>
struct is_stateless
{
static const bool value = helper<T,T>::value;
};
class FrameBufferContext; class FrameBufferContext;
class CLVAContext; class CLVAContext;
class NanoVGContext; class NanoVGContext;
@ -71,8 +96,8 @@ template<typename T> std::string int_to_hex( T i )
return stream.str(); return stream.str();
} }
template<typename T, typename... U> std::string func_id(std::function<T (U ...)> f) { template<typename Tfn> std::string func_id(Tfn& fn) {
return int_to_hex((size_t) &f); return int_to_hex((size_t) &fn);
} }
} }
@ -181,15 +206,24 @@ public:
*/ */
CV_EXPORTS cv::ogl::Texture2D& texture(); CV_EXPORTS cv::ogl::Texture2D& texture();
CV_EXPORTS std::string title(); CV_EXPORTS std::string title();
CV_EXPORTS void gl(std::function<void()> fn); template <typename Tfn, typename ... Args>
CV_EXPORTS void gl(std::function<void(const cv::Size&)> fn); void gl(Tfn fn, Args&& ... args) {
/*! TimeTracker::getInstance()->execute("gl(" + detail::func_id(fn) + ")/" + std::to_string(-1), [this, fn, &args...](){
* Execute function object fn inside an opengl context. glCtx(-1).render([=]() {
* This is how all OpenGL operations should be executed. fn(args...);
* @param fn A function object that is passed the size of the framebuffer });
*/ });
CV_EXPORTS void gl(std::function<void(const cv::Size&)> fn, const uint32_t& idx); }
CV_EXPORTS void gl(std::function<void()> fn, const uint32_t& idx);
template <typename Tfn, typename ... Args>
void gl(const size_t& idx, Tfn fn, Args&& ... args) {
TimeTracker::getInstance()->execute("gl(" + detail::func_id(fn) + ")/" + std::to_string(-1), [this, fn, idx, &args...](){
glCtx(idx).render([=]() {
fn(args...);
});
});
}
/*! /*!
* Execute function object fn inside a framebuffer context. * Execute function object fn inside a framebuffer context.
* The context acquires the framebuffer from OpenGL (either by up-/download or by cl-gl sharing) * The context acquires the framebuffer from OpenGL (either by up-/download or by cl-gl sharing)
@ -197,7 +231,13 @@ public:
* directly on the framebuffer. * directly on the framebuffer.
* @param fn A function object that is passed the framebuffer to be read/manipulated. * @param fn A function object that is passed the framebuffer to be read/manipulated.
*/ */
CV_EXPORTS void fb(std::function<void(cv::UMat&)> fn); template <typename Tfn, typename ... Args>
void fb(Tfn fn, Args& ... args) {
CV_Assert(detail::is_stateless<decltype(fn)>::value);
TimeTracker::getInstance()->execute("fb(" + detail::func_id(fn) + ")", [this, fn, &args...]{
fbCtx().execute(fn, args...);
});
}
/*! /*!
* Execute function object fn inside a nanovg context. * Execute function object fn inside a nanovg context.
* The context takes care of setting up opengl and nanovg states. * The context takes care of setting up opengl and nanovg states.
@ -205,8 +245,15 @@ public:
* @param fn A function that is passed the size of the framebuffer * @param fn A function that is passed the size of the framebuffer
* and performs drawing using cv::viz::nvg * and performs drawing using cv::viz::nvg
*/ */
CV_EXPORTS void nvg(std::function<void(const cv::Size&)> fn); template <typename Tfn, typename ... Args>
CV_EXPORTS void nvg(std::function<void()> fn); void nvg(Tfn fn, Args&& ... args) {
TimeTracker::getInstance()->execute("nvg(" + detail::func_id(fn) + ")", [this, fn, &args...](){
nvgCtx().render([this, fn, &args...]() {
fn(args...);
});
});
}
CV_EXPORTS void imgui(std::function<void(ImGuiContext* ctx)> fn); CV_EXPORTS void imgui(std::function<void(ImGuiContext* ctx)> fn);
/*! /*!
@ -316,7 +363,7 @@ public:
* Get the current size of the window. * Get the current size of the window.
* @return The window size. * @return The window size.
*/ */
CV_EXPORTS cv::Size framebufferSize(); CV_EXPORTS cv::Size fbSize();
/*! /*!
* Set the window size * Set the window size
* @param sz The future size of the window. * @param sz The future size of the window.

@ -249,25 +249,25 @@ static bool iteration(cv::Ptr<V4D> window) {
if (!faceRect.empty() && facemark->fit(down, faceRects, shapes)) { if (!faceRect.empty() && facemark->fit(down, faceRects, shapes)) {
FaceFeatures features(faceRect, shapes[0], float(down.size().width) / WIDTH); FaceFeatures features(faceRect, shapes[0], float(down.size().width) / WIDTH);
window->nvg([&features]() { window->nvg([](FaceFeatures& f) {
//Draw the face oval of the first face //Draw the face oval of the first face
draw_face_oval_mask(features); draw_face_oval_mask(f);
}); }, features);
window->fb([](cv::UMat &frameBuffer) { window->fb([](cv::UMat &frameBuffer) {
//Convert/Copy the mask //Convert/Copy the mask
cvtColor(frameBuffer, faceOval, cv::COLOR_BGRA2GRAY); cvtColor(frameBuffer, faceOval, cv::COLOR_BGRA2GRAY);
}); });
window->nvg([&features]() { window->nvg([](FaceFeatures& f) {
//Draw eyes eyes and lips areas of the first face //Draw eyes eyes and lips areas of the first face
draw_face_eyes_and_lips_mask(features); draw_face_eyes_and_lips_mask(f);
}); }, features);
window->fb([](cv::UMat &frameBuffer) { window->fb([](cv::UMat &frameBuffer, cv::UMat& e) {
//Convert/Copy the mask //Convert/Copy the mask
cvtColor(frameBuffer, eyesAndLipsMaskGrey, cv::COLOR_BGRA2GRAY); cvtColor(frameBuffer, e, cv::COLOR_BGRA2GRAY);
}); }, eyesAndLipsMaskGrey);
//Create the skin mask //Create the skin mask
cv::subtract(faceOval, eyesAndLipsMaskGrey, faceSkinMaskGrey); cv::subtract(faceOval, eyesAndLipsMaskGrey, faceSkinMaskGrey);
@ -316,9 +316,9 @@ static bool iteration(cv::Ptr<V4D> window) {
} }
//write the result to the framebuffer //write the result to the framebuffer
window->fb([](cv::UMat &frameBuffer) { window->fb([](cv::UMat &frameBuffer, cv::UMat& f) {
cvtColor(frameOut, frameBuffer, cv::COLOR_BGR2BGRA); cvtColor(f, frameBuffer, cv::COLOR_BGR2BGRA);
}); }, frameOut);
window->write(); window->write();

@ -224,7 +224,7 @@ static void glow_effect(const cv::UMat& src, cv::UMat& dst, const int ksize) {
using namespace cv::v4d; using namespace cv::v4d;
static bool iteration(cv::Ptr<V4D> window) { static bool iteration(cv::Ptr<V4D> window) {
window->once([=](){ window->gl(init_scene);}); window->once([=](){ window->gl(init_scene, window->fbSize());});
//Render using OpenGL //Render using OpenGL
window->gl(render_scene); window->gl(render_scene);

@ -44,15 +44,15 @@ int main() {
return false; return false;
//Render "Hello Rainbow!" over the video //Render "Hello Rainbow!" over the video
win->nvg([hr](const Size& sz) { win->nvg([](const Size& sz, const string& str) {
using namespace cv::v4d::nvg; using namespace cv::v4d::nvg;
fontSize(40.0f); fontSize(40.0f);
fontFace("sans-bold"); fontFace("sans-bold");
fillColor(Scalar(255, 0, 0, 255)); fillColor(Scalar(255, 0, 0, 255));
textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP); textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP);
text(sz.width / 2.0, sz.height / 2.0, hr.c_str(), hr.c_str() + hr.size()); text(sz.width / 2.0, sz.height / 2.0, str.c_str(), str.c_str() + str.size());
}); }, win->fbSize(), hr);
win->write(); win->write();

@ -17,16 +17,16 @@ int main() {
//We have to manually resize and color convert the image when using direct frambuffer access. //We have to manually resize and color convert the image when using direct frambuffer access.
UMat resized; UMat resized;
UMat converted; UMat converted;
resize(image, resized, window->framebufferSize()); resize(image, resized, window->fbSize());
cvtColor(resized, converted, COLOR_RGB2BGRA); cvtColor(resized, converted, COLOR_RGB2BGRA);
window->run([converted](Ptr<V4D> win){ window->run([converted](Ptr<V4D> win){
//Create a fb context and copy the prepared image to the framebuffer. The fb context //Create a fb context and copy the prepared image to the framebuffer. The fb context
//takes care of retrieving and storing the data on the graphics card (using CL-GL //takes care of retrieving and storing the data on the graphics card (using CL-GL
//interop if available), ready for other contexts to use //interop if available), ready for other contexts to use
win->fb([&](UMat& framebuffer){ win->fb([](UMat& framebuffer, const cv::UMat& c){
converted.copyTo(framebuffer); c.copyTo(framebuffer);
}); }, converted);
return win->display(); return win->display();
}); });
} }

@ -26,33 +26,33 @@ int main() {
//Execute only once //Execute only once
win->once([win, &image]() { win->once([win, &image]() {
//Creates a NanoVG context. The wrapped C-functions of NanoVG are available in the namespace cv::v4d::nvg; //Creates a NanoVG context. The wrapped C-functions of NanoVG are available in the namespace cv::v4d::nvg;
win->nvg([&image](const cv::Size sz) { win->nvg([](Image_t& img) {
using namespace cv::v4d::nvg; using namespace cv::v4d::nvg;
//Create the image and receive a handle. //Create the image and receive a handle.
int handle = createImage(image.filename_.c_str(), NVG_IMAGE_NEAREST); int handle = createImage(img.filename_.c_str(), NVG_IMAGE_NEAREST);
//Make sure it was created successfully //Make sure it was created successfully
CV_Assert(handle > 0); CV_Assert(handle > 0);
//Query the image size //Query the image size
imageSize(handle, &image.w_, &image.h_); imageSize(handle, &img.w_, &img.h_);
//Create a simple image pattern with the image dimensions //Create a simple image pattern with the image dimensions
image.paint_ = imagePattern(0, 0, image.w_, image.h_, 0.0f/180.0f*NVG_PI, handle, 1.0); img.paint_ = imagePattern(0, 0, img.w_, img.h_, 0.0f/180.0f*NVG_PI, handle, 1.0);
}); }, image);
}); });
//Creates a NanoVG context to draw the loaded image over again to the screen. //Creates a NanoVG context to draw the loaded image over again to the screen.
win->nvg([&image](const cv::Size sz) { win->nvg([](const Image_t& img, const cv::Size& sz) {
using namespace cv::v4d::nvg; using namespace cv::v4d::nvg;
beginPath(); beginPath();
//Scale all further calls to window size //Scale all further calls to window size
scale(double(sz.width)/image.w_, double(sz.height)/image.h_); scale(double(sz.width)/img.w_, double(sz.height)/img.h_);
//Create a rounded rectangle with the images dimensions. //Create a rounded rectangle with the images dimensions.
//Note that actually this rectangle will have the size of the window //Note that actually this rectangle will have the size of the window
//because of the previous scale call. //because of the previous scale call.
roundedRect(0,0, image.w_, image.h_, 50); roundedRect(0,0, img.w_, img.h_, 50);
//Fill the rounded rectangle with our picture //Fill the rounded rectangle with our picture
fillPaint(image.paint_); fillPaint(img.paint_);
fill(); fill();
}); }, image, win->fbSize());
//Displays the framebuffer in the window. Returns false if the windows has been closed. //Displays the framebuffer in the window. Returns false if the windows has been closed.
return win->display(); return win->display();
}); });

@ -110,11 +110,11 @@ static bool iteration(cv::Ptr<V4D> window) {
circle(rng.uniform(0, sz.width) , rng.uniform(0, sz.height), size / 2.0); circle(rng.uniform(0, sz.width) , rng.uniform(0, sz.height), size / 2.0);
stroke(); stroke();
} }
}); }, window->fbSize());
window->fb([](cv::UMat& frameBuffer){ window->fb([](cv::UMat& frameBuffer, cv::UMat& f){
frameBuffer.copyTo(stars); frameBuffer.copyTo(f);
}); }, stars);
update_stars = false; update_stars = false;
} }
@ -129,7 +129,7 @@ static bool iteration(cv::Ptr<V4D> window) {
update_perspective = false; update_perspective = false;
} }
window->nvg([translateY](const cv::Size& sz) { window->nvg([](const cv::Size& sz, const int32_t& ty) {
using namespace cv::v4d::nvg; using namespace cv::v4d::nvg;
clear(); clear();
fontSize(font_size); fontSize(font_size);
@ -138,22 +138,22 @@ static bool iteration(cv::Ptr<V4D> window) {
textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP); textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP);
/** only draw lines that are visible **/ /** only draw lines that are visible **/
translate(0, translateY); translate(0, ty);
for (size_t i = 0; i < lines.size(); ++i) { for (size_t i = 0; i < lines.size(); ++i) {
y = (i * font_size); y = (i * font_size);
if (y + translateY < textHeight && y + translateY + font_size > 0) { if (y + ty < textHeight && y + ty + font_size > 0) {
text(sz.width / 2.0, y, lines[i].c_str(), lines[i].c_str() + lines[i].size()); text(sz.width / 2.0, y, lines[i].c_str(), lines[i].c_str() + lines[i].size());
} }
} }
}); }, window->fbSize(), translateY);
window->fb([](cv::UMat& framebuffer) { window->fb([](cv::UMat& framebuffer, cv::UMat& w, cv::UMat& s, cv::Mat& t) {
//Pseudo 3D text effect. //Pseudo 3D text effect.
cv::warpPerspective(framebuffer, warped, tm, framebuffer.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar()); cv::warpPerspective(framebuffer, w, t, framebuffer.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar());
//Combine layers //Combine layers
cv::add(stars, warped, framebuffer); cv::add(s, w, framebuffer);
}); }, warped, stars, tm);
if(-translateY > textHeight) { if(-translateY > textHeight) {
//reset the scroll once the text is out of the picture //reset the scroll once the text is out of the picture

@ -11,15 +11,15 @@ int main() {
window->run([hw](Ptr<V4D> win){ window->run([hw](Ptr<V4D> win){
//Render the text at the center of the screen. Note that you can load you own fonts. //Render the text at the center of the screen. Note that you can load you own fonts.
win->nvg([hw](const Size& sz) { win->nvg([](const Size& sz, const string& str) {
using namespace cv::v4d::nvg; using namespace cv::v4d::nvg;
clear(); clear();
fontSize(40.0f); fontSize(40.0f);
fontFace("sans-bold"); fontFace("sans-bold");
fillColor(Scalar(255, 0, 0, 255)); fillColor(Scalar(255, 0, 0, 255));
textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP); textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP);
text(sz.width / 2.0, sz.height / 2.0, hw.c_str(), hw.c_str() + hw.size()); text(sz.width / 2.0, sz.height / 2.0, str.c_str(), str.c_str() + str.size());
}); }, win->fbSize(), hw);
return win->display(); return win->display();
}); });

@ -24,15 +24,15 @@ int main() {
window->run([&](Ptr<V4D> win) { window->run([&](Ptr<V4D> win) {
//Render the text at the center of the screen using parameters from the GUI. //Render the text at the center of the screen using parameters from the GUI.
win->nvg([&](const Size& sz) { win->nvg([](const Size& sz, const string& str, float s, float c[3]) {
using namespace cv::v4d::nvg; using namespace cv::v4d::nvg;
clear(); clear();
fontSize(size); fontSize(s);
fontFace("sans-bold"); fontFace("sans-bold");
fillColor(Scalar(color[2] * 255, color[1] * 255, color[0] * 255, 255)); fillColor(Scalar(c[2] * 255, c[1] * 255, c[0] * 255, 255));
textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP); textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP);
text(sz.width / 2.0, sz.height / 2.0, hw.c_str(), hw.c_str() + hw.size()); text(sz.width / 2.0, sz.height / 2.0, str.c_str(), str.c_str() + str.size());
}); }, win->fbSize(), hw, size, color);
return win->display(); return win->display();
}); });

@ -230,7 +230,7 @@ using namespace cv::v4d;
static bool iteration(cv::Ptr<V4D> window) { static bool iteration(cv::Ptr<V4D> window) {
window->once([=](){ window->once([=](){
for(size_t i = 0; i < NUMBER_OF_CUBES; ++i) for(size_t i = 0; i < NUMBER_OF_CUBES; ++i)
window->gl([=](const cv::Size sz){ init_scene(sz, i); }, i); window->gl(i, [](const cv::Size& sz, const size_t& idx){ init_scene(sz, idx); }, window->fbSize(), i);
}); });
window->gl([](){ window->gl([](){
@ -241,10 +241,10 @@ static bool iteration(cv::Ptr<V4D> window) {
//Render using multiple OpenGL contexts //Render using multiple OpenGL contexts
for(size_t i = 0; i < NUMBER_OF_CUBES; ++i) { for(size_t i = 0; i < NUMBER_OF_CUBES; ++i) {
window->gl([i](){ window->gl(i, [](const size_t idx){
double pos = (((double(i) / NUMBER_OF_CUBES) * 2.0) - 1) + (1.0 / NUMBER_OF_CUBES); double pos = (((double(idx) / NUMBER_OF_CUBES) * 2.0) - 1) + (1.0 / NUMBER_OF_CUBES);
double angle = sin((double(i) / NUMBER_OF_CUBES) * 2 * M_PI); double angle = sin((double(idx) / NUMBER_OF_CUBES) * 2 * M_PI);
render_scene(pos, pos, angle, i); render_scene(pos, pos, angle, idx);
}, i); }, i);
} }
//To slow for WASM //To slow for WASM

@ -164,9 +164,9 @@ static bool iteration(cv::Ptr<V4D> window) {
}); });
//Render using nanovg //Render using nanovg
window->nvg([hue](const cv::Size &sz) { window->nvg([](const cv::Size &sz, const double& h) {
draw_color_wheel(sz.width - 300, sz.height - 300, 250.0f, 250.0f, hue); draw_color_wheel(sz.width - 300, sz.height - 300, 250.0f, 250.0f, h);
}); }, window->fbSize(), hue);
window->write(); window->write();

@ -406,7 +406,7 @@ static bool iteration(cv::Ptr<V4D> window) {
if(!window->capture()) if(!window->capture())
return false; return false;
static thread_local cv::Size fbSz = window->framebufferSize(); static thread_local cv::Size fbSz = window->fbSize();
//BGRA //BGRA
static thread_local cv::UMat background, down; static thread_local cv::UMat background, down;
static thread_local cv::UMat foreground(fbSz, CV_8UC4, cv::Scalar::all(0)); static thread_local cv::UMat foreground(fbSz, CV_8UC4, cv::Scalar::all(0));

@ -212,12 +212,12 @@ static bool iteration(cv::Ptr<V4D> window) {
float cy = tracked.y * HEIGHT_SCALE + (height / 2.0f); float cy = tracked.y * HEIGHT_SCALE + (height / 2.0f);
ellipse(cx, cy, width / 2.0f, height / 2.0f); ellipse(cx, cy, width / 2.0f, height / 2.0f);
stroke(); stroke();
}); }, window->fbSize());
//Put it all together //Put it all together
window->fb([](cv::UMat& frameBuffer){ window->fb([](cv::UMat& frameBuffer, cv::UMat& bg){
composite_layers(background, frameBuffer, frameBuffer, BLUR_KERNEL_SIZE); composite_layers(bg, frameBuffer, frameBuffer, BLUR_KERNEL_SIZE);
}); }, background);
window->write(); window->write();

@ -268,12 +268,12 @@ static void setup_gui(cv::Ptr<V4D> window) {
} }
static bool iteration(cv::Ptr<V4D> window) { static bool iteration(cv::Ptr<V4D> window) {
window->once([=](){ window->gl(init_scene);}); window->once([=](){ window->gl(init_scene, window->fbSize());});
if(!window->capture()) if(!window->capture())
return false; return false;
window->gl(render_scene); window->gl(render_scene, window->fbSize());
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
window->fb([](cv::UMat& frameBuffer) { window->fb([](cv::UMat& frameBuffer) {

@ -91,7 +91,7 @@ int main() {
ellipse(rx, ry, ex, ey); ellipse(rx, ry, ex, ey);
fillPaint(gloss); fillPaint(gloss);
fill(); fill();
}); }, win->fbSize());
return win->display(); return win->display();
}); });

@ -90,7 +90,7 @@ int main() {
ellipse(rx, ry, ex, ey); ellipse(rx, ry, ex, ey);
fillPaint(gloss); fillPaint(gloss);
fill(); fill();
}); }, win->fbSize());
//Provides the framebuffer as left-off by the nvg context. //Provides the framebuffer as left-off by the nvg context.
win->fb([](UMat& framebuffer) { win->fb([](UMat& framebuffer) {

@ -34,15 +34,15 @@ int main(int argc, char** argv) {
return false; //end of input video return false; //end of input video
//Render on top of the video //Render on top of the video
win->nvg([hv](const Size& sz) { win->nvg([](const Size& sz, const string& str) {
using namespace cv::v4d::nvg; using namespace cv::v4d::nvg;
fontSize(40.0f); fontSize(40.0f);
fontFace("sans-bold"); fontFace("sans-bold");
fillColor(Scalar(255, 0, 0, 255)); fillColor(Scalar(255, 0, 0, 255));
textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP); textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP);
text(sz.width / 2.0, sz.height / 2.0, hv.c_str(), hv.c_str() + hv.size()); text(sz.width / 2.0, sz.height / 2.0, str.c_str(), str.c_str() + str.size());
}); }, win->fbSize(), hv);
//Write video to the sink (do nothing in case of WebAssembly) //Write video to the sink (do nothing in case of WebAssembly)
win->write(); win->write();

@ -5,8 +5,6 @@
#include "opencv2/v4d/v4d.hpp" #include "opencv2/v4d/v4d.hpp"
#include "opencv2/v4d/detail/framebuffercontext.hpp" #include "opencv2/v4d/detail/framebuffercontext.hpp"
#include "opencv2/v4d/util.hpp" #include "opencv2/v4d/util.hpp"
#include "glcontext.hpp"
#include "nanovgcontext.hpp"
#include "opencv2/core/ocl.hpp" #include "opencv2/core/ocl.hpp"
#include "opencv2/core/opengl.hpp" #include "opencv2/core/opengl.hpp"
#include <exception> #include <exception>
@ -631,24 +629,6 @@ void FrameBufferContext::copyFrom(const cv::UMat& src) {
}); });
} }
void FrameBufferContext::execute(std::function<void(cv::UMat&)> fn) {
run_sync_on_main<2>([&,this](){
#ifndef __EMSCRIPTEN__
if(!getCLExecContext().empty()) {
CLExecScope_t clExecScope(getCLExecContext());
FrameBufferContext::GLScope glScope(*this, GL_FRAMEBUFFER);
FrameBufferContext::FrameBufferScope fbScope(*this, framebuffer_);
fn(framebuffer_);
} else
#endif
{
FrameBufferContext::GLScope glScope(*this, GL_FRAMEBUFFER);
FrameBufferContext::FrameBufferScope fbScope(*this, framebuffer_);
fn(framebuffer_);
}
});
}
cv::ogl::Texture2D& FrameBufferContext::getTexture2D() { cv::ogl::Texture2D& FrameBufferContext::getTexture2D() {
return *texture_; return *texture_;
} }

@ -3,7 +3,7 @@
// of this distribution and at http://opencv.org/license.html. // of this distribution and at http://opencv.org/license.html.
// Copyright Amir Hassan (kallaballa) <amir@viel-zu.org> // Copyright Amir Hassan (kallaballa) <amir@viel-zu.org>
#include "glcontext.hpp" #include "opencv2/v4d/detail/glcontext.hpp"
#include "opencv2/v4d/detail/gl.hpp" #include "opencv2/v4d/detail/gl.hpp"
namespace cv { namespace cv {
@ -18,8 +18,8 @@ GLContext::GLContext(FrameBufferContext& fbContext) :
#endif #endif
} }
void GLContext::render(std::function<void(const cv::Size&)> fn) { void GLContext::render(std::function<void()> fn) {
run_sync_on_main<15>([&,this](){ run_sync_on_main<15>([this, fn](){
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
if(!fbCtx().isShared()) { if(!fbCtx().isShared()) {
UMat tmp; UMat tmp;
@ -38,7 +38,7 @@ void GLContext::render(std::function<void(const cv::Size&)> fn) {
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT)); GL_CHECK(glClear(GL_COLOR_BUFFER_BIT));
GL_CHECK(glClearColor(cColor[0], cColor[1], cColor[2], cColor[3])); GL_CHECK(glClearColor(cColor[0], cColor[1], cColor[2], cColor[3]));
#endif #endif
fn(fbCtx().size()); fn();
} }
if(!fbCtx().isShared()) { if(!fbCtx().isShared()) {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__

@ -3,7 +3,7 @@
// of this distribution and at http://opencv.org/license.html. // of this distribution and at http://opencv.org/license.html.
// Copyright Amir Hassan (kallaballa) <amir@viel-zu.org> // Copyright Amir Hassan (kallaballa) <amir@viel-zu.org>
#include "nanovgcontext.hpp" #include "opencv2/v4d/detail/nanovgcontext.hpp"
#include "opencv2/v4d/nvg.hpp" #include "opencv2/v4d/nvg.hpp"
#include "opencv2/v4d/detail/gl.hpp" #include "opencv2/v4d/detail/gl.hpp"
#include "nanovg_gl.h" #include "nanovg_gl.h"
@ -41,7 +41,7 @@ NanoVGContext::NanoVGContext(FrameBufferContext& fbContext) :
}); });
} }
void NanoVGContext::render(std::function<void(const cv::Size&)> fn) { void NanoVGContext::render(std::function<void()> fn) {
run_sync_on_main<14>([this, fn]() { run_sync_on_main<14>([this, fn]() {
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
if (!fbCtx().isShared()) { if (!fbCtx().isShared()) {
@ -59,7 +59,7 @@ void NanoVGContext::render(std::function<void(const cv::Size&)> fn) {
#endif #endif
NanoVGContext::Scope nvgScope(*this); NanoVGContext::Scope nvgScope(*this);
cv::v4d::nvg::detail::NVG::initializeContext(context_); cv::v4d::nvg::detail::NVG::initializeContext(context_);
fn(fbCtx().size()); fn();
} }
if (!fbCtx().isShared()) { if (!fbCtx().isShared()) {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__

@ -5,7 +5,7 @@
* Author: elchaschab * Author: elchaschab
*/ */
#include "timetracker.hpp" #include "opencv2/v4d/detail/timetracker.hpp"
TimeTracker* TimeTracker::instance_; TimeTracker* TimeTracker::instance_;

@ -6,11 +6,10 @@
#include "opencv2/v4d/v4d.hpp" #include "opencv2/v4d/v4d.hpp"
#include "opencv2/v4d/detail/framebuffercontext.hpp" #include "opencv2/v4d/detail/framebuffercontext.hpp"
#include "detail/clvacontext.hpp" #include "detail/clvacontext.hpp"
#include "detail/nanovgcontext.hpp"
#include "detail/glcontext.hpp"
#include "detail/timetracker.hpp"
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <opencv2/core.hpp>
#include <vector>
namespace cv { namespace cv {
namespace v4d { namespace v4d {
@ -156,59 +155,6 @@ size_t V4D::numGlCtx() {
return std::max(off_t(0), off_t(glContexts_.size()) - 1); return std::max(off_t(0), off_t(glContexts_.size()) - 1);
} }
void V4D::gl(std::function<void()> fn) {
TimeTracker::getInstance()->execute("gl(" + detail::func_id(fn) + ")/" + std::to_string(-1), [this, fn](){
glCtx(-1).render([=](const cv::Size& sz) {
CV_UNUSED(sz);
fn();
});
});
}
void V4D::gl(std::function<void(const cv::Size&)> fn) {
TimeTracker::getInstance()->execute("gl(" + detail::func_id(fn) + ")/" + std::to_string(-1), [this, fn](){
glCtx(-1).render(fn);
});
}
void V4D::gl(std::function<void()> fn, const uint32_t& idx) {
TimeTracker::getInstance()->execute("gl(" + detail::func_id(fn) + ")/" + std::to_string(idx), [this, fn, idx](){
glCtx(idx).render([=](const cv::Size& sz) {
CV_UNUSED(sz);
fn();
});
});
}
void V4D::gl(std::function<void(const cv::Size&)> fn, const uint32_t& idx) {
TimeTracker::getInstance()->execute("gl(" + detail::func_id(fn) + ")/" + std::to_string(idx), [this, fn, idx](){
glCtx(idx).render(fn);
});
}
void V4D::fb(std::function<void(cv::UMat&)> fn) {
TimeTracker::getInstance()->execute("fb(" + detail::func_id(fn) + ")", [this, fn](){
fbCtx().execute(fn);
});
}
void V4D::nvg(std::function<void()> fn) {
TimeTracker::getInstance()->execute("nvg(" + detail::func_id(fn) + ")", [this, fn](){
nvgCtx().render([fn](const cv::Size& sz) {
CV_UNUSED(sz);
fn();
});
});
}
void V4D::nvg(std::function<void(const cv::Size&)> fn) {
TimeTracker::getInstance()->execute("nvg(" + detail::func_id(fn) + ")", [this, fn](){
nvgCtx().render(fn);
});
}
void V4D::imgui(std::function<void(ImGuiContext* ctx)> fn) { void V4D::imgui(std::function<void(ImGuiContext* ctx)> fn) {
TimeTracker::getInstance()->execute("imgui(" + detail::func_id(fn) + ")", [this, fn](){ TimeTracker::getInstance()->execute("imgui(" + detail::func_id(fn) + ")", [this, fn](){
@ -355,18 +301,19 @@ void V4D::feed(cv::InputArray in) {
in.copyTo(videoFrame); in.copyTo(videoFrame);
}, frame); }, frame);
fb([&frame](cv::UMat& framebuffer){ //V4DAndFbAndArgsInFunctor<cv::UMat&> fn();
frame.copyTo(framebuffer); fb([](cv::UMat& fb, cv::UMat& f) {
}); f.copyTo(fb);
}, frame);
}); });
} }
cv::_InputArray V4D::fetch() { cv::_InputArray V4D::fetch() {
cv::UMat frame; cv::UMat frame;
TimeTracker::getInstance()->execute("copyTo", [this, &frame](){ TimeTracker::getInstance()->execute("copyTo", [this, &frame](){
fb([frame](cv::UMat& framebuffer){ fb([](cv::UMat& fb, cv::UMat& f) {
framebuffer.copyTo(frame); fb.copyTo(f);
}); }, frame);
}); });
return frame; return frame;
} }
@ -426,9 +373,9 @@ bool V4D::capture(std::function<void(cv::UMat&)> fn) {
return v->clvaCtx().capture(func, frame); return v->clvaCtx().capture(func, frame);
}, this, fn, nextReaderFrame_); }, this, fn, nextReaderFrame_);
fb([this](cv::UMat& frameBuffer){ fb([](cv::UMat& fb, cv::UMat& f){
currentReaderFrame_.copyTo(frameBuffer); f.copyTo(fb);
}); }, this->currentReaderFrame_);
}); });
return res; return res;
} }
@ -465,9 +412,9 @@ void V4D::write(std::function<void(const cv::UMat&)> fn) {
if (futureWriter_.valid()) if (futureWriter_.valid())
futureWriter_.get(); futureWriter_.get();
fb([this](cv::UMat& frameBuffer){ fb([](cv::UMat& fb, cv::UMat& f){
frameBuffer.copyTo(currentWriterFrame_); fb.copyTo(f);
}); }, currentWriterFrame_);
futureWriter_ = thread_pool_.enqueue([](V4D* v, std::function<void(const UMat&)> func, cv::UMat& frame) { futureWriter_ = thread_pool_.enqueue([](V4D* v, std::function<void(const UMat&)> func, cv::UMat& frame) {
v->clvaCtx().write(func, frame); v->clvaCtx().write(func, frame);
@ -495,7 +442,7 @@ float V4D::pixelRatioY() {
return fbCtx().pixelRatioY(); return fbCtx().pixelRatioY();
} }
cv::Size V4D::framebufferSize() { cv::Size V4D::fbSize() {
return fbCtx().size(); return fbCtx().size();
} }

Loading…
Cancel
Save