2017-01-06 11 views
1

私はウェブカメラを使ってOCRを使ってプロジェクトを進めています。私は、フレームを保存するためのcapture()関数を定義しました。この関数は、最小で20の等高線と、60ピクセルを超える領域が3秒間に含まれています。私はサイクルが常に働いている間、メインを必要とします。だから私はcapture()関数を呼び出すスレッドを使用しています。コードを実行すると、Python Shellがエラーを返しました:NameError:グローバル名フレーム、ln2が定義されていません。 13番目のコメント行は、変数フレームのエラーを解決します。 whileサイクルの中にあるすべてのコードを複製する必要があることを意味しますか?グローバル変数のエラーがPythonのスレッド関数で定義されていません

はここ
import cv2 
import time 
import threading 

cap = cv2.VideoCapture(0) 

def capture(): 
    global frame, ln2 
    if ln2 > 20: 
     cv2.imwrite("frame.jpg", frame) 
     time.sleep(3) 

#ret, frame = cap.read() #it solves the error for variable 'frame' 

child_t = threading.Thread(target = capture) 
child_t.setDaemon(True) 
child_t.start() 

while(1): 
    a = [] 
    ret, frame = cap.read() 
    img1 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 
    _, img2 = cv2.threshold(img1, 127, 255, cv2.THRESH_BINARY) 
    (_, contornos, _) = cv2.findContours(img2, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 
    ln = len(contornos) 

    for i in range (0, ln): 
     cn = contornos[i] 
     x, y, w, h = cv2.boundingRect(cn) 
     area = 2*(w+h) 

     if area > 60 and area < 1000: 
      cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 255, 0), 2) 
      a.append(area) 

    ln2 = len(a) 
    print ln2 

    #here I want to call capture() function 

    cv2.imshow('Webcam', frame) 

    if cv2.waitKey(1) & 0xFF == ord('x'): 
     break 

child_t.join() 

cap.release() 
cv2.destroyAllWindows() 
+0

私は今日も最初のコーヒーにいますが、トップスコープでグローバルを宣言することはありません。関数内でのみ。あなたは機能の外でそれを行う必要があります。バイトコードでは、それを却下したい場合はSTORE_GLOBALと表示され、関数にはLOAD_GLOBALと表示されます。もちろん、STOREとLOADは失敗しません。 –

答えて

0

あなたが行く:私はここに

のWindows 7上のpython 2.7を使用してい

はコードです。私はthreading.Threadの代わりにthreading.Timerを使用しており、その後にtime.sleepを使用しています。

はまた、あなたが60個のピクセルよりも大きな面積を有する最小20の輪郭を含むフレームを保存するために、しかし、あなたのコード内の関連if文はそれをしない必要があると述べました。だから私はそれを加えました。

メッセージ名前エラー:グローバル名フレーム、ln2が定義されていませんは、frameが読み取られる前でもスレッドが開始されているためです。変数ln2にも同じことが適用されます。これは以下のコードでも修正されています。基本的に私はこの問題を克服するためにフラグwriteToFileを使用しました。

import threading 
import cv2 

writeToFile = False 
exitTask = False 

def threadTask(): 
    global frame 
    if not exitTask: 
     threading.Timer(3.0, threadTask).start() 
     if writeToFile: 
      cv2.imwrite("Threads.jpg", frame) 
      print "Wrote to file" 


cap = cv2.VideoCapture(0) 
threadTask() 

while(True): 
    areasList = [] 

    try: 
     ret, frame = cap.read() 

     img1 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 
     _, img2 = cv2.threshold(img1, 127, 255, cv2.THRESH_BINARY) 
     (_, contours, _) = cv2.findContours(img2, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 
     nContours = len(contours) 

     for contour in contours: 
      x, y, w, h = cv2.boundingRect(contour) 
      area = 2*(w+h) 

      #if area > 60 and area < 1000: 
      if (nContours > 10) and (area > 20): 
       cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 255, 0), 2) 
       areasList.append(area) 
       writeToFile = True 
      else: 
       writeToFile = False 

     #print len(areasList) 

     cv2.imshow('Webcam', frame) 

     if cv2.waitKey(1) & 0xFF == ord('x'): 
      raise KeyboardInterrupt 

    except KeyboardInterrupt: 
     exitTask = True 
     cap.release() 
     cv2.destroyAllWindows() 
     exit(0) 
+0

それはうまく動作します!私は疑問を持っています。コードはたびに1つのスレッドを開始するか、メインと並行して実行されるスレッドを1つだけ作成しますか? –

+0

高レベルの観点では、ある時点でメイン関数と並行して実行されるスレッドは1つだけですが、 'threading.Timer(3.0、threadTask).start()'という行を注意深く見ると、基本的に3秒後に 'threadTask'を実行するスレッドを作成します。 –

+0

スレッドが起動すると 'threadTask'関数が実行されます。現時点では、スレッドを何度も何度もやり直していないか、 'if'文が1回だけ実行されるとフレームがどのように保存されるのでしょうか? –

関連する問題