🦁

画像にノイズを加える

2022/10/18に公開2

本投稿では、Pythonを用いて画像にノイズを加えていきます。

加えるノイズ

今回実装するノイズは、塩ごまノイズです。

塩ごまノイズとは?

塩ごまノイズは、インパルスノイズの確率pの値が0.5の時のノイズである

# ライブラリ読み込み
import cv2
import numpy as np
import random

# ノイズ付与用のクラス
class NoiseImage:
    def __init__(self):
        self.img = None

    # 画像読み込み
    def image_read(self, filename, gray=False):
        if gray == True:
            img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
        else:
            img = cv2.imread(filename)
        self.img = img
        return img

    # ノイズ付与関数
    def noise_in_image(self, noise_level=0.02):
        noise_img = salt_and_pepper(self.img, noise_level)
        return noise_img


# 塩ごまノイズ
def salt_and_pepper(img, noise_level):
    rate = 0.5
    img_size = (img.shape[0]) * (img.shape[1])
    noise_sum = int(img_size * noise_level)
    noise_xy_random = random.sample(range(1, img_size+1), k=noise_sum)

    if len(img.shape) == 2: # グレースケール用
        for i in range(len(noise_xy_random)):
            noise_img = img
            noise_fig = np.random.choice([0, 255], p=[rate, 1-rate])
            x = int((noise_xy_random[i] - 1)  / img.shape[0])
            y = (noise_xy_random[i] - 1) - (img.shape[1] * x)
            noise_img[x][y] = noise_fig

    elif len(img.shape) == 3: # カラー用
        channels = 3
        noise_img = img
        for i in range(len(noise_xy_random)):
            noise_fig = np.random.choice([0, 255], p=[rate, 1-rate])
            x = int((noise_xy_random[i] - 1)  / img.shape[0])
            y = (noise_xy_random[i] - 1) - (img.shape[1] * x)
            for j in range(channels):
                noise_img[x][y][j] = noise_fig
    return noise_img


if __name__ == "__main__":
    # 画像読み込み
    filename = "Lenna.bmp"
    noise_class = NoiseImage()
    img = noise_class.image_read(filename, gray=True)
    # ノイズ付与
    ## 塩ごまノイズ
    noise_img = noise_class.noise_in_image()
    cv2.imwrite("LennaSaltPepperNoise.bmp", noise_img)

出力

次の画像は、オリジナルの元画像です。

次の画像は、塩ごまノイズを付与した画像です。

他のノイズについても

ブログの方で塩ごまノイズ、インパルスノイズ、ガウシアンノイズについても書いていますので、よろしければこちらも!

Discussion

kzm4269kzm4269

高速化したい場合はこういう書き方もできますね。

def salt_and_pepper_2(img, noise_level):
    rate = 0.5
    img_size = img.shape[0] * img.shape[1]
    noise_sum = int(img_size * noise_level)
    noise_xy_random = random.sample(range(1, img_size + 1), k=noise_sum)

    noise_xy_random_ = np.array(noise_xy_random) - 1
    noise_value = np.random.choice(
        [0, 255],
        size=noise_sum,
        p=[rate, 1 - rate],
    )

    if img.ndim == 2:
        img.reshape(img_size)[noise_xy_random_] = noise_value
    elif img.ndim == 3:
        img.reshape(img_size, -1)[noise_xy_random_] = noise_value[:, None]

    return img