OpenCVのcopyMakeBorderのオプションを調べてみた

#初めに
OpenCVでのフィルタリング処理（Blur, Filter）は、特定の領域を定義して、その総和をとる事により画像を加工（ぼかし・ノイズ除去）しています
この時、画像の縁部分に対しては領域を拡張して計算するわけですが、その拡張方法について調べてみました。


#動作環境
Python3,OpenCV

##定数値で拡大(BORDER_CONSTANT)
黒色(0, 0, 0)で拡張します

```python
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

black = [0x00, 0x00, 0x00]
dimgray = [0x69, 0x69, 0x69]
gray = [0x80, 0x80, 0x80]
darkgray = [0xa9, 0xa9, 0xa9]
silver = [0xc0, 0xc0, 0xc0]
lighgray  = [0xd3, 0xd3, 0xd3]
gainsboro = [0xdc, 0xdc, 0xdc]
whiteSmoke = [0xf5, 0xf5, 0xf5]
white = [0xFF, 0xFF, 0xFF]

img = np.array([
                [black, white, black, white, black]
                ,[white, dimgray, white, dimgray, white]
                ,[gray, white, gray, white, gray]
                ,[white, darkgray, white, darkgray, white]
                ,[silver, white, silver, white, silver]
                ,[white, lighgray, white, lighgray, white]
                ,[gainsboro, white, gainsboro, white, gainsboro]
                ,[white, whiteSmoke, white, whiteSmoke, white]
                ])
# 拡張ピクセル数
exPixelNum = 8

plt.subplot(121),plt.imshow(img),plt.imshow(img),plt.title('Original')
conBdImg = cv.copyMakeBorder(img, exPixelNum, exPixelNum, exPixelNum, exPixelNum, cv.BORDER_CONSTANT)
plt.subplot(122),plt.imshow(conBdImg),plt.title('BORDER_CONSTANT')
plt.show()
```

<img width="544" alt="Screen Shot 2020-05-17 at 16.02.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/5e6e12b8-1b40-dfc0-6771-fcad81cac657.png">



##反対側のピクセルを複数(BORDER_WRAP)

```python
# オリジナル画像（比較のために黒色で拡張しています）
orgImg = cv.copyMakeBorder(img, exPixelNum, exPixelNum, exPixelNum, exPixelNum, cv.BORDER_CONSTANT)
plt.subplot(121),plt.imshow(orgImg),plt.title('Original')
plt.xticks([]), plt.yticks([])

# Wrap画像
wrpBdImg = cv.copyMakeBorder(img, exPixelNum, exPixelNum, exPixelNum, exPixelNum, cv.BORDER_WRAP)
plt.subplot(122),plt.imshow(wrpBdImg),plt.title('BORDER_WRAP')
plt.xticks([]), plt.yticks([])
plt.show()
```
<img width="509" alt="Screen Shot 2020-05-17 at 16.23.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/895a3e48-a049-a0e4-9fce-fb929896133b.png">

下図のように、対象の画像を繰り返し配置している事がわかります

![BorderWrapDiff.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/63d7d323-97d6-25d1-7359-0577b62156ca.png)

##エッジのピクセルをコピー(BORDER_REPLICATE)

```python
# Replicate画像
repBdImg = cv.copyMakeBorder(img, exPixelNum, exPixelNum, exPixelNum, exPixelNum, cv.BORDER_REPLICATE)
plt.subplot(122),plt.imshow(repBdImg),plt.title('BORDER_REPLICATE')
plt.xticks([]), plt.yticks([])
plt.show()
```

<img width="513" alt="Screen Shot 2020-05-17 at 16.42.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/2d2513a2-de8e-b956-2324-3077e8963dc2.png">

下図のように末端のピクセルを、そのまま用いている事がわかります

![BorderReplace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/b4415111-0e52-cbc1-db1e-0a43d93441da.png)

##反射(BORDER_REFLECT)

```python
# Replicate画像
# Reflect画像
refBdImg = cv.copyMakeBorder(img, exPixelNum, exPixelNum, exPixelNum, exPixelNum, cv.BORDER_REFLECT)
plt.subplot(122),plt.imshow(refBdImg),plt.title('BORDER_REFLECT')
plt.xticks([]), plt.yticks([])
plt.show()
```
<img width="509" alt="Screen Shot 2020-05-17 at 17.36.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/070a4089-c462-7493-a347-b6fe2259b7a4.png">

下図のように、反転して画像を配置している事がわかります

![BorderReflect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/9d846448-757c-4f12-96e3-7e75fc61ffe5.png)

##反射(BORDER_REFLECT_101)

```python
# Reflect画像（エッジのピクセルを繰り返さない）
# BORDER_DEFAULTとした時も同じ加工を行う
ref101BdImg = cv.copyMakeBorder(img, exPixelNum, exPixelNum, exPixelNum, exPixelNum, cv.BORDER_REFLECT_101)
plt.subplot(122),plt.imshow(ref101BdImg),plt.title('BORDER_REFLECT_101')
plt.xticks([]), plt.yticks([])
plt.show()
```

<img width="508" alt="Screen Shot 2020-05-17 at 17.47.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/df53cd68-7af0-8add-8879-57129a95cbc8.png">

BORDER_REFLECTと同じ反射ですが、エッジのピクセルを繰り返しません
BORDER_REFLECT_101をBORDER_DEFAULTとした時も同じ加工となります

![BorderReflect101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/a94fa9d5-4047-c6ff-03c1-185ac2eb8d47.png)