【Python】エッジの検出|OpenCVによる画像の特徴抽出(Canny・Sobel・ラプレシアンフィルタ)

こんにちは、DXCEL WAVEの運営者(@dxcelwave)です!

こんな方におすすめ
  • Pythonによる画像処理に興味がある。
  • OpenCVの画像処理技法を活用して「エッジを検出」する方法が知りたい。
目次

OpenCVとは

OpenCV(Open Source Computer Vision Library)とは、画像処理やコンピュータビジョンの分野で広く活用されているオープンソースライブラリです。画像データの数値処理に強いのが特徴であり、高度な統計アルゴリズムも多数含まれていることから、近年機械学習の分野でも広く利用されています。

【OpenCV】エッジ検出とは

エッジ検出とは、黒から白、白から黒などのように、画像の明暗が急激に変わる境目(エッジ)を検出する処理を指します。また、エッジ検出のために用いられるフィルタをエッジフィルタと呼びます。

本記事ではエッジ検出に用いられる代表的なエッジフィルタの活用方法をご紹介します。

  • Canny法
  • Sobelフィルタ
  • ラプレシアンフィルタ

【Python×OpenCV】エッジの検出|Canny

Canny法を活用して画像のエッジ検出を行う場合、cv2.Canny()メソッドを用いた次のコードを実行します。

読込画像部分に画像のディレクトリを指定し、実行してみましょう。

import cv2

# 画像読込(グレースケール)
img = cv2.imread("image_data.jpg",0)

# Cannyのエッジ検出
canny_img  = cv2.Canny(img,   # 入力画像
                       10,    # 2段階の閾値処理で利用する低い閾値
                       180    # 2段階の閾値処理で利用する高い閾値
                      )

# 表示
cv2.imshow("img",img)               # オリジナル画像
cv2.imshow("canny_img",canny_img)   # Cannyのエッジ検出
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.Canny()では2つの閾値を用いるのが特徴です。この閾値を調整することで、正確にエッジを区別できるようになります。

またエッジ検出を適用する際は、事前に画像のグレースケール化を行う必要があることに注意が必要です。

【Python×OpenCV】エッジの検出|Sobelフィルタ

Sobelフィルタを活用してエッジ検出を行う場合を示します。

Sobelフィルタの特徴は、x方向、y方向微分の次数を指定し、エッジ検出を行う点です。例えば、dx=1, dy=0の場合はx方向の微分を行い、画像上に縦方向のエッジが特徴的に出力されるようになります。dx=0, dy=1の場合はy方向の微分を行い、画像上に横方向のエッジが特徴的に出力されるようになります。dx, dyどちらも1に設定すると、縦横両方のエッジが検出されるようになります。

以下、具体例を見ていきましょう。

x方向微分|縦方向のエッジ検出

import cv2

# 画像読込(グレースケール)
img = cv2.imread("image_data.jpg", 0)

# ソーベルフィルタ(x方向に微分)
sobel_x_img = cv2.Sobel(img,         # 入力画像
                        cv2.CV_32F,  # ビット深度
                        1,           # x方向に微分
                        0,           # y方向に微分
                        ksize=3      # カーネルサイズ(3 x 3)
                       ) 

# 微分した際のマイナス値を絶対値に変換
sobel_x_img = cv2.convertScaleAbs(sobel_x_img)

# 微分値
print('sobel_x_img')
print(sobel_x_img)

# 表示・比較
cv2.imshow("img",img)                   # オリジナル画像
cv2.imshow("sobel_x_img",sobel_x_img)   # エッジ検出(x方向微分)
cv2.waitKey(0)
cv2.destroyAllWindows()

y方向微分|横方向のエッジ検出

import cv2

# 画像読込(グレースケール)
img = cv2.imread("image_data.jpg", 0)

# ソーベルフィルタ(x方向に微分)
sobel_y_img = cv2.Sobel(img,         # 入力画像
                        cv2.CV_32F,  # ビット深度
                        0,           # x方向に微分
                        1,           # y方向に微分
                        ksize=3      # カーネルサイズ(3 x 3)
                       ) 

# 微分した際のマイナス値を絶対値に変換
sobel_y_img = cv2.convertScaleAbs(sobel_y_img)

# 微分値
print('sobel_y_img')
print(sobel_y_img)

