如何将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项目中直接调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/973739.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新一代MPP数据库:StarRocks

文章目录 1.StarRocks简介2.StarRocks 在数据生态的定位3.StartRocks的使用场景3.1 实时数据仓库3.2 高并发查询3.3 日志与事件分析3.4 物联网&#xff08;IoT&#xff09;数据分析3.5 金融风控与实时监控3.6 数据湖查询加速3.7 A/B 测试与实验分析 4.StarRocks与MySQL比较4.1 …

利用 OpenCV 进行棋盘检测与透视变换

利用 OpenCV 进行棋盘检测与透视变换 1. 引言 在计算机视觉领域&#xff0c;棋盘检测与透视变换是一个常见的任务&#xff0c;广泛应用于 摄像机标定、文档扫描、增强现实&#xff08;AR&#xff09; 等场景。本篇文章将详细介绍如何使用 OpenCV 进行 棋盘检测&#xff0c;并…

kafka-保姆级配置说明(producer)

配置说明的最后一部分&#xff1b; ##指定kafka集群的列表&#xff0c;以“,”分割&#xff0c;格式&#xff1a;“host:port,host:port” ##此列表用于producer&#xff08;consumer&#xff09;初始化连接使用&#xff0c;server列表可以为kafka集群的子集 ##通过此servers列…

Windows 下 Ollama 安装deepseek本地模型

Windows 下 Ollama 安装deepseek本地模型 安装 Ollama 下载 Ollama 下载链接&#xff1a;https://ollama.org.cn/download/windows 下载完成后&#xff0c;按照提示进行安装。 安装过程 安装完成后&#xff0c;安装页面会自动关闭&#xff0c;这是正常现象。 接下来&#…

Java面试——Tomcat

优质博文&#xff1a;IT_BLOG_CN 一、Tomcat 顶层架构 Tomcat中最顶层的容器是Server&#xff0c;代表着整个服务器&#xff0c;从上图中可以看出&#xff0c;一个Server可以包含至少一个Service&#xff0c;用于具体提供服务。Service主要包含两个部分&#xff1a;Connector和…

MySql面试宝典【刷题系列】

文章目录 一、Mysql 的存储引擎 myisam 和 innodb 的区别。二、MySQL数据库作发布系统的存储&#xff0c;一天五万条以上的增量&#xff0c;预计运维三年,怎么优化&#xff1f;三、对于大流量的网站,您采用什么样的方法来解决各页面访问量统计问题&#xff1f;四、锁的优化策略…

图表控件Aspose.Diagram入门教程:使用 Python 将 VSDX 转换为 PDF

将VSDX转换为PDF可让用户轻松共享图表。PDF 文件保留原始文档的布局和设计。它们广泛用于演示文稿、报告和文档。在这篇博文中&#xff0c;我们将探讨如何在 Python 中将 VSDX 转换为 PDF。 本文涵盖以下主题&#xff1a; Python VSDX 到 PDF 转换器库使用 Python 将 VSDX 转…

【含开题报告+文档+PPT+源码】基于springboot加vue 前后端分离的校园新闻审核发布管理系统

开题报告 本研究旨在设计并实现一套基于SpringBoot后端框架结合Vue前端技术的校园新闻发布系统&#xff0c;该系统面向学生用户群体提供了全面的功能服务。学生用户通过身份验证登录后&#xff0c;能够便捷高效地获取校园内的各类新闻资讯&#xff0c;实时了解校内动态。系统不…

Spring BOOT 启动参数

Spring BOOT 启动参数 在Java Web的开发完成后&#xff0c;以前我们都会打包成war文件&#xff0c;然后放大web容器&#xff0c;比如tomcat、jetty这样的容器。现在基于SpringBoot开发的项目&#xff0c;我们直接打包成jar文件&#xff0c;基于内嵌的tomcat来实现一样的效果。…

探索无网用Deepseek+qwen来助力Solidworks二次开发

