数值计算与图像处理NumPy、SciPy、Pillow数据分析链路中除表格处理外还涉及两类底层能力数值计算数组运算、线性代数、插值与优化、信号处理与图像处理。本节以 NumPy、SciPy、Pillow 三个库为例说明这些能力的调用方式及各自的适用条件。前几节的数据处理以 pandas 为主其底层依赖 NumPy 的数组结构而线性代数、插值、优化与信号处理由 SciPy 提供图像读写与变换由 Pillow 提供。三者的分工为NumPy 提供数组与向量化运算SciPy 在其上提供数值算法Pillow 提供图像接口。本节不重复各库的基础教程而是按数组计算 → 数值算法 → 信号处理 → 图像处理的顺序说明常用接口的调用方式与适用条件并与本系列的 NumPy、SciPy、Pillow 专题博客互为补充。实现基于 NumPy 1.26、SciPy 1.11 与 Pillow 10.0运行环境为 Python 3.10OpenCV 4.8 为可选依赖。1 NumPy数组计算NumPy 的基本用法是以数组运算替代逐元素循环。借助广播机制形状不同的数组在满足广播规则时可直接进行逐元素运算无需显式复制importnumpyasnp rngnp.random.default_rng(42)Xrng.random((1000,50))XcX-X.mean(axis0)# 广播(1000,50) - (50,) 每列减均值outnp.empty_like(Xc)np.multiply(Xc,2,outout)# out 复用缓冲省一次内存分配anp.arange(6).reshape(2,3)print((a-a.mean(axis0)).round(2))[[-1.5 -1.5 -1.5] [ 1.5 1.5 1.5]]上述结果为按列去均值a.mean(axis0)得到形状为 (3,) 的行均值与形状 (2,3) 的数组相减时按列广播。向量化与广播的作用在于避免 Python 层循环减少解释执行开销其性能提升幅度取决于运算类型与数据规模因此加速比应以实际测量为准。out参数用于复用已有数组的存储空间减少内存分配。2 SciPy线性代数线性代数中的常见操作是求解线性方程组Ax b。直接计算A的逆再与b相乘的做法在数值上不稳定当A接近奇异时其逆矩阵的元素会被放大求解结果的误差随之增大。矩阵的性态可用条件数衡量条件数越大表示矩阵越接近奇异fromscipyimportlinalgdefrobust_solve(A,b):condnp.linalg.cond(A)ifcond1e10:# 病态改用最小二乘returnlinalg.lstsq(A,b)[0],{cond:cond,method:lstsq}returnlinalg.solve(A,b),{cond:cond,method:solve}函数按条件数选择解法条件数较小时使用solve基于 LU 分解求解方阵方程组条件数较大时改用lstsq最小二乘在方程无精确解或矩阵病态时给出误差最小的解。条件数阈值为经验取值实际使用时可按问题的精度要求调整。3 SciPy插值与优化插值用于在已知数据点之间估计中间取值。interp1d已不推荐使用宜改用CubicSpline三次样条在相邻节点处保证函数值与一阶、二阶导数连续插值曲线较为平滑。需注意插值仅适用于数据范围之内超出范围的外推结果不再受数据约束fromscipyimportinterpolate,optimize csinterpolate.CubicSpline(x,y)# 推荐interp1d 已弃用resoptimize.minimize(fun,x0,jacgrad,methodL-BFGS-B,boundsbounds)ifnotres.success:raiseRuntimeError(res.message)# 必须检查收敛不能假定成功优化部分使用minimize求解无约束或有界约束问题methodL-BFGS-B适用于带边界的可微目标函数jac提供梯度可加快收敛。优化结果需检查res.success数值优化可能在迭代次数或精度限制下提前终止未检查即使用结果会引入错误。4 信号处理滤波与频谱滤波是对序列进行频域或时域的局部处理。高阶滤波器若直接以传递函数系数b, a实现其极点分布会导致数值不稳定因此改用二阶节SOS形式fromscipyimportsignal,fft sossignal.butter(6,20,btypelow,fsfs,outputsos)# SOS高阶滤波更稳定ysignal.sosfiltfilt(sos,x)# 零相位滤波避免端点失真ampnp.abs(fft.rfft(y))/len(y)*2# 实信号用 rfft 归一化sosfiltfilt对序列作前向与反向两次滤波从而抵消滤波引入的相位偏移零相位滤波代价是无法用于在线处理仅适用于已获得完整序列的场景。频谱部分使用rfft实信号的频谱具有共轭对称性只需计算一半频点除以序列长度并乘以 2可将幅值归一化到与时域幅值一致的量级。5 Pillow图像处理与批量规格统一单张图像的读取与变换较为直接实际工程中的难点在于批量处理时的规格统一。以下函数将输入图像统一为固定尺寸的方形画布并输出处理结果路径frompathlibimportPathfromPILimportImage,ImageOpsdefnormalize_image(src:Path,dst:Path,size512):withImage.open(src)asim:imImageOps.exif_transpose(im)# 按 EXIF 纠方向否则可能躺倒imim.convert(RGB)# 去 alpha避免透明变黑im.thumbnail((size,size),Image.LANCZOS)# 等比缩放 抗锯齿canvasImage.new(RGB,(size,size),(0,0,0))canvas.paste(im,((size-im.width)//2,(size-im.height)//2))dst.parent.mkdir(parentsTrue,exist_okTrue)canvas.save(dst,formatPNG)returnstr(dst)该函数依次完成四项处理按 EXIF 信息纠正方向部分图像的像素数据与显示方向不一致转换为 RGB 以去除透明通道避免透明区域在后续合成中变为黑色等比缩放至画布范围内thumbnail保持宽高比LANCZOS为重采样算法在以黑色铺底的方形画布上居中粘贴使输出尺寸统一。批量处理时可用进程池并行执行上述函数并对结果作质量校验检查文件可正常打开、尺寸符合规格fromconcurrent.futuresimportProcessPoolExecutor IMG_EXT{.jpg,.jpeg,.png,.bmp,.webp}对 JPEG 大图可在解码阶段即降采样以减少内存占用im.draft(RGB, (512, 512))会在读取时按比例缩小而非读取完整分辨率后再缩放。6 小结NumPy 提供数组与向量化运算广播机制使不同形状的数组可直接参与逐元素计算out参数用于复用存储空间。SciPy 在此基础上提供数值算法线性代数部分按条件数在solve与lstsq之间选择解法避免直接求逆插值使用CubicSpline且仅适用于数据范围之内优化需检查收敛标志后再使用结果。信号处理使用二阶节形式的高阶滤波与零相位滤波频谱分析对实信号使用rfft并作幅值归一化。Pillow 用于图像读写与变换批量处理时需统一尺寸、方向与颜色模式并对结果作质量校验。至此本系列以实习僧 · 互联网 IT 类实习岗位数据为线索走完了从环境搭建、数据获取与加工到分析与建模、数值与图像处理的完整链路。各篇共享若干共同约定处理前先确定统计范围与口径结论以此为前提预处理参数仅在训练集估计特征文本去除目标信息原始数据与原文保持只读口径调整另行留档方法前提无法满足时以修订并记录的方式处理随机种子、依赖版本、阶段编号与回归锚点统一固定以保证结果可复现。采集环节需遵守目标网站的使用协议并控制访问频率文中不公开原始数据以及任何包含个人或公司敏感信息的明细。全系列完7 延伸参考相关文章0. NumPy 系列教程、NumPy 数据分析与图像处理入门、SciPy 信号处理解析、SciPy 插值方法详解、Pillow 基础图像操作与数据预处理、Pillow 图像分割、切片与拼接处理NumPy / SciPy / Pillow 官方文档上一篇08 机器学习建模与实验评估