C/C++调用Python [OpenCV与Numpy]

C/C++调用Python [opencv与numpy]

目前的情况下,如果你有一个深度学习模型,很想在项目中使用,但模型是用python写的,项目使用的是C++,怎么办?直观的做法是从C++调用python解释器,本文遇到的情景是C++环境下有张图片,需要将其中一个区域(ROI)进行放大(超分辨率重建),放大算法是python环境下的函数(pytorch模型),之后在C++环境下进行后续处理,假设希望从C/C++端调用的python函数如下(暂不介绍超分辨率,用opencv的resize替代):

import cv2 as cv
def super_resolution(img, scale=4):
    height, width = img.shape[:2]
    dsize = (width*scale, height*scale)
    big_img = cv.resize(img, dsize)
    return big_img

先介绍环境配置,再讲从C/C++调用Python的关键操作。

1. 环境设置

以windows环境为例,开发时需要做好相关配置,我的环境:Windows10,VS2017 Community,Python3.6.4_x64,OpenCV3.4.1_x64。

OpenCV环境

官方文档

  1. Visual Studio配置包含目录(编译错),D:\Program Files\opencv3\build\include
  2. Visual Studio配置库目录(链接错),D:\Program Files\opencv3\build\x64\vc15\lib
  3. Visual Studio配置链接器输入(链接错):opencv_world341.lib
  4. 追加Path环境变量(运行错):Path=Path;D:\Program Files\opencv3\build\x64\vc15\bin,改完环境变量一定要重启Visual Studio才能生效。

下面的例子读取一张图片并显示。

//opencv_demo.cpp
#include<opencv/cv.hpp>
using namespace cv;

int main(int argc, char *argv[]){
   
    Mat img = imread("lena.jpg");
    imshow("lena", img);
    waitKey(0);
    destroyAllWindows();
    return 0;
}

Python环境

官方文档——Python和C相互调用

  1. Visual Studio配置包含目录(编译错):D:\Program Files\Python36\include
  2. Visual Studio配置库目录(链接错):D:\Program Files\Python36\libs
  3. 新增环境变量(运行错):PYTHONHOME=D:\Program Files\Python36,改完环境变量一定要重启Visual Studio才能生效。

下面的例子从C调用Python解释器,并执行Python代码,打印时间和日期。

//python_demo.cpp
// https://docs.python.org/3.6/extending/embedding.html#very-high-level-embedding
#include <Python.h> 

int main(int argc, char *argv[])
{
   
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    if (program == NULL) {
   
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    Py_SetProgramName(program);  /* optional but recommended */
    Py_Initialize();
    PyRun_SimpleString("from time import time,ctime\n"
                       "print('Today is', ctime(time()))\n");
    if (Py_FinalizeEx() < 0) {
   
        exit(120);
    }
    PyMem_RawFree(program);
    getchar();
    return 0;
}

Numpy环境

官方文档——如何利用Numpy的C API

numpy更多C API

  1. Visual Studio头文件目录(编译错):D:\Program Files\Python36\Lib\site-packages\numpy\core\include
  2. 关键代码(运行错):在Py_Initialize();之后必须调用import_array();以加载所有numpy函数(C API),与加载dll类似。

下面的例子展示用numpy接口实现矩阵计算矩阵乘法,并验证结果。

// numpy_demo.cpp 
#include <Python.h> 
#include <iostream>
#include <numpy/arrayobject.h>
using namespace std;

int main(int argc, char *argv[])
{
   
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    if (program == NULL) {
   
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    Py_SetProgramName(program);  /* optional but recommended */
    Py_Initialize();
    
    import_array();		/* load numpy api */
    double array_1[2][3] = {
    {
    2,5,6 },{
    5,6,5 } };
    npy_intp dims_1[] = {
    2, 3 };
    PyObject *mat_1 = PyArray_SimpleNewFromData(2, dims_1, NPY_DOUBLE, array_1);

    double array_2[3][4] = {
    {
    1,
  • 33
    点赞
  • 158
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
可以通过使用`ctypes`库来实现Python调用C++代码的功能。具体来说,您需要编写C++函数并将其编译为共享库(.so或.dll文件),然后使用`ctypes`库在Python中加载该库并调用该函数。 以下是一个简单的示例,演示如何使用`ctypes`库从Python调用C++函数,该函数使用OpenCV库并返回一个`np.array`类型的图像: C++代码(mylib.cpp): ```c++ #include <opencv2/opencv.hpp> extern "C" { void process_image(unsigned char* data, int width, int height, int channels, unsigned char* output) { cv::Mat img(height, width, CV_MAKETYPE(CV_8U, channels), data); cv::Mat out_img; cv::cvtColor(img, out_img, cv::COLOR_BGR2GRAY); out_img.copyTo(cv::Mat(height, width, CV_MAKETYPE(CV_8U, 1), output)); } } ``` Python代码: ```python import ctypes import numpy as np import cv2 # Load shared library lib = ctypes.cdll.LoadLibrary('./mylib.so') # Define function arguments and return type lib.process_image.argtypes = [ctypes.POINTER(ctypes.c_ubyte), ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_ubyte)] lib.process_image.restype = None # Load input image img = cv2.imread('input.png') data = np.frombuffer(img.tobytes(), dtype=np.uint8) width, height, channels = img.shape # Allocate output buffer out_data = np.zeros((height, width), dtype=np.uint8) # Call C++ function lib.process_image(data.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte)), width, height, channels, out_data.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))) # Convert output buffer to np.array out_img = np.frombuffer(out_data.tobytes(), dtype=np.uint8).reshape((height, width)) # Display output image cv2.imshow('Output', out_img) cv2.waitKey(0) ``` 在这个示例中,我们使用`ctypes`库加载了名为`mylib.so`的共享库,并定义了一个名为`process_image`的函数,该函数使用OpenCV库将输入图像转换为灰度图像,并将结果保存到输出缓冲区中。然后,我们从Python中加载输入图像,并为输出图像分配一个缓冲区。最后,我们调用C++函数,并将输入和输出数据指针传递给该函数。最后,我们将输出缓冲区转换为`np.array`类型,并在OpenCV窗口中显示结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值