OpenCV-Python bindings是如何生成的(1)

翻译自How OpenCV-Python Bindings Works?

目标

学习

  • OpenCV-Python bindings是如何生成的
  • 如何为Python扩展新的opencv模块

OpenCV-Python bindings是如何生成的

在OpenCV里,所有算法都是用C++实现的。但是这些算法可以在别的语言里使用,比如Python,Java等。这就是通过bindings生成器实现的。这个生成器产生一个C++和Python之间的桥梁,让用户可以在Python里调用C++函数。要完整了解后台发生了什么,需要Python/C API的知识,在Python官方文档里有一个扩展C++的函数到Python里的简单例子。通过手工写包装函数的方法在OpenCV里把所有函数扩展到Python是个很费时的任务,所以OpenCV用了个更智能的办法。OpenCV用一些Python脚本从C++的头文件自动生成这些包装函数,这些脚本放在modules/python/src2。我们来看看他们做了什么。

首先,modules/python/CMakeFiles.txt是一个CMake脚本,用来检查要扩展到Python的模块。它会自动检查所有要扩展的模块,并抓取他们的头文件。这些头文件包含那个模块的所有类,函数,常量的列表等。

然后,这些头文件被传给Python脚本modules/python/src2/gen2.py。这就是那个Python bindings生成脚本。它会调用另外一个Python脚本modules/python/src2/hdr_parser.py。这是头文件语法分析器脚本。这个头文件语法分析器把整个头文件拆分成小的Python列表。这些列表包含所有特定函数和类的详细内容。比如,一个函数会被解析成一个包含函数名,返回类型,输入参数,参数类型等的列表。最后的列表会包含那个头文件里所有的函数,结构体,类等的详细信息。

但是头文件语法分析器并不解析头文件里所有的函数和类。开发人员得指定哪些函数是要导出到Python的。为此在这些声明开始添加了一些宏,好让头文件语法分析器能识别要解析的函数。这些宏是由要写特定函数的开发人员添加的。简单来说,开发人员来决定哪些函数要扩展到Python,而哪些不用。

头文件语法分析器会返回一个最后的解析了的函数的大列表。我们的生成器脚本(gen2.py)会为所有被分析器解析的 函数/类/枚举/结构体 创建包装函数(你可以在编译阶段在build/modules/python/目录找到类似于pyopencv_generated_*.h这样的头文件)。但是有些基础的OpenCV数据类型比如Mat, Vec4i, Size 需要手工扩展。比如,一个Mat类型应该被扩展成Numpy数组,Size应该被扩展成两个整数的元组等。类似的,有些复杂的 结构体/类/函数 需要被手工扩展。所有这种手工扩展函数都放在modules/python/src2/cv2.cpp。

现在唯一剩下的事情是编译这些包装文件成cv2模块。所以当你在Python里调用一个函数时,比如 res = equalizeHist(img1, img2)。你传入两个numpy数组,并希望输出另一个numpy数组。这些numpy数组被转换成了cv::Mat并在C++里调用equalizeHist()函数。最后的结果res被转换回Numpy数组。简单来说,就是几乎所有的运算都是在C++里完成的,这使执行速度也和C++里几乎一样。

这就是OpenCV-Python binding 如何产生的基本介绍。

如何在Python里扩展新的模块

头文件语法分析器基于一些添加在函数声明里的包装的宏来分析头文件。枚举常量不需要任何包装宏,他们是被自动包装的。但是剩下的函数和类需要包装宏。

函数使用CV_EXPORTS_W宏来扩展,下面是例子:

CV_EXPORTS_W void equalizeHist( InputArray src, OutputArray dst );

头文件语法分析器可以从关键字如 InputArray, OutputArray等理解输入和输出参数。但是有时候,我们可能需要硬编码输入和输出,这时就需要用到CV_OUT, CV_IN_OUT等宏。

CV_EXPORTS_W void minEnclosingCircle( InputArray points, CV_OUT Point2f& center, CV_OUT float& radius );

对大的类也用 CV_EXPORTS_W。要扩展类方法,可以用 CV_WRAP。类似的,CV_PROP用来扩展类字段。

class CV_EXPORTS_W CLAHE : public Algorithm
{
public:    CV_WRAP virtual void apply(InputArray src, OutputArray dst) = 0;    CV_WRAP virtual void setClipLimit(double clipLimit) = 0;    CV_WRAP virtual double getClipLimit() const = 0;
}

