DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
 
 
利用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()
 

 

posted on   DoubleLi  阅读(630)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2016-08-24 GCC 编译使用动态链接库和静态链接库
2015-08-24 区分execl与system——应用程序中执行命令
2015-08-24 CMOS Sensor的调试经验分享
2015-08-24 嵌入式ARM-Linux开发工具下载地址合集
2014-08-24 CentOS6使用第三方yum源安装更多rpm软件包
2014-08-24 linux下的软件包安装
2014-08-24 如何查询一个库文件属于哪个rpm包
点击右上角即可分享
微信分享提示