Pythonで画像の余白を削除する(Pillow編)
PythonのPillowモジュールを使って、画像の余白部分を削除(クロップ、トリミング)します。
背景差分法と2値化の2種類について述べます。画像によって適切な方法を選択してください。
目次
サンプル画像
本稿でクロップする画像はこちらです。
プロ生ちゃんこと暮井慧さんです。
Pillowで背景差分法によるクロップを行う
背景差分法というのは、クロップ(トリミング)したい画像と背景画像の差分からクロップする範囲を求める方法です。
大凡のな手順は下記です。
背景部分の色を求める。
背景色で元画像と同じ大きさの画像を作成する。
元画像と背景色画像の差を計算する。(差分画像の生成)
差分画像のゼロでない領域のボックスを計算する。
求めたボックスで元画像をクロップする。
これらの計算は、Pillowモジュールの機能でできてしまいます。
背景差分法のコード例
from PIL import Image, ImageChops
img = Image.open('test.jpg')
# 背景色の抽出
bg_img = Image.new('RGB', img.size, img.getpixel((0,0)))
# 差分画像の生成
diff_img = ImageChops.difference(img, bg_img)
# クロップ範囲の計算
crop_range = diff_img.convert('RGB').getbbox()
# クロップの実行と出力
crop_img = img.crop(crop_range)
crop_img.save('out.jpg')
背景差分法での実施例
元画像は347x347のJpegファイルで、(0,0)画素の色は白(255,255,255)です。ですから、背景画像は347x347の白色の画像になります。
背景画像と元画像の差分は、このような画像になります。
背景(余白)部分が黒になっています。
get_bbox()メソッドで差分画像を計算すると(32, 0, 336, 347)という結果が得られます。画素が0(黒色)でない範囲が計算されるわけです。
この範囲を使って元画像をクロップすると、下記の画像が得られます。
う~ん、まだ少し余白が残ってますね。
背景差分法は背景色が白色でなくても同じ手順が使えることがメリットです。
ただし背景色が1色しか指定できないので、見た目は白色だけれども数値的には微妙に異なる画素があったりすると背景とは見なされなくなるのかもしれません。
Pillowで2値化によるクロップを行う
背景が白に近い色であるならば、2値化してクロップの範囲を決めてしまいましょう。
大凡の手順はこうです。
元画像を2値化する。
2値化した画像を、白黒反転する。
白黒反転画像の、画素がゼロでない領域のボックスを計算する。
計算したボックスで元画像をクロップする。
2値化の場合のコード例
from PIL import Image, ImageChops
img = Image.open('test.jpg')
# 2値化画像の生成
bw_img = img.convert(mode='1', dither=None)
# 白黒反転
bw_inv_img = ImageChops.invert(bw_img)
# クロップ範囲の計算とクロップの実行
crop_range = bw_inv_img.convert('RGB').getbbox()
crop_img = img.crop(crop_range)
crop_img.save('out.jpg')
2値化での実施例
元画像をconvert()メソッドで2値化すると、このようになります。
この画像を白黒反転すると、このようになります。
余白部分が黒(0)になっていますね。
この反転画像に対してgetbbox()メソッドで範囲を求めると(40, 9, 323, 347)という結果が得られました。
この範囲で元画像をクロップすると、このような画像が得られます。
書類をスキャンした画像など、余白が単一の白色ではなくややばらつきのある白色の場合は、こちらの方法が良さそうです。
主なメソッド
ImageChops.difference
from PIL import ImageChops
out = ImageChops.difference(image1, image2)
変数 |
型 |
内容 |
---|---|---|
image1 |
Image |
比較する画像1 |
image2 |
Image |
比較する画像2 |
out |
Image |
比較の結果画像 |
2つの画像のピクセルごとの差分画像を生成します。
ImageChops.invert
from PIL import ImageChops
out = ImageChops.invert(image)
変数 |
型 |
内容 |
---|---|---|
image |
Image |
元の画像 |
out |
Image |
色反転した画像 |
画像のピクセルの色(チャンネル)を反転します。
Image.getbbox
from PIL import Image
ret = img.getbbox()
変数 |
型 |
内容 |
---|---|---|
img |
Image |
元の画像 |
ret |
tuple |
ボックスを表すタプル(左、上、右、下) |
画像の画素が0でない領域(ボックス)を計算します。戻り値は、ボックスの左上の座標と右下の座標を示すタプルです。タプルの要素の型はintです。
Image.crop
from PIL import Image
ret = img.crop(box)
変数 |
型 |
内容 |
---|---|---|
img |
Image |
元の画像 |
box |
tuple |
ボックスを表すタプル(左、上、右、下) |
ret |
Image |
クロップされた画像 |
元画像の指定された領域(ボックス)を返します。つまり、指定したボックスでクロップした画像を返します。
公開日
広告
Pythonで画像処理カテゴリの投稿
- Python (Pillow)でグラデーション画像を作る
- PythonでGIFアニメを作る(PILでファイルをつなげる編)
- PythonでOpenCVの画像データをMatplotlibで表示する
- PythonでPDFを画像に変換する(Windows10)
- PythonでPSDファイルをJPEGやPNGに変換する
- Pythonでカラー画像をグレイスケールに変換する(OpenCV編)
- Pythonでフォルダ内に同じ画像がないか検索してみた
- Pythonでマスク画像を作る方法(3選)
- Pythonで図形の外接矩形を描く(OpenCV編)
- Pythonで図形の輪郭の大きさを調べる(OpenCV編)
- Pythonで画像の余白を削除する(OpenCV編)
- Pythonで画像の余白を削除する(Pillow編)
- Pythonで画像の大きさやフォーマットを調べる(Pillow編)
- Pythonで画像の減色をする
- Pythonで画像をトリミングする(Pillow編)
- Pythonで画像を他の画像にペーストする(Pillow編)
- Pythonで画像を回転する(Pillow編)
- Pythonで画像を拡大縮小(リサイズ)する(Pillow編)
- Pythonで画像を読み込み、表示し、保存する(OpenCV編)
- Pythonで画像を読み込み、表示し、保存する(Pillow編)
- Pythonで画像を2値化する(OpenCV編)
- Pythonで記号の輪郭を検出する(OpenCV編)
- PythonとOpenCVで画像をグレースケールに変換してみた
- PythonとOpenCVで画像をネガポジ反転してみた