You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C中嵌入Python:向Python函数传递二维像素列表的技术问询

实现C向嵌入的Python函数传递图像像素二维列表

既然你已经搞定了C调用Python的基础测试,那接下来传递图像像素的二维列表其实就是用Python C API手动构建嵌套列表的过程,我给你拆解成具体步骤,附完整代码示例:

1. 先明确Python端的函数定义

假设你的图像处理函数放在image_nn.py里,结构大概是这样(这里以灰度图像为例,每个像素是0-255的整数;如果是RGB就是每个元素是三元组,后面代码稍作调整即可):

# image_nn.py
def process_image_pixels(pixel_2d_list):
    # 这里是你的神经网络图像处理逻辑
    # 输入是[[0,128,255], [200,50,0], ...]这样的二维列表
    height = len(pixel_2d_list)
    width = len(pixel_2d_list[0]) if height > 0 else 0
    print(f"Received image: {height}x{width}")
    
    # 替换成你的实际处理逻辑,比如返回分类结果或者特征
    return f"Processed {height*width} pixels successfully"

2. C端代码实现(核心是构建二维列表)

C里要借助Python C API来创建list对象,先创建每一行的子列表,再把所有子列表添加到外层的二维列表中。下面是完整的可运行示例:

#include <Python.h>
#include <stdio.h>

// 假设我们有一张3x3的测试灰度图像
#define IMG_HEIGHT 3
#define IMG_WIDTH 3
unsigned char test_image[IMG_HEIGHT][IMG_WIDTH] = {
    {0, 128, 255},
    {200, 50, 100},
    {75, 150, 20}
};

int main() {
    // 1. 初始化Python解释器
    Py_Initialize();
    if (!Py_IsInitialized()) {
        printf("Failed to initialize Python\n");
        return 1;
    }

    // 2. 添加当前路径到Python模块搜索路径(确保能找到image_nn.py)
    PyObject* sys_path = PySys_GetObject((char*)"path");
    PyObject* current_dir = PyUnicode_FromString(".");
    PyList_Append(sys_path, current_dir);
    Py_DECREF(current_dir); // 手动释放引用

    // 3. 导入image_nn模块
    PyObject* module = PyImport_ImportModule("image_nn");
    if (!module) {
        PyErr_Print();
        Py_Finalize();
        return 1;
    }

    // 4. 获取process_image_pixels函数对象
    PyObject* func = PyObject_GetAttrString(module, "process_image_pixels");
    if (!func || !PyCallable_Check(func)) {
        printf("Failed to get callable function\n");
        PyErr_Print();
        Py_DECREF(module);
        Py_Finalize();
        return 1;
    }

    // 5. 构建二维列表(核心步骤)
    PyObject* pixel_2d_list = PyList_New(IMG_HEIGHT);
    if (!pixel_2d_list) {
        PyErr_Print();
        goto cleanup;
    }

    for (int i = 0; i < IMG_HEIGHT; i++) {
        // 创建当前行的子列表
        PyObject* row_list = PyList_New(IMG_WIDTH);
        if (!row_list) {
            PyErr_Print();
            goto cleanup;
        }

        for (int j = 0; j < IMG_WIDTH; j++) {
            // 把C的unsigned char转换成Python的int对象
            PyObject* pixel_val = PyLong_FromLong((long)test_image[i][j]);
            if (!pixel_val) {
                PyErr_Print();
                Py_DECREF(row_list);
                goto cleanup;
            }
            // 将像素值添加到行列表中(PyList_SetItem会接管引用,无需手动释放)
            PyList_SetItem(row_list, j, pixel_val);
        }

        // 将行列表添加到二维列表中(同样接管引用)
        PyList_SetItem(pixel_2d_list, i, row_list);
    }

    // 6. 调用Python函数,传递二维列表参数
    PyObject* args = PyTuple_New(1);
    PyTuple_SetItem(args, 0, pixel_2d_list); // 接管二维列表的引用
    PyObject* result = PyObject_CallObject(func, args);

    if (result) {
        // 处理返回结果,转换成C字符串打印
        char* result_str = PyUnicode_AsUTF8(result);
        printf("Python function returned: %s\n", result_str);
        Py_DECREF(result);
    } else {
        PyErr_Print();
    }

    // 清理资源
cleanup:
    Py_DECREF(args);
    Py_DECREF(func);
    Py_DECREF(module);
    Py_Finalize();
    return 0;
}

3. 编译与运行注意事项

  • 编译时要链接Python的库,比如在Linux下:
    gcc -o c_py_image c_py_image.c $(python3-config --cflags --ldflags)
    
  • 确保image_nn.py和编译后的可执行文件在同一目录下
  • 如果是RGB图像,每个像素是三元组,只需在行列表里添加包含三个int的子列表即可,循环里多嵌套一层创建RGB的小列表

4. 性能优化小提示

如果你的图像尺寸很大(比如4K以上),用Python列表会有明显的性能开销,这时候可以考虑用numpy数组来传递数据——C端直接构建numpy数组(借助numpy的C API),Python函数接收numpy数组处理,效率会高很多。不过如果你的现有Python函数已经基于列表编写,先按上面的方法实现,后续再优化也没问题。

内容的提问来源于stack exchange,提问作者Felix.A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:45:18