質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1638閲覧

顔認証のプログラム、waitKey()が実行されない

RayU

総合スコア8

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/09/08 12:28

編集2020/09/08 12:30

Pythonで作った以下の顔認証のプログラムで、新しい顔、名前を登録するためにカメラを開く(TABキーを押す)と、どのキーを押してもカメラが閉じられないという不具合が発生してしまいました。少し確かめてみたところ、新しい顔を登録する処理を行うdef save_frame_camera_key()内のwaitKey()より後ろの処理が実行されていなさそうです。エラー文は出ておりません。
理由が分かる方いらっしゃるでしょうか?

ちなみに、このプログラムはcv2などをダウンロードしたanaconda上で動かしています。

html

1# -*- coding: utf-8 -*- 2"""face_multi.ipynb 3 4Automatically generated by Colaboratory. 5 6Original file is located at 7 https://colab.research.google.com/drive/1oad9u6TYnexZL3A7I86OkMRfnS6tz76B 8 9ランタイムをGPUモードに変更 10""" 11 12# !pip install face_recognition 13 14"""ライブラリーのインポート""" 15 16# -*- coding: utf-8 -*- 17import os 18import sys 19import face_recognition 20import cv2 21import numpy as np 22from PIL import ImageFont, ImageDraw, Image 23import glob 24 25"""設定ファイルの読み込み""" 26 27import config 28emp_info = config.emp_info 29threshold = config.threshold 30mode = config.mode 31 32"""顔情報の初期化""" 33 34face_locations = [] 35face_encodings = [] 36 37"""登録画像の読み込み""" 38 39# image_paths = glob.glob('image/*') 40image_paths = glob.glob('image_jp/*') 41image_paths.sort() 42known_face_encodings = [] 43known_face_names = [] 44checked_face = [] 45 46for image_path in image_paths: 47 im_name = os.path.basename(image_path).split('.')[0] 48 image = face_recognition.load_image_file(image_path) 49 face_encoding = face_recognition.face_encodings(image)[0] 50 known_face_encodings.append(face_encoding) 51 known_face_names.append(im_name) 52 53video_capture = cv2.VideoCapture(0) 54 55def main(): 56 57 # 処理フラグの初期化 58 process_this_frame = True 59 60 while True: 61 # ビデオの単一フレームを取得 62 _, frame = video_capture.read() 63 64 # 時間を節約するために、フレーム毎に処理をスキップ 65 if process_this_frame: 66 # 画像を縦1/4 横1/4に圧縮 67 small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) 68 69 # 顔の位置情報とエンコード 70 face_locations = face_recognition.face_locations(small_frame) 71 face_encodings = face_recognition.face_encodings(small_frame, face_locations) 72 73 #名前配列の初期化 74 face_names = [] 75 76 for face_encoding in face_encodings: 77 78 matches = face_recognition.compare_faces(known_face_encodings, face_encoding, threshold) 79 name = "Unknown" 80 81 # we use the known face with the smallest distance to the new face 82 face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) 83 best_match_index = np.argmin(face_distances) 84 if matches[best_match_index]: 85 name = known_face_names[best_match_index] 86 87 face_names.append(name) 88 89 # 処理フラグの切り替え 90 process_this_frame = not process_this_frame 91 92 #for (top, right, bottom, left) in face_locations: 93 for(top, right, bottom, left), name in zip(face_locations, face_names): 94 95 # 圧縮した画像の座標を復元 96 top *= 4 97 right *= 4 98 bottom *= 4 99 left *= 4 100 101 # B-Boxを描画 102 cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) 103 cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) 104 105 # 日本語表示部分 106 fontpath ='meiryo.ttc' 107 font = ImageFont.truetype(fontpath, 32) # フォントサイズ32pt 108 img_pil = Image.fromarray(frame) # 配列の各値を8bit(1byte)整数型(0~255)をPIL Imageに変換。 109 draw = ImageDraw.Draw(img_pil) # drawインスタンスを生成 110 position = (left + 6, bottom - 40) # テキスト表示位置 111 draw.text(position, name, font = font , fill = (255, 255, 255, 0) ) # drawにテキストを記載 fill:色 B,G,R,Alpha設定は反映されない 112 frame = np.array(img_pil) # PIL を配列に変換 113 114 # # 本人確認 115 # if mode == 1 and name != "Unknown": 116 # check_id(name) 117 118 # 結果をビデオに表示 119 cv2.imshow('Video', frame) 120 121 #TABキーで新しい顔と名前を追加 122 if cv2.waitKey(1) == 9: 123 new_name() 124 125 # ESCキーで終了 126 if cv2.waitKey(1) == 27: 127 break 128 129 130 131def check_id(name): 132 if name in checked_face: 133 return 134 135 emp_id = input (name + "さんの社員番号を入力してください。") 136 137 if emp_info[name] == emp_id: 138 print("出勤しました") 139 checked_face.append(name) 140 else: 141 print("社員番号が不正です") 142 name = "" 143 144def new_name(): 145 name = input("追加する方の名前を入力してください。\n") 146 save_frame_camera_key(device_num=0, dir_path=r"C:\Users\hatae\OneDrive\ドキュメント\face_recognition\image_jp", basename=name, ext='jpg', delay=1, window_name='frame') 147 148#新しい顔を撮影し、保存する 149def save_frame_camera_key(device_num, dir_path, basename, ext='jpg', delay=1, window_name='frame'): 150 process_this_frame = True 151 152 print("SPACEキーで撮影 TABキーで戻る") 153 #cap = video_capture 154 155 #if not cap.isOpened(): 156 if not video_capture.isOpened(): 157 return 158 159 os.makedirs(dir_path, exist_ok=True) 160 base_path = os.path.join(dir_path, basename) 161 162 n = 0 163 while True: 164 #ret, frame = cap.read() 165 ret, frame = video_capture.read() 166 167 # 時間を節約するために、フレーム毎に処理をスキップ 168 if process_this_frame: 169 # 画像を縦1/4 横1/4に圧縮 170 small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) 171 172 # 顔の位置情報とエンコード 173 face_locations = face_recognition.face_locations(small_frame) 174 face_encodings = face_recognition.face_encodings(small_frame, face_locations) 175 176 177 # 処理フラグの切り替え 178 process_this_frame = not process_this_frame 179 180 for (top, right, bottom, left) in face_locations: 181 #for(top, right, bottom, left), name in zip(face_locations, face_names): 182 183 # 圧縮した画像の座標を復元 184 top *= 4 185 right *= 4 186 bottom *= 4 187 left *= 4 188 189 # B-Boxを描画 190 cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 4) 191 192 cv2.imshow(window_name, frame) 193 194 #key = cv2.waitKey(delay) & 0xFF 195 if cv2.waitKey(1) == 10: #Enterキーで静止画保存 196 cv2.imwrite('{}_{}.{}'.format(base_path, n, ext), frame) 197 n += 1 198 if cv2.waitKey(1) == 32: #Spaceキーでカメラを閉じる 199 break 200 201 cap.release() 202 cv2.destroyWindow(window_name) 203 204 205 206 207 208main() 209 210# ウェブカメラへの操作を開放 211video_capture.release() 212cv2.destroyAllWindows()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

