当前位置: 首页 > wzjs >正文

深圳网站建设那家好深圳app开发公司价格怎么算

深圳网站建设那家好,深圳app开发公司价格怎么算,wordpress 客户端登录,灯光照明网站建设操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 G-API 背后的核心理念是可移植性——使用 G-API 构建的流水线必须是可移植的(或者至少具备可移植的能力)。这意味着&…
  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

G-API 背后的核心理念是可移植性——使用 G-API 构建的流水线必须是可移植的(或者至少具备可移植的能力)。这意味着,当为新平台编译时,它要么可以直接运行,要么 G-API 提供必要的工具以确保其在该平台上运行,而算法本身几乎不需要修改。

这一理念通过将内核接口与其具体实现分离来实现。一旦使用内核接口构建了流水线,它就变得与实现无关——实现细节(即使用哪些内核)是在单独的阶段(图编译)中传递的。

内核-实现层次结构可能如下所示:
在这里插入图片描述
流水线表达与内核定义

一个流水线本身只能用诸如A、B等术语来表达,而选择使用哪种实现则成为一个外部参数。

定义一个内核

G-API 提供了一个宏 G_TYPED_KERNEL() 来定义一个新的内核接口:

#include <opencv2/gapi.hpp>
G_TYPED_KERNEL(GFilter2D,<cv::GMat(cv::GMat,int,cv::Mat,cv::Point,double,int,cv::Scalar)>,"org.opencv.imgproc.filters.filter2D")
{static cv::GMatDesc                 // outMeta's return value typeoutMeta(cv::GMatDesc    in       ,  // descriptor of input GMatint             ddepth   ,  // depth parametercv::Mat      /* coeffs */,  // (unused)cv::Point    /* anchor */,  // (unused)double       /* scale  */,  // (unused)int          /* border */,  // (unused)cv::Scalar   /* bvalue */ ) // (unused){return in.withDepth(ddepth);}
};

这个宏是定义新类型的一个快捷方式。它需要三个参数来注册一个新的类型,并且要求类型体必须存在(见下文)。宏的参数包括:

  • 内核接口名称 – 同时作为使用此宏定义的新类型的名称;
  • 内核签名 – 类似于 std::function<> 的签名,用于定义内核的API;
  • 内核的唯一名称 – 当系统中内核的类型信息被移除时用于识别内核。

内核声明可以看作函数声明——在这两种情况下,新实体都必须根据其定义的方式来使用。

内核签名定义了内核的使用语法——即在图构建期间它接受哪些参数。实现也可以使用这个签名将其转换为特定后端的回调签名(参见下一章)。

内核可以接受任何类型的值,而G-API动态类型(如cv::GMat)有特殊的处理方式。所有其他类型对G-API来说是不透明的,在outMeta()或执行回调中按原样传递。

内核的返回值 只能是G-API动态类型——即cv::GMat、cv::GScalar或cv::GArray。如果一个操作有多个输出,应该将其包装在一个std::tuple<>中(该元组只能包含上述提到的G-API类型)。不支持任意数量的输出操作。

一旦定义了一个内核,就可以在流水线中使用由G-API提供的特殊方法"::on()"。这种方法具有与内核定义相同的签名,因此这段代码:

cv::GMat in;
cv::GMat out = GFilter2D::on(/* GMat    */  in,/* int     */  -1,/* Mat     */  conv_kernel_mat,/* Point   */  cv::Point(-1,-1),/* double  */  0.,/* int     */  cv::BORDER_DEFAULT,/* Scalar  */  cv::Scalar(0));

是一个完全合法的构造方式。然而,这个例子有些冗长,因此通常内核声明会附带一个C++函数包装器(“工厂方法”),以启用可选参数、更紧凑的语法、Doxygen注释等:

cv::GMat filter2D(cv::GMat   in,int        ddepth,cv::Mat    k,cv::Point  anchor  = cv::Point(-1,-1),double     scale   = 0.,int        border  = cv::BORDER_DEFAULT,cv::Scalar bval    = cv::Scalar(0))
{return GFilter2D::on(in, ddepth, k, anchor, scale, border, bval);
}

因此,现在它可以像这样使用:

cv::GMat in;
cv::GMat out = filter2D(in, -1, conv_kernel_mat);

额外信息

在当前版本中,内核声明体(大括号内的所有内容)必须包含一个静态函数 outMeta()。此函数建立了操作输入和输出元数据之间的功能依赖关系。

