如何将OpenCV 3映像从Python 3传递到C ++?用技术术语来说,如何将NumPy数组转换为cv::Mat
对象并返回?
为了使我的问题更具体,让我们假设:
我有一个使用OpenCV从网络摄像头捕获图像并将其显示的Python程序。 (在现实生活中,我正在为其中的其他功能制作原型,例如一些Web服务器功能。)
cam.py :
import cv2
def main():
cam = cv2.VideoCapture(0)
while True:
_, img = cam.read()
cv2.imshow('cam', img)
# TODO: Call the C++ function from the sample below
# img = helloWorld(img)
cv2.waitKey(16) # let imshow do its work (16 ms -> 60 FPS)
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
运行python3 cam.py
进行尝试。
我想使用某些C ++库中的现有helloWorld
函数来处理OpenCV图像。 (在现实生活中,它会进行一些信号处理并从图像中提取信息。)为简单起见,我下面的示例函数只是水平镜像图像。 main
函数可用来检查helloWorld
是否按预期工作。
cam.cpp :
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
void helloWorld(Mat img) {
flip(img, img, 1);
}
int main() {
VideoCapture stream1(0);
while (true) {
Mat img;
stream1.read(img);
helloWorld(img);
imshow("cam", img);
waitKey(16);
}
return 0;
}
要编译此代码,请运行g++ -std=c++11 -lopencv_core -lopencv_highgui -lopencv_videoio cam.cpp -o cam
,然后执行./cam
进行尝试。
现在我应该对代码进行哪些更改,以便可以从Python应用程序中调用helloWorld
C ++函数?幸运的是,我可以访问C ++源代码,因此可以在需要时进行扩展和重新编译。
答案 0 :(得分:2)
在这里,您必须进行进程间通信,因为您有同时运行的python进程和c ++进程,因此,要实现所需的功能,而不是在C ++程序中调用函数,只需从共享内存页面文件中读取即可在其中放置mat.data()并将其检索到C ++程序中的地方,只需确保在尝试访问共享内存区域之前就已创建该共享内存区域。
如果您真的想调用c ++函数,则可能需要考虑将C ++源函数/代码编译为dll,在运行时以python加载该dll,然后再调用该函数。
答案 1 :(得分:2)
有关创建模块的入门,请参见Artanis的要旨Python C Extension Hello World,该模块允许您从Python中调用C代码。
要在Python 3 NumPy数组和C ++ Mat之间进行转换,至少有2个地方可以找到示例C ++代码:
OpenCV存储库中的文件cv2.cpp包含函数that are not exposed in its API:
bool pyopencv_to(PyObject* o, UMat& um, const char* name)
和
PyObject* pyopencv_from(const Mat& m)
。
pyboostcvconverter提供了类似的独立转换器功能
PyObject* fromMatToNDArray(const Mat& m)
和Mat fromNDArrayToMat(PyObject* o)
。在调用任何make sure you call the NumPy function import_array()
之前,请在运行时避免Segmentation Fault: 11
。
我将它们全部放在code sample on GitHub中。 Python从相机获取图像,将其传递到C ++模块,然后C ++镜像该图像并将其传递回Python,最后Python显示该图像。