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");
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现