python 调用c++(pybind11 +cv)

1. 编译 pybind11

不需要编译 pybind11

https://github.com/iago-suarez/ELSED.git工程为例

git clone https://github.com/iago-suarez/ELSED.git
mkdir build
cd build 
cmake ..

使用VS studio 打开工程进行编译

可能出现错误: M_PI 未定义 

解决: 

选择:项目——>”XXX属性"——>配置属性——>C/C++——>预处理器——>预处理器定义,将“_USE_MATH_DEFINES”添加进去

编译完成后生成:pyelsed.cp39-win_amd64.pyd  改名为 pyelsed.pyd

创建测试脚本:

import pyelsed
import cv2

img = cv2.imread('../../images/P1020829.jpg', cv2.IMREAD_GRAYSCALE)
segments, scores = pyelsed.detect(img)
print(segments, scores)

若报错:ImportError: DLL load failed while importing pyelsed:找不到指定的模块

需要把 编译pyd 时引用的 opencv 动态dll 放在同样路径下opencv_world420.dll


例子2: 只准备setup.py 和 example.cpp文件

setup.py 中需配置好python/ opencv/ pybind11库路径

setup.py
"""
build:
 python setup.py build_ext --inplace
install:
 python setup.py install 
"""
from setuptools import Extension
from setuptools import setup


__version__ = '0.0.1'

ext_module = Extension(
    name='example',
    sources=
    [
        r'example.cpp',
    ],
    include_dirs=
    [
        r'D:/Program Files/Python/Python39/include',
        r'D:/Program Files/Python/Python39/Lib/site-packages/numpy/core/include',
        r'D:/opencv_build/build64/install/include',
        r'D:/gitrep/pybind11/include'
    ],
    library_dirs=
    [
        r'D:/Program Files/Python/Python39/Lib/site-packages/numpy/core/lib',
        r'D:/opencv_build/build64/install/x64/vc14/lib'
    ],
    libraries=
    [
        'opencv_world420',
        'npymath'
    ],
    language='c++'
)

setup(
    name='example',
    version=__version__,
    author_email='xxxx@qq.com',
    description='A simaple demo',
    ext_modules=[ext_module],
    install_requires=['numpy']
)
example.cpp
 #include <pybind11/pybind11.h>  
#include <opencv2/opencv.hpp>  
  
namespace py = pybind11;  
  
int show_image(const std::string& path) {  
	cv::Mat img = cv::imread(path, cv::IMREAD_COLOR);  
	cv::imshow("x", img);
	cv::waitKey(1);
	return 1;
}  
  
PYBIND11_MODULE(example, m) {  
    m.def("show_image", &show_image, "Read an image from a file path");  
}

编译 example.pyd 

python setup.py build_ext --inplace

上面的例子扩展一下,加入 mat 参数

#include <pybind11/pybind11.h>  
#include <pybind11/numpy.h>
#include <opencv2/opencv.hpp>  
  
namespace py = pybind11;  
  
cv::Mat read_image(const std::string& path) {  
    return cv::imread(path, cv::IMREAD_COLOR);  
}  

int show_image(const std::string& path) {  
	cv::Mat img = cv::imread(path, cv::IMREAD_COLOR);  
	cv::imshow("x", img);
	cv::waitKey(1);
	return 1;
}  

int show(const py::array &py_img)
{
	py::buffer_info info = py_img.request();
        cv::Mat img(info.shape[0], info.shape[1], CV_8UC1, (uint8_t *) info.ptr);
	cv::imshow("x", img);
	cv::waitKey(1000);
	return 1;
}
  
PYBIND11_MODULE(example, m) {  
    m.def("show_image", &show_image, "Read an image from a file path");  
    m.def("show", &show, "show an image from a file path",py::arg("img"));  
}

重新编译 此时可调用 example.show(img) 函数

继续添加  输出 numpy的接口

#include <pybind11/pybind11.h>  
#include <pybind11/numpy.h>
#include <opencv2/opencv.hpp>  
  
namespace py = pybind11;  
/*
C++ Mat ->numpy
*/
py::array_t<unsigned char> cv_mat_uint8_1c_to_numpy(cv::Mat& input) {
    py::array_t<unsigned char> dst = py::array_t<unsigned char>({ input.rows,input.cols }, input.data);
    return dst;
}

py::array_t<unsigned char> cv_mat_uint8_3c_to_numpy(cv::Mat& input) {
    py::array_t<unsigned char> dst = py::array_t<unsigned char>({ input.rows,input.cols,3}, input.data);
    return dst;
}

//py::array_t<std::complex<float>> cv_mat_float_3c_to_numpy(cv::Mat& input) {
//    py::array_t<std::complex<float>> dst = py::array_t<std::complex<float>>({ input.rows,input.cols,3}, input.data);
//    return dst;
//}



py::array_t<float> mat_to_py(cv::Mat& input)
{
    py::buffer_info buffer(
        input.data,
        sizeof(float),
        py::format_descriptor<float>::format(),
        2,
        {input.rows, input.cols},
        { sizeof(float)* input.cols, sizeof(float)}
    );
    return py::array_t<float>(buffer);
}
  

// =============export module ================
py::array_t<unsigned char> read_image(const std::string& path)
{
	cv::Mat img = cv::imread(path, 0);  
	return cv_mat_uint8_1c_to_numpy(img); 
}

int show_image(const std::string& path) {  
	cv::Mat img = cv::imread(path, cv::IMREAD_COLOR);  
	cv::imshow("x", img);
	cv::waitKey(1);
	return 1;
}  

int show(const py::array &py_img)
{
	if (py_img.ndim() != 2)
        throw std::runtime_error("1-channel image must be 2 dims ");
	py::buffer_info info = py_img.request();
        cv::Mat img(info.shape[0], info.shape[1], CV_8UC1, (uint8_t *) info.ptr);
	cv::imshow("x", img);
	cv::waitKey(1000);
	return 1;
}
  
// =====binding=====
PYBIND11_MODULE(example, m) {  
    m.def("show_image", &show_image, "Read an image from a file path");  
    m.def("show", &show, "show an image from a file path",py::arg("img"));  
    m.def("readimg", &read_image, "read an img from file path");
}

添加 输出 python list 的接口

// test output py list
py::list getList()
{
	py::list out;
	for(int i=0;i<10;i++)
	{
	    out.append(i);
	}
	return out;
}

  // =====binding=====
PYBIND11_MODULE(example, m) {  
    m.def("getlist", &getList,"kkkk");
}

 

posted @   哈库拉  阅读(305)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示