小学6年生の長男が夏休みの自由研究にPythonを勉強したいというので付き合ってみました。
どこから手を付けていけばわからないので、いくつか課題を出し、それを実現するコードを一緒に書くということを繰り返しました。
この記事では、「課題9 顔の検出」について扱います。その他の課題については下記の記事をご覧ください。
- 夏休みなので小学生とPythonを勉強してみた - 課題1 FizzBuzz - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題2 掛け算九九 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題3 掛け算ゲーム - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題4 じゃんけん - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題5 サイコロの目の出る確率 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題6 写真の整理 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題7 掛け算ゲームWeb版 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題8 掲示板 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題9 顔の検出 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題10 顔の認識 - Qiita
コードはGitHubにて公開しています。
課題9-1 画像一覧
指示
./srcにある画像の一覧を表示しましょう。
回答例
import glob
import os
for image_path in glob.glob('./src/*.jpg'):
image_name = os.path.basename(image_path)
print(f'image_path: {image_path} image_name: {image_name}')
実行例
image_path: ./src/DSCN0295.jpg image_name: DSCN0295.jpg
image_path: ./src/DSCN0320.jpg image_name: DSCN0320.jpg
image_path: ./src/DSCN0347.jpg image_name: DSCN0347.jpg
image_path: ./src/DSCN0351.jpg image_name: DSCN0351.jpg
image_path: ./src/DSC_6152.jpg image_name: DSC_6152.jpg
image_path: ./src/DSC_6322.jpg image_name: DSC_6322.jpg
image_path: ./src/DSC_6509.jpg image_name: DSC_6509.jpg
以下略
課題9-2 顔の検出
指示
./srcにある画像から、顔の検出を行うプログラムを作りましょう。
ヒント
OpenCVには事前に学習を済ませた顔検出のための識別器があります。
回答例
今回はhaarcascade_frontalface_alt.xmlを使用します。まずcv2.CascadeClassifierで識別器を読み込みます。次にcv2.imreadで画像を読み込み、cv2.cvtColorでグレーに変換し、detectMultiScaleで顔検出を行います。もし顔が検出されれば、検出された顔の位置が出力されます。
import glob
import os
import cv2
cascade_path = cv2.data.haarcascades + 'haarcascade_frontalface_alt.xml'
cascade = cv2.CascadeClassifier(cascade_path)
for image_path in glob.glob('./src/*.jpg'):
image_name = os.path.basename(image_path)
print(f'image_path: {image_path} image_name: {image_name}')
image = cv2.imread(image_path)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
face_list = cascade.detectMultiScale(
gray_image, 1.1, 5, minSize=(100, 100))
if len(face_list) > 0:
print(face_list)
実行例
image_path: ./src/DSCN0295.jpg image_name: DSCN0295.jpg
[[1818 805 353 353]]
image_path: ./src/DSCN0320.jpg image_name: DSCN0320.jpg
[[1976 1350 479 479]]
image_path: ./src/DSCN0347.jpg image_name: DSCN0347.jpg
image_path: ./src/DSCN0351.jpg image_name: DSCN0351.jpg
[[1958 437 826 826]]
image_path: ./src/DSC_6152.jpg image_name: DSC_6152.jpg
[[1210 746 377 377]
[ 449 802 336 336]]
image_path: ./src/DSC_6322.jpg image_name: DSC_6322.jpg
[[1023 1776 204 204]
[ 647 1856 206 206]]
image_path: ./src/DSC_6509.jpg image_name: DSC_6509.jpg
[[2616 307 187 187]
[ 754 247 228 228]
[ 911 1555 260 260]]
以下略
課題9-3 顔の検出と結果の出力
指示
./srcにある画像から、顔の検出を行うプログラムを作りましょう。検出された顔は./faceに、検出された位置は元の画像に白枠を描いたものを./face_rectangleに格納してください。
回答例
import glob
import os
import cv2
cascade_path = cv2.data.haarcascades + 'haarcascade_frontalface_alt.xml'
cascade = cv2.CascadeClassifier(cascade_path)
WHITE = (255, 255, 255)
for image_path in glob.glob('./src/*.jpg'):
image_name = os.path.basename(image_path)
print(f'image_path: {image_path} image_name: {image_name}')
image = cv2.imread(image_path)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
face_list = cascade.detectMultiScale(
gray_image, 1.1, 5, minSize=(100, 100))
if len(face_list) > 0:
print(face_list)
for x, y, w, h in face_list:
face_image = image[y: y + h, x: x + w]
face_path = f'./face/{ image_name[:-4] }_{ x }-{ y }.jpg'
cv2.imwrite(face_path, face_image)
for x, y, w, h in face_list:
cv2.rectangle(image, (x, y), (x + w, y + h), WHITE, 2)
cv2.imwrite('./face_rectangle/' + image_name, image)