OpenCVのフィルタ処理を調べてみた

#初めに
OpenCVで提供されるフィルタリング処理について調べてみました

#動作環境
Python3,OpenCV

##単純平滑化(ぼかし・ブラー）処理
オリジナルの画像は以下のデータ（グレースケール）であるとして、単純平滑化（ブラー）を行います
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/12f93d67-63f9-c960-6bb0-9738484cb7ee.png)

単純平滑化は、それぞれのピクセルを囲む複数のピクセルの長方形の単純平均を、そのピクセルの値とします
ここでは長方形のサイズを(3*3)としている為に以下のように計算されます
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/693a8fdc-8565-b339-ce67-65409bd4427f.png)

全体のピクセルを計算すると以下のようになります
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/2e7b0f5e-c305-1506-f898-eef219ce6134.png)


```python
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cm as cm

black = [0x00, 0x00, 0x00]
white = [0xFF, 0xFF, 0xFF]

img = np.array([
                [black, black, black, black, black, black, black]
                ,[black, black, black, black, black, black, black]
                ,[black, black, white, white, white, black, black]
                ,[black, black, white, white, white, black, black]
                ,[black, black, white, white, white, black, black]
                ,[black, black, black, black, black, black, black]
                ,[black, black, black, black, black, black, black]                               
                ]
                , dtype=np.uint8)

# グレースケール化
img = cv.cvtColor(img, cv.COLOR_RGB2GRAY)

# グラフ描画域
fig = plt.figure(figsize=(8, 3))
ax1 = fig.add_subplot(121, projection='3d')
ax2 = fig.add_subplot(122, projection='3d')

# X,Y
_x = np.arange(img.shape[1])
_y = np.arange(img.shape[0])
_xx, _yy = np.meshgrid(_x, _y)
x, y = _xx.ravel(), _yy.ravel()
width = depth = 1

# 高さ
top = img.ravel()
bottom = np.zeros_like(top)

# 0-255 を 0.0-1.0に変換する関数の定義(グレースケール表示の為)
norm = colors.Normalize(0, 255)

# オリジナル
color_values = cm.gray(top.tolist())
ax1.bar3d(x, y, bottom, width, depth, top, color=color_values)
ax1.set_title('Original')

# Blur（カーネルサイズ 3*3)
blurImg = cv.blur(img, (3, 3))
top = blurImg.ravel()
color_values = cm.gray(norm(top.tolist()))
ax2.bar3d(x, y, bottom, width, depth, top, color=color_values)
ax2.set_title('Blur')

plt.show()
```
<img width="562" alt="Screen Shot 2020-05-30 at 14.47.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/49da5dab-6a5d-e36a-f8f5-f6b7a53f612d.png">

<img width="634" alt="Screen Shot 2020-05-30 at 14.48.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/e47fe1ed-485c-36f9-3cd8-7265ddd0f618.png">


##メディアンフィルタ処理
メディアンフィルタは、それぞれのピクセルを囲む長方形の中間値を、そのピクセルの値とします
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/22909d30-9fcf-9e51-6190-d46118eaa6d7.png)

全体のピクセルを計算すると以下のようになります
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/b422daa7-17a7-d2e8-11bc-d7f0ba96add0.png)


```python
# medianBlur（カーネルサイズ 3*3)
mBlurImg = cv.medianBlur(img, 3)
top = mBlurImg.ravel()
color_values = cm.gray(norm(top.tolist()))
ax2.bar3d(x, y, bottom, width, depth, top, color=color_values)
ax2.set_title('medianBlur')
```

<img width="556" alt="Screen Shot 2020-05-30 at 15.00.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/dd42a574-0e41-8ceb-34f9-b93bd02a15ab.png">

<img width="617" alt="Screen Shot 2020-05-30 at 15.02.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/748e3e75-1c39-a320-faac-fa9f78b080d6.png">


##Gaussian（ガウシアン）フィルタ処理

ガウシアンフィルタは、それぞれのピクセルを囲む長方形にガウスカーネルと呼ばれる行列を乗じて、その合計値をそのピクセルの値とします
ここで用いている３*３のガウスカーネルは以下のようになります

```math
\begin{pmatrix}
1/16 & 2/16 & 1/16 \\
2/16 & 4/16 & 2/16 \\ 
1/16 & 2/16 & 1/16
\end{pmatrix}
```
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/cc0406e4-c023-92cc-e22d-a61dd9a54005.png)

PixelAは以下のように計算されます

```python
import numpy as np

pixelA = np.array([[0, 0, 0]
                   ,[0, 255, 255]
                   ,[0, 255, 255]])
gaussKernel = np.array([[1/16, 2/16, 1/16]
                        ,[2/16, 4/16, 2/16]
                        ,[1/16, 2/16, 1/16]])
print(sum(sum(pixelA * gaussKernel))) 
#143  
```

全体のピクセルを計算すると以下のようになります
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/2e6a6b6b-9ccd-32cb-ad7e-3d708ca11ad0.png)

```python
# GaussianBlur
gBlurImg = cv.GaussianBlur(img, (3, 3), 0, 0)
top = gBlurImg.ravel()
color_values = cm.gray(norm(top.tolist()))
ax2.bar3d(x, y, bottom, width, depth, top, color=color_values)
ax2.set_title('GaussianBlur')
```

<img width="564" alt="Screen Shot 2020-05-30 at 14.56.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/c818014d-56d4-1d40-a1bd-0c7656428121.png">

<img width="620" alt="Screen Shot 2020-05-30 at 14.57.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/91aedc2a-1d94-665a-ae97-6b512c615e49.png">