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

OpenCV-Python bindings生成流程

通过上篇文章和opencv python模块中的CMakeLists.txt文件,可以了解到opencv-python bindings生成的整个流程:

  1. 生成headers.txt文件
    将每个模块的头文件添加到list中,通过一些关键词过滤掉一些不需要扩展的头文件,file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}")将过滤后的list写入文件;
    headers.txt保存需要转换的头文件路径,英文;隔开,注意文件末尾没有换行符

  2. 生成cv2.cpp中需要的头文件

    	set(cv2_generated_hdrs"${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h""${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_funcs.h""${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_types.h""${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_type_reg.h""${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_ns_reg.h")file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}")
    add_custom_command(OUTPUT ${cv2_generated_hdrs}COMMAND ${PYTHON_EXECUTABLE} "${PYTHON_SOURCE_DIR}/src2/gen2.py" ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt"DEPENDS ${PYTHON_SOURCE_DIR}/src2/gen2.pyDEPENDS ${PYTHON_SOURCE_DIR}/src2/hdr_parser.pyDEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txtDEPENDS ${opencv_hdrs})
    

    通过调用gen2.py来实现的,第一个参数是生成头文件后保存的路径,第二个参数是headers.txt文件路径

  3. 将cv2.cpp编译成动态库

OpenCV-Python bindings实践操作

纸上得来终觉浅,绝知此事要躬行。整个事情的来龙去脉都已经讲清楚,单到底怎么应用到自己的项目中呢。比如将自己图像检测功能实现完成,老大要求将它写成Web服务,毕竟B/S模式非常流程。C++写Web?开国际玩笑吧,现在python非常流行的天下。那么接下来看看怎么讲c++功能函数类转换成python的扩展库吧。

网上查查资料,还真有相关的blog:

  • How to convert your OpenCV C++ code into a Python module
  • github code https://github.com/spmallick/learnopencv/tree/master/pymodule

博客写的很好,但是提供的源码千般尝试始终报错,于是乎决定自己从CMakeLists.txt看起,从gen2.py脚本看起,慢慢查实。

mkdir ovex
cd ovex
mkdir src
cp ../opencv-3.1.0/modules/python/src2/{pycompat.hpp,cv2.cpp,gen2.py,hdr_parser.py} ./
cp ../learnopencv-master/pymodule/src/* src/
cp ../learnopencv-master/pymodule/headers.txt ./

准备使用opencv-3.1.0源码中的pycompat.hpp,cv2.cpp,gen2.py,hdr_parser.py文件,使用上面博客中的opencv c++源文件,慢慢来

gen2.py ./ headers.txt命令,第一步就报错了IOError: [Errno 2] No such file or directory: 'src/bvmodule.hpp\n'
看到文件名后面居然有个换行符,哎,拿到windows下删掉换行符。

去掉headers.txt中的换行符在去执行上面的命令,报出另外一个错误

Traceback (most recent call last):File "./gen2.py", line 943, in <module>generator.gen(srcfiles, dstdir)File "./gen2.py", line 855, in genself.code_include.write( '#include "{0}"\n'.format(hdr[hdr.rindex('opencv2/'):]) )
ValueError: substring not found

hdr.rindex('opencv2/')取头文件中opencv/的位置,hdr[hdr.rindex('opencv2/'):])取头文件中opencv/之后的所有字符串。看样子脚本是opencv定制,应用需要改动脚本某些地方,通过不断尝试,几经修改,终于大功告成。gen2.py ./ headers.txt命令在当前目录下生成pyopencv_generated_funcs.h pyopencv_generated_include.h pyopencv_generated_ns_reg.h pyopencv_generated_type_reg.h pyopencv_generated_types.h文件。gen2.py修改如下
gen2.py修改

调整博客提供的编译命令,编译动态库

g++ -shared -rdynamic -g -O3 -Wall -fPIC \
-I . -I../ -I/usr/local/python2.7.14/lib/python2.7/site-packages/numpy/core/include \
cv2.cpp src/bvmodule.cpp \
-DNDEBUG \
`PKG_CONFIG_PATH=/usr/local/opencv_with_contrib3.1.0/lib/pkgconfig pkg-config --cflags --libs opencv` \
`/usr/local/python2.7.14/bin/python2.7-config --includes --ldflags` \
-L`/usr/local/python2.7.14/bin/python2.7-config --exec-prefix`/lib \
-o bv.so

出错

cv2.cpp:124: 错误:‘Stitcher’未声明
cv2.cpp:124: 错误:expected initializer before ‘Status’
cv2.cpp:474: 错误:ISO C++ 不允许声明无类型的‘Status’
cv2.cpp:474: 错误:expected ‘,’ or ‘...’ before ‘&’ token
cv2.cpp:474: 错误:‘PyObject* pyopencv_from(int)’的模板标识符‘pyopencv_from<>’不匹配任何模板声明
cv2.cpp:1257: 警告:‘int convert_to_char(PyObject*, char*, const char*)’定义后未使用

类型未声明,用不到的话就删掉吧
在这里插入图片描述
再次执行编译命令,期待的so动态库在当前目录生成了。那就试他一试吧,

ovex]$ python2.7
Python 2.7.14 (default, Jul 25 2018, 13:52:02) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-23)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import bv
Traceback (most recent call last):File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initbv)

这个错误的出现不得不促使我去了解一下C/C++为python做扩展的整个流程,Extending and Embedding the Python Interpreter,注意python2与python3是有差异的。

很容易发现,模块需要一个对应初始化函数来初始化模块,比如PyInit_bv,那么在opencv中这个初始化函数在哪定义的呢?直接点在当前目录下执行grep -n --color=auto "cv2" -R *,在cv2.cpp中找到我们想要的函数了,接下来就是修改了
cv2.cpp修改
模块的名称是通过MODULESTR来定义的,python2以及python3中模块初始化函数的声明与定义。
再次编译成功通过,测试OK

$ python2.7
Python 2.7.14 (default, Jul 25 2018, 13:52:02) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-23)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import bv
>>> import numpy as np
>>> dir(bv)
['CV_16S', 'CV_16SC1', 'CV_16SC2', 'CV_16SC3', 'CV_16SC4', 'CV_16U', 'CV_16UC1', 'CV_16UC2', 'CV_16UC3', 'CV_16UC4', 'CV_32F', 'CV_32FC1', 'CV_32FC2', 'CV_32FC3', 'CV_32FC4', 'CV_32S', 'CV_32SC1', 'CV_32SC2', 'CV_32SC3', 'CV_32SC4', 'CV_64F', 'CV_64FC1', 'CV_64FC2', 'CV_64FC3', 'CV_64FC4', 'CV_8S', 'CV_8SC1', 'CV_8SC2', 'CV_8SC3', 'CV_8SC4', 'CV_8U', 'CV_8UC1', 'CV_8UC2', 'CV_8UC3', 'CV_8UC4', 'Filters', '__doc__', '__file__', '__name__', '__package__', '__version__', 'createTrackbar', 'error', 'fillHoles', 'setMouseCallback']
>>> import cv2
>>> img = cv2.imread("holes.jpg")
>>> bv.fillHoles(img)
>>> cv2.imwrite("filledHoles.jpg", img)
True
>>>

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

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

相关文章

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

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

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源和第三方库源管理配置本地…

NS2相关学习——创建Xgraph的输出文件

经过前面学习代码的编写&#xff0c;这一部分&#xff0c;我们要学会如何进行分析&#xff0c;一个很直观的方式就是将结果图形化表示出来。 ns-allinone包的一部分是“xgraph”&#xff0c;一个绘图程序&#xff0c;可用于创建模拟结果的图形表示。 在本节中&#xff0c;将向…

An Energy-Efficient Ant-Based Routing Algorithm for Wireless Sensor Networks (无线传感网中基于蚁群算法的能量有效路由)2

牙说&#xff1a;接着上一篇继续写。论文标题&#xff1a;An Energy-Efficient Ant-Based Routing Algorithm forWireless Sensor Networks作者&#xff1a;Tiago Camilo, Carlos Carreto, Jorge S Silva, Fernando Boavida正文&#xff1a; 2、相关工作可以考虑无线传感器网络…

NS2仿真分析无线网络的攻击防御(1)

这个学期有个选题是NS2仿真分析无线网络的攻击防御&#xff0c;比较有意思的样子&#xff0c;现在来慢慢学一下这个是什么东西。 首先&#xff0c;还是一篇文章&#xff08;老长老长了&#xff09;&#xff0c;还是全英文的&#xff0c;还是先来分析一下它到底在说什么&#x…

Java集合之HashMap源码分析

以下源码均为jdk1.7 HashMap概述 HashMap是基于哈希表的Map接口的非同步实现. 提供所有可选的映射操作, 并允许使用null值和null健. 此类不保证映射的顺序. 需要注意的是: HashMap不是同步的. 哈希表 哈希表定义: 哈希表是一种根据关键码去寻找值的数据映射结构, 该结构通…

NS2相关学习——可靠的MANET应用程序的Gossip协议分析

好久不写&#xff0c;应该努力啦&#xff01;老师把这篇论文给了我&#xff0c;现在还不知道它在讲什么&#xff0c;来边翻译边学习吧&#xff01; 文章链接&#xff1a;https://www.researchgate.net/publication/316844643_Analyzing_Gossip_Protocols_for_Reliable_MANET_Ap…

Java集合之LinkedList源码分析

概述 LinkedLIst和ArrayLIst一样, 都实现了List接口, 但其内部的数据结构不同, LinkedList是基于链表实现的(从名字也能看出来), 随机访问效率要比ArrayList差. 它的插入和删除操作比ArrayList更加高效, 但还是要遍历部分链表的指针才能移动到下标所指的位置, 只有在链表两头的…

lex和yacc环境配置

lex和yacc的使用很简单&#xff0c;但环境配置却是各种问题&#xff0c;本章说明lex和yacc在windows下的环境配置。 软件需求&#xff1a; 系统 win7-64位(win7-32, win8, win10全部通过) c编译器&#xff1a; vs2010(2008,2013,2015也全部通过) lex和yacc编译器&#xff1a…

Java集合之Vector源码分析

概述 Vector与ArrayLIst类似, 内部同样维护一个数组, Vector是线程安全的. 方法与ArrayList大体一致, 只是加上 synchronized 关键字, 保证线程安全, 下面就不具体分析源码了, 具体可以查看ArrayList中的源码分析. Vector源码分析 1.主要字段 2.构造函数 3.增删改查 其他方法…

Gossip协议的P2P会员管理

阅读此论文主要目的在于理解gossip协议及其背后的原理&#xff0c;此部分详细翻译&#xff0c;其余部分看时间 文章标题&#xff1a;Gossip协议的P2P会员管理 作者&#xff1a;Ayalvadi J. Ganesh, Anne-Marie Kermarrec, and Laurent Massoulie Abstract&#xff1a;基于…

Java集合之LinkedHashSet源码分析

概述 LinkedHashSet与HashSet类似, 不同的是LinkedHashSet底层使用LinkedHashMap维护元素插入的顺序. LinkedHashSet继承自HashSet, 只是重写了HashSet的构造方法, 初始化一个LinkedHashMap, 其他均与HashSet相同. LinkedHashSet构造方法 HashSet的构造方法: 以上几乎就是Li…

Java集合之ArrayList源码分析

概述 ArrayList可以理解为动态数组, 根据MSDN的说法, 就是Array的复杂版本. 与数组相比, 它的容量能动态增长. ArrayList是List接口的可变数组的实现. 实现了所有可选列表操作, 允许包括null在内的所有元素. 数组的特点, 查询快增删慢. 每个ArrayList实例都有一个容量, 该容…

Java集合之Hashtable源码分析

概述 Hashtable也是基于哈希表实现的, 与map相似, 不过Hashtable是线程安全的, Hashtable不允许 key或value为null. 成员变量 Hashtable的数据结构和HashMap一样, 采用 数组加链表的方式实现. 几个成员变量与HashMap一样: 方法 Hashtable的方法与HashMap基本一样, 只是 Ha…

视频质量检测中的TP、FP、Reacll、Precision

在看论文《Measuring Vedio QoE from Encrypted Traffic》的时候看到TP&#xff08;True Positives&#xff09;、FP&#xff08;False Positives&#xff09;、Precison、Recall的概念&#xff0c;这属于数据挖掘方面的内容&#xff0c;学习之后特来记录。 首先&#xff0c;下…

Java集合之LinkedHashMap源码分析

概述 HashMap是无序的, 即put的顺序与遍历顺序不保证一样. LinkedHashMap是HashMap的一个子类, 它通过重写父类的相关方法, 实现自己的功能. 它保留插入的顺序. 如果需要输出和输入顺序相同时, 就选用此类. LinkedHashMap原理 LinkedHashMap是如何保证输入输出顺序的呢? L…

Java集合之HashSet源码分析

概述 HashSet是基于HashMap来实现的, 底层采用HashMap的key来保存数据, 借此实现元素不重复, 因此HashSet的实现比较简单, 基本上的都是直接调用底层HashMap的相关方法来完成. HashSet的构造方法就是创建HashMap: 基本操作 1.添加操作 2.删除操作 3.迭代器 其他方法基本也是调…

三次握手wireshark抓包分析,成功握手和失败握手

转载之前&#xff1a;基于HTTP的视频流中&#xff0c;客户端有时会打开使用多条TCP与服务器连接&#xff0c;为了验证每一对话的sessionID是否相同&#xff0c;使用wireshark进行了抓包分析&#xff08;抓到的都是加密的包&#xff0c;无卵用orz....&#xff09;&#xff0c;这…

Java 内部类及其原理

Java中实现内部类 内部类相信大家都用过很多次了&#xff0c;就不说它是怎么用的了。 内部类 1.成员内部类 需要注意的是&#xff0c; 当成员内部类拥有和外部类同名的成员变量或这方法时&#xff0c; 默认情况下访问的是内部类的成员&#xff0c; 如要访问外部类的同名成员&…

Java8 Lambda表达式

概述 lambda表达式&#xff0c; 是Java8中的一个新特性。可以理解为一个匿名函数。 lambda表达式可以理解为将一个函数浓缩为一行代码&#xff0c;使代码更加简洁紧凑。 lambda表达式语法&#xff1a; (parameters) -> statement; 或 (parameters) -> {statements;} 参…