ISP Pipeline(9):Noise Filter for Chroma 色度去噪
Noise Filter for Chroma(色度去噪)
这是 ISP(Image Signal Processing)流水线中的一个步骤,主要目的是:
降低色度通道(Cb、Cr)的噪声,提高图像质量,特别是在低光、压缩或传感器噪声较高的场景下。
为什么只滤波 Chroma?
-
噪声主要集中在色度通道(Cb、Cr),而亮度(Y)更重要,用来体现图像细节。
-
人眼对颜色变化不敏感,对亮度变化非常敏感。
-
所以:
-
对 Cb/Cr 用更强的去噪
-
对 Y 保留更多细节
-
工作流程(常见方式)
RGB → YCbCr → 仅对 Cb 和 Cr 做去噪(如双边滤波) → 合并回 → RGB
代码:
def NFC(cbcr_img, alpha, thresh):"""inputs:cbcr_img = Cb and Cr channels of the YCbCr imagealpha = controls intensity of correction for noisy pixelsthresh = controls strictness of noisy pixel detectionoutputs:nfc_img = Cb and Cr channels of YCbCr image after applying noise filter on both"""cbcr_img = cbcr_img.astype(np.uint16)nfc_img = np.copy(cbcr_img) # make a copy of the cbcr_img to apply noise filter for chromafor k in range(len(cbcr_img[0,0])):# apply the filter to both Cb and Crimg = cbcr_img[:, :, k]padded_img = np.pad(img, (1, 1), 'reflect') # apply reflect padding on the image to give edge pixels neighborsp1 = padded_img[:-2:1, :-2:1] # define p0 : p8 to use in filterp2 = padded_img[:-2:1, 1:-1:1]p3 = padded_img[:-2:1, 2::1]p4 = padded_img[1:-1:1, :-2:1]p0 = padded_img[1:-1:1, 1:-1:1]p5 = padded_img[1:-1:1, 2::1]p6 = padded_img[2::1, :-2:1]p7 = padded_img[2::1, 1:-1:1]p8 = padded_img[2::1, 2::1]neighbors = np.array([p1, p2, p3, p4, p5, p6, p7, p8]) # place all neighbor pixels into a seperate arraymean = np.mean(neighbors, axis = 0) # calculate meanstd = np.std(neighbors, axis = 0) # calculate standard deviationlimit_upper = mean + (thresh * std) # calculate upper and lower limits for the values of p0 relative to neighborslimit_lower = mean - (thresh * std)editted_img = np.where((p0 > limit_upper) | (p0 < limit_lower), alpha * mean + (1 - alpha) * p0, img) # apply filternfc_img[:, :, k] = editted_img # update the nfc_imgreturn nfc_img.astype(np.uint8) # rescale the nfc_img
关键点:
limit_upper = mean + (thresh * std)limit_lower = mean - (thresh * std)
定义异常检测的上下限。
-
如果某像素超出这个区间,就认为它可能是噪声;
-
thresh
是倍数阈值,比如2.5
表示“超出 2.5×标准差”。
editted_img = np.where((p0 > limit_upper) | (p0 < limit_lower),alpha * mean + (1 - alpha) * p0,img)
使用 np.where()
来做条件更新:
-
如果
p0
超出范围,则更新为“均值修正值”:
alpha * mean + (1 - alpha) * p0
→ 更平滑但保留部分原始信息; -
否则,保留原像素。
alpha * mean + (1 - alpha) * p0
这是在色度去噪中的 柔性替代(soft replacement)策略,在图像处理里非常常见,用来平滑掉异常像素,但又不完全丢弃原始信息。
这句的意思是:
如果当前像素
p0
被判断为噪声(即远离周围邻域像素太多),
就用“邻域均值” 和 “当前像素自身值”的加权平均来修正它。
其中:
-
mean
:邻域 8 个像素的平均值(认为更可靠) -
p0
:当前像素值(可能是噪声,但可能也包含真实信息) -
alpha ∈ [0,1]
:控制你更相信 mean 还是 p0
修正后 = α × 周围均值 + (1 - α) × 当前值
-
如果 α=1 → 完全信任邻居(最大去噪,最模糊)
-
如果 α=0 → 完全保留原值(无去噪)
-
如果 α=0.6 → 更倾向邻域均值,但保留一部分原始信息 ✨