そもそもプログラムの組み方に問題があります。

まず、main()にwhileが使われている上にsave_frame_camera_key()にもwhileが使われているので、2重ループになっています。
そして、main()内のframeでWebカメラの画像を取得してるのにsave_frame_camera_key()でもう一回Webカメラの画像を取得して2度手間になっています。

極端な話、save_frame_camera_key()自体が必要がないと思います。

ご質問されたコードを直すとすれば、以下のコードになると思います。動作確認はしていませんが、やりたいことはちゃんと満たされているはずです。

python

1# -*- coding: utf-8 -*- 2"""face_multi.ipynb 3 4Automatically generated by Colaboratory. 5 6Original file is located at 7 https://colab.research.google.com/drive/1oad9u6TYnexZL3A7I86OkMRfnS6tz76B 8 9ランタイムをGPUモードに変更 10""" 11 12# !pip install face_recognition 13 14"""ライブラリーのインポート""" 15 16# -*- coding: utf-8 -*- 17import os 18import sys 19import face_recognition 20import cv2 21import numpy as np 22from PIL import ImageFont, ImageDraw, Image 23import glob 24 25"""設定ファイルの読み込み""" 26 27import config 28emp_info = config.emp_info 29threshold = config.threshold 30mode = config.mode 31 32"""顔情報の初期化""" 33 34face_locations = [] 35face_encodings = [] 36 37"""登録画像の読み込み""" 38 39# image_paths = glob.glob('image/*') 40image_paths = glob.glob('image_jp/*') 41image_paths.sort() 42known_face_encodings = [] 43known_face_names = [] 44checked_face = [] 45 46for image_path in image_paths: 47 im_name = os.path.basename(image_path).split('.')[0] 48 image = face_recognition.load_image_file(image_path) 49 face_encoding = face_recognition.face_encodings(image)[0] 50 known_face_encodings.append(face_encoding) 51 known_face_names.append(im_name) 52 53video_capture = cv2.VideoCapture(0) 54 55def main(): 56 57 # 処理フラグの初期化 58 process_this_frame = True 59 n = 0 60 61 while True: 62 # ビデオの単一フレームを取得 63 _, frame = video_capture.read() 64 65 # 時間を節約するために、フレーム毎に処理をスキップ 66 if process_this_frame: 67 # 画像を縦1/4 横1/4に圧縮 68 small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) 69 70 # 顔の位置情報とエンコード 71 face_locations = face_recognition.face_locations(small_frame) 72 face_encodings = face_recognition.face_encodings(small_frame, face_locations) 73 74 #名前配列の初期化 75 face_names = [] 76 77 for face_encoding in face_encodings: 78 79 matches = face_recognition.compare_faces(known_face_encodings, face_encoding, threshold) 80 name = "Unknown" 81 82 # we use the known face with the smallest distance to the new face 83 face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) 84 best_match_index = np.argmin(face_distances) 85 if matches[best_match_index]: 86 name = known_face_names[best_match_index] 87 88 face_names.append(name) 89 90 # 処理フラグの切り替え 91 process_this_frame = not process_this_frame 92 93 #for (top, right, bottom, left) in face_locations: 94 for(top, right, bottom, left), name in zip(face_locations, face_names): 95 96 # 圧縮した画像の座標を復元 97 top *= 4 98 right *= 4 99 bottom *= 4 100 left *= 4 101 102 # B-Boxを描画 103 cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) 104 cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) 105 106 # 日本語表示部分 107 fontpath ='meiryo.ttc' 108 font = ImageFont.truetype(fontpath, 32) # フォントサイズ32pt 109 img_pil = Image.fromarray(frame) # 配列の各値を8bit(1byte)整数型(0~255)をPIL Imageに変換。 110 draw = ImageDraw.Draw(img_pil) # drawインスタンスを生成 111 position = (left + 6, bottom - 40) # テキスト表示位置 112 draw.text(position, name, font = font , fill = (255, 255, 255, 0) ) # drawにテキストを記載 fill:色 B,G,R,Alpha設定は反映されない 113 frame = np.array(img_pil) # PIL を配列に変換 114 115 # # 本人確認 116 # if mode == 1 and name != "Unknown": 117 # check_id(name) 118 119 # 結果をビデオに表示 120 cv2.imshow('Video', frame) 121 122 #TABキーで新しい顔と名前を追加 123 if cv2.waitKey(1) == 9: 124 name = input("追加する方の名前を入力してください。\n") 125 dir_path=r"C:\Users\hatae\OneDrive\ドキュメント\face_recognition\image_jp" 126 cv2.imwrite('{}_{}.jpg'.format(dir_path, n), frame) 127 n += 1 128 129 # ESCキーで終了 130 if cv2.waitKey(1) == 27: 131 break 132 133 134def check_id(name): 135 if name in checked_face: 136 return 137 138 emp_id = input (name + "さんの社員番号を入力してください。") 139 140 if emp_info[name] == emp_id: 141 print("出勤しました") 142 checked_face.append(name) 143 else: 144 print("社員番号が不正です") 145 name = "" 146 147 148 149main() 150 151# ウェブカメラへの操作を開放 152video_capture.release() 153cv2.destroyAllWindows() 154

