• Windows10 pybind11 opencv 和numpy相互转换 (tcy)


     
     
    利用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()
     
  • 相关阅读:
    听过闰年闰月,可你听过闰秒吗?
    在线学习的“后浪”:现代学习系统中的人工智能
    idea在service窗口中显示现有微服务启动类
    Intellij IDEA导入项目出现Cannot load settings from file错误
    HttpServletRequest的getRequestURL方法获取不到https协议请求问题
    新增gitignore无效的解决办法
    访问腾讯存储桶中的文件,跨域问题的解决
    线程池的创建方法推荐
    TreeMap在自定义排序时的坑
    vue.js功能学习
  • 原文地址:https://www.cnblogs.com/lidabo/p/16621397.html
Copyright © 2020-2023  润新知