QA@IT

python でのプログラムによる、attribute errorについて

972 PV

現在、python3.5.5とOpenCV3.4.3を使用し、ハフ変換でのリアルタイム円検出と各円の出現時間を個別に計測できるシステムを作製しようと考えています。各円は重心の座標により識別しようと考えました。作成したコードが以下の通りです。

from datetime import datetime
import math
import numpy as np
import cv2

FIND_DIST = 10 
i1 = []
i2 = []
targets = []

def inp_points():
    pts = []
    while True: 
        s = (i1,i2)
        pt = s.split(',')
        if len(s) < 2:
            break
        pts.append( (float(pt[0]), float(pt[1])))
    return pts

id = 1
cap = cv2.VideoCapture(0)
while True:
    now_time = datetime.now()
    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
    gray = cv2.GaussianBlur(gray, (33,33), 1)
    circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 60, param1=10, param2=85, minRadius=10, maxRadius=80)
    if circles is not  None:
        circles = np.uint16(np.around(circles))
        for i in circles[0,:]:
            cv2.circle(frame,(i[0],i[1]),i[2],(255,255,0),2)
            cv2.circle(frame,(i[0],i[1]),2,(0,0,255),3)
            i1 = (i[0])
            i2 = (i[1])   

        pts = inp_points()
        if len(pts) <= 0:
            break

        for tgt in targets:
            tgt['bIn'] = False

        new_tgts = []

        for pt in pts:
            bIn = False
            for tgt in targets:

                if math.sqrt( math.pow(pt[0] - tgt['pos'][0], 2) + math.pow(pt[1] - tgt['pos'][1], 2)) <= FIND_DIST:
                    tgt['bIn'] = True
                    tgt['pos'] = pt
                    bIn = True

            if not bIn:
                new_tgt = {'id':id,'bIn':True,'pos':pt,'in_time':now_time}
                new_tgts.append(new_tgt)
                print("come:", new_tgt)
                id += 1

        for tgt in targets:
            if tgt['bIn']: 
                new_tgts.append(tgt)
            else:         
                print('out:',tgt)
                print('{}sec'.format((now_time - tgt['in_time']).total_seconds()))

        targets = new_tgts
        print('-----')

    cv2.imshow('preview', frame) 
    key = cv2.waitKey(10)
    if key == ord("q"):
        break

cv2.destroyAllWindows()

起動させたところ、画面上に円が現れると、以下のエラーが出て止まってしまいます。
File "circles_ dot.py", line37, in
pts = inp_points()
File "circles_ dot.py", line15, in inp_points
pt = split(',')
Attribute Error: 'tuple' object has no attribute 'split'

属性が違うと怒られていると思うのですが、どのように合わせればよいかわからない状態です。
やりたいこととしては、入力 s にハフ変換により求めた円の重心(i[0],i[1])を入れるということです。
どのような改善が必要か教えていただけると助かります。よろしくお願いいたします。

回答

if文で何をチェックしたいのかわかりませんが、
s はtupleであり、文字のようなものではありませんので、splitする必要がありません。

def inp_points():
    pts = []
    while True: 
        s = (i1,i2)
        pt = s.split(',')
        if len(s) < 2:
            break
        pts.append( (float(pt[0]), float(pt[1])))
    return pts

i1,i2もリストとして初期化してますが、代入文見るにリストとして使ってない(i1 = (i[0]) ちなみにこれはカンマがないのでTupleではない)みたいですし、
コードとして不明点が多いのでアドバイスできませんが、以下のようにすれば、最後の円について何か動くと思います。

def inp_points():
    pts = []
    pt = (i1,i2)
    pts.append( (float(pt[0]), float(pt[1])))
    return pts

変数、リスト、タプルについて復習するといいと思います。
また、関数(inp_points)で必要なあたいはなるべく引数として受け取るようにしましょう。

追記: 書き忘れましたが、if文はずすだけだと無限ループになるので、While文ごと外しました。全ての円について操作したかったのかとは思いますが、現状座標?は最後の円の分しか格納されていませんので、全ての円について操作するのであれば、リストの使い方を調べてi1,i2への値の追加方法を考え直してください。変数名もわかりやすいものを心がけましょう。

編集 履歴 (1)
  • 丁寧な説明、たいへんためになりました。inp_points関数を無くし、そのままptsに加えるように書き換えたらスムーズに動くようになりました。flied_onion様がおっしゃる通り、まずはリスト、タプル等について学習したいと思います。ありがとうございました。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。