# 表示・比較
cv2.imshow("img",img)                   # オリジナル画像
cv2.imshow("sobel_y_img",sobel_y_img)   # エッジ検出(y方向微分)
cv2.waitKey(0)
cv2.destroyAllWindows()

x, y微分|縦横双方のエッジ検出

import cv2

# 画像読込(グレースケール)
img = cv2.imread("image_data.jpg", 0)

# ソーベルフィルタ(x方向に微分)
sobel_multi_img = cv2.Sobel(img,         # 入力画像
                            cv2.CV_32F,  # ビット深度
                            1,           # x方向に微分
                            1,           # y方向に微分
                            ksize=3      # カーネルサイズ(3 x 3)
                        ) 

# 微分した際のマイナス値を絶対値に変換
sobel_multi_img = cv2.convertScaleAbs(sobel_multi_img)

# 微分値
print('sobel_multi_img')
print(sobel_multi_img)

# 表示・比較
cv2.imshow("img",img)                           # オリジナル画像
cv2.imshow("sobel_multi_img",sobel_multi_img)   # エッジ検出
cv2.waitKey(0)
cv2.destroyAllWindows()

【Python×OpenCV】エッジの検出|ラプレシアンフィルタ

ラプレシアンフィルタ(Laplacian Filter)を活用してエッジ検出を行う場合、cv2.Laplacian()メソッドを用いた次のようなコードを実行します。

import cv2

# 画像読込(グレースケール)
img = cv2.imread("image_data.jpg", 0)

# ラプラシアンフィルタ
laplacian_img = cv2.Laplacian(img,        # 入力画像
                              cv2.CV_32F  # ビット深度
                             )

# フィルタのマイナス値を絶対値変換
laplacian_img = cv2.convertScaleAbs(laplacian_img)

# 任意|エッジを3倍ほど強調
laplacian_img = laplacian_img * 3

# フィルタ出力
print(laplacian_img)

# 表示
cv2.imshow("img",img)                       # オリジナル画像
cv2.imshow("laplacian_img",laplacian_img)   # ラプレシアンフィルタ
cv2.waitKey(0)
cv2.destroyAllWindows()

ラプレシアンフィルタの場合、ガウシアンフィルタと合わせて実行されるケースが多いです。ガウシアンフィルタを活用した場合のコードも以下に言及します。

import cv2

# 画像読込(グレースケール)
img = cv2.imread("image_data.jpg", 0)

# Gauusianフィルタ
gauusian_img = cv2.GaussianBlur(img,    # 入力画像
                                (3,3),  # カーネルサイズ(x,y)  
                                2       # σの値
                                )

# LaplacianにGaussianフィルタを適用した入力画像を指定
laplacian_img = cv2.Laplacian(gauusian_img,  # 入力画像
                              cv2.CV_32F     # ビット深度
                             )

# フィルタのマイナス値を絶対値変換
laplacian_img = cv2.convertScaleAbs(laplacian_img)

# 任意|エッジを5倍ほど強調
laplacian_img = laplacian_img * 5

# 表示
cv2.imshow("img",img)                       # オリジナル画像
cv2.imshow("laplacian_img",laplacian_img)   # ラプレシアン/ガウシアンフィルタ
cv2.waitKey(0)
cv2.destroyAllWindows()

【参考】Python・OpenCVを用いた画像処理

当サイトでは、PythonのOpenCVライブラリを用いた画像処理ノウハウを多数公開しています。

用途【Python×OpenCV】記事名
画像変換画像のリサイズ・拡大・縮小
画像変換画像の回転・反転・平行移動|アフィン変換
画像変換画像の明るさ調節|ガンマ補正
画像変換グレースケール・HSV・L*a*b|色空間の変換
画像変換モノクロ(白黒)画像変換|2値化処理
画像変換ヒストグラムの描画・ヒストグラム均一化処理
画像変換画像上にテキスト・図形(直線・長方形・円)を描画
画像変換画像の透視変換・遠近法
画像変換画像のノイズ除去・平滑化
画像変換画像の畳み込み(空間フィルタリング)
特徴抽出エッジの検出方法

画像認識や物体検出を学ぶ上でおすすめの教材はこちらをご参考ください。

最後に

この記事が気に入ったら
フォローしてね!

本記事をシェア!
目次