投稿2020/09/08 13:31

編集2020/09/08 13:50
Supernove

総合スコア1154

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RayU

2020/09/08 14:24

このプログラムの場合、新しく撮影して保存される顔写真はどういうものになるのでしょうか?
Supernove

2020/09/08 14:48 編集

すみません、質問の回答になるかわかりませんが、tabキーを押した時点のフレームが画像データとして保存されます。
RayU

2020/09/08 15:11

ありがとうございます。 先ほど直していただいたコードを実行してみたのですが、dir_pathで指定した先に撮影した画像が保存されていませんでした。他にも何か問題があるのでしょうか?
Supernove

2020/09/08 15:20

あとはWindowsではパスをバックスラッシュでやりますが、バックスラッシュ一つだと組み合わせによってはエスケープシーケンスと勘違いされることがあるので、バックスラッシュになっているところにもう一つバックスラッシュを追加してください。(例)C:\hoge\huga\
Supernove

2020/09/08 15:24

もう一つだけ言っておくと極力プログラムでパスを指定するときには日本語は避けたいです。他の人にプログラムを渡すときに文字化けになる可能性があることと、今回のようにエラーが出たときに原因の切り分けが必要になるので初心者の方こそなるべくすべてアルファベットのパスになるようにするのがいいと思います
RayU

2020/09/09 12:36

おっしゃる通りでした、日本語での入力を求めていたのですが、ファイル名が文字化けしてしまいました。 imwriteを実行するとき、日本語のファイル名で保存することは出来ないのでしょうか?
Supernove

2020/09/09 12:42

一応参考なりそうな記事はありましたが、ちょっとややこしいのでちゃんと読んで丸コピすることなく必要な部分だけをちゃんと自分のコードに入れるようにしてくださいね。 https://qiita.com/SKYS/items/cbde3775e2143cad7455
RayU

2020/09/09 13:31

上手くいきました。 何度も質問に答えていただいて、本当にありがとうございます。とても助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問