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 Intel Corporation |
6 | |
7 | |
8 | #include "precomp.hpp" |
9 | |
10 | #include <ade/util/algorithm.hpp> |
11 | #include <opencv2/gapi/util/throw.hpp> |
12 | #include <opencv2/gapi/garg.hpp> |
13 | #include <opencv2/gapi/gproto.hpp> |
14 | |
15 | #include "api/gorigin.hpp" |
16 | #include "api/gproto_priv.hpp" |
17 | |
18 | // FIXME: it should be a visitor! |
19 | // FIXME: Reimplement with traits? |
20 | |
21 | const cv::GOrigin& cv::gimpl::proto::origin_of(const cv::GProtoArg &arg) |
22 | { |
23 | switch (arg.index()) |
24 | { |
25 | case cv::GProtoArg::index_of<cv::GMat>(): |
26 | return util::get<cv::GMat>(v: arg).priv(); |
27 | |
28 | case cv::GProtoArg::index_of<cv::GMatP>(): |
29 | return util::get<cv::GMatP>(v: arg).priv(); |
30 | |
31 | case cv::GProtoArg::index_of<cv::GFrame>(): |
32 | return util::get<cv::GFrame>(v: arg).priv(); |
33 | |
34 | case cv::GProtoArg::index_of<cv::GScalar>(): |
35 | return util::get<cv::GScalar>(v: arg).priv(); |
36 | |
37 | case cv::GProtoArg::index_of<cv::detail::GArrayU>(): |
38 | return util::get<cv::detail::GArrayU>(v: arg).priv(); |
39 | |
40 | case cv::GProtoArg::index_of<cv::detail::GOpaqueU>(): |
41 | return util::get<cv::detail::GOpaqueU>(v: arg).priv(); |
42 | |
43 | default: |
44 | util::throw_error(e: std::logic_error("Unsupported GProtoArg type" )); |
45 | } |
46 | } |
47 | |
48 | const cv::GOrigin& cv::gimpl::proto::origin_of(const cv::GArg &arg) |
49 | { |
50 | // Generic, but not very efficient implementation |
51 | // FIXME: Walking a thin line here!!! Here we rely that GArg and |
52 | // GProtoArg share the same object and this is true while objects |
53 | // are reference-counted, so return value is not a reference to a tmp. |
54 | return origin_of(arg: rewrap(arg)); |
55 | } |
56 | |
57 | bool cv::gimpl::proto::is_dynamic(const cv::GArg& arg) |
58 | { |
59 | // FIXME: refactor this method to be auto-generated from |
60 | // - GProtoArg variant parameter pack, and |
61 | // - traits over every type |
62 | switch (arg.kind) |
63 | { |
64 | case detail::ArgKind::GMAT: |
65 | case detail::ArgKind::GMATP: |
66 | case detail::ArgKind::GFRAME: |
67 | case detail::ArgKind::GSCALAR: |
68 | case detail::ArgKind::GARRAY: |
69 | case detail::ArgKind::GOPAQUE: |
70 | return true; |
71 | |
72 | default: |
73 | return false; |
74 | } |
75 | } |
76 | |
77 | cv::GRunArg cv::value_of(const cv::GOrigin &origin) |
78 | { |
79 | switch (origin.shape) |
80 | { |
81 | case GShape::GSCALAR: return GRunArg(util::get<cv::Scalar>(v: origin.value)); |
82 | case GShape::GARRAY: return GRunArg(util::get<cv::detail::VectorRef>(v: origin.value)); |
83 | case GShape::GMAT: return GRunArg(util::get<cv::Mat>(v: origin.value)); |
84 | default: util::throw_error(e: std::logic_error("Unsupported shape for constant" )); |
85 | } |
86 | } |
87 | |
88 | cv::GProtoArg cv::gimpl::proto::rewrap(const cv::GArg &arg) |
89 | { |
90 | // FIXME: replace with a more generic any->variant |
91 | // (or variant<T> -> variant<U>) conversion? |
92 | switch (arg.kind) |
93 | { |
94 | case detail::ArgKind::GMAT: return GProtoArg(arg.get<cv::GMat>()); |
95 | case detail::ArgKind::GMATP: return GProtoArg(arg.get<cv::GMatP>()); |
96 | case detail::ArgKind::GFRAME: return GProtoArg(arg.get<cv::GFrame>()); |
97 | case detail::ArgKind::GSCALAR: return GProtoArg(arg.get<cv::GScalar>()); |
98 | case detail::ArgKind::GARRAY: return GProtoArg(arg.get<cv::detail::GArrayU>()); |
99 | case detail::ArgKind::GOPAQUE: return GProtoArg(arg.get<cv::detail::GOpaqueU>()); |
100 | default: util::throw_error(e: std::logic_error("Unsupported GArg type" )); |
101 | } |
102 | } |
103 | |
104 | cv::GMetaArg cv::descr_of(const cv::GRunArg &arg) |
105 | { |
106 | switch (arg.index()) |
107 | { |
108 | case GRunArg::index_of<cv::Mat>(): |
109 | return cv::GMetaArg(cv::descr_of(mat: util::get<cv::Mat>(v: arg))); |
110 | |
111 | case GRunArg::index_of<cv::Scalar>(): |
112 | return cv::GMetaArg(descr_of(scalar: util::get<cv::Scalar>(v: arg))); |
113 | |
114 | case GRunArg::index_of<cv::detail::VectorRef>(): |
115 | return cv::GMetaArg(util::get<cv::detail::VectorRef>(v: arg).descr_of()); |
116 | |
117 | case GRunArg::index_of<cv::detail::OpaqueRef>(): |
118 | return cv::GMetaArg(util::get<cv::detail::OpaqueRef>(v: arg).descr_of()); |
119 | |
120 | case GRunArg::index_of<cv::gapi::wip::IStreamSource::Ptr>(): |
121 | return cv::util::get<cv::gapi::wip::IStreamSource::Ptr>(v: arg)->descr_of(); |
122 | |
123 | case GRunArg::index_of<cv::RMat>(): |
124 | return cv::GMetaArg(cv::util::get<cv::RMat>(v: arg).desc()); |
125 | |
126 | case GRunArg::index_of<cv::MediaFrame>(): |
127 | return cv::GMetaArg(cv::util::get<cv::MediaFrame>(v: arg).desc()); |
128 | |
129 | default: util::throw_error(e: std::logic_error("Unsupported GRunArg type" )); |
130 | } |
131 | } |
132 | |
133 | cv::GMetaArgs cv::descr_of(const cv::GRunArgs &args) |
134 | { |
135 | cv::GMetaArgs metas; |
136 | ade::util::transform(c: args, it: std::back_inserter(x&: metas), p: [](const cv::GRunArg &arg){ return descr_of(arg); }); |
137 | return metas; |
138 | } |
139 | |
140 | // FIXME: Is it tested for all types? |
141 | cv::GMetaArg cv::descr_of(const cv::GRunArgP &argp) |
142 | { |
143 | switch (argp.index()) |
144 | { |
145 | #if !defined(GAPI_STANDALONE) |
146 | case GRunArgP::index_of<cv::UMat*>(): return GMetaArg(cv::descr_of(mat: *util::get<cv::UMat*>(v: argp))); |
147 | #endif // !defined(GAPI_STANDALONE) |
148 | case GRunArgP::index_of<cv::Mat*>(): return GMetaArg(cv::descr_of(mat: *util::get<cv::Mat*>(v: argp))); |
149 | case GRunArgP::index_of<cv::Scalar*>(): return GMetaArg(descr_of(scalar: *util::get<cv::Scalar*>(v: argp))); |
150 | case GRunArgP::index_of<cv::MediaFrame*>(): return GMetaArg(descr_of(frame: *util::get<cv::MediaFrame*>(v: argp))); |
151 | case GRunArgP::index_of<cv::detail::VectorRef>(): return GMetaArg(util::get<cv::detail::VectorRef>(v: argp).descr_of()); |
152 | case GRunArgP::index_of<cv::detail::OpaqueRef>(): return GMetaArg(util::get<cv::detail::OpaqueRef>(v: argp).descr_of()); |
153 | default: util::throw_error(e: std::logic_error("Unsupported GRunArgP type" )); |
154 | } |
155 | } |
156 | |
157 | // FIXME: Is it tested for all types?? |
158 | bool cv::can_describe(const GMetaArg& meta, const GRunArgP& argp) |
159 | { |
160 | switch (argp.index()) |
161 | { |
162 | #if !defined(GAPI_STANDALONE) |
163 | case GRunArgP::index_of<cv::UMat*>(): return meta == GMetaArg(cv::descr_of(mat: *util::get<cv::UMat*>(v: argp))); |
164 | #endif // !defined(GAPI_STANDALONE) |
165 | case GRunArgP::index_of<cv::Mat*>(): return util::holds_alternative<GMatDesc>(v: meta) && |
166 | util::get<GMatDesc>(v: meta).canDescribe(mat: *util::get<cv::Mat*>(v: argp)); |
167 | case GRunArgP::index_of<cv::Scalar*>(): return meta == GMetaArg(cv::descr_of(scalar: *util::get<cv::Scalar*>(v: argp))); |
168 | case GRunArgP::index_of<cv::MediaFrame*>(): return meta == GMetaArg(cv::descr_of(frame: *util::get<cv::MediaFrame*>(v: argp))); |
169 | case GRunArgP::index_of<cv::detail::VectorRef>(): return meta == GMetaArg(util::get<cv::detail::VectorRef>(v: argp).descr_of()); |
170 | case GRunArgP::index_of<cv::detail::OpaqueRef>(): return meta == GMetaArg(util::get<cv::detail::OpaqueRef>(v: argp).descr_of()); |
171 | default: util::throw_error(e: std::logic_error("Unsupported GRunArgP type" )); |
172 | } |
173 | } |
174 | |
175 | // FIXME: Is it tested for all types?? |
176 | bool cv::can_describe(const GMetaArg& meta, const GRunArg& arg) |
177 | { |
178 | switch (arg.index()) |
179 | { |
180 | #if !defined(GAPI_STANDALONE) |
181 | case GRunArg::index_of<cv::UMat>(): return meta == cv::GMetaArg(descr_of(mat: util::get<cv::UMat>(v: arg))); |
182 | #endif // !defined(GAPI_STANDALONE) |
183 | case GRunArg::index_of<cv::Mat>(): return util::holds_alternative<GMatDesc>(v: meta) && |
184 | util::get<GMatDesc>(v: meta).canDescribe(mat: util::get<cv::Mat>(v: arg)); |
185 | case GRunArg::index_of<cv::Scalar>(): return meta == cv::GMetaArg(descr_of(scalar: util::get<cv::Scalar>(v: arg))); |
186 | case GRunArg::index_of<cv::detail::VectorRef>(): return meta == cv::GMetaArg(util::get<cv::detail::VectorRef>(v: arg).descr_of()); |
187 | case GRunArg::index_of<cv::detail::OpaqueRef>(): return meta == cv::GMetaArg(util::get<cv::detail::OpaqueRef>(v: arg).descr_of()); |
188 | case GRunArg::index_of<cv::gapi::wip::IStreamSource::Ptr>(): return util::holds_alternative<GMatDesc>(v: meta); // FIXME(?) may be not the best option |
189 | case GRunArg::index_of<cv::RMat>(): return util::holds_alternative<GMatDesc>(v: meta) && |
190 | util::get<GMatDesc>(v: meta).canDescribe(mat: cv::util::get<cv::RMat>(v: arg)); |
191 | case GRunArg::index_of<cv::MediaFrame>(): return meta == cv::GMetaArg(util::get<cv::MediaFrame>(v: arg).desc()); |
192 | default: util::throw_error(e: std::logic_error("Unsupported GRunArg type" )); |
193 | } |
194 | } |
195 | |
196 | bool cv::can_describe(const GMetaArgs &metas, const GRunArgs &args) |
197 | { |
198 | return metas.size() == args.size() && |
199 | std::equal(first1: metas.begin(), last1: metas.end(), first2: args.begin(), |
200 | binary_pred: [](const GMetaArg& meta, const GRunArg& arg) { |
201 | return can_describe(meta, arg); |
202 | }); |
203 | } |
204 | |
205 | void cv::gimpl::proto::validate_input_meta_arg(const cv::GMetaArg& meta) |
206 | { |
207 | switch (meta.index()) |
208 | { |
209 | case cv::GMetaArg::index_of<cv::GMatDesc>(): |
210 | { |
211 | cv::gimpl::proto::validate_input_meta(meta: cv::util::get<GMatDesc>(v: meta)); //may throw |
212 | break; |
213 | } |
214 | default: |
215 | break; |
216 | } |
217 | } |
218 | |
219 | void cv::gimpl::proto::validate_input_meta(const cv::GMatDesc& meta) |
220 | { |
221 | if (meta.dims.empty()) |
222 | { |
223 | if (!(meta.size.height > 0 && meta.size.width > 0)) |
224 | { |
225 | cv::util::throw_error |
226 | (e: std::logic_error( |
227 | "Image format is invalid. Size must contain positive values" |
228 | ", got width: " + std::to_string(val: meta.size.width ) + |
229 | (", height: " ) + std::to_string(val: meta.size.height))); |
230 | } |
231 | |
232 | if (!(meta.chan > 0)) |
233 | { |
234 | cv::util::throw_error |
235 | (e: std::logic_error( |
236 | "Image format is invalid. Channel mustn't be negative value, got channel: " + |
237 | std::to_string(val: meta.chan))); |
238 | } |
239 | } |
240 | |
241 | if (!(meta.depth >= 0)) |
242 | { |
243 | cv::util::throw_error |
244 | (e: std::logic_error( |
245 | "Image format is invalid. Depth must be positive value, got depth: " + |
246 | std::to_string(val: meta.depth))); |
247 | } |
248 | // All checks are ok |
249 | } |
250 | |
251 | // FIXME: Is it tested for all types? |
252 | // FIXME: Where does this validation happen?? |
253 | void cv::validate_input_arg(const GRunArg& arg) |
254 | { |
255 | // FIXME: It checks only Mat argument |
256 | switch (arg.index()) |
257 | { |
258 | #if !defined(GAPI_STANDALONE) |
259 | case GRunArg::index_of<cv::UMat>(): |
260 | { |
261 | const auto desc = cv::descr_of(mat: util::get<cv::UMat>(v: arg)); |
262 | cv::gimpl::proto::validate_input_meta(meta: desc); //may throw |
263 | break; |
264 | } |
265 | #endif // !defined(GAPI_STANDALONE) |
266 | case GRunArg::index_of<cv::Mat>(): |
267 | { |
268 | const auto desc = cv::descr_of(mat: util::get<cv::Mat>(v: arg)); |
269 | cv::gimpl::proto::validate_input_meta(meta: desc); //may throw |
270 | break; |
271 | } |
272 | default: |
273 | // No extra handling |
274 | break; |
275 | } |
276 | } |
277 | |
278 | void cv::validate_input_args(const GRunArgs& args) |
279 | { |
280 | for (const auto& arg : args) |
281 | { |
282 | validate_input_arg(arg); |
283 | } |
284 | } |
285 | |
286 | namespace cv { |
287 | std::ostream& operator<<(std::ostream& os, const cv::GMetaArg &arg) |
288 | { |
289 | // FIXME: Implement via variant visitor |
290 | switch (arg.index()) |
291 | { |
292 | case cv::GMetaArg::index_of<util::monostate>(): |
293 | os << "(unresolved)" ; |
294 | break; |
295 | |
296 | case cv::GMetaArg::index_of<cv::GMatDesc>(): |
297 | os << util::get<cv::GMatDesc>(v: arg); |
298 | break; |
299 | |
300 | case cv::GMetaArg::index_of<cv::GScalarDesc>(): |
301 | os << util::get<cv::GScalarDesc>(v: arg); |
302 | break; |
303 | |
304 | case cv::GMetaArg::index_of<cv::GArrayDesc>(): |
305 | os << util::get<cv::GArrayDesc>(v: arg); |
306 | break; |
307 | |
308 | case cv::GMetaArg::index_of<cv::GOpaqueDesc>(): |
309 | os << util::get<cv::GOpaqueDesc>(v: arg); |
310 | break; |
311 | |
312 | case cv::GMetaArg::index_of<cv::GFrameDesc>(): |
313 | os << util::get<cv::GFrameDesc>(v: arg); |
314 | break; |
315 | |
316 | default: |
317 | GAPI_Error("InternalError" ); |
318 | } |
319 | |
320 | return os; |
321 | } |
322 | } // namespace cv |
323 | |
324 | const void* cv::gimpl::proto::ptr(const GRunArgP &arg) |
325 | { |
326 | switch (arg.index()) |
327 | { |
328 | #if !defined(GAPI_STANDALONE) |
329 | case GRunArgP::index_of<cv::UMat*>(): |
330 | return static_cast<const void*>(cv::util::get<cv::UMat*>(v: arg)); |
331 | #endif |
332 | case GRunArgP::index_of<cv::Mat*>(): |
333 | return static_cast<const void*>(cv::util::get<cv::Mat*>(v: arg)); |
334 | case GRunArgP::index_of<cv::Scalar*>(): |
335 | return static_cast<const void*>(cv::util::get<cv::Scalar*>(v: arg)); |
336 | case GRunArgP::index_of<cv::RMat*>(): |
337 | return static_cast<const void*>(cv::util::get<cv::RMat*>(v: arg)); |
338 | case GRunArgP::index_of<cv::detail::VectorRef>(): |
339 | return cv::util::get<cv::detail::VectorRef>(v: arg).ptr(); |
340 | case GRunArgP::index_of<cv::detail::OpaqueRef>(): |
341 | return cv::util::get<cv::detail::OpaqueRef>(v: arg).ptr(); |
342 | case GRunArgP::index_of<cv::MediaFrame*>(): |
343 | return static_cast<const void*>(cv::util::get<cv::MediaFrame*>(v: arg)); |
344 | default: |
345 | util::throw_error(e: std::logic_error("Unknown GRunArgP type!" )); |
346 | } |
347 | } |
348 | |