AsPylib中translate_Bspline加载Bspline模块失败求助
场景说明
按照AsPylib官方文档编写图像平移代码,执行以下命令时出现错误,但其他几何变换功能正常:
data2 = astro.translate_Bspline(data, [40.3, 150.2], 3)
报错信息
Error in aspylib.astro.translate_Bspline()
Traceback (most recent call last):
File "C:\Aspylib_v3.0.0\aspylib\astro\transform.py", line 40, in translate_Bspline
cdll.Bspline.Translate.argtypes = [c_long, c_long, c_long, ndpointer(dtype=np.float32), ndpointer(dtype=np.float32), c_long, ndpointer(dtype=np.float32)]
^^^^^^^^^^^^
File "C:\Users\hfedd\AppData\Local\Programs\Python\Python311\Lib\ctypes_init_.py", line 446, in getattr
dll = self.dlltype(name)
^^^^^^^^^^^^^^^^^^^
File "C:\Users\hfedd\AppData\Local\Programs\Python\Python311\Lib\ctypes_init.py", line 376, in init
self._handle = _dlopen(self._name, mode)
^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: Could not find module 'Bspline' (or one of its dependencies). Try using the full path with constructor syntax.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\hfedd\Downloads\new8.py", line 19, in
data2 = astro.translate_Bspline(data, [40.3, 150.2], 3)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Aspylib_v3.0.0\aspylib\astro\transform.py", line 54, in translate_Bspline
raise Exception("more than 3 consecutive failures, execution stopped")
Exception: more than 3 consecutive failures, execution stopped
问题代码
怀疑问题出在transform.py文件的ctypes用法上,原代码如下:
# -*- coding: iso_8859_1 -*- import numpy as np import platform as pf import aspylib.conf as conf from ctypes import c_long, c_float, cdll from numpy.ctypeslib import ndpointer def translate_Bspline(images, shift, spline_degree): """ --------------------- Purpose Translates an image (or list of images) by non-integer shifts in both X and Y directions. B-Spline interpolation with arbitrary order (from 2 to 9) is used to calculate the translated pixels. --------------------- Inputs * images (2D or 3D Numpy array) = array that contains the data of one image (2D case) or the data of a list of images (3D case). * shift ([float, float]) = 2 elements list that contains respectively the shifts in X (vertical) and Y (horizontal) directions. * spline_degree (integer) = the degree of the B-Spline that is used for interpolation : it can be 2, 3, 4, 5, 6, 7, 8 or 9. --------------------- Output (2D or 3D Numpy array) = transformed image data. --------------------- """ ierror = 0 while True: try: if len(images.shape)==2: dim = 1 dim_x, dim_y = images.shape else: dim, dim_x, dim_y = images.shape indata = np.ascontiguousarray(np.array(images, dtype = np.float32)) dxy = np.ascontiguousarray(np.array(shift, dtype = np.float32)) outdata = np.ascontiguousarray(np.empty(images.shape, dtype = np.float32)) if pf.system()=='Windows': cdll.Bspline.Translate.argtypes = [c_long, c_long, c_long, ndpointer(dtype=np.float32), ndpointer(dtype=np.float32), c_long, ndpointer(dtype=np.float32)] cdll.Bspline.Translate(dim,dim_x,dim_y,indata,dxy,spline_degree,outdata) elif pf.system()=='Linux': mydll = cdll.LoadLibrary("libbspline.so") mydll.Translate.argtypes = [c_long, c_long, c_long, ndpointer(dtype=np.float32), ndpointer(dtype=np.float32), c_long, ndpointer(dtype=np.float32)] mydll.Translate(dim,dim_x,dim_y,indata,dxy,spline_degree,outdata) del indata del dxy break except: print("error in aspylib.astro.translate_Bspline()") ierror+=1 if ierror>3: raise Exception("more than 3 consecutive failures, execution stopped") pass return outdata
修复方案
针对原代码的问题,修改后的transform.py代码如下:
# -*- coding: iso_8859_1 -*- import numpy as np import platform as pf import aspylib.conf as conf import os from ctypes import c_long, c_float, cdll from numpy.ctypeslib import ndpointer # 缓存加载的DLL实例,避免重复加载 _bspline_dll = None def translate_Bspline(images, shift, spline_degree): """ --------------------- Purpose 对单张图像(2D数组)或多张图像(3D数组)进行非整数像素的XY方向平移。 使用2-9阶B样条插值计算平移后的像素值。 --------------------- Inputs * images (2D或3D Numpy数组):单张图像数据(2D)或多张图像数据(3D) * shift ([float, float]):XY方向的平移量,分别对应垂直(X)和水平(Y)方向 * spline_degree (整数):B样条插值阶数,可选2-9 --------------------- Output (2D或3D Numpy数组):变换后的图像数据 --------------------- """ global _bspline_dll # 处理图像维度 if len(images.shape) == 2: dim = 1 dim_x, dim_y = images.shape else: dim, dim_x, dim_y = images.shape # 转换为连续内存的float32数组 indata = np.ascontiguousarray(images, dtype=np.float32) dxy = np.ascontiguousarray(shift, dtype=np.float32) outdata = np.empty_like(indata, dtype=np.float32) # 加载Bspline库 if _bspline_dll is None: system = pf.system() if system == 'Windows': # 优先从AsPylib安装目录的lib文件夹加载DLL lib_path = os.path.join(os.path.dirname(conf.__file__), 'lib', 'Bspline.dll') if not os.path.exists(lib_path): # 找不到则尝试系统PATH或当前目录 lib_path = 'Bspline.dll' _bspline_dll = cdll.LoadLibrary(lib_path) elif system == 'Linux': _bspline_dll = cdll.LoadLibrary("libbspline.so") else: raise RuntimeError(f"不支持的操作系统: {system}") # 设置函数参数类型,明确要求数组为C连续内存 _bspline_dll.Translate.argtypes = [ c_long, c_long, c_long, ndpointer(dtype=np.float32, flags='C_CONTIGUOUS'), ndpointer(dtype=np.float32, flags='C_CONTIGUOUS'), c_long, ndpointer(dtype=np.float32, flags='C_CONTIGUOUS') ] # 调用插值函数 _bspline_dll.Translate(dim, dim_x, dim_y, indata, dxy, spline_degree, outdata) return outdata
修改说明
- 修复DLL加载问题:Windows下显式指定DLL的可能路径,避免隐式加载找不到模块的问题;同时用全局变量缓存DLL实例,避免重复加载。
- 优化数组处理:用
np.empty_like替代np.empty,简化代码且保证输出数组与输入维度一致。 - 改进错误处理:移除无意义的循环重试逻辑,直接抛出明确错误,便于排查问题。
- 严谨参数类型:给
ndpointer添加C_CONTIGUOUS标志,确保传递给C函数的数组是连续内存布局,符合ctypes要求。
内容的提问来源于stack exchange,提问作者Hendrik

