当前位置: 首页 > article >正文

如何将Python函数打包成.so库?

将Python函数打包成.so库的基本流程

  1. 安装依赖

    • 安装Cython:pip install cython
    • 安装OpenCV的Python包和开发库:
      pip install opencv-python
      # Ubuntu系统安装OpenCV开发库
      sudo apt-get install libopencv-dev
      
  2. 编写Cython代码.pyx文件):

    • 使用cdefcpdef定义C/C++接口。
    • 处理Python对象与C/C++类型的转换。
  3. 配置setup.py

    • 使用Cython.Build.cythonize编译代码。
    • 指定头文件路径和链接库(如OpenCV)。
  4. 编译生成.so文件

    • 运行 python setup.py build_ext --inplace
  5. 测试生成的库

    • 在Python中导入.so文件并调用函数。

示例:图像亮度调整库(使用OpenCV)

目录结构
project/
├── imgproc.pyx    # Cython代码
├── setup.py       # 编译配置
└── test.py        # 测试脚本

1. Cython代码(imgproc.pyx
# distutils: language=c++
# cython: language_level=3

# 导入C++标准库和OpenCV
from libcpp.string cimport string
from libc.math cimport abs
cimport numpy as np
import numpy as np

# 导入OpenCV的C++接口
cdef extern from "opencv2/opencv.hpp" namespace "cv":
    cdef cppclass Mat:
        Mat()
        int rows, cols, channels()
        uchar* data

    Mat imread(const string& filename, int flags)
    b imwrite(const string& filename, const Mat& img)
    void cvtColor(Mat& src, Mat& dst, int code)

# Python接口函数
cpdef adjust_brightness(str input_path, str output_path, float alpha=1.0, int beta=0):
    cdef string c_input = input_path.encode('utf-8')
    cdef string c_output = output_path.encode('utf-8')
    
    # 读取图像
    cdef Mat image = imread(c_input, 1)  # 1表示彩色图
    if image.rows == 0:
        raise ValueError("无法读取图像文件: " + input_path)
    
    # 调整亮度/对比度:image = alpha * image + beta
    cdef Mat adjusted_image
    image.convertTo(adjusted_image, -1, alpha, beta)
    
    # 保存图像
    if not imwrite(c_output, adjusted_image):
        raise RuntimeError("保存图像失败: " + output_path)

2. 编译配置(setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
import numpy as np

# 配置OpenCV的头文件和库路径(根据系统实际路径调整)
opencv_inc = '/usr/local/include/opencv4'  # 常见路径
opencv_libdir = '/usr/local/lib'

extensions = [
    Extension(
        name="imgproc",
        sources=["imgproc.pyx"],
        language="c++",
        include_dirs=[np.get_include(), opencv_inc],
        libraries=["opencv_core", "opencv_highgui", "opencv_imgcodecs", "opencv_imgproc"],
        library_dirs=[opencv_libdir],
        extra_compile_args=["-std=c++11"],  # 启用C++11标准
    )
]

setup(ext_modules=cythonize(extensions, compiler_directives={'language_level' : "3"}))

3. 编译并测试
  1. 编译

    python setup.py build_ext --inplace
    

    生成 imgproc.cpython-xxx-linux-gnu.so

  2. 测试脚本(test.py

    import imgproc
    
    input_path = "input.jpg"
    output_path = "output.jpg"
    
    # 增加亮度(alpha=1.2,亮度增量beta=50)
    imgproc.adjust_brightness(input_path, output_path, alpha=1.2, beta=50)
    print("处理完成!")
    

常见问题与解决方案

1. 头文件找不到(fatal error: opencv2/opencv.hpp: No such file or directory
  • 原因:OpenCV开发头文件未安装或路径配置错误。
  • 解决
    # 安装OpenCV开发包
    sudo apt-get install libopencv-dev
    # 或手动指定头文件路径(修改setup.py中的opencv_inc)
    
2. 链接错误(undefined reference to cv::imread()
  • 原因:未正确链接OpenCV库(如缺少opencv_imgcodecs)。
  • 解决:检查setup.pylibraries是否包含所有依赖的OpenCV组件。
3. Python字符串到C++ string的转换错误
  • 现象:传入非字符串类型或编码错误。
  • 解决:在Cython中使用.encode('utf-8')显式转换字符串。
4. 图像保存失败(RuntimeError: 保存图像失败
  • 原因:输出路径无写入权限或格式不支持。
  • 解决:检查路径权限并使用OpenCV支持的格式(如.jpg/.png)。
5. 生成的.so文件无法导入
  • 原因:依赖的OpenCV动态库未找到。
  • 解决
    # 添加OpenCV库路径到LD_LIBRARY_PATH
    export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
    

高级优化:直接处理NumPy数组

如果需要直接传递NumPy数组(避免文件IO),需处理数据指针转换:

# 在imgproc.pyx中添加
cpdef adjust_brightness_np(np.ndarray img, float alpha=1.0, int beta=0):
    cdef Mat image
    cdef np.ndarray[np.uint8_t, ndim=3] img_bgr = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)  # 确保通道顺序
    image = Mat(img_bgr.shape[0], img_bgr.shape[1], CV_8UC3, <uchar*>img_bgr.data)
    # ...处理并返回numpy数组

注意:需处理OpenCV(BGR)与NumPy(RGB)的通道顺序差异。


通过上述步骤,你可以将Python图像处理函数高效地编译为.so库,并在其他Python项目中直接调用。


http://www.kler.cn/a/556135.html

相关文章:

  • [c++]--类和对象
  • GPT-4 它不仅仅是 ChatGPT 的升级版,更是人工智能的一次革命性突破!简单原理剖析
  • 从 Linux 权限管理历史看 sudo、SUID 和 Capability 的演进
  • netcore libreoffice word转pdf中文乱码
  • OnlyOffice:前端编辑器与后端API实现高效办公
  • new 一个构造函数的过程以及手写 new
  • 互推机制在开源AI智能名片2+1链动模式S2B2C商城小程序源码推广中的应用探索
  • spring boot知识点5
  • 【基础架构篇十一】《DeepSeek日志体系:ELK+Prometheus监控方案》
  • python: SQLAlchemy (ORM) Simple example using mysql in Ubuntu 24.04
  • django-vue-lyadmin---学习#
  • 如何通过Windows环境远程控制MusicGPT在线生成高质量AI音乐
  • 【文件夹合并——树链剖分,树状数组】
  • 分布式光伏运维云平台:智能化运维,助力光伏电站高效运行
  • 随机森林时间序列预测实现|随机森林在潮位数据预测中的应用
  • 【Linux-网络】HTTP的清风与HTTPS的密语
  • STM32MP157A单片机移植Linux驱动深入版
  • 矩阵-旋转图像
  • Oops! 更改field的数据类型,影响到rabbitmq消费了...(有关于Java序列化)
  • 探秘IP地址与MAC地址:网络世界的身份标识