opencv-python 4.2 で Hello World と顔検出

## 概要

- OpenCV 非公式の opencv-python パッケージを pip でインストールする
- Hello World 画像を出力するサンプルコードを書いて実行する
- 画像から顔の位置を検出するサンプルコードを書いて実行する

## 今回の環境

- macOS Catalina
- Python 3.8

```
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.4
BuildVersion:	19E287
```

```
$ python --version
Python 3.8.2
```

## opencv-python パッケージとは

opencv-python は pip でインストールが可能な Python のパッケージ。
OpenCV 公式のものではないパッケージ。

[opencv\-python · PyPI](https://pypi.org/project/opencv-python/)

> Unofficial pre-built OpenCV packages for Python.

opencv-python には OpenCV が含まれているから、別途 OpenCV をインストールする必要はない。

[opencv\-python · PyPI](https://pypi.org/project/opencv-python/)

> Q: Do I need to install also OpenCV separately?
> 
> A: No, the packages are special wheel binary packages and they already contain statically built OpenCV binaries.

競合するといけないのですでにインストールされている OpenCV があれば事前に削除するようドキュメントに書かれている。

[opencv\-python · PyPI](https://pypi.org/project/opencv-python/)

> If you have previous/other manually installed (= not installed via pip) version of OpenCV installed (e.g. cv2 module in the root of Python's site-packages), remove it before installation to avoid conflicts.

## pip で opencv-python パッケージをインストール

依存関係で NumPy もインストールされる。

```
$ pip install opencv-python
```

```
$ pip list | grep -E "opencv|numpy"
numpy         1.18.4
opencv-python 4.2.0.34
```

## Hello World 画像生成

ソースコード: hello.py

```hello.py
import numpy
import cv2

# 画像データを入れる numpy.ndarray オブジェクト
image = numpy.zeros((256, 256, 3), numpy.uint8)

# テキストを描画する
text = "Hello, world"
org = (0, 100)
font_face = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1.0
color = (0, 127, 255) # Blue, Green, Red
thickness = 1
line_type = cv2.LINE_AA
cv2.putText(image, text, org, font_face, font_scale, color, thickness, line_type)

# 画像を出力する
path = "hello-world.png"
cv2.imwrite(path, image)
```

実行すると Hello World 画像が出力される。

```
$ python hello.py
```

![hello-world.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/e2b524af-1b0b-1f79-2a7f-93910e6dc506.png)

## 画像から顔の位置を検出

ソースコード: facedetect.py

```facedetect.py
import sys
import numpy
import cv2

# コマンドライン引数を読む
if len(sys.argv) < 3:
  print("画像ファイルのパスを指定してください。")
  sys.exit(1)
input_image_path  = sys.argv[1]
output_image_path = sys.argv[2]

# 画像を読み込む
# アルファチャンネル付きに対応するため IMREAD_UNCHANGED を使う
input_image = cv2.imread(input_image_path, cv2.IMREAD_UNCHANGED)

# Haar 特徴ベースのカスケード分類器による物体検出の準備
# 顔検出用のカスケード分類器を使用
face_cascade_name = cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(face_cascade_name)

# 顔を検出
faces = face_cascade.detectMultiScale(input_image)

# 出力画像データを入れるオブジェクト
# 入力画像データを出力画像データにコピー
output_image = numpy.copy(input_image)

for (x, y, w, h) in faces:

  # 検出した顔の座標を出力
  print("Face: [{} x {} from ({}, {})]".format(w, h, x, y))

  # 顔の位置に楕円を描画
  center = (x + w // 2, y + h // 2)
  size = (w // 2, h // 2)
  angle = 0
  startAngle = 0
  endAngle = 360
  color = (127, 0, 255, 255) # Blue, Green, Red, Alpha
  thickness = 4
  cv2.ellipse(output_image, center, size, angle, startAngle, endAngle, color, thickness)

# 画像を出力
cv2.imwrite(output_image_path, output_image)
```

入力画像ファイルパスと出力画像ファイルパスを指定して実行する。

いくつかの画像で試す。

[File:Lenna \(test image\)\.png \- Wikipedia](https://en.wikipedia.org/wiki/File:Lenna_(test_image).png)

```
$ python facedetect.py lenna.png lenna-output.jpg
Face: [173 x 173 from (217, 201)]
```

![lenna-output.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/8d64a0ca-1e99-18c9-f5b4-cc221934a590.jpeg)

[人気バンドと扱いが違うソロデビューしたてのドイツ人ハーフ｜無料の写真素材はフリー素材のぱくたそ](https://www.pakutaso.com/20160220038post-6891.html)

```
$ python facedetect.py IRIS16011442_TP_V.jpg IRIS16011442_TP_V-output.jpg
Face: [189 x 189 from (1221, 85)]
Face: [147 x 147 from (736, 247)]
Face: [136 x 136 from (211, 270)]
Face: [58 x 58 from (697, 952)]
```

![IRIS16011442_TP_V-output.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/afe06a78-f0b0-6361-1918-b65c1454d45d.jpeg)

[これでも糖質制限ダイエット中の三銃士を連れてきたよ｜無料の写真素材はフリー素材のぱくたそ](https://www.pakutaso.com/20150920253post-6016.html)

```
$ python facedetect.py 150711109603_TP_V.jpg 150711109603_TP_V-output.jpg
Face: [193 x 193 from (684, 115)]
Face: [131 x 131 from (1114, 151)]
```

![150711109603_TP_V-output.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/2ba1f3f7-d49f-efb8-f06c-8198100ff419.jpeg)

[カルビを焼く自分を想像する自分を想像する自分を想像する看護師 \| 看護師フリー写真素材サイト スキマナース](https://nurse-web.jp/photo/archives/279)

```
$ python facedetect.py cut32_karubi2-1200x801.jpg cut32_karubi2-1200x801-output.jpg
Face: [69 x 69 from (713, 106)]
Face: [102 x 102 from (469, 179)]
Face: [158 x 158 from (93, 270)]
```

![cut32_karubi2-1200x801-output.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/6a666084-9379-32d3-57f2-3b86702073e7.jpeg)

[集合している人たちのイラスト（世界） \| かわいいフリー素材集 いらすとや](https://www.irasutoya.com/2019/10/blog-post_448.html)

```
$ python facedetect.py group_young_world.png group_young_world-output.png
Face: [327 x 327 from (718, 154)]
Face: [283 x 283 from (437, 178)]
Face: [266 x 266 from (990, 350)]
Face: [276 x 276 from (245, 394)]
Face: [309 x 309 from (520, 717)]
Face: [121 x 121 from (28, 701)]
```

![group_young_world-output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/890420b8-f141-f27d-8af7-4ee5dbc038ad.png)

## 参考資料

- [opencv\-python · PyPI](https://pypi.org/project/opencv-python/)
- [OpenCV 4\.3 \+ Python で Hello World と顔検出 \- Qiita](https://qiita.com/niwasawa/items/03b1496dbb360ca157e0)