重载函数可以用CV_EXPORTS_AS来扩展。但是我们需要传入一个新名字,这样在Python里能够通过新名字调用函数。下面的例子,有三个函数,每个在Python里都带一个前缀。类似的CV_WRAP_AS可以被用来包装重载方法。

CV_EXPORTS_W void integral( InputArray src, OutputArray sum, int sdepth = -1 );
CV_EXPORTS_AS(integral2) void integral( InputArray src, OutputArray sum,OutputArray sqsum, int sdepth = -1, int sqdepth = -1 );
CV_EXPORTS_AS(integral3) void integral( InputArray src, OutputArray sum,OutputArray sqsum, OutputArray tilted,int sdepth = -1, int sqdepth = -1 );

小的类/结构体用CV_EXPORTS_W_SIMPLE来扩展。这些结构体通过传值的方式给C++函数。比如KeyPoint, Match等。他们的方法用CV_WRAP扩展,属性字段用CV_PROP_RW扩展。

class CV_EXPORTS_W_SIMPLE DMatch
{
public:    CV_WRAP DMatch();CV_WRAP DMatch(int _queryIdx, int _trainIdx, float _distance);    CV_WRAP DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance);CV_PROP_RW int queryIdx; // query descriptor indexCV_PROP_RW int trainIdx; // train descriptor indexCV_PROP_RW int imgIdx;   // train image indexCV_PROP_RW float distance;
};

一些其他的小类/结构体可以用CV_EXPORTS_W_MAP来导出,导出到Python的原生字典。Moments()就是这样一个例子:

class CV_EXPORTS_W_MAP Moments
{
public:    //! spatial moments    CV_PROP_RW double  m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;    //! central moments    CV_PROP_RW double  mu20, mu11, mu02, mu30, mu21, mu12, mu03;    //! central normalized momentsCV_PROP_RW double  nu20, nu11, nu02, nu30, nu21, nu12, nu03;
};

所以这些是OpenCV里主要的扩展宏,一般来说,开发人员得在合适的位置放上合适的宏。剩下的工作就由生成器脚本完成。有时候可能有意外情况生成器脚本没法创建包装器,这样的函数需要手工处理。但是大多数情况,用OpenCV编码指导写的代码应该就能被生成器脚本自动包装了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV-Python bindings是如何生成的(2)

OpenCV-Python bindings生成流程 通过上篇文章和opencv python模块中的CMakeLists.txt文件,可以了解到opencv-python bindings生成的整个流程: 生成headers.txt文件 将每个模块的头文件添加到list中,通过一些关键词过滤掉一些不需要扩展的头文件&#x…

【TensorFlow】学习资源汇总以及知识总结

官方资源 官方网站 https://tensorflow.org 非翻墙神器不能访问也(关键是我用了翻墙神器也没能访问)伪官方网站 https://tensorflow.google.cn/ 墙内的人可以查阅的资料github https://github.com/tensorflow/tensorflow官方提供的models以及tutorial h…

机器学习资源锦集

http://www.cnblogs.com/pinard 十年码农,对数学统计学,数据挖掘,机器学习,大数据平台,大数据平台应用开发,大数据可视化感兴趣。github 深度学习 【深度学习】批归一化(Batch Normalization&…

获取训练数据的方式

下载搜狗词库 https://pinyin.sogou.com/dict/ 在官网搜索相关的词库下载,比如地名等,然后使用脚本将此条转换成txt保存, 来源 # -*- coding: utf-8 -*- import os import sys import struct # 主要两部分 # 1.全局拼音表,貌似…

浅谈python MRO与Mixin模式

MRO(Method Resolution Order) In object-oriented programming languages with multiple inheritance, the diamond problem (sometimes referred to as the “deadly diamond of death”) is an ambiguity that arises when two classes B and C inherit from A, and class D…

CentOS7开发环境搭建(2)

关闭SELinux # 查看 $ getenforce Disabled $ sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: targeted Current mode: …

IntelliJ IDEA开发环境应用

安装 下载windows压缩包获取帮助: idea.medeming.com/jihuoma 常用设置 全局设置,对新建的工程生效 【File】【Other Settings】【Setings for New Projects…】 比如配置maven的路径以及配置文件的路径,基本设置一次即可,不需要每次新建工…

tcp状态机-三次握手-四次挥手以及常见面试题

