python 调用c++程序 以及python调c++处理图像

  1. python调用c++程序,传入参数类型为基本数据类型
  2. python调用c++程序处理图像,需要传入图片信息

前言:

        由于c语言是最为接近底层的语言,所以运行速度相对于其他高级语言来说会比较快。使用python处理图像时可以考虑使用c处理图像来提升运行速度。但是我在网上学习c语言opencv的时候见到的大多是c++语言,老师给的示例代码也是c++的,c++和c比起来效率不会差太多,所以就直接用c++了。
        至于学习图像处理使用到的opencv的相关资料,c语言版本《学习opencv》,c++版本《opencv3编程入门》,这两本是我在搜索相关资料时找到的两本,网上也有相关的电子版书籍可以下载(无广告商,纯友情推荐,大佬可忽略不计)

python调用c++程序,传入参数为基本数据类型

        这一部分推荐看这位博主的,简单明了。讲的是python与c/c++程序的互相调用。链接:python与c/c++程序的互相调用
        使用博主里的例子时有一点需要注意,例子使用的python语法是python2,但现在一般使用的是python3,所以需要将 print '×××’修改为 print(“×××”)
        下面是python调用c++部分。

        Python调用C++程序时需要extern "C"来辅助,也就是说还是只能调用C函数,不能直接调用方法,但是能解析C++方法。extern "C"在这里的作用相当于给c++程序披了一层c程序的外衣(披了羊皮的狼)
        首先是c++程序,文件名为pycallclass.cpp

#include <iostream>  
using namespace std;  
class TestLib  {  
    public:  
        void display();  
        int display(int a);  
};  
void TestLib::display() {  
    cout<<"First display"<<endl;  
}  
int TestLib::display(int a) {  
    cout<<"Second display:"<<a<<endl; 
    return a+100;
}  
extern "C" {  
    TestLib obj;  
    void display() {  
        obj.display();   
    }  
    int display_int(int x) {  
        return obj.display(x);
    }  
}

然后是python程序,文件名为:pycallclass.py
ctypes这个库具体的可以去查一下,作用就是可以让python调用c++的动态库,也就是.so文件。

import ctypes  
so = ctypes.cdll.LoadLibrary   
lib = so("./pycallclass.so")   
print("display()")
lib.display()
print("display(200)") 
t = lib.display_int(200)
print(t)

这里c++程序和python程序处于同一文件目录下。
运行(在命令行运行):

g++ -o libpycallclass.so -shared -fPIC pycallclass.cpp//编译生成动态库文件
python3 pycallclass.py//运行.py文件
//运行结果:

在这里插入图片描述
c++示例里的函数也可以直接写在extern "C"中,如下:

#include <iostream>  
using namespace std;  

extern "C" { 
    void display() {  
          cout<<"First display"<<endl;
      }  
    int display_int(int x) {  
         cout<<"Second display:"<<x<<endl; 
         return x+100;
      }  
}

python调用c++程序处理图像,需要传入图片信息

        传入图像这块,编译c++的命令还和上面不一样(导致又气了很久),具体原因:处理图像需要用到opencv,使用opencv需要引入相关的函数,所以编译时需要加上相关的库,也就是下面示例编译时添加的-l内容,如果不想每次写那么多的话,可以使用CMakeList(但是我现在还不会),有关CMakeList的用法可以网上查(有好的链接可以拿出来分享一下,先行谢过啦,嘿嘿)
这部分主要是看的这位博主的链接 链接
c++程序如下,文件名为iden.cpp

#include <opencv2/opencv.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
class Mydisplay{
    public:
    void testplay(int height,int width,uchar* data);
};
void Mydisplay::testplay(int height,int width,uchar* data){
    Mat image(height,width,CV_8UC3);//将data转换为Mat类型,也就是C++中的图像存储类型
    uchar* pxvec = image.ptr<uchar>(0);
    //image.str可以得到图像任意行的首地址.例如uchar*data=image.ptr<uchar>(j),则它返回给uchar*data的值就是image的第j行的首地址
	
	//下面这一部分可以不考虑,这里主要是遍历一下
    int count = 0;
    for(int i=0;i<height;i++){
        pxvec = image.ptr<uchar>(i);
        for(int j=0;j<width;j++){
            for(int k=0;k<3;k++){
                cout<<(int)pxvec[i*3+j]<<" ";
                //这里需要转换为int型数据,否则输出的会是对应的ASCII码
                pxvec[j*3+k] = data[count];
                count++;
            }
            cout<<endl;
        }
        cout<<i<<" output end"<<height<<width<<endl;
    }


    cout<<"end"<<endl;
    return ;
}

extern "C"
{
    Mydisplay obj;
    void test(int height,int width,uchar* data){
        obj.testplay(height,width,data);
    }
}

python程序,文件名为:ien.py

import ctypes
import cv2
import numpy as np

img = cv2.imread('example.jpg')
h,w,c = img.shape
if c > 1:
    img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

img_data = np.asarray(img, dtype=np.uint8)
img_data = img_data.ctypes.data_as(ctypes.c_char_p)  
    
test_pyc = ctypes.cdll.LoadLibrary("./iden.so")
#test_pyc.test.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_ubyte))
#argtypes写明输入类型,例子中未使用
test_pyc.test.restype = ctypes.POINTER(ctypes.c_uint8)#restype写明返回类型
#ctypes.POINTER可以看下文的链接,里面有详细介绍
test_pyc.test(h,w,img_data)

运行(命令行上运行):

g++ -o iden.so -shared -fPIC iden.cpp -lopencv_core -lopencv_highgui -lopencv_imgcodecs
python3 ien.py
//运行结果如下:

在这里插入图片描述
ctypes.POINTER相关介绍:ctypes介绍

后记

学会一门编程语言之后学其它语言会轻松很多,但这不代表会毫无压力。就比如c++,在写这个的时候,改了一堆错误,比如将结构体里面的函数拿出来写时,需要函数名前面加 “结构体名::”,总之,如果不想深入学习,但是暂时需要使用的话,建议还是多看看示例,多仔细对比一下,不要想当然地大概略过,不然被气了半天之后会发现只是个语法问题,那滋味……

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值