最近碰到一個過擬合問題(感覺在工程裏大部分時間都在解決過擬合,只要選正確模型~),想通過增加椒鹽噪聲來增加訓練樣本的多樣性,對椒鹽噪聲有了新的認識——原來 椒鹽噪聲 = 椒噪聲 + 鹽噪聲
椒鹽噪聲概念
椒鹽噪聲又稱爲脈衝噪聲,它是一種隨機出現的白點或者黑點,如下圖。
在機器學習的圖像分類任務中,爲圖像增加椒鹽噪聲是一種常用的數據增強方法,這裏就介紹添加椒鹽噪聲的函數(基於python)。
椒鹽噪聲數學定義
信噪比
在噪聲的概念中,通常採用信噪比(Signal-Noise Rate, SNR)衡量圖像噪聲。通俗的講就是信號佔多少,噪聲佔多少,SNR越小,噪聲佔比越大。
在信號系統中,計量單位爲dB,爲10lg(PS/PN), PS和PN分別代表信號和噪聲的有效功率。
在這裏,採用信號像素點的佔比充當SNR,以衡量所添加噪聲的多少。
舉個例,假設一張圖像的寬x高 = 10x10 ,共計100個像素,想讓其中20個像素點變爲噪聲,其餘80個像素點保留原值,則這裏定義的SNR=80/100 = 0.8 。
一開始也說了,椒鹽噪聲 = 椒噪聲 + 鹽噪聲 ,椒鹽噪聲的值爲0(黑色)或者255(白色),這裏假設爲等概率的出現0或者255。
爲圖像添加椒鹽噪聲的的步驟如下:
- 依SNR製作mask,用於判斷像素點是原始信號,還是噪聲
- 依mask給原圖像賦噪聲值
椒鹽噪聲代碼實現
def addsalt_pepper(img, SNR):
img_ = img.copy()
c, h, w = img_.shape
mask = np.random.choice((0, 1, 2), size=(1, h, w), p=[SNR, (1 - SNR) / 2., (1 - SNR) / 2.])
mask = np.repeat(mask, c, axis=0) # 按channel 複製到 與img具有相同的shape
img_[mask == 1] = 255 # 鹽噪聲
img_[mask == 2] = 0 # 椒噪聲
return img_
注意事項,輸入的img的shape有規定,需要是 c,h,w。可自行修改
執行以下腳本,可以查看不同SNR下添加椒鹽噪聲的效果。
# coding: utf-8
import numpy as np
import cv2
from matplotlib import pyplot as plt
def addsalt_pepper(img, SNR):
img_ = img.copy()
c, h, w = img_.shape
mask = np.random.choice((0, 1, 2), size=(1, h, w), p=[SNR, (1 - SNR) / 2., (1 - SNR) / 2.])
mask = np.repeat(mask, c, axis=0) # 按channel 複製到 與img具有相同的shape
img_[mask == 1] = 255 # 鹽噪聲
img_[mask == 2] = 0 # 椒噪聲
return img_
img = cv2.imread('your_path.jpg')
SNR_list = [0.9, 0.7, 0.5, 0.3]
sub_plot = [221, 222, 223, 224]
plt.figure(1)
for i in range(len(SNR_list)):
plt.subplot(sub_plot[i])
img_s = addsalt_pepper(img.transpose(2, 1, 0), SNR_list[i]) # c,
img_s = img_s.transpose(2, 1, 0)
cv2.imshow('PepperandSalt', img_s)
cv2.waitKey(0)
plt.imshow(img_s[:,:,::-1]) # bgr --> rgb
plt.title('add salt pepper noise(SNR={})'.format(SNR_list[i]))
plt.show()
最終得到小貓圖像如下: