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

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

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

OpenPoseとは、深層学習を使って人の体や指などの位置(座標)や向きといったポーズを可視化する技術。関節点など人の体における特徴点が座標のどこにあるかを検出することができます。高性能プロセッサを使えば動画像内の複数の人物もリアルタイムで検出することが可能です。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

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

Q&A

解決済

1回答

657閲覧

Python3 OpenPose【配列がNoneの場合、if文で対処する方法】

mia_flower

総合スコア66

OpenPose

OpenPoseとは、深層学習を使って人の体や指などの位置(座標)や向きといったポーズを可視化する技術。関節点など人の体における特徴点が座標のどこにあるかを検出することができます。高性能プロセッサを使えば動画像内の複数の人物もリアルタイムで検出することが可能です。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

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

0グッド

0クリップ

投稿2022/03/06 02:47

前提・実現したいこと

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

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

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

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

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

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

melian

2022/03/06 03:01

if points: とします。
mia_flower

2022/03/06 04:16

早速のご回答ありがとうございます。 以下のようにコードを書き換えてみましたが、 else以下が動作しませんでした。 Noneの際にnose_xに要素を渡せない為に TypeErrorが発生してしているように思います。 ``` if points : nose_x = points[0][0]#鼻のx座標 #ここでTypeErrorが発生 nose_y = points[0][1]#鼻のy座標 print(nose_x, nose_y) print('鼻発見') else: print('鼻が見つかりません') ``` 配列にNoneが含まれている場合でも、コードを実行し続けるにはどのようにしたら良いでしょうか。
melian

2022/03/06 04:27

コードの最初で points.append((int(x), int(y)) if conf > thr else None) としている部分を見落としていました。これだと points に None が追加されてしまいますので、 if conf > thr: points.append((int(x), int(y)) としてみて下さい(これで None は追加されなくなります)。
mia_flower

2022/03/06 05:35

早速のご返信ありがとうございます。 if conf > thr: points.append((int(x), int(y))としたところ、以下のエラーが出てしまいました。 ``` File "<ipython-input-1-8d284f427985>", line 66 for pair in POSE_PAIRS: ^ SyntaxError: invalid syntax ``` また、if points : 以下を下記のように書き換えてみても、TypeErrorを起こしてしまいました。 ``` if points : nose = points[0]#ここにNoneが入っても動作する noseX = nose[0]#noseのx座標のみを取り出す。ここにNoneが入ると、TypeErrorを引き起こす ``` どのようにしたらよろしいのでしょうか。
melian

2022/03/06 05:39

ごめんなさい、最後に ) が足りませんでした。正しくは以下になります。 if conf > thr: points.append((int(x), int(y)))
mia_flower

2022/03/06 05:49

ご丁寧に教えて頂きまして感謝いたします。 `````` IndexError Traceback (most recent call last) <ipython-input-1-b58b284003ba> in <module> 74 idTo = BODY_PARTS[partTo] 75 ---> 76 if points[idFrom] and points[idTo]: 77 cv.line(frame, points[idFrom], points[idTo], (0, 255, 0), 3) 78 cv.ellipse(frame, points[idFrom], (3, 3), 0, 0, 360, (0, 0, 255), cv.FILLED) IndexError: list index out of range ``` すみません。新しくIndexError:が出てしまいました。 今までNoneを入れることで対処していたものが、Noneを入れないと動作しなくなってしまうのでしょうか。
melian

2022/03/06 05:53

はい、どうやら None を意図的に入れて何らかのフラグとして使っている様ですね。
mia_flower

2022/03/06 06:07

ありがとうございます。そうなのですね。 この場合、if文などで回避する事は難しいのでしょうか。
melian

2022/03/06 06:23

では、 if points[:1][0] is None: に変更して試してみてもらえますか?
mia_flower

2022/03/06 06:56

ありがとうございます!! 期待通りに動作しました。 ここ数日間悩んでいたので本当に嬉しいです。 (ベストアンサーにさせて頂きたいのですが、 記入して頂いた欄が、「質問への修正依頼欄」でして ベストアンサーにすることができず...)
melian

2022/03/06 07:42

解決できて良かったです。ベストアンサーに関しては mia_flower さんの自己回答でよろしいかと思います。
mia_flower

2022/03/06 10:38

ご丁寧に回答してくださり、ありがとうございました。 学びになりました。 回答欄に記載させて頂きました。 またどうぞ宜しくお願い致します。
guest

回答1

0

自己解決

melian さんにご教授頂き、該当のソースコードの内、if文を

if points[:1][0] is None:

としたところif文が正常に動作しました。

また、nose_x = points[0][0] で、鼻のx座標を取得できていると思っていたのですが
誤っていたようで、その点も修正したところ無事に期待通りの結果を出力する事ができました。

投稿2022/03/06 10:37

mia_flower

総合スコア66

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問