github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/opencv4/include/opencv2/gapi/fluid/gfluidkernel.hpp (about) 1 // This file is part of OpenCV project. 2 // It is subject to the license terms in the LICENSE file found in the top-level directory 3 // of this distribution and at http://opencv.org/license.html. 4 // 5 // Copyright (C) 2018-2019 Intel Corporation 6 7 8 #ifndef OPENCV_GAPI_FLUID_KERNEL_HPP 9 #define OPENCV_GAPI_FLUID_KERNEL_HPP 10 11 #include <vector> 12 #include <functional> 13 #include <map> 14 #include <unordered_map> 15 16 #include <opencv2/gapi/opencv_includes.hpp> 17 #include <opencv2/gapi/gcommon.hpp> 18 #include <opencv2/gapi/gkernel.hpp> 19 #include <opencv2/gapi/garg.hpp> 20 21 #include <opencv2/gapi/fluid/gfluidbuffer.hpp> 22 23 // FIXME: namespace scheme for backends? 24 namespace cv { 25 26 namespace gapi 27 { 28 /** 29 * @brief This namespace contains G-API Fluid backend functions, structures, and symbols. 30 */ 31 namespace fluid 32 { 33 /** 34 * \addtogroup gapi_std_backends G-API Standard Backends 35 * @{ 36 */ 37 /** 38 * @brief Get a reference to Fluid backend. 39 * 40 * @sa gapi_std_backends 41 */ 42 GAPI_EXPORTS cv::gapi::GBackend backend(); 43 /** @} */ 44 } // namespace fluid 45 } // namespace gapi 46 47 48 class GAPI_EXPORTS GFluidKernel 49 { 50 public: 51 enum class Kind 52 { 53 Filter, 54 Resize, 55 YUV420toRGB //Color conversion of 4:2:0 chroma sub-sampling formats (NV12, I420 ..etc) to RGB 56 }; 57 58 // This function is a generic "doWork" callback 59 using F = std::function<void(const cv::GArgs&, const std::vector<gapi::fluid::Buffer*> &)>; 60 61 // This function is a generic "initScratch" callback 62 using IS = std::function<void(const cv::GMetaArgs &, const cv::GArgs&, gapi::fluid::Buffer &)>; 63 64 // This function is a generic "resetScratch" callback 65 using RS = std::function<void(gapi::fluid::Buffer &)>; 66 67 // This function describes kernel metadata inference rule. 68 using M = std::function<GMetaArgs(const GMetaArgs &, const GArgs &)>; 69 70 // This function is a generic "getBorder" callback (extracts border-related data from kernel's input parameters) 71 using B = std::function<gapi::fluid::BorderOpt(const GMetaArgs&, const GArgs&)>; 72 73 // This function is a generic "getWindow" callback (extracts window-related data from kernel's input parameters) 74 using GW = std::function<int(const GMetaArgs&, const GArgs&)>; 75 76 // FIXME: move implementations out of header file 77 GFluidKernel() {} 78 GFluidKernel(Kind k, int l, bool scratch, const F& f, const IS &is, const RS &rs, const B& b, const GW& win) 79 : m_kind(k) 80 , m_lpi(l) 81 , m_scratch(scratch) 82 , m_f(f) 83 , m_is(is) 84 , m_rs(rs) 85 , m_b(b) 86 , m_gw(win) {} 87 88 Kind m_kind; 89 const int m_lpi = -1; 90 const bool m_scratch = false; 91 92 const F m_f; 93 const IS m_is; 94 const RS m_rs; 95 const B m_b; 96 const GW m_gw; 97 }; 98 99 // FIXME!!! 100 // This is the temporary and experimental API 101 // which should be replaced by runtime roi-based scheduling 102 /** \addtogroup gapi_compile_args 103 * @{ 104 */ 105 /** 106 * @brief This structure allows to control the output image region 107 * which Fluid backend will produce in the graph. 108 * 109 * This feature is useful for external tiling and parallelism, but 110 * will be deprecated in the future releases. 111 */ 112 struct GFluidOutputRois 113 { 114 std::vector<cv::Rect> rois; 115 }; 116 117 /** 118 * @brief This structure forces Fluid backend to generate multiple 119 * parallel output regions in the graph. These regions execute in parallel. 120 * 121 * This feature may be deprecated in the future releases. 122 */ 123 struct GFluidParallelOutputRois 124 { 125 std::vector<GFluidOutputRois> parallel_rois; 126 }; 127 128 /** 129 * @brief This structure allows to customize the way how Fluid executes 130 * parallel regions. 131 * 132 * For example, user can utilize his own threading runtime via this parameter. 133 * The `parallel_for` member functor is called by the Fluid runtime with the 134 * following arguments: 135 * 136 * @param size Size of the parallel range to process 137 * @param f A function which should be called for every integer index 138 * in this range by the specified parallel_for implementation. 139 * 140 * This feature may be deprecated in the future releases. 141 */ 142 struct GFluidParallelFor 143 { 144 //this function accepts: 145 // - size of the "parallel" range as the first argument 146 // - and a function to be called on the range items, designated by item index 147 std::function<void(std::size_t size, std::function<void(std::size_t index)>)> parallel_for; 148 }; 149 /** @} gapi_compile_args */ 150 151 namespace detail 152 { 153 template<> struct CompileArgTag<GFluidOutputRois> 154 { 155 static const char* tag() { return "gapi.fluid.outputRois"; } 156 }; 157 158 template<> struct CompileArgTag<GFluidParallelFor> 159 { 160 static const char* tag() { return "gapi.fluid.parallelFor"; } 161 }; 162 163 template<> struct CompileArgTag<GFluidParallelOutputRois> 164 { 165 static const char* tag() { return "gapi.fluid.parallelOutputRois"; } 166 }; 167 168 } // namespace detail 169 170 namespace detail 171 { 172 template<class T> struct fluid_get_in; 173 template<> struct fluid_get_in<cv::GMat> 174 { 175 static const cv::gapi::fluid::View& get(const cv::GArgs &in_args, int idx) 176 { 177 return *in_args[idx].unsafe_get<cv::gapi::fluid::View*>(); 178 } 179 }; 180 181 template<> struct fluid_get_in<cv::GScalar> 182 { 183 // FIXME: change to return by reference when moved to own::Scalar 184 static const cv::Scalar get(const cv::GArgs &in_args, int idx) 185 { 186 return in_args[idx].unsafe_get<cv::Scalar>(); 187 } 188 }; 189 190 template<typename U> struct fluid_get_in<cv::GArray<U>> 191 { 192 static const std::vector<U>& get(const cv::GArgs &in_args, int idx) 193 { 194 return in_args.at(idx).unsafe_get<cv::detail::VectorRef>().rref<U>(); 195 } 196 }; 197 198 template<typename U> struct fluid_get_in<cv::GOpaque<U>> 199 { 200 static const U& get(const cv::GArgs &in_args, int idx) 201 { 202 return in_args.at(idx).unsafe_get<cv::detail::OpaqueRef>().rref<U>(); 203 } 204 }; 205 206 template<class T> struct fluid_get_in 207 { 208 static const T& get(const cv::GArgs &in_args, int idx) 209 { 210 return in_args[idx].unsafe_get<T>(); 211 } 212 }; 213 214 template<bool, typename Impl, typename... Ins> 215 struct scratch_helper; 216 217 template<typename Impl, typename... Ins> 218 struct scratch_helper<true, Impl, Ins...> 219 { 220 // Init 221 template<int... IIs> 222 static void help_init_impl(const cv::GMetaArgs &metas, 223 const cv::GArgs &in_args, 224 gapi::fluid::Buffer &scratch_buf, 225 detail::Seq<IIs...>) 226 { 227 Impl::initScratch(get_in_meta<Ins>(metas, in_args, IIs)..., scratch_buf); 228 } 229 230 static void help_init(const cv::GMetaArgs &metas, 231 const cv::GArgs &in_args, 232 gapi::fluid::Buffer &b) 233 { 234 help_init_impl(metas, in_args, b, typename detail::MkSeq<sizeof...(Ins)>::type()); 235 } 236 237 // Reset 238 static void help_reset(gapi::fluid::Buffer &b) 239 { 240 Impl::resetScratch(b); 241 } 242 }; 243 244 template<typename Impl, typename... Ins> 245 struct scratch_helper<false, Impl, Ins...> 246 { 247 static void help_init(const cv::GMetaArgs &, 248 const cv::GArgs &, 249 gapi::fluid::Buffer &) 250 { 251 GAPI_Assert(false); 252 } 253 static void help_reset(gapi::fluid::Buffer &) 254 { 255 GAPI_Assert(false); 256 } 257 }; 258 259 template<typename T> struct is_gmat_type 260 { 261 static const constexpr bool value = std::is_same<cv::GMat, T>::value; 262 }; 263 264 template<bool CallCustomGetBorder, typename Impl, typename... Ins> 265 struct get_border_helper; 266 267 template<typename Impl, typename... Ins> 268 struct get_border_helper<true, Impl, Ins...> 269 { 270 template<int... IIs> 271 static gapi::fluid::BorderOpt get_border_impl(const GMetaArgs &metas, 272 const cv::GArgs &in_args, 273 cv::detail::Seq<IIs...>) 274 { 275 return util::make_optional(Impl::getBorder(cv::detail::get_in_meta<Ins>(metas, in_args, IIs)...)); 276 } 277 278 static gapi::fluid::BorderOpt help(const GMetaArgs &metas, 279 const cv::GArgs &in_args) 280 { 281 return get_border_impl(metas, in_args, typename detail::MkSeq<sizeof...(Ins)>::type()); 282 } 283 }; 284 285 template<typename Impl, typename... Ins> 286 struct get_border_helper<false, Impl, Ins...> 287 { 288 static gapi::fluid::BorderOpt help(const cv::GMetaArgs &, 289 const cv::GArgs &) 290 { 291 return {}; 292 } 293 }; 294 295 template<bool CallCustomGetWindow, typename, typename... Ins> 296 struct get_window_helper; 297 298 template<typename Impl, typename... Ins> 299 struct get_window_helper<true, Impl, Ins...> 300 { 301 template<int... IIs> 302 static int get_window_impl(const GMetaArgs &metas, 303 const cv::GArgs &in_args, 304 cv::detail::Seq<IIs...>) 305 { 306 return Impl::getWindow(cv::detail::get_in_meta<Ins>(metas, in_args, IIs)...); 307 } 308 309 static int help(const GMetaArgs &metas, const cv::GArgs &in_args) 310 { 311 return get_window_impl(metas, in_args, typename detail::MkSeq<sizeof...(Ins)>::type()); 312 } 313 }; 314 315 template<typename Impl, typename... Ins> 316 struct get_window_helper<false, Impl, Ins...> 317 { 318 static int help(const cv::GMetaArgs &, 319 const cv::GArgs &) 320 { 321 return Impl::Window; 322 } 323 }; 324 325 template<typename C, typename T> 326 struct has_Window 327 { 328 private: 329 template<class U> 330 static constexpr auto Check(U*) -> typename std::is_same<decltype(U::Window), T>::type; 331 332 template<typename> 333 static constexpr std::false_type Check(...); 334 335 typedef decltype(Check<C>(0)) Result; 336 337 public: 338 static constexpr bool value = Result::value; 339 }; 340 341 template<bool hasWindow, typename Impl> 342 struct callCustomGetBorder; 343 344 template<typename Impl> 345 struct callCustomGetBorder<true, Impl> 346 { 347 static constexpr bool value = (Impl::Window != 1); 348 }; 349 350 template<typename Impl> 351 struct callCustomGetBorder<false, Impl> 352 { 353 static constexpr bool value = true; 354 }; 355 356 template<typename, typename, typename, bool UseScratch> 357 struct FluidCallHelper; 358 359 template<typename Impl, typename... Ins, typename... Outs, bool UseScratch> 360 struct FluidCallHelper<Impl, std::tuple<Ins...>, std::tuple<Outs...>, UseScratch> 361 { 362 static_assert(all_satisfy<is_gmat_type, Outs...>::value, "return type must be GMat"); 363 static_assert(contains<GMat, Ins...>::value, "input must contain at least one GMat"); 364 365 // Execution dispatcher //////////////////////////////////////////////////// 366 template<int... IIs, int... OIs> 367 static void call_impl(const cv::GArgs &in_args, 368 const std::vector<gapi::fluid::Buffer*> &out_bufs, 369 detail::Seq<IIs...>, 370 detail::Seq<OIs...>) 371 { 372 Impl::run(fluid_get_in<Ins>::get(in_args, IIs)..., *out_bufs[OIs]...); 373 } 374 375 static void call(const cv::GArgs &in_args, 376 const std::vector<gapi::fluid::Buffer*> &out_bufs) 377 { 378 constexpr int numOuts = (sizeof...(Outs)) + (UseScratch ? 1 : 0); 379 call_impl(in_args, out_bufs, 380 typename detail::MkSeq<sizeof...(Ins)>::type(), 381 typename detail::MkSeq<numOuts>::type()); 382 } 383 384 // Scratch buffer initialization dispatcher //////////////////////////////// 385 static void init_scratch(const GMetaArgs &metas, 386 const cv::GArgs &in_args, 387 gapi::fluid::Buffer &b) 388 { 389 scratch_helper<UseScratch, Impl, Ins...>::help_init(metas, in_args, b); 390 } 391 392 // Scratch buffer reset dispatcher ///////////////////////////////////////// 393 static void reset_scratch(gapi::fluid::Buffer &scratch_buf) 394 { 395 scratch_helper<UseScratch, Impl, Ins...>::help_reset(scratch_buf); 396 } 397 398 static gapi::fluid::BorderOpt getBorder(const GMetaArgs &metas, const cv::GArgs &in_args) 399 { 400 constexpr bool hasWindow = has_Window<Impl, const int>::value; 401 402 // User must provide "init" callback if Window != 1 403 // TODO: move to constexpr if when we enable C++17 404 return get_border_helper<callCustomGetBorder<hasWindow, Impl>::value, Impl, Ins...>::help(metas, in_args); 405 } 406 407 static int getWindow(const GMetaArgs &metas, const cv::GArgs &in_args) 408 { 409 constexpr bool callCustomGetWindow = !(has_Window<Impl, const int>::value); 410 return get_window_helper<callCustomGetWindow, Impl, Ins...>::help(metas, in_args); 411 } 412 }; 413 } // namespace detail 414 415 416 template<class Impl, class K, bool UseScratch> 417 class GFluidKernelImpl : public cv::detail::KernelTag 418 { 419 static const int LPI = 1; 420 static const auto Kind = GFluidKernel::Kind::Filter; 421 using P = detail::FluidCallHelper<Impl, typename K::InArgs, typename K::OutArgs, UseScratch>; 422 423 public: 424 using API = K; 425 426 static GFluidKernel kernel() 427 { 428 // FIXME: call() and getOutMeta() needs to be renamed so it is clear these 429 // functions are internal wrappers, not user API 430 return GFluidKernel(Impl::Kind, Impl::LPI, 431 UseScratch, 432 &P::call, &P::init_scratch, &P::reset_scratch, &P::getBorder, &P::getWindow); 433 } 434 435 static cv::gapi::GBackend backend() { return cv::gapi::fluid::backend(); } 436 }; 437 438 #define GAPI_FLUID_KERNEL(Name, API, Scratch) struct Name: public cv::GFluidKernelImpl<Name, API, Scratch> 439 440 } // namespace cv 441 442 #endif // OPENCV_GAPI_GCPUKERNEL_HPP