【Python/PIL】getbboxとcropで画像の余白を削除する

画像の余白を削除する方法の解説ページアイキャッチ

このページにはプロモーションが含まれています

このページでは、Python で PIL を用いて「画像の余白を削除する方法」について解説していきます。

今回紹介する方法を用いれば、下の画像のように絵の周りに不要な透明な余白がある場合、

余白がついている画像の紹介図

この透明な余白を削除し、絵の部分のみの画像を取得することができます。

余白を削除する様子

あくまでも取得できるのは矩形単位(長方形単位)で、絵の縁に沿うように取得できるわけではないので注意してください。

また、ほぼ同じ考え方で、透明度が設定されていない画像の不要な黒色・白色の余白を削除することも可能なので、これらについての方法も紹介していきます!

透明な余白を削除する方法:getbboxcrop を実行

まずは、透明度が設定された画像における「透明な余白を削除する方法」について解説します。

より具体的に言えば、この方法は「画像の縁付近の不要な透明画素を除去する方法」となります。

結論としては、PIL を用いて下記のような処理を実行することで、画像の縁付近の不要な余白を削除することが可能です。

透明な余白の削除
from PIL import Image

# ファイルパスの設定
LOAD_PATH = "読み込みたい画像のファイルパス"
SAVE_PATH = "保存先の画像のファイルパス"

# 画像を読み込む
image = Image.open(LOAD_PATH)

# 不要な透明画素を除去
cropped_image = image.crop(image.getbbox())

# 画像を保存
cropped_image.save(SAVE_PATH)

上記スクリプトを実行すれば、LOAD_PATH で設定されたパスの画像の「透明な余白を除去した画像」が SAVE_PATH で設定されたパスに保存されます。

スクリプト実行によって不要な透明な余白が削除された様子

ただし、LOAD_PATH で設定されたパスの画像に透明度が設定されていない場合、黒色の余白が除去されることになります。これについては後述の 黒色の余白を削除する方法:透明な余白を削除するときと同じ で解説します。

透明な余白の削除を行なっているのは、先程のスクリプトで太字で示した下記部分になります。

cropとgetbbox
# 不要な透明画素を除去
cropped_image = image.crop(image.getbbox())

crop メソッドでの不要な領域の削除

PIL には crop メソッドが用意されており、画像から引数で指定した領域のみを切り出すことが可能です。つまり、領域外の画素を除去することができます。

cropメソッドの動作を示す図

ですので、画像の不要な余白(透明画素)を除いた領域を指定して crop を実行すれば、不要な余白を除去することができることになります。

余白を除いた領域の座標を指定してcropメソッドを実行する様子

したがって、画像の不要な余白を除いた領域さえ取得できれば、後は crop メソッドを実行すれば良いということになりますね!

スポンサーリンク

getbbox での余白を除いた領域の取得

その領域の取得を行なっているのが getbbox メソッドになります。

getbbox メソッドでは、実行した画像オブジェクトに透明度が設定されている場合、透明でない画素が存在する矩形領域の座標を取得することができます。

getbboxで余白を除いた矩形領域の座標を取得する様子

したがって、getbbox メソッドで取得した座標を引数に指定して crop メソッドを実行すれば、その実行した画像オブジェクトから不要な余白を削除した結果を返却値として得ることができます。

getbboxとcropで不要な余白を取り除く様子

もう少し具体的にいうと、画像での透明度はアルファチャンネルというデータで画素ごとに設定されており、ここで言う “透明な画素” とはアルファチャンネルが 0 に設定されている画素となります。つまり、完全に透明な画素です。

半透明な画素は getbbox メソッドにおいて透明な画素とは見做されないので注意してください。

ちなみにアルファチャンネルについては下記ページの前半で解説していますので、詳しく知りたい方は下記ページをご参照いただければと思います。

Pythonでアルファチャンネルのみを取得する方法の解説ページアイキャッチ 【Python】アルファチャンネルのみを画像から取得する方法(PIL・NumPy・OpenCV)

