導入
写真には細かなザラつき(ノイズ)が乗っています。そのまま二値化すると、ノイズが黒い点として残り、OCR が「ゴミ」を文字と誤認します。ノイズは軽くぼかすことで抑えられます。
説明
import numpy as np
import cv2
import matplotlib.pyplot as plt
# ノイズを載せたグレー画像を用意する
rng = np.random.default_rng(0)
base = np.full((120, 240), 200, dtype=np.uint8) # 明るい灰色の背景
cv2.putText(base, "NOISE", (20, 80), cv2.FONT_HERSHEY_SIMPLEX, 2, 0, 5)
noise = rng.integers(-60, 60, base.shape)
noisy = np.clip(base.astype(int) + noise, 0, 255).astype(np.uint8)
# ぼかしでノイズを平滑化
blur = cv2.GaussianBlur(noisy, (5, 5), 0) # ガウシアンぼかし
median = cv2.medianBlur(noisy, 5) # メディアンフィルタ(粒ノイズに強い)
fig, ax = plt.subplots(1, 3, figsize=(10, 3))
ax[0].imshow(noisy, cmap="gray"); ax[0].set_title("noisy"); ax[0].axis("off")
ax[1].imshow(blur, cmap="gray"); ax[1].set_title("gaussian"); ax[1].axis("off")
ax[2].imshow(median, cmap="gray"); ax[2].set_title("median"); ax[2].axis("off")
cv2.putText… OpenCV でも文字を描けます(ここではノイズを載せる素材作り)。cv2.GaussianBlur(画像, (5,5), 0)… 5×5 の範囲で周囲と平均を取り、なめらかにします。数字を大きくするほど強くぼけます。cv2.medianBlur(画像, 5)… 範囲内の中央値を取るフィルタ。ぽつぽつした粒ノイズ(ごま塩ノイズ)に特に強いのが特徴です。
ぼかしは「ノイズを消す」一方で「文字も少しぼやける」トレードオフがあります。消しすぎないのがコツです。
やってみよう
cv2.GaussianBlur(noisy, (5, 5), 0) の (5, 5) を (11, 11) にすると、強くぼけてノイズは減りますが文字も甘くなります。ちょうど良い強さを探してみましょう(フィルタサイズは奇数にします)。
演習
ノイズ画像 noisy に cv2.medianBlur を カーネルサイズ 3 でかけた結果を表示してください。
ヒント1を見る
out = cv2.medianBlur(noisy, 3) として plt.imshow(out, cmap="gray")。
ヒント2を見る
サイズは奇数(3, 5, 7…)。小さいほど効果は弱く、文字は保たれます。