即興で適当に画像二値化を実装した (Python)

はじめに

普段は大人しいラボのS先輩が,修論を終えて自己主張が激しくなり,こんなことをホワイトボードに書いてどこかに行ってしまった.

研究室のホワイトボードは,みんなの議論に使うのに,これでは研究に支障がでる.
でも,なんか味があるから綺麗に(字だけはっきりするように)電子化しておきたい.
ということで,画像の鮮明化をPythonで実装してみます.とはいえ,濃淡がはっきりしているので極めて簡単な操作です.
以下の記事を参考にしました.

実装

ホワイトボードを正面から撮影し,適当にトリミングしたものを用意.

このままだと,ホワイトボードの地が少し反射していたり,はっきり白になっていないので,
黒字部分をはっきりさせて,ホワイトボードの地は白に塗りつぶすことを目標とする.
(*) わざわざPythonでやる必要もないが,手を動かすのも大事.

In [1]:
# パッケージのインストール
from PIL import Image
import numpy as np
In [2]:
# 画像の読み込み
img = Image.open("original.jpg")


#画像サイズを取得
width, height = img.size

# 新規に作成する画像オブジェクトを用意しておく
img2 = Image.new("RGB", (width, height))
扱いやすいnumpy.array形式の画像データを作成する.
imgオブジェクトに対して,.getpixel((c,i))関数を実行すれば,c列,i行のピクセルのRGB値を取得できる.
要素指定の引数の順番が一般的な行列とは逆なので注意が必要.

In [3]:
#画像ファイルをnp.arrayとして扱う

cal_img = np.zeros(shape=((height,width)), dtype="object")

#わかりやすいように二重ループで書き写し
for i in range(height):
    for c in range(width):
        #img処理は列,行の順
        cal_img[i,c]  = img.getpixel((c,i))
cal_imgの各要素はRGB値を保持したタプルとなっている.

In [4]:
cal_img[2,13]
Out[4]:
(195, 196, 198)
cal_imgを参照しながら,新規イメージimg2の各ピクセルのRGB値を指定していく.
imgオブジェクトには,.putpixel((c, i), (R, G, B))と関数を呼ぶことで,RGB設定ができる.第一引数がピクセル位置(c列,i行!!),第二引数がRGB値である.
今回は,一度グレースケールに変換する関数
g = lambda x : np.mean(x)
をかませて,グレースケールの値に対して適当な閾値を設定し,白(255,255,255)と黒(0,0,0)の二色化した.
グレースケール化は,真面目にやればガンマ補正などのテクニックが必要であるが今回は単純にRGB値の平均:
$$
g = (R + G + B)/3
$$とした.

In [5]:
for i in range(height):
    for c in range(width):
        #gray scaleに変換
        g = lambda x : np.mean(x)
        
        #閾値を設定し白黒に
        if g(cal_img[i,c]) < 130:
            img2.putpixel((c, i), (0, 0, 0))
        else:
            img2.putpixel((c, i), (255, 255, 255))
閾値はいろいろ調節した結果130が丁度良かった.
画像は.show()で確認可能.

In [6]:
img2.show()

In [7]:
#保存
img2.save('new.jpg')

おわりに

the 車輪の再発明だけどまあいいでしょう.お目当てのものはできた.
できた画像は印刷してS先輩の机に置いておきました.

安心して,ホワイトボードの方は消しました.

2