条纹噪声是 CT 成像的 “BUG”,可能来自机器本身、病人配合度,或者数据计算过程。如CT 机里有一排 “感光元件”(探测器),负责接收穿过人体的 X 射线。如果其中某个或某几个元件坏了、灵敏度下降,就会像相机传感器有坏点一样,在图像上形成一条固定的条纹(比如竖条纹,因为探测器是一排排排列的)。
def add_stripe_noise(image, intensity=200, stripe_width=5, stripe_spacing=10, direction='vertical'):
noise = np.zeros_like(image, dtype=np.float32)
height, width = image.shape
if direction == 'vertical':
for x in range(0, width, stripe_spacing):
start = x
end = min(x + stripe_width, width)
noise[:, start:end] = intensity * (np.random.rand(height, end - start) - 0.5)
elif direction == 'horizontal':
for y in range(0, height, stripe_spacing):
start = y
end = min(y + stripe_width, height)
noise[start:end, :] = intensity * (np.random.rand(end - start, width) - 0.5)
noisy_image = image + noise
return np.clip(noisy_image, np.min(image), np.max(image))
这个函数的作用是给图像添加 "条纹噪声",就像给图片蒙上一层有规律的条纹状干扰。用大白话一步一步解释:
打比方理解
把图像想象成一张干净的画,这个函数就是用画笔在上面画一些平行的条纹(竖纹或竖纹),让画面变得有干扰。
步骤拆解(以添加竖纹为例)
- 准备一张 "透明的涂鸦纸"
noise = np.zeros_like(image) |
→ 先准备一张和原图一样大的透明纸(初始全黑,相当于透明),专门用来画条纹。
- 确定条纹的位置和宽度
for x in range(0, width, stripe_spacing): start = x # 条纹开始的位置 end = min(x + stripe_width, width) # 条纹结束的位置(避免超出图像) |
→ 比如设定stripe_spacing=10(每隔 10 个像素画一条),stripe_width=5(每条宽 5 个像素),就会在第 0、10、20... 的位置画竖纹,每条宽 5 像素。
- 在涂鸦纸上画条纹
noise[:, start:end] = intensity * (np.random.rand(...) - 0.5) |
→ 在刚才确定的位置上画条纹:
-
- np.random.rand() 生成随机的明暗值(像用不同力度画画)
- 减 0.5 是为了让条纹有明有暗(有的比原图亮,有的比原图暗)
- intensity 控制条纹的明显程度(值越大,条纹越清晰)
- 把涂鸦纸盖到原图上
noisy_image = image + noise |
→ 把画好条纹的透明纸叠到原图上,条纹就 "印" 到原图上了。
- 修正过度明暗的地方
return np.clip(noisy_image, np.min(image), np.max(image)) |
→ 避免条纹太亮或太暗导致画面失真,把亮度限制在原图的明暗范围内。
举个具体例子
如果是一张 40x40 的图像,设置:
- direction='vertical'(竖纹)
- stripe_spacing=10(每隔 10 像素一条)
- stripe_width=5(每条宽 5 像素)
最终会在图像上画出:
- 第 0-4 列:一条竖纹
- 第 10-14 列:一条竖纹
- 第 20-24 列:一条竖纹
- 第 30-34 列:一条竖纹
每条条纹的明暗是随机的,整体看起来就像图像被竖条纹干扰了。
总结
这个函数就像给图像加了一层有规律的 "条纹滤镜",可以控制条纹是横的还是竖的、条纹多宽、间隔多远、以及条纹有多明显,最终让图像出现类似信号干扰的条纹效果。