機械系エンジニアの備忘録

20代独身社会人。仕事では機械・機構の研究開発を行っているエンジニアが、自分の専門分野ではないpythonを扱って楽しむブログです。

MENU

【python】【OpenCV】画像の輪郭抽出を行う

OpenCVのSobelとLaplacianを使って輪郭抽出を行う

f:id:stjun:20200222152657p:plain

 

1. 誰に向けた記事か

pythonを勉強している人

OpenCVに興味がある人

・画像処理に興味がある人

※初心者向けにpythonの勉強法とその手順を記事にしました。

www.stjun.com

 

 

2. はじめに

これまで画像の2値化や3値化を行いました。

www.stjun.com

www.stjun.com

今回は画像の輪郭抽出を行ってみます。

 

3. コードと実行結果と説明

3.1 コード:Sobelを用いた輪郭抽出
#エッジ検出:Sobel
import cv2
#画像の読み込み
img=cv2.imread('./test.jpg',0)

#x方向の輪郭抽出
img_sx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
#y方向の輪郭抽出
img_sy=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)

#絶対値に直す
img_sx=cv2.convertScaleAbs(img_sobelx)
img_sy=cv2.convertScaleAbs(img_sobely)

#画像の表示
cv2.imshow("Sobel_x",img_sx)
cv2.imshow("Sobel_y",img_sy)
cv2.waitKey(0)
cv2.destroyAllWindows()

上記を実行すると、次のように横方向(x方向)と縦方向(y方向)のSobelフィルターを使った画像が表示されます。 

f:id:stjun:20200222154915p:plain

 

3.2 コード:Laplacianを用いた輪郭抽出
#エッジ検出:Laplacian(2次微分)
import cv2

#画像の読み込み
img=cv2.imread('./test.jpg',0)
#輪郭抽出
img_lap=cv2.Laplacian(img,cv2.CV_64F)
#絶対値に直す
img_lap=cv2.convertScaleAbs(img_lap)

#画像の表示
cv2.imshow("y",img_lap)
cv2.waitKey(0)
cv2.destroyAllWindows()

以上を実行すると次の画像が現れます。

f:id:stjun:20200222155134p:plain

 

3.3 説明1:輪郭抽出とは

輪郭抽出とは物体の輪郭を際立たせる処理のことを言います。

輪郭抽出の原理ですが、結論から言うと隣り合う画素値の変化量を見ています。

例えば、隣り合う画素値が200,204だと変化量は4と小さいですね。逆に隣り合う画素値が黒(0)と白(255)だと変化量は255と非常に大きいです。この変化量が大きいところが輪郭だとして処理を行っています。

 

3.4 説明2:Sobelとは

Sobelは1次微分と言われます。簡単に言ってしまえば隣り合う画素値の差を計算しています。

Sobelには方向があります。選んだ方向と平行な線は抽出が困難なので気を付けて下さい。例えば縦方向に差を取ると以下の画像になります。赤で囲った部分の輪郭はSobelの方向と平行なので抽出されていませんね。

f:id:stjun:20200222161747p:plain

そのため画像によって横方向の差をとるか縦方向の差をとるか,自分で決める必要があります。なお単純に差を取ってるわけではなく、以下のフィルター(例:縦方向)を用いて差を計算しています。

f:id:stjun:20200222162942p:plain

 

3.5 説明3:Sobelのコード
#x方向の輪郭抽出
img_sx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
#y方向の輪郭抽出
img_sy=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)

#絶対値に直す
img_sx=cv2.convertScaleAbs(img_sobelx)
img_sy=cv2.convertScaleAbs(img_sobely)

Sobel()で輪郭抽出を行います。

カッコの中の引数は左から、

・処理したい画像(=img)

・計算後の数値のタイプ(64Fだと正負を表示できます、cv_8Uにすると負の変化量を全て0にしてしまいますので64Fにしましょう)

・差分を取る方向(1,0なら横方向、0,1なら縦方向)

カーネルのサイズ(基本3で良いと思います)

またconvertScaleAbsで絶対値に変換します。

どういうことかと言うと、変化率を取っているので、黒⇒白の変化率は正になりますが白⇒黒の変化率は負になります。以下の画像でも負の数値がありますね。

f:id:stjun:20200222161011p:plain

Sobel()で計算後の値

しかしグレースケールで扱えるのは0(=黒)~255(=白)の正の値だけでした。

そこでconvertScaleAbsで絶対値を取ります。

f:id:stjun:20200222161138p:plain

convertScaleAbsで絶対値を取った値

後は、画像を表示するだけです。

 

3.6 説明4:Laplacianとは

Laplacianは2次微分と言われます。簡単に言ってしまえば隣り合う画素値の差の差を計算しています。つまり2回差をとっています。

Laplacianには方向がありません。しかし差の差を取るので変化量の値がSobelより小さくなり、輪郭が薄くなります。

 

3.7 説明5:Laplacianのコード
#輪郭抽出
img_lap=cv2.Laplacian(img,cv2.CV_64F)
#絶対値に直す
img_lap=cv2.convertScaleAbs(img_lap)

Laplacian()で輪郭抽出を行います。

引数は、

・処理したい画像

・計算後の数値のタイプ

です。

後はSobelの時と同じようにconvertScaleAbsで絶対値を取ります。

 

自分が使ってるお得情報の紹介

私はAmazon kindle unlimitedというサービスを1年以上利用しています。

これは月額980円で 和書12万冊以上の電子書籍を読めるサービスです。

ビジネス本、雑誌、漫画、技術本など様々な本を読むことができます。10冊まで端末にダウンロードできるのでネット環境がなくても(オフラインでも)見れます。

なおkindle unlimitedは最初の30日間無料のため、気軽に登録してみて、あまり読みたい本が無ければすぐに解約しても問題ありません。

それか30日内に気になる本を全て読破すれば実質タダです。

ぜひ気になった方はチェックしてみて下さい。

なおkindleにない本等を買う時はamazonギフト券(amazonで使えるポイント)を買い、ポイントで数冊まとめて買った方がお得です。

ギフト券(ポイント)は買ったら10年も有効で、ポイントが付きます。さらに本をまとめ買い(2冊以上同時に)買うと、ポイントがもらえます。

https://www.amazon.co.jp/b?ie=UTF8&node=5431437051

学生さんであればkindle unlimitedよりも年2450円(月210円程度)で映画見放題、音楽聞き放題、本読み放題の「prime student」がおすすめです。