python+opencvで画像処理の勉強1 画像の読み込みと表示

OpenCVを使った画像処理の基礎を勉強していきます。
OpenCVを使用するので、細かい理論や1からの実装は行いません。

### 画像の読み込みと表示
何はともあれまずは画像を読み込み表示してみます。
読み込みはimread()、表示はmatplotlibのimshow()を使用します。

```python
import cv2
import matplotlib.pyplot as plt

image_path = "./image.jpg" # 画像のパス

img = cv2.imread(image_path)
plt.imshow(img)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/1e295bab-39d6-ab40-b1c5-e798379526ee.png)

色が不自然に感じます。
ここで、読み込んだ画像のサイズを確認します。
numpyの配列同様に.shapeで表示できます。

```python
img.shape
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/391a1f99-83b1-258a-3671-4a44bd345ae2.png)
これは縦に2592pixel、横に4608pixel、チャンネル数が3であることを表しています。
3つの画像が重なっていると考えられますが、これが何を表しているか考えてみます。

### カラー画像
まずは色の話をします。
複数の色の光を混ぜあわせることで別の色の光を作ることを**混色**と呼び、**加法混色**と**減法混色**があります。
加法混色では、異なる色の光を重ねて投影することで別の色を作るような混色で、通常R(赤)・G(緑)・B(青)の3色の光を使います。
PCのモニタなどの表示面は赤・緑・青の発光領域が細かく配置されています。
一方、減法混色では色付きのフィルタを通して白色項を見るような混色であり、C(シアン)・M(マゼンダ)・Y(イエロー)を原色とすることが多いです。

画像の話に移ります。
画素の位置の明るさのみを表す画像を、グレースケール画像と呼びます。白黒画像です。
加法混色を用いれば、赤・緑・青の3つの原色の量(画素値)を使えば、画像中のすべての位置ですべての色を表すことができます。
この画像中の位置に対応した赤・緑・青の3つの画素値を持つカラー画像を、**RGBカラー画像**と呼びます。

### 色の変換
今回はカラー画像を使用しているので、チャンネル数が3とは加法混色で使う3つの色の赤・緑・青を表していると予想できます。
実はOpenCVではimread()で読み込んだ画像は**青(B)・緑(G)・赤(R)**表示となっています。
これをRGB表示に直すにはcvtColor()でcv2.COLOR_RGB2BGRを指定します。

```python
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/7cd9f824-2454-57fe-0bf0-b1441455c7f6.png)

処理によってはグレー画像で十分である場合もあります。
その際はcv2.COLOR_BGR2GRAYを指定します。(RGBからはcv2.COLOR_RGB2GRAY)

```python
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(img_gray, 'gray')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/5ea02a2c-2e06-0fa9-f096-c2b08991000b.png)

サイズを確認してみます。

```python
img_gray.shape
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/25faf078-7be3-555c-baf7-14db5c579a65.png)

チャンネル数が1になっていることが分かります。

### 画像のリサイズ・切り抜き
取得した画像はサイズが大きすぎたり、バラバラだったりするのでサイズを合わせる必要があります。

画像のリサイズではresize()で行います。
dsizeで変換後のサイズを指定します。

```python
img_resize = cv2.resize(img_rgb, dsize=[200,120], fx=None, fy=None)
plt.imshow(img_resize)
print(img_resize.shape)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/a32bf6b5-deeb-3cf9-cdb0-24e539829bf5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/a5203a21-8f3d-779d-d3fd-2c1b5f716027.png)

または、fx、fyで倍率を指定します。

```python
img_resize = cv2.resize(img_rgb, dsize=None, fx=0.5, fy=0.5)
plt.imshow(img_resize)
print(img_resize.shape)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/acd7f700-cc36-298a-77f9-c212adc66680.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/bf8b370d-c242-266c-dae2-906f3cfe625f.png)

画像を大きくすることもできます。
interpolationに指定する補完方法としては以下のものがあります。

- cv2.INTER_NEAREST: 最近傍補間
- cv2.INTER_LINEAR: バイリニア補間
- cv2.INTER_CUBIC: バイキュービック補間
- cv2.INTER_AREA: ピクセル領域の関係を利用したリサンプリング
- cv2.INTER_LANCZOS4: Lanczos 補間


画像の切り抜きはnumpy配列同様にスライス機能を使用します。

```python
img_clip = img_rgb[:2000,1000:3500,:]
plt.imshow(img_clip)
print(img_clip.shape)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/af3ee1f0-7225-d727-b36b-61b0e8d1cfb4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358656/a134f722-1800-9088-1102-8b72279aa2d8.png)

これで画像を読み込んで、表示できるようになりました。
次からは画像処理の基礎をOpenCVを使って勉強していきます。


### 次回
画素ごとの濃淡変換

https://qiita.com/tanaka_benkyo/items/11a9b99b4703516711e3

### 参考書籍
ディジタル画像処理[改訂第二版] 

https://www.amazon.co.jp/%E3%83%87%E3%82%A3%E3%82%B8%E3%82%BF%E3%83%AB%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86-%E6%94%B9%E8%A8%82%E7%AC%AC%E4%BA%8C%E7%89%88-%E3%83%87%E3%82%A3%E3%82%B8%E3%82%BF%E3%83%AB%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86%E7%B7%A8%E9%9B%86%E5%A7%94%E5%93%A1%E4%BC%9A/dp/490347464X