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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

1877閲覧

Python 動作確認

daigakuse-

総合スコア67

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2017/04/18 13:33

編集2017/04/18 14:05

python3を使いネットで拾ったコードをほんの少し自分なりに変形して実行しているのですが、for文が回らない箇所がいくつかあります。

回っていないfor文は

for item in filtered: for item in finals:

です。原因がわかりません。

Python

1import numpy as np 2import sys 3import os 4import math 5import cv2 6import glob 7 8IMAGE_SIZE = 112 9INPUT_SIZE = 96 10 11xml_dir = '/usr/local/Cellar/opencv3/3.2.0/share/OpenCV/haarcascades' 12face_cascade = cv2.CascadeClassifier(os.path.join(xml_dir, 'haarcascade_frontalface_alt2.xml')) 13eye_cascade = cv2.CascadeClassifier(os.path.join(xml_dir, 'haarcascade_eye.xml')) 14mouth_cascade = cv2.CascadeClassifier(os.path.join(xml_dir, 'haarcascade_mcs_mouth.xml')) 15nose_cascade = cv2.CascadeClassifier(os.path.join(xml_dir, 'haarcascade_mcs_nose.xml')) 16 17 18def detect_face_rotate(img_file, out_dir = 'out'): 19 base_dir = "." 20 #out_dir = "out" 21 filename = os.path.basename(os.path.normpath(img_file)) 22 (fn, ext) = os.path.splitext(filename) 23 img_dir = '%s/%s/%s' % (".", out_dir, fn) 24 25 26 input_img = cv2.imread(img_file) 27 rows, cols, colors = input_img.shape 28 29 print ('size',rows,cols) 30 limit = 800 31 if rows > limit or cols > limit: 32 if rows > cols: 33 input_img = cv2.resize(input_img, (cols * limit / rows, limit)) 34 else: 35 input_img = cv2.resize(input_img, (int(limit), int(rows * limit / cols))) 36 rows, cols, colors = input_img.shape 37 print ('resized', rows, cols) 38 39 gray = cv2.cvtColor(input_img, cv2.COLOR_BGR2GRAY) 40 hypot = int(math.hypot(rows, cols)) 41 frame = np.zeros((hypot, hypot), np.uint8) 42 frame[int((hypot - rows) * 0.5):int((hypot + rows) * 0.5), int((hypot - cols) * 0.5):int((hypot + cols) * 0.5)] = gray 43 results = [] 44 face_id_seed = 0 45 46 #5度ずつ元画像を回転し、顔の候補を全部取得 47 #for deg in range(-50, 51, 5): 48 for deg in range(-5, 5, 5): 49 print('deg:%s' % deg) 50 M = cv2.getRotationMatrix2D((hypot * 0.5, hypot * 0.5), -deg, 1.0) 51 rotated = cv2.warpAffine(frame, M, (hypot, hypot)) 52 #""" 53 out_file = '%s/deg_%s.jpg' % (img_dir, deg) 54 55 faces = face_cascade.detectMultiScale(rotated, 1.02, 5) 56 for (x, y, w, h) in faces: 57 58 face_cand = rotated[y:y+h, x:x+w] 59 60 center = (int(x + w * 0.5), int(y + h * 0.5)) 61 origin = (int(hypot * 0.5), int(hypot * 0.5)) 62 r_deg = -deg 63 center_org = rotate_coord(center, origin, r_deg) 64 print ('face', (x,y,w,h), center_org) 65 66 resized = face_cand 67 if w < IMAGE_SIZE: 68 print ('resizing..') 69 resized = cv2.resize(face_cand, (IMAGE_SIZE, IMAGE_SIZE)) 70 71 result = { 72 'face_id': 'f%s' % face_id_seed, 73 'img_resized': resized, #顔候補bitmap(小さい場合zoom) 74 'img': face_cand, #顔候補bitmap(元サイズ) 75 'deg': deg, #回転 76 'frame': (x, y, w, h), #回転状態における中心座標+size 77 'center_org': center_org, #角度0時における中心座標 78 } 79 results.append(result) 80 face_id_seed += 1 81 82 eyes_id_seed = 0 83 eyes_faces = [] 84 85 for result in results: 86 print ('#eyes:',result['face_id']) 87 88 img = np.copy(result["img_resized"]) 89 fw,fh = img.shape 90 eyes = eye_cascade.detectMultiScale(img, 1.02) 91 left_eye = right_eye = None #左上/右上にそれぞれ目が1つずつ検出できればOK 92 for (x,y,w,h) in eyes: 93 94 print ('## eye:',x,y,w,h,fw/8,fw/4,fh/8,fh/4) 95 cv2.rectangle(img,(x,y),(x+w,y+h),(64,64,0),1) 96 97 if not (fw/6 < w and w < fw/2): 98 print ('eye width invalid') 99 continue 100 if not (fh/6 < h and h < fh/2): 101 print ('eye height invalid') 102 continue 103 if not fh * 0.5 - (y + h * 0.5) > 0: #上半分に存在する 104 print ('eye position invalid') 105 continue 106 if fw * 0.5 - (x + w * 0.5) > 0: 107 if left_eye: 108 print ('too many left eye') 109 continue 110 else: 111 left_eye = (x,y,w,h) 112 else: 113 if right_eye: 114 print ('too many right eye') 115 continue 116 else: 117 right_eye = (x,y,w,h) 118 if left_eye and right_eye: 119 print ('>>> valid eyes detect') 120 result['left_eye'] = left_eye 121 result['right_eye'] = right_eye 122 eyes_faces.append(result) 123 124 #重複検出を除去 125 candidates = [] 126 for i, result in enumerate(eyes_faces): 127 print ('result:',result['face_id']) 128 result['duplicated'] = False 129 for cand in candidates: 130 c_x, c_y = cand['center_org'] 131 _,_,cw,ch = cand['frame'] 132 r_x, r_y = result['center_org'] 133 _,_,rw,rh = result['frame'] 134 if abs(c_x - r_x) < ((cw+rw)*0.5*0.3) and abs(c_y - r_y) < ((ch+rh)*0.5*0.3): #近い場所にある顔候補 135 c_diff = eyes_vertical_diff(cand) 136 r_diff = eyes_vertical_diff(result) 137 print ('c_diff:',cand['face_id'],c_diff) 138 print ('r_diff:',result['face_id'],r_diff) 139 if c_diff < r_diff: #より左右の目の水平位置が近いほうが採用 140 result['duplicated'] = True 141 else: 142 cand['duplicated'] = True 143 candidates.append(result) 144 filtered = filter(lambda n: n['duplicated'] == False, candidates) 145 146 #""" 147 for cand in filtered: 148 149 out_file = '%s/cand_%s_face_%s_%s.jpg' % (img_dir, cand['face_id'], cand['deg'], cand['center_org']) 150 #cv2.imwrite(out_file, cand['img']) 151 #res.append(out_file) 152 #""" 153 finals = [] 154 #候補に対してさらに口検出チェック 155 for item in filtered: 156 img = np.copy(item["img_resized"]) 157 fw,fh = img.shape 158 mouthes = mouth_cascade.detectMultiScale(img, 1.02) #faceの中心下部付近にあればOK 159 mouth_found = False 160 for (mx,my,mw,mh) in mouthes: 161 162 print ('mouth',(mx,my,mw,mh)) 163 cv2.rectangle(img,(mx,my),(mx+mw,my+mh),(128,128,0),2) 164 h_diff = fh/2 - (my+mh/2) 165 print (fh, h_diff) 166 if h_diff < 0: 167 mouth_found = True 168 break 169 #""" 170 out_file = '%s/mouth_%s_face_%s_%s.jpg' % (img_dir, item['face_id'], item['deg'], item['center_org']) 171 #cv2.imwrite(out_file, img) 172 #""" 173 print (item['face_id'], 'mouth found?', mouth_found) 174 if mouth_found: 175 finals.append(item) 176 out_file1 = '%s/final_%s_%s_%s_%s.jpg' % (out_dir, fn, item['face_id'], item['deg'], item['center_org']) 177 out_file2 = '%s/final_%s_%s_%s_%s.jpg' % (img_dir, fn, item['face_id'], item['deg'], item['center_org']) 178 #cv2.imwrite(out_file1, item['img']) 179 #cv2.imwrite(out_file2, item['img']) 180 181 #最後にカラー画像として切り出し 182 res = [] 183 for item in finals: 184 185 out_file = crop_color_face(item, input_img, base_dir, out_dir, fn) 186 res.append(out_file) 187 return res 188 189def crop_color_face(item, img, base_dir, out_dir, fn): 190 rows, cols, colors = img.shape 191 hypot = int(math.hypot(rows, cols)) 192 frame = np.zeros((hypot, hypot, 3), np.uint8) 193 frame[int((hypot - rows) * 0.5):int((hypot + rows) * 0.5), int((hypot - cols) * 0.5):int((hypot + cols) * 0.5)] = img 194 195 deg = item['deg'] 196 M = cv2.getRotationMatrix2D((hypot * 0.5, hypot * 0.5), -deg, 1.0) 197 rotated = cv2.warpAffine(frame, M, (hypot, hypot)) 198 199 #""" 200 #out_file = '%s/7_color_deg_%s.jpg' % (img_dir, deg) 201 #cv2.imwrite(out_file, rotated) 202 #""" 203 204 x,y,w,h = item['frame'] 205 face = rotated[y:y+h, x:x+w] 206 face = cv2.resize(face, (IMAGE_SIZE, IMAGE_SIZE)) 207 #""" 208 web_path = '%s/%s_%s.jpg' % (out_dir, fn, item['face_id']) 209 out_file = '%s/%s' % (base_dir, web_path) 210 print ('web_path', web_path) 211 print ('out_file', out_file) 212 cv2.imwrite(out_file, face) 213 #""" 214 215 return web_path 216 217def eyes_vertical_diff(face): 218 _,ly,_,lh = face["left_eye"] 219 _,ry,_,rh = face["right_eye"] 220 return abs((ly + lh * 0.5) - (ry + rh * 0.5)) 221 222def rotate_coord(pos, origin, deg): 223 """ 224 posをdeg度回転させた座標を返す 225 pos: 対象となる座標tuple(x,y) 226 origin: 原点座標tuple(x,y) 227 deg: 回転角度 228 @return: 回転後の座標tuple(x,y) 229 @see: http://www.geisya.or.jp/~mwm48961/kou2/linear_image3.html 230 """ 231 x, y = pos 232 ox, oy = origin 233 r = np.radians(deg) 234 xd = ((x - ox) * np.cos(r) - (y - oy) * np.sin(r)) + ox 235 xy = ((x - ox) * np.sin(r) + (y - oy) * np.cos(r)) + oy 236 return (int(xd), int(xy)) 237 238def show(img): 239 cv2.imshow('img',img) 240 cv2.waitKey(0) 241 cv2.destroyAllWindows() 242if __name__ == "__main__": 243 param = sys.argv 244 245 img_dir = param[1] 246 dir_check = os.path.exists(img_dir+"_out_img")#指定の画像格納ディレクトリの有無 247 #無ければ作成 248 if dir_check == False: 249 os.mkdir(img_dir+"_out_img") 250 251 #os.chdir(dir) 252 #ファイル読み込み 253 img_file = glob.glob("./"+img_dir+"/*") 254 outdir = img_dir+"_out_img" 255 256 for img in img_file: 257 detect_face_rotate(img,outdir)

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

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

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

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

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

yukkeorg

2017/04/18 13:58

質問を最後まで記載してください、また、実行した時にエラーが出る場合は、そのまま記載をお願いします、
daigakuse-

2017/04/18 14:05

誤字訂正しました。エラーはないです。
guest

回答1

0

ベストアンサー

Python3に組み込みのfilter関数はイテレータをを返します。イテレータは一度ループで処理(for cond in filterd:)してしまうと巻き戻りが起きないため、その後のループ(for item in filtered:)で利用しようとしてもイテレータがさすデータがないことから、ループ処理が行われません。

今回の場合は、以下のようにfilter関数で帰ってきたイテレータで順次取得できる値をリストすると良いかと思います。

python

1 filtered = list(filter(lambda n: n['duplicated'] == False, candidates))

finalsのほうは上のfilteredのループが動いていないため、空リストとなっています。

投稿2017/04/18 15:05

編集2017/04/18 15:06
yukkeorg

総合スコア985

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問