c++调用python函数, cv::Mat类转ndarray

系统:Windows10

IDE:VS2019

 

本文讲解如何从C++调用python函数,且包含opencv。

比如我有一个python函数show_img,我想在C++调用它。py文件名为showimg.py。

import cv2

def show_img(img):
    cv2.namedWindow('img',0)
    cv2.imshow('img',img)
    cv2.waitKey(0)
    #...some process
    print(img.shape)
    print(img[:,:,0])
    return str(img.shape)

一、环境配置

配置release,因为没有debug版。

属性->通用属性->VC++目录->包含目录     添加:

D:\opencv\build\include\
C:\Users\TOMATO\AppData\Local\Programs\Python\Python38\include
C:\Users\TOMATO\AppData\Local\Programs\Python\Python38\Lib\site-packages\numpy\core\include

属性->通用属性->VC++目录->库目录     添加:

D:\opencv\build\x64\vc15\lib
C:\Users\TOMATO\AppData\Local\Programs\Python\Python38\libs
C:\Users\TOMATO\AppData\Local\Programs\Python\Python38\Lib\site-packages\numpy\core\lib

属性->通用属性->链接器->输入->附加依赖项    添加:

opencv_world420.lib
python38.lib
python3.lib
_tkinter.lib
npymath.lib

如果未使用opencv和python的默认安装路径,请换成自己的。

注意opencv版本。比如我之前报错qt.qpa.plugin: Could not find the Qt platform plugin "windows" in "":

但这并不是真的缺少qt插件。而是因为C++中的opencv和python中的版本不一样!将版本换成一致的即可。

二、主程序

#include <opencv2/opencv.hpp>
#include<iostream>
#include<string>
#include <Python.h>  
#include <numpy/arrayobject.h>


using namespace std;

int main() {
	Py_SetPythonHome(L"C:/Users/TOMATO/AppData/Local/Programs/Python/Python38");
	Py_Initialize();
	import_array();//千万不要忘
	PyRun_SimpleString("import sys");   
        PyRun_SimpleString("sys.path.append('C:/Users/TOMATO/AppData/Local/Programs/Python/Python38/Lib/site-packages')");
	PyRun_SimpleString("sys.path.append('./')");
	PyRun_SimpleString("import numpy as np");
	PyRun_SimpleString("import cv2");
        cv::Mat img = cv::imread("D:/projects/test_images/coins.jpg", -1);
	PyObject* pModule(0);
	pModule = PyImport_ImportModule("showimg");//myModel:Python文件名 
	PyObject* pDict = PyModule_GetDict(pModule);

	int m, n, c;
	m = img.rows;
	n = img.cols;
	c = img.channels();
	std::cout << m << std::endl << n << std::endl << c << std::endl;
	
	npy_intp Dims[3] = { m,	n, c };//图像维度信息
	PyObject* pyArray = PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE, img.data);
	PyObject* ArgArray = PyTuple_New(1);
	PyTuple_SetItem(ArgArray,0,pyArray);
	PyObject* pFunc = PyDict_GetItemString(pDict, "show_img");//函数名show_img
	PyObject* pValue=PyObject_CallObject(pFunc, ArgArray);
	char* re_val;
	PyArg_Parse(pValue, "s", &re_val);
	std::cout << "re_val=" << re_val << std::endl;
	Py_Finalize();

	cv::destroyAllWindows();
	return 0;
}

如码所示,所有py对象都是PyObject,非常省心。cv::Mat其实就是通过函数PyArray_SimpleNewFromData包装成了PyObject* pyArray。值得一提的是返回类型的转换,本文是字符转为C++的char*。若是int值,可用如下方式转换。

int re_val;
re_val = PyInt_AsLong(pValue)

若使用Anaconda,会出现错误:"Importing the numpy c-extensions failed."。使用pip重新安装包即可解决。

pip install --upgrade --force-reinstall numpy

opencv也不行,同理

pip install --upgrade --force-reinstall opencv-python

三、运行结果

把showimg.py文件放在工作目录下,运行程序。结果如下

可见我们从C++读入一张图片赋值到cv::Mat img,然后把img转换成PyObject* pyArray,传入python函数,实现了图像的显示,并取得了函数返回值,转成char* 打印出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值