OpenCVのチュートリアルをやる -その2 変換系-

#前書き
OpenCVの開発環境は作ったので、実際になにか動かしてみます。
今回はOpenCV-Pythonのチュートリアル、[OpenCV-Python Tutorials](https://opencv-python-tutroals.readthedocs.io/en/latest/)の**[日本語版](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/index.html)**をやっていきます。
多少アレンジすると思う。

# シリーズ
* [pythonでOpenCV使うための環境づくり](https://qiita.com/Ryo87/items/939b370c06c60c9d63c8)
* [OpenCVのチュートリアルをやる](https://qiita.com/Ryo87/items/c20be948d261f1be2f22)
* [OpenCVのチュートリアルをやる -その2 変換系-](https://qiita.com/Ryo87/items/6f367bf1eb69c4f3c80e)
* [OpenCVのチュートリアルをやる -その3 -](https://qiita.com/Ryo87/items/0ffc633fb918cb704566)

#開発環境
機種名 : MacBook Pro
OS : Mojave 10.14.2
プロセッサ名 : Intel Core i5 2.6 GHz
メモリ : 16 GB
グラフィック : Intel Iris 1536MB

## python系
```
% pip freeze
numpy==1.15.4
opencv-python==4.0.0.21
```

## 画像データ
神奈川大学から画像データをお借りしてやります。
[神奈川工科大学 情報学部 情報工学科 信号処理応用研究室](http://www.ess.ic.kanagawa-it.ac.jp/app_images_j.html#image)

#本題
## 画像の算術演算
```sample.py
import numpy as np
import cv2

# 変数の定義
a = np.uint8([250])
b = np.uint8([10])

# OpenCV
print(cv2.add(a,b))

# Numpy
print(a+b)

# カラー画像読み込み
img1 = cv2.imread('Lenna.bmp')
img2 = cv2.imread('Earth.bmp')

# 画像のブレンディング
## 単純加算
imgAdd = img1 + img2
## OpenCVの加算
imgcv = cv2.add(img1, 100)
## ブレンディング
imgAddWeighted = cv2.addWeighted(img1,0.7,img2,0.3,0)

cv2.imshow('img1',img1)
cv2.imshow('img2',img2)
cv2.imshow('imgAdd',imgAdd)
cv2.imshow('imgcv',imgcv)
cv2.imshow('imgAddWeighted',imgAddWeighted)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

単純に加算した画像は、それぞれの座標ごとに値を加算して255でmodした値になってる
OpenCV加算した画像は、すべての座標に値を加算して255でmodした値になってる
ブレンドは、重み付けして加算。255*a+255*(1-a)になるから、mod255はする必要ないはず

<img width="929" alt="imgAddWeighted_と_imgcv_と_imgAdd_と_img2.png" src="https://qiita-image-store.s3.amazonaws.com/0/35860/a94d7281-c518-5d69-3db3-33343018e2d0.png">

## 色空間の変換
> BGR画像をHSV画像へ変換する方法を学んだので，この方法を使って特定の色を持つ物体の検出ができるようになります．HSV空間では，RGB空間より色を表現するのが簡単だからです．以下に示す例では青色をした物体の検出を試みます．

<img width="990" alt="imgGray_と_imgHsv_と_img.png" src="https://qiita-image-store.s3.amazonaws.com/0/35860/fe96d9ea-cb0a-d6b1-6a42-13c37e48cb97.png">

色の強弱は出たかなと思うけど、例えば帽子のもふもふだけ選択しようとしたときに背景の鏡の縁の色とかと近い色になってるから、切り抜きとか難しそう。

## 画像の幾何変換
このあたりは、画像処理するときに十中八九活用しまくるよね。

### 拡大縮小
```sample.py
import numpy as np
import cv2

# カラー画像読み込み
img = cv2.imread('Lenna.bmp')

# 縮小(スケール指定)
res1 = cv2.resize(img,None,fx=0.5, fy=0.5, interpolation = cv2.INTER_AREA)

# 拡大
## チャネル以外を取る
height, width = img.shape[:2]
## 高さ、幅を具体的に指定する
res2 = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_LINEAR)

cv2.imshow('img',img)
cv2.imshow('res1',res1)
cv2.imshow('res2',res2)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
<img width="984" alt="img_と_res1_と_res2.png" src="https://qiita-image-store.s3.amazonaws.com/0/35860/5f767c8a-890a-fa2e-dc67-04295e46f37e.png">

`resize`メソッドの`interpolation`パラメータに入れられる定数それぞれ試してみる。
[定数値](http://pynote.hatenablog.com/entry/opencv-resize)

```sample.py
# 縮小(スケール指定)
## 最近傍補間法
res1 = cv2.resize(img,None,fx=0.8, fy=0.8, interpolation = cv2.INTER_NEAREST)
## バイリニア補間
res2 = cv2.resize(img,None,fx=0.8, fy=0.8, interpolation = cv2.INTER_LINEAR)
## バイキュービック補間
res3 = cv2.resize(img,None,fx=0.8, fy=0.8, interpolation = cv2.INTER_CUBIC)
## ピクセル領域の関係を利用したリサンプリング
res4 = cv2.resize(img,None,fx=0.8, fy=0.8, interpolation = cv2.INTER_AREA)
## Lanczos法補間
res5 = cv2.resize(img,None,fx=0.8, fy=0.8, interpolation = cv2.INTER_LANCZOS4)
```

<img width="925" alt="INTER_LINEAR_default__と_INTER_NEAREST_と_INTER_CUBIC_と_INTER_LANCZOS_と_img.png" src="https://qiita-image-store.s3.amazonaws.com/0/35860/0f8b1767-e90a-3cc0-2f36-c4c12fd19183.png">

補間方法を選択するってことは、その補間方法によって見た目が変わるってことよね。
バイリニア補間を基準に考えると、

* Lanczos法補間
    * もこもこが綺麗に見える
* 最近傍補間法
    * 線がジャギジャギ(帽子のところ)
* ピクセル領域の関係を利用したリサンプリング
    * 少しぼやける
* バイキュービック補間
    * 帽子の境界線がはっきり見えている(気がする

詳しくやるとまた1毎記事が書けるだろうから一旦こんなところで。

### 並進
```sample.py
import numpy as np
import cv2

# カラー画像読み込み
img = cv2.imread('Lenna.bmp')

# 並進
rows,cols,_ = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))

cv2.imshow('img',img)
cv2.imshow('dst',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()
```
<img width="919" alt="dst_と_img.png" src="https://qiita-image-store.s3.amazonaws.com/0/35860/d1845b21-9ba0-d40d-f01a-5ced1147148e.png">

### 回転
```sample.py
import numpy as np
import cv2

# カラー画像読み込み
img = cv2.imread('Lenna.bmp')

# 回転
rows,cols,_ = img.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))

cv2.imshow('img',img)
cv2.imshow('dst',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()
```
<img width="921" alt="dst_と_img-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/35860/f4929e8b-6707-8014-e4ef-9914269a4db3.png">

### アフィン変換
特定の3点を特定の3点に変換する
拡大縮小しながら、回転させる変換？

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

# カラー画像読み込み
img = cv2.imread('Lenna.bmp')

# アフィン変換
rows,cols,ch = img.shape

pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])

M = cv2.getAffineTransform(pts1,pts2)

dst = cv2.warpAffine(img,M,(cols,rows))

cv2.imshow('img',img)
cv2.imshow('dst',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()
```

<img width="917" alt="dst_と_img-3.png" src="https://qiita-image-store.s3.amazonaws.com/0/35860/0f60614f-e52c-27b1-20d3-e3e34a65139f.png">

### 射影変換
四角形を特定の四角形に変換する

```
import numpy as np
import cv2

# カラー画像読み込み
img = cv2.imread('Lenna.bmp')

# 射影変換
pts1 = np.float32([[56,65],[108,52],[28,187],[129,120]])
pts2 = np.float32([[0,0],[255,0],[0,255],[255,255]])

M = cv2.getPerspectiveTransform(pts1,pts2)

dst = cv2.warpPerspective(img,M,(255,255))

cv2.imshow('img',img)
cv2.imshow('dst',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()
```
<img width="922" alt="img_と_dst.png" src="https://qiita-image-store.s3.amazonaws.com/0/35860/702571ed-09e3-7f1b-7a38-445bd9681132.png">

#感想
これで、画像のかさ増しができるようになった。
色周りはわかりやすく変化が見れていいね。