LoginSignup
0
1

More than 1 year has passed since last update.

画像をだいたい全部グレースケールにしたい

Posted at

やりたいこと

カラーで保存されたpngファイルがたくさんあります。ほとんどの画像は文字画像なのでグレースケールで保存して容量削減したいのだけれど、一部は写真画像なのでカラーのままにしたい、というケースがあり、Python3+Pillow でやってみました

事前調査

ググり力がたりないけれどいくつか似た要望を持っている人を見つけました。これらをもとに少し頑張ってみます

やったこと

ようはグレーっぽさなる指標を得られればいいわけです。それは、RGBからHSVに変換した際のS値(彩度)です。S値は白・黒・グレーの場合には値が0で, そこから離れるにしたがって値が大きくなり, 最大で255になります(Pillowの場合です。上限を100%にする流儀や1.0にする流儀もあるようです)。

そこで閾値としてS値の平均値を採用し、例えば10くらいにすると「写真画像」と「テキスト画像」の判別ができそうです。

というわけで上述の「やりたいこと」をスクリプト化してみました。

import os, sys, shutil
from PIL import Image

"""
通常のグレー判定なら閾値は1とかでもいいけど,
HTML Linkで色のついた画像の場合もグレーと判定したいなら10くらいの閾値は必要
"""
def check_vivid(im, threshold=10):
    if im.mode in ["1", "L"]:
        return (False, 0)
    pxs = im.convert("HSV").getdata()
    score = sum(map(lambda hsv: hsv[1], pxs)) / len(pxs)
    return (score > threshold, score)

def main(src, dst):
    for f in os.listdir(src):
        f0, ext = os.path.splitext(f)
        if not ext in [".jpg", ".jpeg", ".png"]:
            continue
        im = Image.open(os.path.join(src, f))
        t,v = check_vivid(im)
        print(t,v,f)
        if t:
           shutil.copy(os.path.join(src, f), os.path.join(dst, f))
        else:
           im.convert("L").save(os.path.join(dst, f"{f0}_g{ext}"))

if __name__ == "__main__":
    d = os.path.abspath(sys.argv[1])
    workdir = os.path.dirname(d)
    src = os.path.basename(d)
    dst = os.path.join(workdir, f"{src}_gray")
    os.chdir(workdir)
    os.makedirs(dst, exist_ok=True)
    main(src, dst)

自分の用途ではこれで十分でした。知見があるひとはコメントくれると助かります。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1