PythonとOpenCVの開発環境を構築する with pipenv

# はじめに

ふと、「OpenCVを使って画像処理したいな」と思うことありますよね？私はありました[^1]。

OpenCVと言えばC++で実装された画像処理ライブラリですが、Pythonから利用することができることは広く知られています。

2020年のC++は(C++11以前と比べると)比較的まともな言語ですが、とりあえず試そうと思ったときに使いやすい言語にはなっていません(※個人の感想です)。

そこで、今回はPythonを用いたOpenCVの入門を行いました。

環境はmacOS 10.14で、`brew`が入ってます。

## TL;DR

- `brew install pipenv`
- `pipenv install`
- `pipenv install opencv-python==4.1.2.30`
- `pipenv shell && python main.py`

## Pythonの仮想環境やライブラリの管理など

私は普段フロントエンド周りの技術を触っているため、ライブラリの管理や実行環境自体の管理は`yarn`や`nvm`を用いて行っています。

Pythonにも似たような概念があると思って軽く調べてみましたが、歴史的経緯もあって正直何が何やらわかりませんでした(人によっておすすめや言ってることが違う…)。

色々な記事を読み、「環境作りに時間取られるの本質的じゃないな」と思い、エイヤで`pipenv`を使うことにしました。

`pipenv`を使うことに決めたのは、

- [pyenv、pyenv-virtualenv、venv、Anaconda、Pipenv。私はPipenvを使う。](https://qiita.com/KRiver1/items/c1788e616b77a9bad4dd)という記事が読みやすかった
- `Pipfile.lock`というファイルが作られ、ライブラリのバージョン管理がより厳格に行えそうだった

というのが理由です。

## `pipenv`のインストール

```bash
brew install pipenv
```

サイコー

## 実行環境を作る

前述の記事と、[pipenv を使ってみたのでメモ](https://qiita.com/subarunari/items/dcbdad68ba1809b721b9)という記事を参考に、以下のコマンドを実行した。

```bash
mkdir learn-opencv
cd learn-opencv
pipenv install
```

すると、

```
Creating a virtualenv for this project…
Pipfile: /Users/remew/workspace/learn-opencv/Pipfile
Using /usr/local/Cellar/pipenv/2018.11.26_3/libexec/bin/python3.8 (3.8.1) to create virtualenv…
⠙ Creating virtual environment...Already using interpreter /usr/local/Cellar/pipenv/2018.11.26_3/libexec/bin/python3.8
Using real prefix '/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8'
New python executable in /Users/remew/.local/share/virtualenvs/learn-opencv-CItTnWle/bin/python3.8
Also creating executable in /Users/remew/.local/share/virtualenvs/learn-opencv-CItTnWle/bin/python
Installing setuptools, pip, wheel...
done.

✔ Successfully created virtual environment!
Virtualenv location: /Users/remew/.local/share/virtualenvs/learn-opencv-CItTnWle
Creating a Pipfile for this project…
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (db4242)!
Installing dependencies from Pipfile.lock (db4242)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 00:00:00
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
```

という出力とともに`Pipfile`/`Pipfile.lock`というファイルが作成されました。

どうやら`pipenv shell`を実行することで、インストールしたライブラリなどが使えるようになるようです(この辺ちょっと曖昧)。

試しに、`pipenv shell`を実行した前後でPythonのバージョンを比較してみました。

```bash
python --version # => Python 2.7.10
pipenv shell
python --version # => Python 3.8.1
exit # pipenvの環境から抜けるときには exit する
```

すごい簡単だ(小並感)。

## OpenCVのインストール&バージョン確認

Python向けのOpenCV自体は、単純に`pip(もしくはpipenv) install opencv-python`を実行するだけでインストールできます。
しかし後述の動作確認で、カメラを取得できないという問題が発生したため、以下の記事を参考にバージョン4.1.2.30をインストールしました。

[python-opencvでQt plugin "cocoa"が見つからないというエラー](https://qiita.com/jmtsn/items/aa73d837b3a8d4158885)

```bash
pipenv install opencv-python==4.1.2.30
```

opencv-pythonがインストールできたかを確認するため、以下のコードを作成して実行します。

```python:sample.py
import cv2
print(cv2.__version__)
```

以下のコマンドを実行し、OpenCVのバージョンが出力されればインストール成功です。

```bash
pipenv shell
python sample.py
```

## カメラの表示

OpenCVといえば、PCのカメラからの映像を取得して表示することが簡単というイメージがあると思います。私はありました。

そこで、以下のページのサンプルコードを用いてカメラ映像の取得と表示を行いました。
[OpenCV 接続したカメラから動画を取得しよう (Python)](https://weblabo.oscasierra.net/python/opencv-videocapture-camera.html)

コピペだとつまらないので、カメラから取得した画像のエッジ検出をして表示するように少しアレンジしてみました([OpenCVでエッジ検出してみる](https://qiita.com/hitomatagi/items/2c3a2bfefe73ab5c86a4))。

```python
import cv2

capture = cv2.VideoCapture(0)

while True:
    ret, frame = capture.read()
    canny_frame = cv2.Canny(cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY), 10, 100)
    cv2.imshow('frame', canny_frame)
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break

capture.release()
cv2.destroyAllWindows()
```

実行結果↓  
<img width="1392" alt="スクリーンショット 2020-03-07 0.30.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94164/2a7ba967-420e-0c1d-e4c0-ca9644589f4d.png">

## 感想

- `pipenv`便利だった。Python自体のバージョンも管理できるみたいなのでこれからは`pipenv`使っていきたい。
- OpenCVの導入もめっちゃ簡単だった(バージョンの罠にハマったけど…)
    - 昔WindowsかつC++で触ったこともあるのですが、exe落としてライブラリインストールしてパスを通して…みたいなことをやった思い出があります。
- カメラ映像取得からエッジ検出して表示するのも、かなりシンプルなコードで実装できてOpenCVすごいと思った(小並感)
- 画像処理やっていき :muscle: 

[^1]: 厳密には、画像処理をしてやってみたいことがあったのでとりあえず昔一瞬だけ触ったことがあるOpenCVを触った、という経緯です。