TCP状态机介绍 在网络协议栈中,目前只有TCP提供了一种面向连接的可靠性数据传输。而可靠性,无非就是保证,我发给你的,你一定要收到。确保中间的通信过程中,不会丢失数据和乱序。在TCP保证可靠性数据传输的实现来看&am…

Visual studio Code的C/C++开发环境搭建

文章目录VS CodeC/C环境配置环境准备使用实例基于 VSCode 的远程开发平台环境准备参考VS Code Visual Studio Code(简称VS Code)是一个由微软开发,同时支持Windows 、 Linux和macOS等操作系统且开放源代码的代码编辑器,它支持测试…

Linux网络编程--文件描述符

文件描述符 在Unix和Unix-like操作系统中,文件描述符(file descriptor, FD)是一个文件或者像pipe或者network socket等之类的输入/输出源的唯一标识。 文件描述符通常是一个非负整数,负数通常代表无值或者错误。 文件描述符是POSIX API的一部分。每个除…

深信服 linux软件开发面试题整理

1、结构体可以进行比较 int memcmp ( const void * ptr1, const void * ptr2, size_t num ); Compare two blocks of memory Compares the first num bytes of the block of memory pointed by ptr1 to the first num bytes pointed by ptr2, returning zero if they all match…

大端小端模式判断以及数据转换

简介 在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)&#xff…

MSYS2下搭建Qt开发环境

最近随意浏览了一下俺们大省会城市的招聘信息,发现C招聘中涉及Qt经验的要求有不少,为了牛奶和面包,决心深入一下Qt开发。本篇文章由此而出。 Qt 关于Qt的人生经历在这不在累赘,资料随处可得,这里只记录干货。 环境搭…

CentOS7开发环境搭建(1)

文章目录BIOS开启VT支持U盘安装系统(2019-03-11)CentOS DNS配置CentOS网络配置配置静态IP克隆虚拟机网卡名称变更 CentOS6.5时间配置安装VMWare-tools用户管理 (2019-03-15 7.6.1810)给一般账号 root 权限Samba服务配置安装必备软件获取本机公网ipyum源和第三方库源管理配置本地…

ACM 欧拉公式

给出一个数X,求小于X的与X互质的数的个数,使用欧拉公式。 如果x1*x2*...*xnX,则个数nX*(1-1/x1)*(1-/x2)*... 使用这个的题目,超典型 相遇周期(HDOJ)

HDU 1495 非常可乐(BFS)

思路 最难在于想到这道题是BFS&#xff0c;想到之后只有六种情况就很好理解了。 代码 #include<stdio.h> #include<string.h> #include<math.h> #include<queue> using namespace std; int a,b,s; struct shui {int count;int ha,hb,hs; }t,t1; int m…

NBU计算机专业期末考试记录

考试科目&#xff1a;操作系统 软件工程 数据库 计算机网络 JAVA高级应用 汇编 计算机算法设计 操作系统&#xff1a;题目比较简单&#xff0c;这学期的大题有写读写互斥的代码、求平均磁道数、银行家算法、页面调度算法的缺页次数计算。期中考试有参考价值&#xff0c;要看懂…

蚁群算法的若干记录

1、蚁群算法的特点&#xff1a; ① 结合了分布式算法、正反馈机制、贪婪式搜索的算法&#xff1a;正反馈可以快速发现较优解、分布式算法避免早熟收敛、贪婪式搜索有助于早期找出可解决方案&#xff1b; ② 蚁群算法具有很强的并行性&#xff1b; ③ 个体之间通过信息素合作…

蚁群算法之二

1、蚂蚁系统模型的建立 给定G(V,A)&#xff0c;其中V为定点集&#xff0c;A为各顶点互相连接组成的边集,已知各顶点之间的连接距离&#xff0c;要求确定一条长度最短的回路&#xff0c;仅遍历一次所有顶点的回路。引入记号&#xff1a; m&#xff1a;蚁群中蚂蚁的数量&#x…

ns2相关学习——tcl脚本编写(1)

新建一个仿真实例&#xff1a; set ns [new Simulator]为了让nam文件和trace文件有地方可以依托&#xff0c;我们要打开.nam文件进行写入&#xff0c;并且使用句柄nf set nf [open out.nam w] $ns namtrace-all $nf设置拓扑图 1、设置节点的脚本语言&#xff1a;建了两个节点&…