利用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()

 

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