<jupyter_start><jupyter_text>最終課題PPM画像を読み込み，モザイク処理を施した上でファイルに出力するプログラム  パラメータ<jupyter_code>data_dir = '/drive/My Drive/Colab Notebooks/'
infile = 'yufuin_800_580.ppm'
block_size = 23
outfile = 'yufuin_pixelized.ppm'
from google.colab import drive
drive.mount('/drive')<jupyter_output>Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&scope=email%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdocs.test%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.photos.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fpeopleapi.readonly&response_type=code

Enter your authorization code:
··········
Mounted at /drive<jupyter_text>画像情報の取得 (第13回のやつ)<jupyter_code># ファイルを開いてデータ読み込み
#   binary read-onlyモードでファイルを開いて
with open(data_dir + infile, 'rb') as f:
    # データを読み込んでファイルを閉じる
    img_raw = f.read()
# 改行文字で分離
img_split = img_raw.split(b'\n')<jupyter_output><empty_output><jupyter_text>画像サイズを取得<jupyter_code># P6は必ず先頭行
# その後のコメント行を読み飛ばす
line_no = 1
while True:
    # 念のため、改行文字などを除去
    target_line = img_split[line_no].decode().strip()
    if target_line[0] != '#':
        break
    line_no += 1
# 画像サイズの行を抽出
img_size_str = img_split[line_no].decode().strip()
# スペースで分離
img_size_str = img_size_str.split(' ')
import numpy as np
if not all(np.char.isnumeric(img_size_str)):
    print('不正な画像ファイルです')
    quit()
# 数値に変換
img_size = np.array(list(map(int, img_size_str)))
print("画像サイズ: {:d}x{:d}".format(img_size[0], img_size[1]))<jupyter_output>画像サイズ: 800x580<jupyter_text>画像の色階調数の抽出<jupyter_code>line_no += 1
img_depth_str = img_split[line_no].decode().strip()
if not np.char.isnumeric(img_depth_str):
    print('不正な画像ファイルです')
    quit()
img_depth = int(img_depth_str)

# PPM形式のimg_depthは必ず255のはず
if img_depth != 255:
    print('不正なPPM画像ファイルです')
    quit()<jupyter_output><empty_output><jupyter_text>画像データ読み込み<jupyter_code># RGBの3色それぞれが img_bytes ずつのデータとして格納されている
line_no += 1
img_data = b'\n'.join(img_split[line_no:])
# 8-bitのunsigned intが並んでいるものとして画像データを読み込み
data = np.frombuffer(img_data, dtype=np.uint8)<jupyter_output><empty_output><jupyter_text>画像データの加工<jupyter_code># R, G, Bの順に1 byteずつで明るさが並んでいるので並べ替えて3次元配列にする
# まず3色の順に並んでいるので3色に分け、
# 次に横軸に並んでいるので横軸の数で分け、
# 最後に縦軸の数で分ける
data = data.reshape(img_size[1], img_size[0], 3)

# 分かりやすくするため軸の順番を入れ替える
data = data.transpose(2,1,0)<jupyter_output><empty_output><jupyter_text>モザイクブロックの代表値を計算する関数 (第12回のやつを応用して3色データに対応)<jupyter_code>def smooth_image_ext(block_size, block_loc, img):
    # imgは(color, x, y)の次元とする
    topx = block_loc[0]
    topy = block_loc[1]

    # 画像サイズ外の場所を指定されたらエラー
    if topx < 0 or topy < 0 or topx >= img.shape[1] or topy >= img.shape[2]:
        return np.nan

    # 画像の端ではみ出す場合は端を基準にする
    # 右端
    if topx + block_size >= img.shape[1]:
        topx = img.shape[1] - block_size
    # 下端
    if topy + block_size >= img.shape[2]:
        topy = img.shape[2] - block_size

    # 平均化処理は演習問題と同じ，intの代わりにnp.roundなどを使っても良い（結果は変わるけど・・・）
    return (np.mean(img[:, topx:topx+block_size, topy:topy+block_size], axis=(1,2))).astype(np.int)<jupyter_output><empty_output><jupyter_text>モザイクブロックに適用<jupyter_code># 処理するブロックの数 (x, y)
blocks = (np.ceil(np.array(data.shape[1:]) / block_size)).astype(np.int)
# 結果格納先を用意
result = np.empty(data.shape, dtype=np.uint8)

for x in range(blocks[0]):
    for y in range(blocks[1]):
        # 各ブロックの代表値を計算 (色ごとに3次元になって返却)
        ret = smooth_image_ext(block_size, [x*block_size,y*block_size], data)
        # 結果を格納 (元画像のサイズに合わせて、ブロック全部を代表値で埋める必要がある)
        ## 格納先が端になる場合はサイズが異なるのでサイズを計算しておく
        fill_size = [block_size, block_size]
        if (x+1)*block_size > data.shape[1]:
            fill_size[0] = data.shape[1] % block_size
        if (y+1)*block_size > data.shape[2]:
            fill_size[1] = data.shape[2] % block_size
        ## 格納先サイズに合わせて結果をコピーしてから格納
        result[:,x*block_size:x*block_size+fill_size[0],y*block_size:y*block_size+fill_size[1]] = \
            np.tile(ret, [fill_size[0], fill_size[1], 1]).transpose(2,0,1)<jupyter_output><empty_output><jupyter_text>画像の保存<jupyter_code>result.shape
# 保存のために軸の順序を元に戻す
result = result.transpose(2,1,0)
result.shape
with open(data_dir + outfile, 'wb') as f:
    # ヘッダ情報は元画像と同じなのでそのまま出力
    f.write(b'\n'.join(img_split[:line_no]))
    f.write(b'\n')
    # 並べ替え済みのデータはそのまま保存
    f.write(result.tobytes())<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1397107897664071, 'fraction_numerical': 0.03159065628476085, 'mean_word_length': 5.544395924308588, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 41, 'https://': 1, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '441794', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2428, 'n_tokens_neox': 2373, 'n_words': 238, 'path': 'final.ipynb', 'repo_name': 'pman0214/qu-kikan-prog-2020-enshu-answers', 'size': '4495'}