在本教程中&#xff0c;我们将详细介绍如何在本地环境中使用 DeepSeek 和 Qwen 模型&#xff0c;结合 AnythingLLM&#xff0c;构建一个用于 SolidWorks 二次开发的私有化智能知识库。 目录 前言 环境准备 2.1 安装 Ollama 2.2 安装 Docker Desktop DeepSeek 本地部署 3.1…

在nodejs中使用ElasticSearch(一)安装,使用

使用docker安装ElasticSearch和Kibana 1&#xff09;创建相应的data文件夹和子文件夹用来持久化ElasticSearch和kibana数据 2&#xff09;提前创建好elasticsearch配置文件 data/elasticsearch/config/elasticsearch.yml文件 # Elasticsearch Configuration # # NOTE: Elas…

Jenkins整合Jmeter实现接口自动化测试

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、安装jmeter 下载&#xff1a;http://jmeter.apache.org/download_jmeter.cgi 这里我用了一台Windows安装jmeter用来写接口测试的脚本&#xff0c;启动前修改j…

宇树科技13家核心零部件供应商梳理!

2025年2月6日&#xff0c;摩根士丹利&#xff08;Morgan Stanley&#xff09;发布最新人形机器人研报&#xff1a;Humanoid 100: Mapping the Humanoid Robot Value Chain&#xff08;人形机器人100&#xff1a;全球人形机器人产业链梳理&#xff09;。 Humanoid 100清单清单中…

PostgreSQL 与 MySQL 有哪些区别

PostgreSQL 和 MySQL 是两种流行的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它们在功能、性能、扩展性和适用场景等方面存在显著差异。 以下是 PostgreSQL 和 MySQL 的主要区别&#xff1a; 1. 架构与设计理念 PostgreSQL&#xff1a; 强调标准兼…

springboot整合 xxl-job

文章目录 一、xxl-job是什么二、使用步骤 1. 下载并运行管理端代码2. 访问管理页面&#xff0c;确认是否启动成功3. 配置执行器【在自己的springboot项目中配置】4. 在页面上创建执行器和任务&#xff0c;与项目中绑定 总结参考 一、xxl-job是什么 XXL-JOB 是一个分布式任务调…

conda、anaconda、pip、pytorch、tensorflow有什么区别?

先画一张图&#xff0c;可以大致看出它们的区别和关联&#xff1a; pytorch、tensorflow都是Python的第三方库&#xff0c;相当于封装的代码工具集库&#xff0c;通过import导入使用。这两个都是深度学习框架&#xff0c;用来搭建AI模型什么的&#xff0c;使用范围非常之广&…

java后端开发day18--学生管理系统

&#xff08;以下内容全部来自上述课程&#xff09; 1.业务分析并搭建主菜单 1.需求 采取控制台的方式去书写学生管理系统 2.分析 1.初始菜单 2.学生类 属性&#xff1a;id&#xff0c;姓名&#xff0c;年龄&#xff0c;家庭住址 3.添加功能 键盘录入每一个学生信息并添…

【设计模式精讲】结构型模式之代理模式(静态代理、JDK动态代理、cglib动态代理)

文章目录 第五章 结构型模式5.1 代理模式5.1.1 代理模式介绍5.1.2 代理模式原理5.1.3 静态代理实现5.1.4 JDK动态代理5.1.4.1 JDK动态代理实现5.1.4.2 类是如何动态生成的5.1.4.3 代理类的调用过程 5.1.5 cglib动态代理5.1.5.1 cglib动态代理实现5.1.5.2 cglib代理流程 5.1.6 代…

业务流程中的流程管理

流程管理是业务流程管理中至关重要的一环。它专注于规划、组织、指导、控制和优化组织内的各项业务流程&#xff0c;以提高效率、降低成本、提升质量和增强客户满意度。简单来说&#xff0c;流程管理就是管理你的业务是如何完成工作的。 下面将从几个方面详细讲解业务流程中的…

2025年股指期货和股指期权合约交割的通知!

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 2025年股指期货和股指期权合约交割的通知&#xff01; 根据中国金融期货交易所规则及相关规定&#xff0c;以下股指期货和股指期权合约于指定日期进行交割&#xff0c;现将各合…