黒色の余白を削除する方法:透明な余白を削除するときと同じ

透明な余白を削除する方法:getbbox と crop を実行 で紹介したスクリプトで LOAD_PATH に透明度が設定された画像を指定した場合、その画像の透明な余白を削除することができました。

では、LOAD_PATH に透明度が設定されない画像を指定した場合はどのようにスクリプトは動作するでしょうか?

この場合、黒色の余白が削除されることになります。

スクリプト実行により黒色の余白が削除される様子

つまり、黒色の余白の削除は 透明な余白を削除する方法:getbbox と crop を実行 と同じ方法で実現することができることになります。

getbbox メソッドでは、透明度が設定されている画像の場合、”透明でない画素が存在する矩形領域” の座標を取得することができます。その一方で、透明度が設定されていない画像の場合、getbbox メソッドでは “黒色でない画素が存在する矩形領域” の座標が取得されます。

したがって、その座標を crop メソッドの引数に指定して実行すれば、その領域以外を除去した画像を取得することができ、黒色の余白を削除することができることになります。

ちなみに “黒色の画素” とは、画素の R と G と B の値が全て 0 に設定されている画素となります。

白色の余白を削除する方法:色反転してから getbbox を行う

ただ、余白は白色であることが多いので、黒色の余白が削除できてもそこまで旨みがありません。

では白色の余白を削除するにはどうすれば良いでしょうか?

これは、一旦画像の色を反転してから getbbox メソッドを実行することで実現することができます。

具体的なスクリプトは下記のようになります。

白色の余白の削除
from PIL import Image, ImageOps

# 読み込みたい画像のファイルパス
LOAD_PATH = "読み込みたい画像のファイルパス"
SAVE_PATH = "保存先の画像のファイルパス"

# 画像を読み込む
image = Image.open(LOAD_PATH)

# 色を反転した画像を生成
inverted_image = ImageOps.invert(image)

# 不要な白色画素を除去
cropped_image = image.crop(inverted_image.getbbox())

# 画像を保存
cropped_image.save(SAVE_PATH)

ImageOps.invert(image) を実行することで、元画像の色を反転した画像を生成しています(ImageOpsimport する必要があるので注意してください)。

したがって、元々白色の余白だった部分は黒色の余白に色が反転することになります。

invert関数で画像の色が反転する様子

ですので、あとは 黒色の余白を削除する方法:透明な余白を削除するときと同じ と同じ要領で、getbbox メソッドでその黒色の余白を除いた矩形領域の座標を取得し、それを引数として元画像の画像オブジェクト imagecrop メソッドを実行させれば、白色の余白を削除した画像を取得することができます。

スクリプトの実行で白色の余白が削除される様子

あくまでも ImageOps.invert を実行するのは getbbox メソッドで座標を取得するためであり、最終的な crop メソッドの実行は元画像の image に実行させる必要があるので注意してください。

スポンサーリンク

まとめ

このページでは、Python で PIL を用いて「画像の余白を削除する方法」について解説しました!

透明な余白、黒色の余白、白色の余白ともに、getbbox メソッドと crop メソッドの利用により削除を実現することができます。

白色の余白の場合は getbbox メソッド実行時に色の反転が必要なので注意してください。getbbox メソッドで取得できる領域は、透明でない画素が存在する領域の矩形 or 黒色でない画素が存在する領域の矩形となります。

また、他の色の余白であっても、getbbox メソッド実行前に余白を完全な黒色に加工した画像を作成してやれば、同様の方法で余白の削除が可能です。例えば背景の色と元画像の差分画像に対して getbbox メソッドを実行してやれば、余白の削除が実現できそうですね!

getbbox メソッドの解説ページ自体は少ないですが、割と活躍する場面が多いメソッドだと思いますので、是非このメソッドの意味合いや存在は覚えておいてください!

同じカテゴリのページ一覧を表示