提问人:Gabriel Garcia 提问时间:11/7/2023 更新时间:11/8/2023 访问量:41
将 Python 代码转换为 Cython: 'assert len(cubemap.shape) == 3' 编译错误
Converting Python Code to Cython: 'assert len(cubemap.shape) == 3' Compilation Error
问:
我获取了一个 Python 代码,需要将其转换为 Cython 以提高性能,但是当我尝试编译它时,它在这部分代码中给了我一个错误:
assert len(cubemap.shape) == 3
这是我的代码:
import numpy
from . import utils
cimport numpy
cimport cython
cdef bytes mode_bilinear = b'bilinear'
cdef bytes mode_nearest = b'nearest'
cdef bytes cube_format_horizon = b'horizon'
cdef bytes cube_format_list = b'list'
cdef bytes cube_format_dict = b'dict'
cdef bytes cube_format_dice = b'dice'
@cython.boundscheck(False)
@cython.wraparound(False)
def c2e(numpy.ndarray[numpy.float64_t, ndim=3] cubemap, int h, int w, bytes mode=mode_bilinear, bytes cube_format=cube_format_dice):
cdef int order
if mode == mode_bilinear:
order = 1
elif mode == mode_nearest:
order = 0
else:
raise NotImplementedError('unknown mode')
if cube_format == cube_format_horizon:
pass
elif cube_format == cube_format_list:
cubemap = utils.cube_list2h(cubemap)
elif cube_format == cube_format_dict:
cubemap = utils.cube_dict2h(cubemap)
elif cube_format == cube_format_dice:
cubemap = utils.cube_dice2h(cubemap)
else:
raise NotImplementedError('unknown cube_format')
assert len(cubemap.shape) == 3
assert cubemap.shape[0] * 6 == cubemap.shape[1]
assert w % 8 == 0
cdef int face_w = cubemap.shape[0]
cdef numpy.ndarray[numpy.float64_t, ndim=2] uv = utils.equirect_uvgrid(h, w)
cdef numpy.ndarray[numpy.float64_t, ndim=2] u = uv[:, 0]
cdef numpy.ndarray[numpy.float64_t, ndim=2] v = uv[:, 1]
cdef numpy.ndarray[numpy.float64_t, ndim=3] cube_faces = numpy.stack(numpy.split(cubemap, 6, 1), 0)
# Get face id to each pixel: 0F 1R 2B 3L 4U 5D
cdef numpy.ndarray[numpy.int32_t, ndim=2] tp = utils.equirect_facetype(h, w)
cdef numpy.ndarray[numpy.float64_t, ndim=2] coor_x = numpy.zeros((h, w))
cdef numpy.ndarray[numpy.float64_t, ndim=2] coor_y = numpy.zeros((h, w))
for i in range(4):
mask = (tp == i)
coor_x[mask] = 0.5 * numpy.tan(u[mask] - numpy.pi * i / 2)
coor_y[mask] = -0.5 * numpy.tan(v[mask]) / numpy.cos(u[mask] - numpy.pi * i / 2)
mask = (tp == 4)
cdef numpy.ndarray[numpy.float64_t, ndim=2] c = 0.5 * numpy.tan(numpy.pi / 2 - v[mask])
coor_x[mask] = c * numpy.sin(u[mask])
coor_y[mask] = c * numpy.cos(u[mask])
mask = (tp == 5)
c = 0.5 * numpy.tan(numpy.pi / 2 - numpy.abs(v[mask]))
coor_x[mask] = c * numpy.sin(u[mask])
coor_y[mask] = -c * numpy.cos(u[mask])
# Final renormalize
coor_x = (numpy.clip(coor_x, -0.5, 0.5) + 0.5) * face_w
coor_y = (numpy.clip(coor_y, -0.5, 0.5) + 0.5) * face_w
cdef numpy.ndarray[numpy.float64_t, ndim=3] equirec = numpy.stack([
utils.sample_cubefaces(cube_faces[..., i], tp, coor_y, coor_x, order=order)
for i in range(cube_faces.shape[2])
], axis=-1)
return equirec
错误:
Compiling utils.pyx because it changed.
Compiling c2e.pyx because it changed.
[1/2] Cythonizing c2e.pyx
C:\Users\Ju-Bei\AppData\Local\Programs\Python\Python311\Lib\site-packages\Cython\Compiler\Main.py:384: FutureWarning: Cython directive 'language_level' not set, using '3str' for now (Py3). This has changed from earlier releases! File: C:\Users\Ju-Bei\Documents\Hyper Render 360\Hyper 360 Convert\fullcython\c2e.pyx
tree = Parsing.p_module(s, pxd, full_module_name)
Error compiling Cython file:
------------------------------------------------------------
...
elif cube_format == cube_format_dice:
cubemap = utils.cube_dice2h(cubemap)
else:
raise NotImplementedError('unknown cube_format')
assert len(cubemap.shape) == 3
^
------------------------------------------------------------
c2e.pyx:37:22: Cannot convert 'npy_intp *' to Python object
Traceback (most recent call last):
File "C:\Users\Ju-Bei\Documents\Hyper Render 360\Hyper 360 Convert\fullcython\setup.py", line 5, in <module>
ext_modules = cythonize([
^^^^^^^^^^^
File "C:\Users\Ju-Bei\AppData\Local\Programs\Python\Python311\Lib\site-packages\Cython\Build\Dependencies.py", line 1134, in cythonize
cythonize_one(*args)
File "C:\Users\Ju-Bei\AppData\Local\Programs\Python\Python311\Lib\site-packages\Cython\Build\Dependencies.py", line 1301, in cythonize_one
raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: c2e.pyx
答:
1赞
Erik Kevin
11/7/2023
#1
看起来最近对 Cython API 进行了更改,该更改必须破坏了 pip 获取的 h5py。 在我的机器上克隆 master 分支并从中编译工作正常。希望修复的代码能够进入 pip 从中获取的 tarball。
评论
0赞
DavidW
11/8/2023
我看不出这与 h5py 有什么关系,这绝对不是最近的变化。
0赞
DavidW
11/8/2023
#2
Cython 优化对使用类型定义的变量的访问的一种方式是,它将属性替换为指向数组的指针:numpy.ndarray[...]
.shape
dimensions
请参阅代码。
这使得查找形状的速度要快得多,但这也意味着它并不完全与 Python 兼容。例如,指针没有“长度”。
无论如何,您可能只想检查该属性,并相信 Numpy 会获得其数组的大小。.ndim
评论