第 10 章 ソースコード一覧¶
書籍第 10 章「画像処理の基礎」に掲載しているソースコードの一覧です。番号は書籍の「入力」番号と対応しています。上のバッジから、この章のコードをまとめた Google Colab ノートブックを開けます。
入力 10.1: サンプル画像の生成と保存¶
import numpy as np
from PIL import Image
# 60×60 のRGB画像を作成(3色の縦ストライプ)
img_array = np.zeros((60, 60, 3),
dtype=np.uint8)
img_array[:, :20, :] = [255, 0, 0] # 左:赤
img_array[:, 20:40, :] = [0, 255, 0] # 中:緑
img_array[:, 40:, :] = [0, 0, 255] # 右:青
# NumPy配列からPillow画像を作成して保存
img = Image.fromarray(img_array)
img.save("sample.png")
print("画像を保存しました")
入力 10.2: 画像の読み込みと基本情報の確認¶
from PIL import Image
# 画像の読み込み
img = Image.open("sample.png")
# 画像の基本情報
print(f"フォーマット: {img.format}")
print(f"サイズ: {img.size}") # (幅, 高さ)
print(f"モード: {img.mode}") # RGB, L, RGBA
入力 10.3: 画像のNumPy配列への変換¶
import numpy as np
from PIL import Image
img = Image.open("sample.png")
# NumPy配列に変換
img_array = np.array(img)
print(f"データ型: {img_array.dtype}")
print(f"形状: {img_array.shape}")
print(f"最小値: {img_array.min()}")
print(f"最大値: {img_array.max()}")
# 左上の画素 (0, 0) の RGB 値
print(f"左上の画素値: {img_array[0, 0]}")
入力 10.4: Matplotlibによる画像の表示¶
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
img = Image.open("sample.png")
img_array = np.array(img)
fig, axs = plt.subplots(1, 2, figsize=(8, 3))
# Pillow画像を直接表示
axs[0].imshow(img)
axs[0].set_title("Pillow画像")
axs[0].axis("off")
# NumPy配列として表示
axs[1].imshow(img_array)
axs[1].set_title("NumPy配列")
axs[1].axis("off")
plt.tight_layout()
plt.show()
入力 10.5: RGB画像のチャンネル分解と表示¶
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
from urllib.request import urlretrieve
# サンプル画像のダウンロード
url = "https://ml.kano.ac/chapters/data/chikuwa.png"
urlretrieve(url, "chikuwa.png")
# RGBA画像を白背景に合成してRGB画像として読み込む
img_rgba = Image.open("chikuwa.png")
background = Image.new("RGB", img_rgba.size, (255, 255, 255))
background.paste(img_rgba, mask=img_rgba.split()[3])
img_array = np.array(background)
print(f"形状: {img_array.shape}")
# カラー画像とR・G・Bの各チャンネルをグレースケールの明暗として表示
fig, axs = plt.subplots(1, 4, figsize=(12, 3.4))
axs[0].imshow(img_array)
axs[0].set_title("カラー画像")
for i, name in enumerate(["Rチャンネル", "Gチャンネル", "Bチャンネル"]):
axs[i + 1].imshow(img_array[:, :, i],
cmap="gray", vmin=0, vmax=255)
axs[i + 1].set_title(name)
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
入力 10.6: 単純平均法によるグレースケール変換¶
import numpy as np
from PIL import Image
img = Image.open("sample.png")
img_array = np.array(img, dtype=np.float64)
# 単純平均法
gray_simple = img_array.mean(axis=2)
print(f"形状: {gray_simple.shape}")
print(f"左上: {gray_simple[0, 0]:.1f}")
print(f"中央: {gray_simple[30, 30]:.1f}")
入力 10.7: 加重平均法によるグレースケール変換¶
import numpy as np
from PIL import Image
img = Image.open("sample.png")
img_array = np.array(img, dtype=np.float64)
# 加重平均法(ITU-R BT.601)
weights = np.array([0.299, 0.587, 0.114])
gray_weighted = np.dot(img_array, weights)
print(f"形状: {gray_weighted.shape}")
print(f"赤領域: {gray_weighted[30, 10]:.4f}")
print(f"緑領域: {gray_weighted[30, 30]:.4f}")
print(f"青領域: {gray_weighted[30, 50]:.4f}")
入力 10.8: convert("L")によるグレースケール変換¶
from PIL import Image
import numpy as np
img = Image.open("sample.png")
# Pillowのconvertメソッドでグレースケール変換
gray_img = img.convert("L")
print(f"モード: {gray_img.mode}")
print(f"サイズ: {gray_img.size}")
gray_array = np.array(gray_img)
print(f"配列の形状: {gray_array.shape}")
print(f"赤領域: {gray_array[30, 10]}")
print(f"緑領域: {gray_array[30, 30]}")
print(f"青領域: {gray_array[30, 50]}")
入力 10.9: 固定しきい値による二値化¶
import numpy as np
from PIL import Image
# グレースケールのグラデーション画像を作成
gradient = np.tile(np.arange(256, dtype=np.uint8), (100, 1))
img_gray = Image.fromarray(gradient)
img_gray.save("gradient.png")
# NumPy配列に変換
gray_array = np.array(img_gray)
# 固定しきい値 T=128 で二値化
T = 128
binary = np.where(gray_array >= T, 255, 0).astype(np.uint8)
print(f"入力画像の画素値の範囲: {gray_array.min()} - {gray_array.max()}")
print(f"しきい値: {T}")
print(f"二値化後のユニーク値: {np.unique(binary)}")
binary_img = Image.fromarray(binary)
binary_img.save("binary_fixed.png")
print("二値化画像を保存しました")
入力 10.10: 大津の二値化¶
import numpy as np
from PIL import Image
from skimage.filters import threshold_otsu
# テスト用の画像を作成(2つの明るさ領域を持つ画像)
img_array = np.zeros((100, 100), dtype=np.uint8)
img_array[:50, :] = 80 # 上半分: 暗い
img_array[50:, :] = 200 # 下半分: 明るい
# ノイズを追加
rng = np.random.default_rng(42)
noise = rng.normal(0, 20, img_array.shape)
img_noisy = np.clip(img_array + noise, 0, 255).astype(np.uint8)
# 大津の二値化でしきい値を自動決定
thresh = threshold_otsu(img_noisy)
print(f"大津の二値化で求めたしきい値: {thresh}")
# 二値化
binary_otsu = (img_noisy >= thresh).astype(np.uint8) * 255
print(f"二値化後のユニーク値: {np.unique(binary_otsu)}")
入力 10.11: ガウシアンフィルタによるノイズ除去¶
import numpy as np
from PIL import Image
from urllib.request import urlretrieve
from skimage.filters import gaussian
# サンプル画像のダウンロード
url = "https://ml.kano.ac/chapters/data/hanpen.png"
urlretrieve(url, "hanpen.png")
# RGBA画像を白背景に合成してからグレースケール化(0〜1に正規化)
img_rgba = Image.open("hanpen.png")
background = Image.new("RGB", img_rgba.size, (255, 255, 255))
background.paste(img_rgba, mask=img_rgba.split()[3])
img_clean = np.array(background.convert("L")) / 255.0
# ガウスノイズを追加
rng = np.random.default_rng(42)
noise = rng.normal(0, 0.3, img_clean.shape)
img_noisy = np.clip(img_clean + noise, 0, 1)
# ガウシアンフィルタでノイズ除去
img_filtered_s1 = gaussian(img_noisy, sigma=1)
img_filtered_s2 = gaussian(img_noisy, sigma=2)
print(f"ノイズ画像 - 平均: {img_noisy.mean():.4f}", end=", ")
print(f"標準偏差: {img_noisy.std():.4f}")
print(f"sigma=1 - 平均: {img_filtered_s1.mean():.4f}", end=", ")
print(f"標準偏差: {img_filtered_s1.std():.4f}")
print(f"sigma=2 - 平均: {img_filtered_s2.mean():.4f}", end=", ")
print(f"標準偏差: {img_filtered_s2.std():.4f}")
入力 10.12: ノイズ除去結果の比較表示¶
import matplotlib.pyplot as plt
fig, axs = plt.subplots(1, 4, figsize=(12, 3.4))
axs[0].imshow(img_clean, cmap="gray", vmin=0, vmax=1)
axs[0].set_title("元画像")
axs[1].imshow(img_noisy, cmap="gray", vmin=0, vmax=1)
axs[1].set_title("ノイズあり")
axs[2].imshow(img_filtered_s1, cmap="gray", vmin=0, vmax=1)
axs[2].set_title("ぼかし (sigma=1)")
axs[3].imshow(img_filtered_s2, cmap="gray", vmin=0, vmax=1)
axs[3].set_title("ぼかし (sigma=2)")
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
入力 10.13: Sobelフィルタによるエッジ検出¶
import cv2
import numpy as np
import matplotlib.pyplot as plt
# サンプル画像(scikit-image 付属のカメラマン画像、グレースケール)
from skimage.data import camera
img = camera()
# Sobelフィルタの適用
sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) # x方向
sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) # y方向
# エッジ強度の計算
sobel_mag = np.sqrt(sobel_x**2 + sobel_y**2)
sobel_mag = np.uint8(sobel_mag / sobel_mag.max() * 255)
# 結果の表示
fig, axs = plt.subplots(1, 4, figsize=(12, 3.4))
axs[0].imshow(img, cmap="gray")
axs[0].set_title("元画像")
axs[1].imshow(np.abs(sobel_x), cmap="gray")
axs[1].set_title("Sobel X")
axs[2].imshow(np.abs(sobel_y), cmap="gray")
axs[2].set_title("Sobel Y")
axs[3].imshow(sobel_mag, cmap="gray")
axs[3].set_title("エッジ強度")
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
入力 10.14: Cannyエッジ検出の適用¶
import cv2
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
# サンプル画像(10.3.1項でダウンロードした hanpen.png)
img_rgba = Image.open("hanpen.png")
background = Image.new("RGB", img_rgba.size, (255, 255, 255))
background.paste(img_rgba, mask=img_rgba.split()[3])
img = np.array(background.convert("L")) # 0〜255 の uint8
# ガウシアン平滑化でノイズを抑えてからCannyエッジ検出を適用
img_blur = cv2.GaussianBlur(img, (5, 5), 0)
edges = cv2.Canny(img_blur, threshold1=50, threshold2=150)
# 結果の表示
fig, axs = plt.subplots(1, 2, figsize=(10, 4))
axs[0].imshow(img, cmap="gray")
axs[0].set_title("元画像")
axs[1].imshow(edges, cmap="gray")
axs[1].set_title("Cannyエッジ")
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()
入力 10.15: HOG特徴量の計算と可視化¶
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
from skimage.feature import hog
# サンプル画像(入力10.11でダウンロードした hanpen.png)
img_rgba = Image.open("hanpen.png")
background = Image.new("RGB", img_rgba.size, (255, 255, 255))
background.paste(img_rgba, mask=img_rgba.split()[3])
img = np.array(background.convert("L"))
# HOG特徴量の計算(可視化画像も取得)
features, hog_image = hog(
img,
orientations=9,
pixels_per_cell=(8, 8),
cells_per_block=(2, 2),
block_norm="L2-Hys",
visualize=True,
feature_vector=True
)
print(f"HOG特徴量の次元数: {features.shape[0]}")
# 結果の表示
fig, axs = plt.subplots(1, 2, figsize=(10, 5))
axs[0].imshow(img, cmap="gray")
axs[0].set_title("元画像")
axs[1].imshow(hog_image, cmap="gray")
axs[1].set_title("HOG可視化")
for ax in axs:
ax.axis("off")
plt.tight_layout()
plt.show()