PILで画像の輪郭抽出(エッジ抽出)をする【Python 画像処理】

Python

今すぐ試したい!機械学習・深層学習(ディープラーニング)画像認識プログラミングレシピ [ 川島 賢 ]

 

こんにちは、monachan_papaです。
スマホのカメラで日々、色々な写真を撮るのがもう当たり前の世の中ですね。
私は写真を趣味にしているわけではないですが、撮ることが好きです。撮った写真を必要に応じて加工するのも。

どこまでも楽しめる無限の可能性が写真にはあります。写真のプロでなくても、カメラ愛好家でもなくても構わない、そんな魅力が詰まっています。

ということで、今回はPythonの写真関連のテーマを扱います。
いわゆる画像処理です。その中でも、輪郭抽出(エッジ抽出) について解説します。
この機能自体は、写真加工アプリを使えば簡単にできます。でも、自分でPythonを使って実装できたら楽しいと思いませんか?

本テーマを読むことにより、以下のことが理解できるようになり、画像処理の楽しさを体験することができます。

  • 輪郭抽出の仕組み
  • ピクセル関連の知識
  • 画像の輪郭をPythonで抽出し出力する

輪郭抽出とは?

人間が「物体」の認識をするとき、どうやっているかをまず考えてみます。
どれくらいの大きさをしているのか、形状はどうなのか、色はどうなのか。パッと思いつくのはこんなところでしょう。

これらを「輪郭」という観点で考えてみると、人間は色の変化、影の様子をもとに認識しています。試しに、目を細めて目の前にあるものを見ると、このことが大変理解できるはずです。

一方、写真加工アプリはどうなのか。実は、人間とやっていることの基本は同じです。
画像の濃淡・色の情報を見ながら、「このピクセルについては、隣りのピクセルと比べて値が急激に変化しているぞ!」というところを輪郭と判断しています。

つまり、この急激な変化は、ピクセルごとに隣りのピクセル(X軸方向、Y軸方向)との差分をとることで算出できます。

 

ピクセルごとに隣りのセルとの差分をとる

輪郭抽出の実装

いよいよ実装です。以下の手順で行います。

  • モジュールインポート
  • もと画像読み込み
  • もと画像サイズ取得
  • 輪郭出力用のキャンバス生成
  • もと画像のグレースケール変換
  • 輪郭抽出

なお、テスト用の画像は私の推しである 名古屋のちんどん べんてんや マーサさんの写真を使います。

モジュールインポート

定番モジュールの matplotlib.pyplot、PILのImage だけあればOKです。
numpy はグレイスケールの説明用に使っているので、インポートしているだけです。輪郭抽出自体には使っていません。

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

もと画像読み込み

もと画像を読み込んで表示します。

src_img = Image.open('martha.JPG')
plt.imshow(src_img)
plt.show()

もと画像サイズ取得

輪郭出力用のキャンバスをこの後用意するので、もと画像サイズをもとに、サイズ取得しておきます。

w, h = src_img.size
w, h
(690, 920)

輪郭出力用のキャンバス生成

輪郭出力用のキャンバスを生成します。
このキャンバスにピクセル単位で輪郭を描画していきます。

dst_img = Image.new('RGB', (w, h))
plt.imshow(dst_img)
plt.show()

もと画像のグレースケール変換

画像処理において、定番の処理です。
グレースケールは、白から黒の濃淡 だけで表現する画像です。0〜255までの明るさ情報だけで表現されているので、取り扱いもシンプルです。よって、処理も高速です。

src_img = src_img.convert('L')
plt.imshow(src_img, cmap='gray')
plt.show()

各ピクセルの値は、以下のようになっています。(※量が多いので、部分表示になっています。)

np.array(src_img)
array([[136, 136, 136, ...,  92,  92,  92],
       [135, 136, 136, ...,  92,  92,  92],
       [135, 136, 136, ...,  92,  92,  92],
       ...,
       [190, 190, 190, ...,  75,  71,  70],
       [190, 190, 190, ...,  72,  70,  70],
       [190, 190, 190, ...,  69,  69,  69]], dtype=uint8)

 


今すぐ試したい!機械学習・深層学習(ディープラーニング)画像認識プログラミングレシピ [ 川島 賢 ]

輪郭抽出

ピクセルごとに隣りのピクセル(X軸方向、Y軸方向)との差分をとるわけなので、二重ループにすることですべてのピクセルにアクセスできます。
そして、プロットX軸方向の差分、Y軸方向の差分。この2つの差分合計が10以上であれば、白色をプロットしています。それ以外は黒色をプロットします。
この10以上という条件(閾値) は必要に応じて、変えればOKです。

for y in range(0, h-1):

    for x in range(0, w-1):

            # 差分計算
            diff_x = src_img.getpixel((x+1, y)) - src_img.getpixel((x, y))
            diff_y = src_img.getpixel((x, y+1)) - src_img.getpixel((x, y))
            diff = diff_x + diff_y

            # 差分を出力
            if diff >= 10:
                dst_img.putpixel((x, y), (255, 255, 255))
            else:
                dst_img.putpixel((x, y), (0, 0, 0))

plt.imshow(dst_img)
plt.show()


以上で、輪郭抽出についての解説を終わります。画像処理の楽しさが体感できたでしょうか?
Pythonによる画像処理で出来ることは、この他にもたくさんあります。ディープ・ラーニングも取り入れれば、もっとすごいことも可能となります。スマホの顔認証など身近な例ですね。

画像処理にもっと詳しく触れてみたい!という御方は、今すぐ試したい!機械学習・深層学習(ディープラーニング)画像認識プログラミングレシピ [ 川島 賢 ]が大変おすすめです。もし、画像処理でやってみたい事がすぐにでも思いつかない場合でも、お題がちゃんと用意されています。
例えば、犬なのか猫なのかを認識する犬猫認識など。Pythonで画像処理をもっと楽しみましょう。


今すぐ試したい!機械学習・深層学習(ディープラーニング)画像認識プログラミングレシピ [ 川島 賢 ]

 

また、爆速で Python画像処理 を学びたい御方にはプログラミングスクールを考えるのも、ひとつの手です。独学よりも効果が出やすいですが、いかんせん投資がけっこうかかります。しかし、techgymというスクールは通うか通わないかは別として、無料のサンプルテキスト&解説動画がもらえます。これをとりあえず getしてまずは試しに体験学習するのもありでしょう。

コメント

タイトルとURLをコピーしました