このように背景紙の前で撮影したたくさんの写真の中から、プロフィール用にアップの写真一枚と全身の写真を一枚、計二枚取り出したいと考えております。
OpenCVを使って顔認識をさせて、顔の幅が最も大きな写真を一枚、顔の幅が最も小さな写真を一枚ピックアップできれば要件を満たすと考え、以下のようなプログラムを組みました。
python
1import os 2import cv2 3import math 4import numpy as np 5from PIL import Image 6 7face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')#学習データ 8 9img_dir_path = input('画像フォルダのパスを入力してください:')# 10 11#img_dir_path = '/Users/user/Desktop/drive-download' 12pictures = os.listdir(img_dir_path)#フォルダリストの中身をリスト化 13 14if '.DS_Store' in pictures: 15 pictures.remove('.DS_Store') 16 17if 'Thumbs.db' in pictures: 18 pictures.remove('Thumbs.db') 19 20print(pictures) 21 22#os.mkdir(os.path.join(img_dir_path,'output')) 23all_faces = []#写真ごと全ての顔の座標や大きさの情報を入れるリスト 24 25i = 0 26 27while i < len(pictures): 28 29 img = cv2.imread(os.path.join(img_dir_path,pictures[i])) 30 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 31 faces = face_cascade.detectMultiScale(gray, scaleFactor = 1.2, minSize = (250,250), maxSize = (1600,1600)) 32 33 print(pictures[i]) 34 35#顔認証に失敗した場合 36 if len(faces) == 0: 37 img = cv2.imread(os.path.join(img_dir_path,pictures[i])) 38 39 40# 回転角の指定 41 for j in range(-15,15):#-45°〜45°まで画像を回転 42 angle = 5*j 43 scale = 1.0 44 height, width = img.shape[:2] 45#回転の中心を指定 46 center = (int(width/2), int(height/2)) 47 trans = cv2.getRotationMatrix2D(center, angle , scale) 48#アフィン変換 49 img_rot = cv2.warpAffine(img, trans, (width,height)) 50 gray = cv2.cvtColor(img_rot, cv2.COLOR_BGR2GRAY) 51 faces = face_cascade.detectMultiScale(gray, scaleFactor = 1.2, minSize = (250,250), maxSize = (1600,1600)) 52 if len(faces) > 0: 53 print('回転させた結果認識!' + str(faces)) 54 face_max = faces[faces[:, 2].argmax()] 55 # img[top : bottom, left : right] 56 #np.insert(all_faces, faces)#空のリストに顔リストを一つ追加 57 58 all_faces.append(face_max) 59 break 60 61 62#顔認証に成功した場合 63 elif len(faces) > 0: 64 face_max = faces[faces[:, 2].argmax()] 65 66 #print(face_max) 67 68 #np.insert(all_faces, faces)#空のリストに顔リストを一つ追加 69 all_faces.append(face_max) 70 71 img = Image.open(os.path.join(img_dir_path,pictures[i])) 72 width, height = img.size 73 74 #print(face_max[0]) 75 76 77 78 79 80 i = i + 1 81 82print('END') 83print(all_faces) 84 85 86 87
その結果、最終行のprint(all_faces)が以下のような形式で書き出されました。
all_faces
1[array([1122, 564, 365, 365], dtype=int32), 2array([1245, 680, 369, 369], dtype=int32), 3array([1157, 605, 378, 378], dtype=int32), 4array([810, 505, 710, 710], dtype=int32), 5array([901, 877, 706, 706], dtype=int32), 6array([783, 652, 723, 723], dtype=int32), 7array([1414, 1150, 1104, 1104], dtype=int32), 8array([1365, 1395, 920, 920], dtype=int32), 9array([669, 976, 476, 476], dtype=int32)]
ここから先つまづいてしまったのですが、この中から幅の最大値と最小値を持つ要素をそれぞれ指定したいと考えております。
OpenCVの顔認識は[X,Y,W,H]の形式で書き出されるので、最大値は下から3行目の1104で最小値は1行目の365だということが自分ではわかるのですが、これをプログラムで指定したいと考えております。
基礎的な部分なのかもしれませんが、ご教示いただければ幸いです。
ここから先は、「最小値がN行目にあるから、写真リストのN番目のが全身の写真だ!」といったプログラムを書いて発展させていこうと考えております。
以上、よろしくお願いいたします。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/13 22:11