利用pybind11实现python和C++图像之间的相互调用。将Mat类引入python中。 图像相互转换通过左值引用及智能指针实现。封装了类操作及8个函数(Mat和numpy相互转换) 以下所有实例都通过测试。欢迎交流
1.dll项目文件:制作py_opencv_module.pyd add.h add.cpp sub.h sub.cpp imageHeader.h NumpyMatConver.h NumpyMatConver.cpp 2.python中调用C++Mat图像 2.1.python文件夹结构 pybind11\test.py pybind11\py_opencv_module.pyd 2.2.用途: python中调用C++中Mat图形 2.3.说明: py::array_t<unsigned char> matToNumpy_Gray(cv::Mat& img); py::array_t<unsigned char> matToNumpy_Color(cv::Mat& img); 其实python调用C++ Mat仅需要以上两个函数 本动态库将Mat类引入python中,你可以调用4个numpy和Mat的相互转换。 3.C++调用python中numpy图像 3.1.文件夹结构 imageHeader.h testpybind11.h test.cpp testpybind11.cpp pyStudent.py testopencv.py 3.2.用途:C++中调用python中图像
//1.1.add.h #pragma once int add(int, int);
//1.2.add.cpp #include "add.h" int add(int i, int j) {return i + j; }
//1.3.sub.h #pragma once int sub(int, int);
//1.4.sub.cpp #include "sub.h" int sub(int x, int y) { return x - y; }
//1.5.imageHeader.h #pragma once #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/imgproc/types_c.h> #include <pybind11/pybind11.h> #include <pybind11/embed.h> #include <pybind11/numpy.h> #include<string> #include<iostream> using std::string; using std::cout; using std::endl; namespace py = pybind11; using namespace py::literals;
//1.6.NumpyMatConver.h #pragma once //$(ProjectName) #include <opencv2/opencv.hpp> #include<pybind11/pybind11.h> #include <pybind11/embed.h> #include <pybind11/numpy.h> #include "imageHeader.h" namespace py = pybind11; using namespace py::literals; //Python->C++ Mat cv::Mat numpyToMat_Gray(py::array_t<unsigned char>& img); cv::Mat numpyToMat_Color(py::array_t<unsigned char>& img); //C++ Mat ->numpy py::array_t<unsigned char> matToNumpy_Gray(cv::Mat& img); py::array_t<unsigned char> matToNumpy_Color(cv::Mat& img); py::array_t<unsigned char> getMat(const char* path, bool graymode = true); class NumpyMatConver{ public: //Python->C++ Mat cv::Mat numpyToMat_Gray(py::array_t<unsigned char>& img); cv::Mat numpyToMat_Color(py::array_t<unsigned char>& img); std::shared_ptr<cv::Mat> numpyToMatGray(py::array_t<unsigned char>& img); std::shared_ptr<cv::Mat> numpyToMatColor(py::array_t<unsigned char>& img); //C++ Mat ->numpy py::array_t<unsigned char> matToNumpy_Gray(cv::Mat& img); py::array_t<unsigned char> matToNumpy_Color(cv::Mat& img); py::array_t<unsigned char> matToNumpyGray(std::shared_ptr<cv::Mat> img); py::array_t<unsigned char> matToNumpyColor(std::shared_ptr<cv::Mat> img); };
//1.7.NumpyMatConver.cpp #include "NumpyMatConver.h" //Python->C++ Mat cv::Mat NumpyMatConver::numpyToMat_Gray(py::array_t<unsigned char>& img){ if (img.ndim() != 2) throw std::runtime_error("1-channel image must be 2 dims "); py::buffer_info buf = img.request(); cv::Mat mat(static_cast<int>(buf.shape[0]), static_cast<int>(buf.shape[1]), CV_8UC1, (unsigned char*)buf.ptr); return mat; //return numpyToMat_Gray(img);能编译警告不能正常工作 } cv::Mat NumpyMatConver::numpyToMat_Color(py::array_t<unsigned char>& img) { if (img.ndim() != 3) throw std::runtime_error("3-channel image must be 3 dims "); py::buffer_info buf = img.request(); cv::Mat mat(static_cast<int>(buf.shape[0]), static_cast<int>(buf.shape[1]), CV_8UC3, (unsigned char*)buf.ptr); return mat; } std::shared_ptr<cv::Mat> NumpyMatConver::numpyToMatGray(py::array_t<unsigned char>& img) { return std::make_shared<cv::Mat>(numpyToMat_Gray(img)); } std::shared_ptr<cv::Mat> NumpyMatConver::numpyToMatColor(py::array_t<unsigned char>& img) { return std::make_shared<cv::Mat>(numpyToMat_Color(img)); } //C++ Mat ->numpy py::array_t<unsigned char> NumpyMatConver::matToNumpy_Gray(cv::Mat& img) { return py::array_t<unsigned char>({ img.rows,img.cols }, img.data); } py::array_t<unsigned char> NumpyMatConver::matToNumpy_Color(cv::Mat& img) { return py::array_t<unsigned char>({ img.rows,img.cols,3 }, img.data); } py::array_t<unsigned char> NumpyMatConver::matToNumpyGray(std::shared_ptr<cv::Mat> img) { return matToNumpy_Gray(*img); } py::array_t<unsigned char> NumpyMatConver::matToNumpyColor(std::shared_ptr<cv::Mat> img) { return matToNumpy_Color(*img); } //===========================函数================================== cv::Mat numpyToMat_Gray(py::array_t<unsigned char>& img) { if (img.ndim() != 2) throw std::runtime_error("1-channel image must be 2 dims "); py::buffer_info buf = img.request(); cv::Mat mat(static_cast<int>(buf.shape[0]), static_cast<int>(buf.shape[1]), CV_8UC1, (unsigned char*)buf.ptr); return mat; } cv::Mat numpyToMat_Color(py::array_t<unsigned char>& img) { if (img.ndim() != 3) throw std::runtime_error("3-channel image must be 3 dims "); py::buffer_info buf = img.request(); cv::Mat mat(static_cast<int>(buf.shape[0]), static_cast<int>(buf.shape[1]), CV_8UC3, (unsigned char*)buf.ptr); return mat; } //C++ Mat ->numpy py::array_t<unsigned char> matToNumpy_Gray(cv::Mat& img) { return py::array_t<unsigned char>({ img.rows,img.cols }, img.data); } py::array_t<unsigned char> matToNumpy_Color(cv::Mat& img) { return py::array_t<unsigned char>({ img.rows,img.cols,3 }, img.data); } py::array_t<unsigned char> getMat(const char* path, bool graymode) { py::array_t<unsigned char> rst; int flag = graymode ? 0 : 1; cv::Mat mat = cv::imread(path, flag); if (graymode) rst = matToNumpy_Gray(mat); else rst = matToNumpy_Color(mat); return rst; }
//1.8.compile.bat ::将多个C++原文件打包成动态库供python调用 ::后缀为pyd,模块名要与pybind11中的模块名一致PYBIND11_MODULE(模块名, m) ::作者:tcy ::g++ ^ ::-O3 -Wall -static -shared -std=c++17 ^ ::-DMS_WIN64 -fPIC -I C:\pybind11-master\include ^ ::-I C:\ProgramData\Anaconda3\include ^ ::-L C:\ProgramData\Anaconda3\libs example1.cpp example.cpp ^ ::-o example.pyd -lPython38 以上代码无问题。 g++ ^ -O3 -Wall -static -shared -std=c++17 ^ -DMS_WIN64 -fPIC -I C:\pybind11-master\include ^ -I C:\opencv\build\include ^ -I C:\opencv\build\include\opencv2 ^ -L C:\opencv\build\include ^ -L C:\opencv\build\include\opencv2 ^ -I C:\ProgramData\Anaconda3\include ^ -L C:\opencv\build\x64\vc14\lib ^ -L C:\opencv\build\x64\vc15\lib ^ -L C:\ProgramData\Anaconda3\libs compile_py_opencv.cpp NumpyMatConver.cpp add.cpp sub.cpp ^ -o py_opencv_module.pyd -lPython38 以上代码有问题,欢迎高手解决。目前利用VS2017编译无问题
//1.9.compile_py_opencv.cpp #include "../test/imageHeader.h" #include "NumpyMatConver.h" #include "add.h" #include "sub.h" PYBIND11_MODULE(py_opencv_module, m) { m.doc() = "pybind11 python opencv convert"; m.def("numpyToMat_Gray", &numpyToMat_Gray); m.def("numpyToMat_Color", &numpyToMat_Color); m.def("matToNumpy_Gray", &matToNumpy_Gray); m.def("matToNumpy_Color", &matToNumpy_Color); m.def("add", &add, "add function"); m.def("sub", &sub, "sub function"); m.def("getMat", &getMat, "getMat function"); py::class_<cv::Mat, std::shared_ptr<cv::Mat>>(m, "Mat") .def(py::init<>()) .def(py::init<int, int, int>()) .def(py::init<const cv::Mat&>()) ; py::class_<NumpyMatConver>(m, "NumpyMatConver") .def(py::init<>()) //包装构造函数(py::init()无参构造) .def("numpyToMat_Gray", &NumpyMatConver::numpyToMat_Gray) .def("numpyToMat_Color", &NumpyMatConver::numpyToMat_Color) .def("matToNumpy_Gray", &NumpyMatConver::matToNumpy_Gray) .def("matToNumpy_Color", &NumpyMatConver::matToNumpy_Color) .def("numpyToMatGray", &NumpyMatConver::numpyToMatGray) .def("numpyToMatColor", &NumpyMatConver::numpyToMatColor) .def("matToNumpyGray", &NumpyMatConver::matToNumpyGray) .def("matToNumpyColor", &NumpyMatConver::matToNumpyColor); }
//2.1.pybind11/test.py # !/usr/bin/env python # -*- coding: utf-8 -*- import numpy as np import os,cv2,sys import pybind_11.py_opencv_module as obj if __name__=="__main__": pass print('ss',obj.add(2,3)) print('ss', obj.sub(2, 3)) color=r'C:\Users\Administrator\Desktop\Fastener\Resources\Pictures\girl.jpg' gray=r'C:\Users\Administrator\Desktop\Fastener\Resources\Pictures\image.jpg' color_img=cv2.imread(color) gray_img=cv2.imread(gray) #C++Mat转numpy m1 = obj.getMat(color,False) m2 = obj.getMat(gray,True) cv2.imshow("m1", m1) cv2.imshow("m2", m2) #测试函数: mat1=obj.numpyToMat_Color(color_img) img1 = obj.matToNumpy_Color(mat1) cv2.imshow("img1",img1) mat2 = obj.numpyToMat_Color(gray_img) img2 = obj.matToNumpy_Color(mat2) cv2.imshow("img2", img2) #测试类:普通函数 a = obj.NumpyMatConver() mat1 = a.numpyToMat_Color(color_img) img1 = a.matToNumpy_Color(mat1) cv2.imshow("img_1", img1) mat2 = a.numpyToMat_Color(gray_img) img2 = a.matToNumpy_Color(mat2) cv2.imshow("img_2", img2) # 测试类:智能指针 a = obj.NumpyMatConver() mat1 = a.numpyToMatColor(color_img) img1 = a.matToNumpyColor(mat1) cv2.imshow("img_p1", img1) mat2 = a.numpyToMat_Color(gray_img) img2 = a.matToNumpy_Color(mat2) cv2.imshow("img_p2", img2) cv2.waitKey()
3.1.testpybind11.h #pragma once #include "imageHeader.h" struct PythonInit { static inline bool py_status = false; static bool interpreter(); }; void imshow_cv(const cv::Mat& mat, const string& no = "Mat image"); void imshow_cv(const string& file, const string& no = "Mat image"); void print_py_dict(py::dict dict); void test_py_list(); void test_py_dict(); void test_pybind11(); void test_ReadPythonNumpy();
3.2.testpybind11.cpp #include "testpybind11.h" //python初始化: bool PythonInit::interpreter() { if (!py_status) { py::scoped_interpreter guard{};//python初始化 py_status = true; } return true; } void imshow_cv(const cv::Mat& mat, const string& no) { if (mat.empty())return; cv::namedWindow(no); cv::imshow(no, mat); cv::waitKey(); } void imshow_cv(const string& file, const string& no) { cv::Mat img = cv::imread(file); imshow_cv(img, no); } //Python对象作为参数 void test_py_list() { py::list lst = py::list(2); //构建list lst[0] = "Tom"; lst.insert(1, 2); //C++中函数 lst.attr("insert")(3, 4); //python中函数 lst.append(5); lst.attr("append")(6); //lst[2] = py::none(); //显示列表: py::print("1.lst=", lst); //['Tom', 2, <NULL>, 4, 5, 6] int i = 0; for (auto it = lst.begin(); it != lst.end(); ++it) { if (!it->ptr()) lst[i] = py::none(); //将list中NULL值改为None ++i; } py::print("2.lst=", lst); //['Tom', 2, None, 4, 5, 6] cout << endl; } void print_py_dict(py::dict dict) { /* Easily interact with Python types */ for (auto item : dict) std::cout << "key=" << std::string(py::str(item.first)) << ", " << "value=" << std::string(py::str(item.second)) << std::endl; } void test_py_dict() { auto d = py::dict("name"_a = "Tom", "age"_a = 42); py::print("1.dict d = ", d); d["city"] = "shanghai"; py::print("2.dict d = ", d); d.attr("clear")(); py::print("3.dict d = ", d); cout << endl; } void test_pybind11() { //调用python模块: py::module os = py::module::import("os"); py::print("1.current path=", os.attr("getcwd")()); //导入python main程序入口: py::object py_environment = py::module_::import("__main__").attr("__dict__"); cout << "2.py_environment exists=" << py_environment.is_none() << endl; py::print("3.environment=",py_environment); cout << endl << "1.exec=" << endl; py::exec( "print('Hello')\n" "print('world!');", py_environment); py::eval_file("testopencv.py", py_environment); auto img = py_environment["img"]; py::print("2.img.shape=",img.attr("shape")); py::object x = py::cast(1); py_environment["x"] = 1; py::print("3.x=",py_environment); int result = py::eval("x + 10", py_environment).cast<int>(); cout << "4.x+10="<<result << endl; } //===================================================== cv::Mat numpyToMat_Gray(py::array_t<unsigned char>& img) { if (img.ndim() != 2) throw std::runtime_error("1-channel image must be 2 dims "); py::buffer_info buf = img.request(); cv::Mat mat(static_cast<int>(buf.shape[0]), static_cast<int>(buf.shape[1]), CV_8UC1, (unsigned char*)buf.ptr); return mat; } cv::Mat numpyToMat_Color(py::array_t<unsigned char>& img) { if (img.ndim() != 3) throw std::runtime_error("3-channel image must be 3 dims "); py::buffer_info buf = img.request(); cv::Mat mat(static_cast<int>(buf.shape[0]), static_cast<int>(buf.shape[1]), CV_8UC3, (unsigned char*)buf.ptr); return mat; } //================================================ void test_ReadPythonNumpy() { const char* color = "C:\\Users\\Administrator\\Desktop\\PybindProject\\pictures\\girl.jpg"; const char* gray = "C:\\Users\\Administrator\\Desktop\\PybindProject\\pictures\\image.jpg"; py::module cv2 = py::module::import("cv2"); py::array_t<unsigned char> np_gray = cv2.attr("imread")(gray, 0); py::array_t<unsigned char> np_color = cv2.attr("imread")(color, 1); cv::Mat mat1 = numpyToMat_Gray(np_gray); cv::Mat mat2 = numpyToMat_Color(np_color); cv::imshow("gray", mat1); cv::imshow("color", mat2); cv::waitKey(); }
3.3.test.cpp #include <iostream> #include"imageHeader.h" #include"testpybind11.h" #include "../dll/NumpyMatConver.h" using namespace std; using namespace cv; //void test_mat() { // Mat mat_girl = imread("../pictures/girl.jpg"); // // auto PyOpenCVModule = py::module_::import("PyOpenCVModule"); // auto np_girl = PyOpenCVModule.attr("matToNumpy_Color")(mat_girl); // auto mat_img = py::cast<Mat>(PyOpenCVModule.attr("numpyToMat_Color")(np_girl)); // // imshow_cv(mat_img); //} int main() { py::scoped_interpreter guard{};//python初始化 //py::scoped_interpreter python;//等效上面 /*test_py_list(); test_py_dict(); test_pybind11();*/ //test_mat(); cout << "============================" << endl; test_ReadPythonNumpy(); }
3.4.pyStudent.py #!/usr/bin/env python3 # -*- coding: utf-8 -*- import numpy as np import pandas as pd #PyStudent.py #define function: def add(a,b): lst=[1,2,3] return a+b def foo(a,b): lst=[1,2,3] return a+b,lst def sortTuple(t:tuple): t=sorted(t) return t def sortList(lst:list): lst.sort() return lst def sortDict(d:dict): s=pd.Series([1,2,3],dtype=np.int64) arr=np.array([10,10,10],dtype=np.int64) arr=arr+np.array(s) lst=list(arr) names=['a1','a2','a3','a4'] d1=dict(zip(names,lst)) d1.update(d) return d1 def getNumpyArr(arr,n): return arr class Student: def __init__(self,name='Tom',age=22): self.name=name self.age=age def getAge(self): return self.age def setAge(self,age): self.age=age def add(self,x,lst): arr=np.array(lst,dtype=np.float64) arr=arr+x arr=arr.tolist() return arr if __name__ =="__main__": t=(1,2,3) lst=[1,2,3] d={'Tom':22,"Bob":30} print(add(2,3)) print(sortTuple(t)) print(sortList(lst)) print(sortDict(d)) a=Student() print(a.age,a.name) a.setAge(33) print(a.age,a.name) print(a.add(10,lst))
3.5.testopencv.py #!/usr/bin/env python3 # -*- coding: utf-8 -*- import cv2 path=r'..\pictures\girl.jpg' img=cv2.imread(path) cv2.imshow("sss",img) cv2.waitKey()
ref: (142条消息) Windows10 pybind11 opencv 和numpy相互转换 (tcy)_tcy23456的博客-CSDN博客 pybind11_tcy23456的博客-CSDN博客 标签:Mat,img,tcy,py,Windows10,opencv,array,include,cv From: https://www.cnblogs.com/lidabo/p/16621397.html