blog

DoG (Difference of Gaussians)

Published:

By nob

Category: Posts

Tags: OpenCV DoG Python

画像の輪郭を抽出できるというDoG (Difference of Gaussians) フィルタを試してみる。

画像を読み込む

import cv2
import matplotlib.pyplot as plt

image_file = "data/image/flower.jpg"
image = cv2.imread(image_file)

plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()

fig-1

グレースケールで読み込んでみる。

gray_image = cv2.imread(image_file, cv2.IMREAD_GRAYSCALE)

plt.imshow(gray_image, cmap=plt.cm.gray)
plt.show()

fig-2

DoGフィルタを定義する

def difference_of_gaussians(image, kernel_size, sigma, k=1.6, gamma=1):
    g1 = cv2.GaussianBlur(
        image, ksize=(kernel_size, kernel_size), sigmaX=sigma, sigmaY=sigma
    )
    g2 = cv2.GaussianBlur(
        image,
        ksize=(kernel_size, kernel_size),
        sigmaX=sigma * k,
        sigmaY=sigma * k,
    )
    return g1 - gamma * g2

DOGフィルタを適用する

def show_images(original_image, kernel_size=11, sigma=1.5, k=1.6, gamma=1):
    fig, axs = plt.subplots(1, 3, figsize=(15, 5))
    gray_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
    dog_image = difference_of_gaussians(
        gray_image, kernel_size, sigma, k, gamma
    )
    axs[0].set_title("grayscale")
    axs[0].imshow(gray_image, cmap=plt.cm.gray)
    axs[1].set_title("DoG")
    axs[1].imshow(dog_image, cmap=plt.cm.gray)
    axs[2].set_title("bitwise not DoG")
    axs[2].imshow(cv2.bitwise_not(dog_image), cmap=plt.cm.gray)
    plt.tight_layout()
    plt.show()


show_images(image, 15, 2)

fig-3

葉脈が綺麗に見えるようになった。

図画工作の授業で作った木版画のようにも見える。木彫りの茶托とかで有りそうな。

人物の写真に適用すると消しゴムはんこっぽくなる。

# https://www.pakutaso.com/20141228343post-4919.html
show_images(cv2.imread("data/image/meeting-1024x711.png"), 17, 3)

fig-4

パラメータを変化させてみると興味深い。

これは水墨画っぽい仕上がり。

show_images(image, kernel_size=11, sigma=1.6, k=1, gamma=1.1)

fig-5

注) gamma に浮動小数点数を指定すると np.uint8 の入力に浮動小数点数を乗ずるため出力の画像が np.float64 の配列となる。

先のDoGフィルタ適用後の画像は以下のように白黒反転 ( cv2.bitwise_not ) した画像に一見似ている。

しかしDoGフィルタ適用後の画像を白黒反転すると前景が暗く、背景が明るくなるのに対して白黒反転した画像を再度白黒反転すると (当然だが) 元の画像に戻る。

fig, axs = plt.subplots(1, 3, figsize=(15, 5))
axs[0].set_title("grayscale")
axs[0].imshow(
    cv2.cvtColor(image, cv2.COLOR_BGR2GRAY),
    cmap=plt.cm.gray,
)
axs[1].set_title("bitwise not grayscale")
axs[1].imshow(
    cv2.bitwise_not(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)),
    cmap=plt.cm.gray,
)
axs[2].set_title("bitwise not (bitwise not grayscale)")
axs[2].imshow(
    cv2.bitwise_not(cv2.bitwise_not(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY))),
    cmap=plt.cm.gray,
)
plt.tight_layout()
plt.show()

fig-6

昔の写真のような雰囲気になる。

show_images(image, kernel_size=11, sigma=1.5, k=1.6, gamma=0.96)

fig-7

参考: