OpenCVで各種フィルター処理をする（グラディエント、ハイパス、ラプラシアン、ガウシアン）

# はじめに

OpenCV(Open Source Computer Vision Library)はBSDライセンスの映像/画像処理ライブラリ集です。画像のフィルタ処理、テンプレートマッチング、物体認識、映像解析、機械学習などのアルゴリズムが多数用意されています。

OpenCVを使った動体追跡の例 (OpenCV Google Summer of Code 2015)
[https://www.youtube.com/watch?v=OUbUFn71S4s](https://www.youtube.com/watch?v=OUbUFn71S4s)

インストールと簡単な使い方はこちら
[http://qiita.com/olympic2020/items/d5d475a446ec9c73261e](http://qiita.com/olympic2020/items/d5d475a446ec9c73261e)

静止画像のフィルター処理についてはこちら
[OpenCVでエッジ検出してみる](http://qiita.com/olympic2020/items/2c3a2bfefe73ab5c86a4)

動画ファイルの処理についてはこちら
[OpenCVで動画をリアルタイムに変換してみる](http://qiita.com/olympic2020/items/ce00fab38d829965db3b)
[OpenCVでWebカメラ/ビデオカメラの動画をリアルタイムに変換してみる](http://qiita.com/olympic2020/items/12a2eceaf65f142ec3df)

今回は、各種フィルターを適用してみます。

# 各種フィルター
今回紹介するフィルターは以下になります。

+ ハイパス フィルタ  
    　方向に関係なくエッジを抽出することができます。  
    　  
+ グラディエント フィルタ  
    　１次微分フィルタと呼ばれることもあります。１方向のエッジ抽出を行うことができます。カーネルを回転させることで、上下方向、左右方向のどの方向のエッジを抽出するのかを指定することができます。  
    　  
+ ラプラシアン フィルタ  
    　２次微分フィルタと呼ばれることもあります。平面の全方向のエッジ抽出します。  
    　  
+ ガウシアン フィルタ  
    　平滑化フィルタの１種です。ノイズ除去に用います。ただし、カーネルが粗いと、かえってノイズがのってしまうこともあります。  
    　  

# プログラム

各種フィルター処理を行うための行列をカーネルとよびます。
プログラムは、各フィルタに対して、以下の処理を行っています。

1. カーネルを定義
2. cv2.filter2D()を適用する
3. ファイルに保存する

```filter.py
import cv2
import numpy as np


# 定数定義
FILE_ORG = "img.png"
FILE_GRAY = "gray.png"
FILE_GRADIENT = "gradient.png"
FILE_HIGH_PASS = "highpass.png"
FILE_LAPLACIAN_3x3 = "laplacian3x3.png"
FILE_LAPLACIAN_5x5 = "laplacian5x5.png"
FILE_GAUSSIAN = "gaussian.png"

# 元の画像を読み込む
img_org = cv2.imread(FILE_ORG, cv2.IMREAD_COLOR)

# グレースケール変換
img_gray = cv2.cvtColor(img_org, cv2.COLOR_BGR2GRAY)
cv2.imwrite(FILE_GRAY, img_gray)

# グラディエント フィルタ（３ｘ３）
kernel_gradient_3x3 = np.array([
                            [ 1,  1,  1],
                            [ 0,  0,  0],
                            [-1, -1, -1]
                            ], np.float32)
img_gradient_3x3 = cv2.filter2D(img_gray, -1, kernel_gradient_3x3)
cv2.imwrite(FILE_GRADIENT_3x3, img_gradient_3x3)

# グラディエント フィルタ（５ｘ５）
kernel_gradient_5x5 = np.array([
                            [ 5,  5,  5,  5,  5],
                            [ 3,  3,  3,  3,  3],
                            [ 0,  0,  0,  0,  0],
                            [-3, -3, -3, -3, -3],
                            [-5, -5, -5, -5, -5]
                            ], np.float32)
img_gradient_5x5 = cv2.filter2D(img_gray, -1, kernel_gradient_5x5)
cv2.imwrite(FILE_GRADIENT_5x5, img_gradient_5x5)

# ハイパス フィルタ
kernel_high_pass = np.array([
                            [-1, -1, -1],
                            [-1,  8, -1],
                            [-1, -1, -1]
                            ], np.float32)
img_high_pass = cv2.filter2D(img_gray, -1, kernel_high_pass)
cv2.imwrite(FILE_HIGH_PASS, img_high_pass)

# ラプラシアン フィルタ（３×３）
kernel_laplacian_3x3 = np.array([
                            [1,  1, 1],
                            [1, -8, 1],
                            [1,  1, 1]
                            ], np.float32)
img_laplacian_3x3 = cv2.filter2D(img_gray, -1, kernel_laplacian_3x3)
cv2.imwrite(FILE_LAPLACIAN_3x3, img_laplacian_3x3)

# ラプラシアン フィルタ（５ｘ５）
kernel_laplacian_5x5 = np.array([
                            [-1, -3, -4, -3, -1],
                            [-3,  0,  6,  0, -3],
                            [-4,  6, 20,  6, -4],
                            [-3,  0,  6,  0, -3],
                            [-1, -3, -4, -3, -1]
                            ], np.float32)
img_laplacian_5x5 = cv2.filter2D(img_gray, -1, kernel_laplacian_5x5)
cv2.imwrite(FILE_LAPLACIAN_5x5, img_laplacian_5x5)

# ガウシアン フィルタ
kernel_gaussian = np.array([
                            [1,  2, 1],
                            [2,  4, 2],
                            [1,  2, 1]
                            ], np.float32) / 16
img_gaussian = cv2.filter2D(img_gray, -1, kernel_gaussian)
cv2.imwrite(FILE_GAUSSIAN, img_gaussian)
```

# 実行結果
実行結果の画像です。３ｘ３のフィルタは建物のエッジをシャープにとらえています。一方、５ｘ５のフィルタは風景の大きな変化をとらえています。

![img.png](https://qiita-image-store.s3.amazonaws.com/0/107056/b2249297-b481-74dc-7746-9e1b684e4f70.png)
　　　　　　　　　　　　　　　**元画像**

![gray.png](https://qiita-image-store.s3.amazonaws.com/0/107056/5a2b9768-1d05-3204-8034-b44d789658b6.png)
　　　　　　　　　　　　　**グレースケール**

![gradient3x3.png](https://qiita-image-store.s3.amazonaws.com/0/107056/fd03a16b-14d8-2ec7-8216-c69f2255af6b.png)
　　　　　　　　　　　**グラディエント フィルタ（３ｘ３）**

![gradient5x5.png](https://qiita-image-store.s3.amazonaws.com/0/107056/479f4f6d-8c43-c2af-85e2-4672597fc48f.png)
　　　　　　　　　　　**グラディエント フィルタ（５ｘ５）**

![highpass.png](https://qiita-image-store.s3.amazonaws.com/0/107056/99baaf9d-661d-846d-c102-c006bd50eb03.png)
　　　　　　　　　　　　　**ハイパス フィルタ**

![laplacian3x3.png](https://qiita-image-store.s3.amazonaws.com/0/107056/2546e7c3-1cb9-4e58-1dc2-c655c578159e.png)
　　　　　　　　　　　**ラプラシアン フィルタ（３ｘ３）**

![laplacian5x5.png](https://qiita-image-store.s3.amazonaws.com/0/107056/788faad9-0b7a-245f-2f15-b00e10474772.png)
　　　　　　　　　　　**ラプラシアン フィルタ（５ｘ５）**

![gaussian.png](https://qiita-image-store.s3.amazonaws.com/0/107056/db10df3f-614e-bacf-e527-4a0291008ac6.png)
　　　　　　　　　　　　　**ガウシアン フィルタ**