From 4dbb8ac4b24eb472a792480836044e31494da8b2 Mon Sep 17 00:00:00 2001 From: Dmitry Matveev Date: Sat, 26 Sep 2020 23:59:26 +0300 Subject: [PATCH] Merge pull request #18387 from dmatveev:dm/slides_upd_44 Update G-API slides to OpenCV 4.4 * G-API: Updated slides to v4.4 (+ sample) * Slight formatting changes + Python API page * Some more updates to slides: - Added more info on 4.2 and 4.4 versions - Added explanation on Operations and their functional wrappers --- modules/gapi/doc/slides/gapi_overview.org | 677 ++++++++++++++++++++-- modules/gapi/samples/slides_blur_gapi.cpp | 19 + 2 files changed, 639 insertions(+), 57 deletions(-) create mode 100644 modules/gapi/samples/slides_blur_gapi.cpp diff --git a/modules/gapi/doc/slides/gapi_overview.org b/modules/gapi/doc/slides/gapi_overview.org index f2bd39fa123e..676c914b6645 100644 --- a/modules/gapi/doc/slides/gapi_overview.org +++ b/modules/gapi/doc/slides/gapi_overview.org @@ -1,10 +1,10 @@ -#+TITLE: OpenCV 4.0 Graph API +#+TITLE: OpenCV 4.4 Graph API #+AUTHOR: Dmitry Matveev\newline Intel Corporation #+OPTIONS: H:2 toc:t num:t #+LATEX_CLASS: beamer #+LATEX_CLASS_OPTIONS: [presentation] #+LATEX_HEADER: \usepackage{transparent} \usepackage{listings} \usepackage{pgfplots} \usepackage{mtheme.sty/beamerthememetropolis} -#+LATEX_HEADER: \setbeamertemplate{frame footer}{OpenCV 4.0 G-API: Overview and programming by example} +#+LATEX_HEADER: \setbeamertemplate{frame footer}{OpenCV 4.4 G-API: Overview and programming by example} #+BEAMER_HEADER: \subtitle{Overview and programming by example} #+BEAMER_HEADER: \titlegraphic{ \vspace*{3cm}\hspace*{5cm} {\transparent{0.2}\includegraphics[height=\textheight]{ocv_logo.eps}}} #+COLUMNS: %45ITEM %10BEAMER_ENV(Env) %10BEAMER_ACT(Act) %4BEAMER_COL(Col) %8BEAMER_OPT(Opt) @@ -21,7 +21,7 @@ - OpenCV meets C++, ~cv::Mat~ replaces ~IplImage*~; -*** Version 3.0: -- Welcome Transparent API (T-API) +*** Version 3.0 -- Welcome Transparent API (T-API) - ~cv::UMat~ is introduced as a /transparent/ addition to ~cv::Mat~; @@ -32,7 +32,7 @@ ** OpenCV evolution in one slide (cont'd) # FIXME: Learn proper page-breaking! -*** Version 4.0: -- Welcome Graph API (G-API) +*** Version 4.0 -- Welcome Graph API (G-API) - A new separate module (not a full library rewrite); - A framework (or even a /meta/-framework); @@ -45,6 +45,24 @@ - Kernels can be written in unconstrained platform-native code; - Halide can serve as a backend (one of many). +** OpenCV evolution in one slide (cont'd) +# FIXME: Learn proper page-breaking! + +*** Version 4.2 -- New horizons + +- Introduced in-graph inference via OpenVINO™ Toolkit; +- Introduced video-oriented Streaming execution mode; +- Extended focus from individual image processing to the full + application pipeline optimization. + +*** Version 4.4 -- More on video + +- Introduced a notion of stateful kernels; + - The road to object tracking, background subtraction, etc. in the + graph; +- Added more video-oriented operations (feature detection, Optical + flow). + ** Why G-API? *** Why introduce a new execution model? @@ -80,7 +98,7 @@ - *Heterogeneity* gets extra benefits like: - Avoiding unnecessary data transfers; - Shadowing transfer costs with parallel host co-execution; - - Increasing system throughput with frame-level pipelining. + - Improving system throughput with frame-level pipelining. * Programming with G-API @@ -96,7 +114,34 @@ - What data objects are /inputs/ to the graph? - What are its /outputs/? -** A code is worth a thousand words +** The code is worth a thousand words + :PROPERTIES: + :BEAMER_opt: shrink=42 + :END: + +#+BEGIN_SRC C++ +#include // G-API framework header +#include // cv::gapi::blur() +#include // cv::imread/imwrite + +int main(int argc, char *argv[]) { + if (argc < 3) return 1; + + cv::GMat in; // Express the graph: + cv::GMat out = cv::gapi::blur(in, cv::Size(3,3)); // `out` is a result of `blur` of `in` + + cv::Mat in_mat = cv::imread(argv[1]); // Get the real data + cv::Mat out_mat; // Output buffer (may be empty) + + cv::GComputation(cv::GIn(in), cv::GOut(out)) // Declare a graph from `in` to `out` + .apply(cv::gin(in_mat), cv::gout(out_mat)); // ...and run it immediately + + cv::imwrite(argv[2], out_mat); // Save the result + return 0; +} +#+END_SRC + +** The code is worth a thousand words :PROPERTIES: :BEAMER_opt: shrink=42 :END: @@ -161,7 +206,7 @@ int main(int argc, char *argv[]) { } #+END_SRC -** A code is worth a thousand words (cont'd) +** The code is worth a thousand words (cont'd) # FIXME: sections!!! *** What we have just learned? @@ -183,59 +228,82 @@ cv::GComputation(cv::GIn(...), cv::GOut(...)) ** On data objects Graph *protocol* defines what arguments a computation was defined on - (both inputs and outputs), and what are the *shapes* (or types) of - those arguments: - - | *Shape* | *Argument* | Size | - |-------------+------------------+-----------------------------| - | ~GMat~ | ~Mat~ | Static; defined during | - | | | graph compilation | - |-------------+------------------+-----------------------------| - | ~GScalar~ | ~Scalar~ | 4 x ~double~ | - |-------------+------------------+-----------------------------| - | ~GArray~ | ~std::vector~ | Dynamic; defined in runtime | +(both inputs and outputs), and what are the *shapes* (or types) of +those arguments: + + | *Shape* | *Argument* | Size | + |--------------+------------------+-----------------------------| + | ~GMat~ | ~Mat~ | Static; defined during | + | | | graph compilation | + |--------------+------------------+-----------------------------| + | ~GScalar~ | ~Scalar~ | 4 x ~double~ | + |--------------+------------------+-----------------------------| + | ~GArray~ | ~std::vector~ | Dynamic; defined in runtime | + |--------------+------------------+-----------------------------| + | ~GOpaque~ | ~T~ | Static, ~sizeof(T)~ | ~GScalar~ may be value-initialized at construction time to allow expressions like ~GMat a = 2*(b + 1)~. -** Customization example +** On operations and kernels + :PROPERTIES: + :BEAMER_opt: shrink=22 + :END: + +*** :B_block:BMCOL: + :PROPERTIES: + :BEAMER_env: block + :BEAMER_col: 0.45 + :END: + +- Graphs are built with *Operations* over virtual *Data*; +- *Operations* define interfaces (literally); +- *Kernels* are implementations to *Operations* (like in OOP); +- An *Operation* is platform-agnostic, a *kernel* is not; +- *Kernels* are implemented for *Backends*, the latter provide + APIs to write kernels; +- Users can /add/ their *own* operations and kernels, + and also /redefine/ "standard" kernels their *own* way. -*** Tuning the execution +*** :B_block:BMCOL: + :PROPERTIES: + :BEAMER_env: block + :BEAMER_col: 0.45 + :END: -- Graph execution model is defined by kernels which are used; -- Kernels can be specified in graph compilation arguments: - #+LaTeX: {\footnotesize - #+BEGIN_SRC C++ - #include - #include - ... - auto pkg = gapi::combine(gapi::core::fluid::kernels(), - gapi::imgproc::fluid::kernels(), - cv::unite_policy::KEEP); - sobel.apply(in_mat, out_mat, compile_args(pkg)); - #+END_SRC - #+LaTeX: } -- OpenCL backend can be used in the same way; - #+LaTeX: {\footnotesize -- *NOTE*: ~cv::unite_policy~ has been removed in OpenCV 4.1.1. - #+LaTeX: } +#+BEGIN_SRC dot :file "000-ops-kernels.eps" :cmdline "-Kdot -Teps" +digraph G { +node [shape=box]; +rankdir=BT; -** Operations and Kernels +Gr [label="Graph"]; +Op [label="Operation\nA"]; +{rank=same +Impl1 [label="Kernel\nA:2"]; +Impl2 [label="Kernel\nA:1"]; +} -*** Specifying a kernel package +Op -> Gr [dir=back, label="'consists of'"]; +Impl1 -> Op []; +Impl2 -> Op [label="'is implemented by'"]; -- A *kernel* is an implementation of *operation* (= interface); -- A *kernel package* hosts kernels that G-API should use; -- Kernels are written for different *backends* and using their APIs; -- Two kernel packages can be *merged* into a single one; -- User can safely supply his *own kernels* to either /replace/ or - /augment/ the default package. - - Yes, even the standard kernels can be /overwritten/ by user from - the outside! -- *Heterogeneous* kernel package hosts kernels of different backends. +node [shape=note,style=dashed]; +{rank=same +Op; +CommentOp [label="Abstract:\ndeclared via\nG_API_OP()"]; +} +{rank=same +Comment1 [label="Platform:\ndefined with\nOpenCL backend"]; +Comment2 [label="Platform:\ndefined with\nOpenCV backend"]; +} -** Operations and Kernels (cont'd) -# FIXME!!! +CommentOp -> Op [constraint=false, style=dashed, arrowhead=none]; +Comment1 -> Impl1 [style=dashed, arrowhead=none]; +Comment2 -> Impl2 [style=dashed, arrowhead=none]; +} +#+END_SRC + +** On operations and kernels (cont'd) *** Defining an operation @@ -245,16 +313,43 @@ Graph *protocol* defines what arguments a computation was defined on - Metadata callback -- describe what is the output value format(s), given the input and arguments. - Use ~OpType::on(...)~ to use a new kernel ~OpType~ to construct graphs. + #+LaTeX: {\footnotesize #+BEGIN_SRC C++ -G_TYPED_KERNEL(GSqrt,,"org.opencv.core.math.sqrt") { +G_API_OP(GSqrt,,"org.opencv.core.math.sqrt") { static GMatDesc outMeta(GMatDesc in) { return in; } }; #+END_SRC #+LaTeX: } -** Operations and Kernels (cont'd) -# FIXME!!! +** On operations and kernels (cont'd) + +*** ~GSqrt~ vs. ~cv::gapi::sqrt()~ + +- How a *type* relates to a *functions* from the example? +- These functions are just wrappers over ~::on~: + #+LaTeX: {\scriptsize + #+BEGIN_SRC C++ + G_API_OP(GSqrt,,"org.opencv.core.math.sqrt") { + static GMatDesc outMeta(GMatDesc in) { return in; } + }; + GMat gapi::sqrt(const GMat& src) { return GSqrt::on(src); } + #+END_SRC + #+LaTeX: } +- Why -- Doxygen, default parameters, 1:n mapping: + #+LaTeX: {\scriptsize + #+BEGIN_SRC C++ + cv::GMat custom::unsharpMask(const cv::GMat &src, + const int sigma, + const float strength) { + cv::GMat blurred = cv::gapi::medianBlur(src, sigma); + cv::GMat laplacian = cv::gapi::Laplacian(blurred, CV_8U); + return (src - (laplacian * strength)); + } + #+END_SRC + #+LaTeX: } + +** On operations and kernels (cont'd) *** Implementing an operation @@ -297,6 +392,467 @@ G_TYPED_KERNEL(GSqrt,,"org.opencv.core.math.sqrt") { - Note ~run~ changes signature but still is derived from the operation signature. +** Operations and Kernels (cont'd) + +*** Specifying which kernels to use + +- Graph execution model is defined by kernels which are available/used; +- Kernels can be specified via the graph compilation arguments: + #+LaTeX: {\footnotesize + #+BEGIN_SRC C++ + #include + #include + ... + auto pkg = cv::gapi::combine(cv::gapi::core::fluid::kernels(), + cv::gapi::imgproc::fluid::kernels()); + sobel.apply(in_mat, out_mat, cv::compile_args(pkg)); + #+END_SRC + #+LaTeX: } +- Users can combine kernels of different backends and G-API will partition + the execution among those automatically. + +** Heterogeneity in G-API + :PROPERTIES: + :BEAMER_opt: shrink=35 + :END: +*** Automatic subgraph partitioning in G-API +*** :B_block:BMCOL: + :PROPERTIES: + :BEAMER_env: block + :BEAMER_col: 0.18 + :END: + +#+BEGIN_SRC dot :file "010-hetero-init.eps" :cmdline "-Kdot -Teps" +digraph G { +rankdir=TB; +ranksep=0.3; + +node [shape=box margin=0 height=0.25]; +A; B; C; + +node [shape=ellipse]; +GMat0; +GMat1; +GMat2; +GMat3; + +GMat0 -> A -> GMat1 -> B -> GMat2; +GMat2 -> C; +GMat0 -> C -> GMat3 + +subgraph cluster {style=invis; A; GMat1; B; GMat2; C}; +} +#+END_SRC + +The initial graph: operations are not resolved yet. + +*** :B_block:BMCOL: + :PROPERTIES: + :BEAMER_env: block + :BEAMER_col: 0.18 + :END: + +#+BEGIN_SRC dot :file "011-hetero-homo.eps" :cmdline "-Kdot -Teps" +digraph G { +rankdir=TB; +ranksep=0.3; + +node [shape=box margin=0 height=0.25]; +A; B; C; + +node [shape=ellipse]; +GMat0; +GMat1; +GMat2; +GMat3; + +GMat0 -> A -> GMat1 -> B -> GMat2; +GMat2 -> C; +GMat0 -> C -> GMat3 + +subgraph cluster {style=filled;color=azure2; A; GMat1; B; GMat2; C}; +} +#+END_SRC + +All operations are handled by the same backend. + +*** :B_block:BMCOL: + :PROPERTIES: + :BEAMER_env: block + :BEAMER_col: 0.18 + :END: + +#+BEGIN_SRC dot :file "012-hetero-a.eps" :cmdline "-Kdot -Teps" +digraph G { +rankdir=TB; +ranksep=0.3; + +node [shape=box margin=0 height=0.25]; +A; B; C; + +node [shape=ellipse]; +GMat0; +GMat1; +GMat2; +GMat3; + +GMat0 -> A -> GMat1 -> B -> GMat2; +GMat2 -> C; +GMat0 -> C -> GMat3 + +subgraph cluster_1 {style=filled;color=azure2; A; GMat1; B; } +subgraph cluster_2 {style=filled;color=ivory2; C}; +} +#+END_SRC + +~A~ & ~B~ are of backend ~1~, ~C~ is of backend ~2~. + +*** :B_block:BMCOL: + :PROPERTIES: + :BEAMER_env: block + :BEAMER_col: 0.18 + :END: + +#+BEGIN_SRC dot :file "013-hetero-b.eps" :cmdline "-Kdot -Teps" +digraph G { +rankdir=TB; +ranksep=0.3; + +node [shape=box margin=0 height=0.25]; +A; B; C; + +node [shape=ellipse]; +GMat0; +GMat1; +GMat2; +GMat3; + +GMat0 -> A -> GMat1 -> B -> GMat2; +GMat2 -> C; +GMat0 -> C -> GMat3 + +subgraph cluster_1 {style=filled;color=azure2; A}; +subgraph cluster_2 {style=filled;color=ivory2; B}; +subgraph cluster_3 {style=filled;color=azure2; C}; +} +#+END_SRC + +~A~ & ~C~ are of backend ~1~, ~B~ is of backend ~2~. + +** Heterogeneity in G-API + +*** Heterogeneity summary + +- G-API automatically partitions its graph in subgraphs (called "islands") + based on the available kernels; +- Adjacent kernels taken from the same backend are "fused" into the same + "island"; +- G-API implements a two-level execution model: + - Islands are executed at the top level by a G-API's *Executor*; + - Island internals are run at the bottom level by its *Backend*; +- G-API fully delegates the low-level execution and memory management to backends. + +* Inference and Streaming + +** Inference with G-API + +*** In-graph inference example + +- Starting with OpencV 4.2 (2019), G-API allows to integrate ~infer~ + operations into the graph: + #+LaTeX: {\scriptsize + #+BEGIN_SRC C++ + G_API_NET(ObjDetect, , "pdf.example.od"); + + cv::GMat in; + cv::GMat blob = cv::gapi::infer(bgr); + cv::GOpaque size = cv::gapi::streaming::size(bgr); + cv::GArray objs = cv::gapi::streaming::parseSSD(blob, size); + cv::GComputation pipelne(cv::GIn(in), cv::GOut(objs)); + #+END_SRC + #+LaTeX: } +- Starting with OpenCV 4.5 (2020), G-API will provide more streaming- + and NN-oriented operations out of the box. + +** Inference with G-API + +*** What is the difference? + +- ~ObjDetect~ is not an operation, ~cv::gapi::infer~ is; +- ~cv::gapi::infer~ is a *generic* operation, where ~T=ObjDetect~ describes + the calling convention: + - How many inputs the network consumes, + - How many outputs the network produces. +- Inference data types are ~GMat~ only: + - Representing an image, then preprocessed automatically; + - Representing a blob (n-dimensional ~Mat~), then passed as-is. +- Inference *backends* only need to implement a single generic operation ~infer~. + +** Inference with G-API + +*** But how does it run? + +- Since ~infer~ is an *Operation*, backends may provide *Kernels* implenting it; +- The only publicly available inference backend now is *OpenVINO™*: + - Brings its ~infer~ kernel atop of the Inference Engine; +- NN model data is passed through G-API compile arguments (like kernels); +- Every NN backend provides its own structure to configure the network (like + a kernel API). + +** Inference with G-API + +*** Passing OpenVINO™ parameters to G-API + +- ~ObjDetect~ example: + #+LaTeX: {\footnotesize + #+BEGIN_SRC C++ + auto face_net = cv::gapi::ie::Params { + face_xml_path, // path to the topology IR + face_bin_path, // path to the topology weights + face_device_string, // OpenVINO plugin (device) string + }; + auto networks = cv::gapi::networks(face_net); + pipeline.compile(.., cv::compile_args(..., networks)); + #+END_SRC + #+LaTeX: } +- ~AgeGender~ requires binding Op's outputs to NN layers: + #+LaTeX: {\footnotesize + #+BEGIN_SRC C++ + auto age_net = cv::gapi::ie::Params { + ... + }.cfgOutputLayers({"age_conv3", "prob"}); // array ! + #+END_SRC + #+LaTeX: } + +** Streaming with G-API + +#+BEGIN_SRC dot :file 020-fd-demo.eps :cmdline "-Kdot -Teps" +digraph { + rankdir=LR; + node [shape=box]; + + cap [label=Capture]; + dec [label=Decode]; + res [label=Resize]; + cnn [label=Infer]; + vis [label=Visualize]; + + cap -> dec; + dec -> res; + res -> cnn; + cnn -> vis; +} +#+END_SRC +Anatomy of a regular video analytics application + +** Streaming with G-API + +#+BEGIN_SRC dot :file 021-fd-serial.eps :cmdline "-Kdot -Teps" +digraph { + node [shape=box margin=0 width=0.3 height=0.4] + nodesep=0.2; + rankdir=LR; + + subgraph cluster0 { + colorscheme=blues9 + pp [label="..." shape=plaintext]; + v0 [label=V]; + label="Frame N-1"; + color=7; + } + + subgraph cluster1 { + colorscheme=blues9 + c1 [label=C]; + d1 [label=D]; + r1 [label=R]; + i1 [label=I]; + v1 [label=V]; + label="Frame N"; + color=6; + } + + subgraph cluster2 { + colorscheme=blues9 + c2 [label=C]; + nn [label="..." shape=plaintext]; + label="Frame N+1"; + color=5; + } + + c1 -> d1 -> r1 -> i1 -> v1; + + pp-> v0; + v0 -> c1 [style=invis]; + v1 -> c2 [style=invis]; + c2 -> nn; +} +#+END_SRC +Serial execution of the sample video analytics application + +** Streaming with G-API + :PROPERTIES: + :BEAMER_opt: shrink + :END: + +#+BEGIN_SRC dot :file 022-fd-pipelined.eps :cmdline "-Kdot -Teps" +digraph { + nodesep=0.2; + ranksep=0.2; + node [margin=0 width=0.4 height=0.2]; + node [shape=plaintext] + Camera [label="Camera:"]; + GPU [label="GPU:"]; + FPGA [label="FPGA:"]; + CPU [label="CPU:"]; + Time [label="Time:"]; + t6 [label="T6"]; + t7 [label="T7"]; + t8 [label="T8"]; + t9 [label="T9"]; + t10 [label="T10"]; + tnn [label="..."]; + + node [shape=box margin=0 width=0.4 height=0.4 colorscheme=blues9] + node [color=9] V3; + node [color=8] F4; V4; + node [color=7] DR5; F5; V5; + node [color=6] C6; DR6; F6; V6; + node [color=5] C7; DR7; F7; V7; + node [color=4] C8; DR8; F8; + node [color=3] C9; DR9; + node [color=2] C10; + + {rank=same; rankdir=LR; Camera C6 C7 C8 C9 C10} + Camera -> C6 -> C7 -> C8 -> C9 -> C10 [style=invis]; + + {rank=same; rankdir=LR; GPU DR5 DR6 DR7 DR8 DR9} + GPU -> DR5 -> DR6 -> DR7 -> DR8 -> DR9 [style=invis]; + + C6 -> DR5 [style=invis]; + C6 -> DR6 [constraint=false]; + C7 -> DR7 [constraint=false]; + C8 -> DR8 [constraint=false]; + C9 -> DR9 [constraint=false]; + + {rank=same; rankdir=LR; FPGA F4 F5 F6 F7 F8} + FPGA -> F4 -> F5 -> F6 -> F7 -> F8 [style=invis]; + + DR5 -> F4 [style=invis]; + DR5 -> F5 [constraint=false]; + DR6 -> F6 [constraint=false]; + DR7 -> F7 [constraint=false]; + DR8 -> F8 [constraint=false]; + + {rank=same; rankdir=LR; CPU V3 V4 V5 V6 V7} + CPU -> V3 -> V4 -> V5 -> V6 -> V7 [style=invis]; + + F4 -> V3 [style=invis]; + F4 -> V4 [constraint=false]; + F5 -> V5 [constraint=false]; + F6 -> V6 [constraint=false]; + F7 -> V7 [constraint=false]; + + {rank=same; rankdir=LR; Time t6 t7 t8 t9 t10 tnn} + Time -> t6 -> t7 -> t8 -> t9 -> t10 -> tnn [style=invis]; + + CPU -> Time [style=invis]; + V3 -> t6 [style=invis]; + V4 -> t7 [style=invis]; + V5 -> t8 [style=invis]; + V6 -> t9 [style=invis]; + V7 -> t10 [style=invis]; +} +#+END_SRC +Pipelined execution for the video analytics application + +** Streaming with G-API: Example + +**** Serial mode (4.0) :B_block:BMCOL: + :PROPERTIES: + :BEAMER_env: block + :BEAMER_col: 0.45 + :END: +#+LaTeX: {\tiny +#+BEGIN_SRC C++ +pipeline = cv::GComputation(...); + +cv::VideoCapture cap(input); +cv::Mat in_frame; +std::vector out_faces; + +while (cap.read(in_frame)) { + pipeline.apply(cv::gin(in_frame), + cv::gout(out_faces), + cv::compile_args(kernels, + networks)); + // Process results + ... +} +#+END_SRC +#+LaTeX: } + +**** Streaming mode (since 4.2) :B_block:BMCOL: + :PROPERTIES: + :BEAMER_env: block + :BEAMER_col: 0.45 + :END: +#+LaTeX: {\tiny +#+BEGIN_SRC C++ +pipeline = cv::GComputation(...); + +auto in_src = cv::gapi::wip::make_src + (input) +auto cc = pipeline.compileStreaming + (cv::compile_args(kernels, networks)) +cc.setSource(cv::gin(in_src)); +cc.start(); + +std::vector out_faces; +while (cc.pull(cv::gout(out_faces))) { + // Process results + ... +} +#+END_SRC +#+LaTeX: } + +**** More information + +#+LaTeX: {\footnotesize +https://opencv.org/hybrid-cv-dl-pipelines-with-opencv-4-4-g-api/ +#+LaTeX: } + +* Latest features +** Latest features +*** Python API + +- Initial Python3 binding is available now in ~master~ (future 4.5); +- Only basic CV functionality is supported (~core~ & ~imgproc~ namespaces, + selecting backends); +- Adding more programmability, inference, and streaming is next. + +** Latest features +*** Python API + +#+LaTeX: {\footnotesize +#+BEGIN_SRC Python +import numpy as np +import cv2 as cv + +sz = (1280, 720) +in1 = np.random.randint(0, 100, sz).astype(np.uint8) +in2 = np.random.randint(0, 100, sz).astype(np.uint8) + +g_in1 = cv.GMat() +g_in2 = cv.GMat() +g_out = cv.gapi.add(g_in1, g_in2) +gr = cv.GComputation(g_in1, g_in2, g_out) + +pkg = cv.gapi.core.fluid.kernels() +out = gr.apply(in1, in2, args=cv.compile_args(pkg)) +#+END_SRC +#+LaTeX: } + * Understanding the "G-Effect" ** Understanding the "G-Effect" @@ -384,15 +940,22 @@ speed-up on QVGA taken as 1.0). * Resources on G-API ** Resources on G-API - + :PROPERTIES: + :BEAMER_opt: shrink + :END: *** Repository - https://github.com/opencv/opencv (see ~modules/gapi~) -- Integral part of OpenCV starting version 4.0; + +*** Article + +- https://opencv.org/hybrid-cv-dl-pipelines-with-opencv-4-4-g-api/ *** Documentation -- https://docs.opencv.org/master/d0/d1e/gapi.html -- A tutorial and a class reference are there as well. +- https://docs.opencv.org/4.4.0/d0/d1e/gapi.html + +*** Tutorials +- https://docs.opencv.org/4.4.0/df/d7e/tutorial_table_of_content_gapi.html * Thank you! diff --git a/modules/gapi/samples/slides_blur_gapi.cpp b/modules/gapi/samples/slides_blur_gapi.cpp new file mode 100644 index 000000000000..53246205b710 --- /dev/null +++ b/modules/gapi/samples/slides_blur_gapi.cpp @@ -0,0 +1,19 @@ +#include // G-API framework header +#include // cv::gapi::blur() +#include // cv::imread/imwrite + +int main(int argc, char *argv[]) { + if (argc < 3) return 1; + + cv::GMat in; // Express the graph: + cv::GMat out = cv::gapi::blur(in, cv::Size(3,3)); // `out` is a result of `blur` of `in` + + cv::Mat in_mat = cv::imread(argv[1]); // Get the real data + cv::Mat out_mat; // Output buffer (may be empty) + + cv::GComputation(cv::GIn(in), cv::GOut(out)) // Declare a graph from `in` to `out` + .apply(cv::gin(in_mat), cv::gout(out_mat)); // ...and run it immediately + + cv::imwrite(argv[2], out_mat); // Save the result + return 0; +}