在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
相关产品推荐
相关产品推荐

