【NumPy】np.clip() 函数:对数组的值进行截断

np.clip 是 NumPy 中的一个函数,用于将数组中的元素限制在指定的范围内(即对数组的值进行截断)。超出范围的值会被替换为指定的上下限值。


函数语法

numpy.clip(a, a_min, a_max, out=None, *, where=True)

参数说明

  1. a

    • 输入的数组,可以是 NumPy 数组或可转换为数组的序列(如列表、元组等)。
  2. a_mina_max

    • 分别表示允许的最小值和最大值。
    • a_mina_max 必须是标量值或与 a 形状一致的数组
    • 如果某一项为 None,则表示不设置相应的限制。例如,如果 a_min=None,只设置上限。
  3. out(可选):

    • 用于存放结果的数组。它必须与 a 的形状相同。
  4. where(可选,默认值为 True):

    • 布尔条件数组,仅在 where=True 的位置应用截断。

返回值

  • 返回一个数组,数组中的每个元素都被限制在 [a_min, a_max] 范围内。
  • 如果指定了 out 参数,则返回 out

示例

1. 基本用法
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
result = np.clip(arr, 2, 4)
print(result)  # 输出:[2 2 3 4 4]

解释:

  • 小于 2 的值被限制为 2,大于 4 的值被限制为 4。

2. 设置仅上限或仅下限
import numpy as np

arr = np.array([-3, -1, 0, 1, 3])
result_min = np.clip(arr, 0, None)  # 仅设置下限
print(result_min)  # 输出:[0 0 0 1 3]

result_max = np.clip(arr, None, 1)  # 仅设置上限
print(result_max)  # 输出:[-3 -1  0  1  1]

解释:

  • result_min 中,所有小于 0 的值被限制为 0,上限没有限制。
  • result_max 中,所有大于 1 的值被限制为 1,下限没有限制。

3. 使用 out 参数
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
out_arr = np.empty_like(arr)  # 创建一个空数组
np.clip(arr, 2, 4, out=out_arr)
print(out_arr)  # 输出:[2 2 3 4 4]

解释:

  • 使用 out 参数将结果存储在 out_arr 中,而不会创建新的数组。

4. 与布尔条件 where 一起使用
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
condition = [True, False, True, True, False]
result = np.clip(arr, 2, 4, where=condition)
print(result)  # 输出:[2 2 3 4 5]

解释:

  • condition=True 的位置应用 clip 操作,其他位置保持原值。

应用场景

  1. 数值限制

    • 当需要限制数据在一定范围内时,例如防止异常值对后续计算产生影响。
  2. 数据正则化

    • 在图像处理或其他数据预处理中,常用 np.clip 限制数据的取值范围。
  3. 梯度修剪

    • 在深度学习中,用于限制梯度的大小,防止梯度爆炸。

注意事项

  1. a_mina_max 的取值

    • 如果 a_min > a_maxnp.clip 会自动交换两者的位置,以保证有效范围。
    • 如果 a_min > a_maxnp.clip ,数组会全部替换为a_max的值输出。
    import numpy as np
    
    arr = np.array([1, 2, 3, 4, 5])
    result = np.clip(arr, 4, 3)
    print(result)  # 输出:[3 3 3 3 3]
    
  2. 多维数组

    • a_mina_max 可以是数组,与输入数组形状一致时,会对每个位置分别设置上下限。

示例:针对多维数组的上下限
import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
min_vals = np.array([[1, 2, 3], [3, 4, 5]])
max_vals = np.array([[2, 3, 4], [5, 6, 7]])

result = np.clip(arr, min_vals, max_vals)
print(result)
# 输出:
# [[1 2 3]
#  [4 5 6]]

解释:

  • 每个位置的值被限制在对应的 min_valsmax_vals 范围内。

总结

  • np.clip 是一个强大的工具,用于限制数组元素的取值范围。
  • 它可以应用于多维数组,支持逐元素的上下限设置。
  • 在数据处理、数值计算和机器学习中具有广泛的应用。