元数据是关于内核操作的数据的信息。由于非G-API类型对G-API来说是不透明的,G-API只关心G* 数据描述符(例如cv::GMat的尺寸和格式等)。

outMeta()也是如何将内核签名转换为派生回调的一个例子——请注意,在这个例子中,outMeta()的签名严格遵循内核签名(在宏中定义),但有所不同——内核期望的是cv::GMat,而outMeta()接收并返回的是cv::GMatDesc(这是G-API结构体,用于cv::GMat的元数据)。

outMeta()的目的在于从输入到输出传播元数据信息,并推断内部(中间、临时)数据对象的元数据。这些信息对于进一步的流水线优化、内存分配以及G-API框架在图编译期间执行的其他操作是必需的。

实现一个内核

一旦内核被声明,其接口可以用于在不同的后端实现该内核的版本。这一概念自然地映射自面向对象编程中的“接口/实现”模式:一个接口可以被多次实现,并且内核的不同实现应该能够相互替换而不破坏算法(流水线)逻辑(里氏替换原则)。

每个后端定义了自己实现内核接口的方式。尽管如此,无论插件是什么,它的内核实现必须从内核接口类型“派生”。

然后,内核实现被组织成内核包。内核包作为编译参数传递给 cv::GComputation::compile(),并提供一些关于如何选择适当的内核的提示给G-API(更多内容见“异构性”[TBD])。

例如,前述的Filter2D在“参考”CPU(OpenCV)插件中这样实现(注意——这是一个简化形式,不正确的边界处理):

