Sobel(ソーベル)フィルタで画像のエッジを抽出する(Python実装編)


本日はSobel(ソーベル)フィルタという画像のディジタルフィルタを紹介し、Sobelフィルタの効果であるエッジの抽出を行うプログラムを紹介してみたいと思います。

以前C++で実装する記事を投稿しましたが、本日はPythonで実装したプログラムを紹介します。C++の方が都合の良い方がいましたら、以下の記事をご参照ください。

今回は、OpenCVでフィルタを使って画像のエッジ抽出をしてみました。 エッジ抽出に使われるフィルタはPrewittフィルタやSob...

Sobelフィルタ

Sobelフィルタは、一次微分を利用して画像から輪郭を抽出するフィルタです。

一次微分というと複雑に感じますが、以下のような係数で与えられるディジタルフィルタです。例のように、水平方向の画素に大きく差がある場合に値が大きくなるため、エッジを抽出することができます。

同じ一次微分フィルタとしてはPrewittフィルタも有名ですが、Sobelフィルタの方がよりくっきりとエッジが抽出できる印象があります。

水平・垂直方向問わずにエッジを抽出したい場合においては、両方のフィルタを掛けた結果を足し合わせるなど、合成することでエッジの抽出が可能です。

画像へのSobelフィルタ適用によるエッジ抽出プログラム(Python+OpenCV)

画像にSobelフィルタを適用するプログラムを以下で紹介します。

以下の3パターンを試せるプログラムとしました。

  1. 水平方向Sobelフィルタ
  2. 垂直方向Sobelフィルタ
  3. 水平・垂直合成Sobelフィルタ

ソースコード

動作環境:OpenCV 4.5.5

import numpy as np
import cv2
import sys
def main():
print("OpenCV Version: " + str(cv2.__version__))
# Loading image data (GRAYSCALE)
filename = "image.png"
image = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
if image is None:
print("Cannot find image data : " + filename)
sys.exit()
# Sobel filter (horizontal)
image_sobel_h = sobel_horizontal(image)
# Sobel filter (vertical)
image_sobel_v = sobel_vertical(image)
# Sobel filter (horizontal & vertical)
image_sobel = sobel(image)
# Saving image
cv2.imwrite('image_sobel_h.png',image_sobel_h)
cv2.imwrite('image_sobel_v.png',image_sobel_v)
cv2.imwrite('image_sobel.png',image_sobel)
def sobel_horizontal(image):
kernel_sobel_h = np.array([[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]])
image_output = cv2.filter2D(image, cv2.CV_64F, kernel_sobel_h)
return image_output
def sobel_vertical(image):
kernel_sobel_v = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
image_output = cv2.filter2D(image, cv2.CV_64F, kernel_sobel_v)
return image_output
def sobel(image):
image_h = sobel_horizontal(image)
image_v = sobel_vertical(image)
image_output = np.sqrt(image_h ** 2 + image_v ** 2)
return image_output
if __name__ == "__main__":
main()

ソースコードの解説

以下の箇所で水平方向Sobelフィルタの処理を記述しています。

def sobel_horizontal(image):
kernel_sobel_h = np.array([[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]])
image_output = cv2.filter2D(image, cv2.CV_64F, kernel_sobel_h)
return image_output

また、以下の箇所で垂直方向Sobelフィルタの処理を記述しています。

def sobel_vertical(image):
kernel_sobel_v = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
image_output = cv2.filter2D(image, cv2.CV_64F, kernel_sobel_v)
return image_output

最後に、以下の箇所で水平・垂直合成Sobelフィルタの処理を記述しています。

def sobel(image):
image_h = sobel_horizontal(image)
image_v = sobel_vertical(image)
image_output = np.sqrt(image_h ** 2 + image_v ** 2)
return image_output

プログラムの動作結果

入力データとしては、以下の2枚の画像を用いました。結果を見る限りでは、エッジが正しく抽出できているように見えます。

画像に alt 属性が指定されていません。ファイル名: lenna-3.png

水平方向Sobelフィルタ

垂直方向Sobelフィルタ

水平・垂直合成Sobelフィルタ

まとめ

本日はSobelフィルタを用いたエッジ抽出を紹介しました。以前にラプラシアンフィルタを用いたエッジ抽出についても紹介しているので、以下の記事も参考にしてみてください。

本日はラプラシアンフィルタという画像のディジタルフィルタを紹介し、ラプラシアンフィルタの効果であるエッジの抽出を行うプログラムを紹介してみ...
スポンサーリンク

シェアする

フォローする