# 基本形 import numpy as np from PIL import Image def error_diffusion_2bit(input_path, output_path): # 1. 画像の読み込み(グレースケール変換) img = Image.open(input_path).convert('L') width, height = img.size # bmpFrom: 変換前の輝度 (0-255) bmpFrom = np.array(img, dtype=np.int32) # bmpTo: 誤差を蓄積・変換後を格納する配列 (0で初期化) # 図3の手順1に従い、最初はすべて0 bmpTo = np.zeros((height, width), dtype=np.int32) # 誤差拡散のパターン設定 (表1より) # 拡散先の相対位置: (dx, dy) tdx = [1, -1, 0, 1] tdy = [0, 1, 1, 1] # 拡散の比率(分子): [7, 3, 5, 1] ratio = [7, 3, 5, 1] denominator = 16 ratioCount = 4 # 2. & 6. 画像の全ピクセルをスキャン for y in range(height): for x in range(width): # [ア] 手順3: 元の輝度と蓄積された誤差を合算 f = bmpFrom[y, x] + bmpTo[y, x] # [イ] 手順4: 判定と誤差dの算出 if f >= 128: pixel_val = 255 d = f - 255 else: pixel_val = 0 d = f # 変換後の値を確定させる # 本来bmpToは誤差用ですが、最終的に出力画像にするため上書きします bmpTo[y, x] = pixel_val # 手順5: 誤差dを周囲に拡散 for c in range(ratioCount): px = x + tdx[c] py = y + tdy[c] # 図5の③: クリッピング(画像範囲内かチェック) if 0 <= px < width and 0 <= py < height: # [ウ]: 小数点以下切り捨てで加算 err_share = (d * ratio[c]) // denominator bmpTo[py, px] += err_share # 7. 画像として出力 result_img = Image.fromarray(bmpTo.astype(np.uint8)) result_img.save(output_path) print(f"変換が完了しました。保存先: {output_path}") # 実行 input_file = '/content/drive/MyDrive/Colab Notebooks/1_AP_programing/parakeet.png' output_file = '/content/drive/MyDrive/Colab Notebooks/1_AP_programing/parakeet_result.png' error_diffusion_2bit(input_file, output_file)