#include <opencv2/gapi/cpu/gcpukernel.hpp>     // GAPI_OCV_KERNEL()
#include <opencv2/imgproc.hpp>                 // cv::filter2D()
GAPI_OCV_KERNEL(GCPUFilter2D, GFilter2D)
{static voidrun(const cv::Mat    &in,       // in - derived from GMatconst int         ddepth,   // opaque (passed as-is)const cv::Mat    &k,        // opaque (passed as-is)const cv::Point  &anchor,   // opaque (passed as-is)const double      delta,    // opaque (passed as-is)const int         border,   // opaque (passed as-is)const cv::Scalar &,         // opaque (passed as-is)cv::Mat          &out)      // out - derived from GMat (retval){cv::filter2D(in, out, ddepth, k, anchor, delta, border);}
};

注意CPU(OpenCV)插件是如何转换原始内核签名的:

  • 输入 cv::GMat 被替换为 cv::Mat,后者持有底层OpenCV函数调用的实际输入数据;
  • 输出 cv::GMat 被转换为额外的输出参数,因此 GCPUFilter2D::run() 比原始内核签名多接受一个参数。

这里对内核开发者的基本直觉是不要关心 cv::Mat 对象是从哪里来的,而不是原来的 cv::GMat——只需遵循插件定义的签名约定。G-API将在执行期间调用此方法,并提供所有必要的信息(并将原始的不透明数据按原样转发)。

复合内核

有时,内核在API层面上是一个单一的事物。这对用户来说很方便,但在特定的实现层面,可能最好有多个内核(子图)来完成这个任务。一个例子是goodFeaturesToTrack()——虽然在OpenCV后端中它可以保持为一个单一的内核,但在Fluid中它变成了复合的——Fluid可以处理Harris响应计算,但不能执行稀疏非极大值抑制和点提取到STL向量:

复合内核的实现可以使用通用宏GAPI_COMPOUND_KERNEL()来定义:

#include <opencv2/gapi/gcompoundkernel.hpp>       // GAPI_COMPOUND_KERNEL()
using PointArray2f = cv::GArray<cv::Point2f>;
G_TYPED_KERNEL(HarrisCorners,<PointArray2f(cv::GMat,int,double,double,int,double)>,"org.opencv.imgproc.harris_corner")
{static cv::GArrayDesc outMeta(const cv::GMatDesc &,int,double,double,int,double){// No special metadata for arrays in G-API (yet)return cv::empty_array_desc();}
};
// Define Fluid-backend-local kernels which form GoodFeatures
G_TYPED_KERNEL(HarrisResponse,<cv::GMat(cv::GMat,double,int,double)>,"org.opencv.fluid.harris_response")
{static cv::GMatDesc outMeta(const cv::GMatDesc &in,double,int,double){return in.withType(CV_32F, 1);}
};
G_TYPED_KERNEL(ArrayNMS,<PointArray2f(cv::GMat,int,double)>,"org.opencv.cpu.nms_array")
{static cv::GArrayDesc outMeta(const cv::GMatDesc &,int,double){return cv::empty_array_desc();}
};
GAPI_COMPOUND_KERNEL(GFluidHarrisCorners, HarrisCorners)
{static PointArray2fexpand(cv::GMat in,int      maxCorners,double   quality,double   minDist,int      blockSize,double   k){cv::GMat response = HarrisResponse::on(in, quality, blockSize, k);return ArrayNMS::on(response, maxCorners, minDist);}
};
// Then implement HarrisResponse as Fluid kernel and NMSresponse
// as a generic (OpenCV) kernel

重要的是要区分复合内核与G-API的高阶函数,即一个看起来像内核但实际上生成子图的C++函数。核心区别在于,复合内核是实现细节,内核实现可以是复合的,也可以不是(取决于后端的能力),而高阶函数在G-API中相当于一种“宏”,因此不能充当一个需要由后端实现的接口。


文章转载自:

http://MlfFXQEd.tpkxs.cn
http://vq2KV3Ro.tpkxs.cn
http://wXaQmK4E.tpkxs.cn
http://Q5TYoYsS.tpkxs.cn
http://R95xheak.tpkxs.cn
http://7wvTN6nY.tpkxs.cn
http://kqsMFMrv.tpkxs.cn
http://YqdcR3uU.tpkxs.cn
http://9r7ijQlu.tpkxs.cn
http://D4VGBW4q.tpkxs.cn
http://4U0vNgcI.tpkxs.cn
http://lmVnTqQm.tpkxs.cn
http://w8k97IRh.tpkxs.cn
http://XT7c6jgN.tpkxs.cn
http://ClfGoBjc.tpkxs.cn
http://o5xFENzN.tpkxs.cn
http://d7QXHfCV.tpkxs.cn
http://kzR8do8y.tpkxs.cn
http://KBnrrPCJ.tpkxs.cn
http://y0IUCoqy.tpkxs.cn
http://LG8Ww0YV.tpkxs.cn
http://clcPr97f.tpkxs.cn
http://MbYAsdP7.tpkxs.cn
http://uhWQSALM.tpkxs.cn
http://08z2BqW9.tpkxs.cn
http://UIfFzByL.tpkxs.cn
http://E5DjzliD.tpkxs.cn
http://fTn9nnvy.tpkxs.cn
http://pe0g9X1s.tpkxs.cn
http://byuJo0pb.tpkxs.cn
http://www.dtcms.com/wzjs/712513.html

相关文章:

  • 深圳做外贸网站公司wordpress显示某一类文章
  • 免费解析素材网站小程序开发视频教程
  • 上海建筑网站建个大型网站要多少钱
  • 建筑设计网站国外网页美工设计的工作流程?
  • qq免费建网站建模培训机构排名
  • 湖州公司做网站wordpress ios 源码
  • 义乌水务建设集团官方网站做印刷网站公司哪家好
  • 注册免费微网站上海网页设计方法
  • 网站推广策划方案书做网站那些好
  • .net网站开发简介wordpress教程视频 下载
  • 互联网做网站属于什么行业莱西市建设局网站
  • 黄页网站介绍网站的扁平化设计理念
  • 那个网站做室内比较好的h5页面制作app
  • 天宁常州做网站江苏建设网站公司
  • 做外贸网站效果图服装网站建设的技术可行性
  • 做网站的报价方案软件开发工具与平台
  • 寺庙网站开发策划书企业做网站公司排名
  • 仙桃建设网站打折网站模板
  • 网站开发设计公司图文设计用什么软件
  • 社区网站建设论文百度seo培训班
  • 网站运营管理员具体做什么wordpress主题开发实例
  • 网站源码上传图片出错中国建设工程项目网
  • 永久免费网站建设整合营销传播的明显特征是
  • 宁波网站建设速成写作网站哪个最好
  • 申报课题所需的网站怎么做遵义会议在线
  • 手机网站自助建站系统中文wordpress教程
  • 德语网站制作提供商城网站建设
  • 网页入口网站推广别人给公司做的网站字体侵权吗
  • 天王手表官方网站网站建设在实际工作中的意义
  • 做网站实现登陆功能昆明app外包