使用matlab编写一个脚本,读取一个文件夹中(可能包含若干子文件夹同样读取子文件夹)所有名称中同时包含"t1"‘t2’(包括大写)且包含"correct"的.mat文件。并使用下述方法进行反演(该方法采用python进行编写,需要转化为matlab),将反演得到的二维图像进行保存,保存格式为对应的.mat文件名称+反演结果.png。方法:def getT1T2Spectrum(_t_inv, _t_cpmg, _Z, T1, T2, alpha=2, cpmg_pts=100, fast=False): Z = np.zeros((_Z.shape[0], cpmg_pts)) #创建一个用于存储Z谱数据的零数,大小为_Z数的行数乘以cpmg_pts t = np.zeros((1, cpmg_pts)) #创建一个用于存储时间序列的零数,大小为1 x cpmg_pts for i in range(_t_inv.shape[0]): t, Z[i], weights = compress(_t_cpmg, _Z[i], cpmg_pts) t = t.transpose() tau1 = _t_inv[:, np.newaxis] tau2 = t[:, np.newaxis] K1 = 1 - np.exp(-tau1 / T1) # SR # K1 = 1 - 2 * np.exp(-tau1 / T1) #IR K2 = np.exp(-tau2 / T2) S, res = flint(K1, K2, Z, alpha, fast=fast) return S def flint(K1, K2, Z, alpha, S=None, fast=False): maxiter = 100000 residuals = [] #用于存储每次迭代后的残差 if S is None: S = np.ones((K1.shape[1], K2.shape[1])) K1 = tsvd(K1) #11*100 K2 = tsvd(K2) #100*100 K1K1 = np.dot(K1.T, K1) K2K2 = np.dot(K2.T, K2) K1ZK2 = np.dot(np.dot(K1.T, Z), K2) # Lipschitz constant L = 2*(K1K1.trace()*K2K2.trace() + alpha) #Lipschitz 常数的一个估计,用于控制迭代步长 tZZ = np.dot(Z, Z.T).trace() # 计算残差的中间项 Y = S tt = 1 fac1 = (L - 2*alpha)/L fac2 = 2/L # 这2个fac的大小,对于是否收敛具有很大的影响,一般都要小于2/L lastres = np.inf # 用于内存占位符号,防止内存位数满了,因为残差的初始特别大 for i in range(maxiter): term2 = K1ZK2 - np.dot(K1K1, np.dot(Y, K2K2)) Snew = np.clip(fac1*Y + fac2*term2, 0, None) ttnew = 0.5*(1 + np.sqrt(1 + 4*tt*tt)) trat = (tt - 1)/ttnew Y = Snew + trat*(Snew-S) #在每次迭代中,根据当前解 Y 和预先计算的常数 L,计算新的解 Snew。这里使用了 np.clip 函数将解限制在非负范围内 tt = ttnew S = Snew if i%1000 == 0: # 每隔一定迭代次数计算一次残差 normS = alpha*np.linalg.norm(S)**2 residual = tZZ - 2*np.dot(S.T, K1ZK2).trace() + np.dot(S.T, np.dot(K1K1, np.dot(S, K2K2))).trace() + normS residuals.append(residual) #预处理后的数据矩阵和当前解 S 的内积项,以及正则化项 alpha 的贡献 res_diff_ratio = np.abs(residual - lastres)/residual #当前残差与上一次迭代的残差之间的相对变化率 lastres = residual # print(i, tt, trat, L, residual, res_diff_ratio) if res_diff_ratio < 1e-4 or (fast and res_diff_ratio < 1e-2): return S, np.array(residuals) raise Exception('Max iterations reached') def tsvd(A,truncation=0.1):########### u, s, v = np.linalg.svd(A, full_matrices=False) # compute SVD without 0 singular values S = np.diag(s) sr, sc = S.shape cnt = 0 for i in range(0, sc - 1): if S[i, i] > truncation: cnt+=1 return u[:,0:cnt].dot(S[0:cnt,0:cnt]).dot(v[0:cnt,:])
03-08
你理解错了,我说的是你提供的这个代码中,是否包含了你所提到的数据预处理,包括暗场校正和对数变换,你之前提供的代码如下import astra import numpy as np # ====== 1. 参数定义 ====== vol_size = (512, 512, 256) # 重建体积(ZYX) n_angles = 1200 angles = np.linspace(0, 8*np.pi, n_angles) pitch = 1.0 # 螺距=扫描床每转前进量 # ====== 2. 螺旋几何定义 ====== # 创建几何向量(关键修正) vectors = np.zeros((n_angles, 12)) for i in range(n_angles): # 源位置公式 src_x = 0 src_y = -1000 # SOD=1000mm src_z = (pitch * angles[i]) / (2*np.pi) # 探测器位置计算 det_center_z = src_z # 简化模型 vectors[i,:] = [ src_x, src_y, src_z, # 源坐标 0, 0, det_center_z, # 探测器中心 0.8, 0, 0, # 探测器u方向 0, 0.8, 0 # 探测器v方向 ] proj_geom = astra.create_proj_geom('cone_vec', 640, 480, vectors) # ====== 3. 加载投影数据 ====== # 模拟数据示例(实际需读取真实数据) projections = np.random.rand(n_angles, 480, 640).astype(np.float32) proj_id = astra.data3d.create('-proj3d', proj_geom, projections) # ====== 4. 重建配置 ====== # 创建重建数据容器 recon_id = astra.data3d.create('-vol', vol_size) cfg = astra.astra_dict('FDK_CUDA') cfg['ProjectionDataId'] = proj_id cfg['ReconstructionDataId'] = recon_id alg_id = astra.algorithm.create(cfg) # ====== 5. 执行重建 ====== astra.algorithm.run(alg_id) # FDK无需迭代参数 # ====== 6. 结果获取 ====== recon_volume = astra.data3d.get(recon_id) # ====== 7. 资源释放 ====== astra.algorithm.delete(alg_id) astra.data3d.delete(proj_id) astra.data3d.delete(recon_id)
03-20
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬彬侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值