前提・実現したいこと
OpenPoseで検出された体の関節座標を用いたプログラムを作成しています。
しかし鼻が認識されない場合、以下のようなTypeErrorが出てしまい、コードの実行が停止してしまいました。
エラーメッセージ
TypeError Traceback (most recent call last) <ipython-input-1-ca1f30d9e7e3> in <module> 85 86 else: ---> 87 nose_x = points[0][0]#鼻のx座標 88 nose_y = points[0][1]#鼻のy座標 89 print('鼻を発見しました') TypeError: 'NoneType' object is not subscriptable
if文を使って、配列points[:1]内がNoneの場合、エラーが発生する下流の処理を実行しないようにしたいのですが、if文が正常に動作しません。
変数の中身が、None(単一の変数)の場合は動作するが、[None] (配列が空)の場合、if文が正常に動作しないようです。
鼻が認識されない場合でも、コードを実行し続けるにはどのようにしたら良いでしょうか。
ご回答どうぞ宜しくお願い致します。
該当のソースコード
import cv2 as cv import matplotlib.pyplot as plt net = cv.dnn.readNetFromTensorflow("graph_opt.pb")#重み #訓練済データの読み込み inWidth = 368 inHeight = 368 thr = 0.2 #域値 BODY_PARTS = { "Nose": 0, "Neck": 1, "RShoulder": 2, "RElbow": 3, "RWrist": 4, "LShoulder": 5, "LElbow": 6, "LWrist": 7, "RHip": 8, "RKnee": 9, "RAnkle": 10, "LHip": 11, "LKnee": 12, "LAnkle": 13, "REye": 14, "LEye": 15, "REar": 16, "LEar": 17, "Background": 18 } POSE_PAIRS = [ ["Neck", "RShoulder"], ["Neck", "LShoulder"], ["RShoulder", "RElbow"], ["RElbow", "RWrist"], ["LShoulder", "LElbow"], ["LElbow", "LWrist"], ["Neck", "RHip"], ["RHip", "RKnee"], ["RKnee", "RAnkle"], ["Neck", "LHip"], ["LHip", "LKnee"], ["LKnee", "LAnkle"], ["Neck", "Nose"], ["Nose", "REye"], ["REye", "REar"], ["Nose", "LEye"], ["LEye", "LEar"] ] cap = cv.VideoCapture(0) cap.set(cv.CAP_PROP_FPS, 10) #cap.set(フレームレート, 新しい値) cap.set(3,800) cap.set(4,800) if not cap.isOpened(): cap = cv.VideoCapture(0) if not cap.isOpened(): raise IOError("Cannot open video") #キーボードが押されるまで処理を待つ while cv.waitKey(1) < 0: hasFrame, frame = cap.read() if not hasFrame: cv.waitKey() break frameWidth = frame.shape[1]# shapeは(行、列).shape[0]は画像の高さ,shape[1]は幅。 frameHeight = frame.shape[0] # データ型blobへ変換,正規化した画像をnetに入れる net.setInput(cv.dnn.blobFromImage(frame, 1.0, (inWidth, inHeight), (127.5, 127.5, 127.5), swapRB=True, crop=False)) # 順伝搬の処理をforwardの中で行う.処理したものをoutとして出力 out = net.forward() # 今回要素は18つまり(19-1)なので、19まで取得する、と書いておく. out = out[:, :19, :, :] # MobileNet output [1, 57, -1, -1], we only need the first 19 elements assert(len(BODY_PARTS) == out.shape[1]) points = [] for i in range(len(BODY_PARTS)): #対応するパーツのheatMapの作成 heatMap = out[0, i, :, :] # cv.minMaxLoc()で、heatMapの配列の最大,最小値を返してくれる # 局所最大値を見つける _, conf, _, point = cv.minMaxLoc(heatMap) x = (frameWidth * point[0]) / out.shape[3] y = (frameHeight * point[1]) / out.shape[2] # 信頼度が閾値より高ければ、配列末尾に要素を追加 points.append((int(x), int(y)) if conf > thr else None) for pair in POSE_PAIRS:# for変数inオブジェクト partFrom = pair[0]#行 partTo = pair[1]#列 # in演算子は配列BODY_PARTSに要素partFromが存在すればTrueを返す assert(partFrom in BODY_PARTS) assert(partTo in BODY_PARTS) # 配列BODY_PARTSからの要素の取り出し idFrom = BODY_PARTS[partFrom] idTo = BODY_PARTS[partTo] if points[idFrom] and points[idTo]: cv.line(frame, points[idFrom], points[idTo], (0, 255, 0), 3) cv.ellipse(frame, points[idFrom], (3, 3), 0, 0, 360, (0, 0, 255), cv.FILLED) cv.ellipse(frame, points[idTo], (3, 3), 0, 0, 360, (0, 0, 255), cv.FILLED) print(points[:1])# points[:1]は、鼻の座標 if points[:1] is None: print('鼻が見つかりません') else: nose_x = points[0][0]#鼻のx座標 nose_y = points[0][1]#鼻のy座標 print('鼻を発見しました') print(nose_x, nose_y) t, _ = net.getPerfProfile() # FPS計算 freq = cv.getTickFrequency() / 1000 # 画像に文字を書くcv2.putText関数.第2引数が描画したいテキスト(日本語不可) cv.putText(frame, '%.2fms' % (t / freq), (10, 20), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0)) # cv.imshow(winnameウィンドウ名, mat ) cv.imshow('Pose estimation Tutorial', frame)
試したこと
・ if points[:1] == None:
・ if points[:1] is not None:
・ points[:1] を新しい配列に置換
etc....
いずれもTypeErrorが解消されませんでした。
(また、tryを用いた例外処理も試して、エラーが発生する箇所を回避できることは分かったのですが、例外処理を用いない方法を探しています。)
補足情報
・環境 : macOS
・使用したGitリポジトリ
https://github.com/quanhua92/human-pose-estimation-opencv/tree/5f86f77242378d5343c6f8a589e40d21c8537b4e
・参考にしている動画
https://www.youtube.com/watch?time_continue=943&v=9jQGsUidKHs&feature=emb_logo
回答1件
あなたの回答
tips
プレビュー