python上的线程函数中未定义全局变量错误

python上的线程函数中未定义全局变量错误,python,multithreading,global-variables,ocr,nameerror,Python,Multithreading,Global Variables,Ocr,Nameerror,我在一个使用网络摄像头的OCR项目中工作。我定义了一个capture()。我需要主while循环一直工作。因此,我使用一个线程来调用capture()函数。当我运行代码时,Python Shell返回一个错误:NameError:global name frame,ln2未定义。第13条注释行解决了可变帧的错误。这是否意味着我必须复制while循环中的所有代码 我正在Windows7上使用Python2.7 代码如下: import cv2 import time import threadin

我在一个使用网络摄像头的OCR项目中工作。我定义了一个
capture()。我需要主while循环一直工作。因此,我使用一个线程来调用
capture()
函数。当我运行代码时,Python Shell返回一个错误:NameError:global name frame,ln2未定义。第13条注释行解决了可变帧的错误。这是否意味着我必须复制while循环中的所有代码

我正在Windows7上使用Python2.7

代码如下:

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()
导入cv2
导入时间
导入线程
cap=cv2.视频捕获(0)
def capture():
全局帧
如果ln2>20:
cv2.imwrite(“frame.jpg”,frame)
时间。睡眠(3)
#ret,frame=cap.read()#它解决了变量“frame”的错误
子线程=线程。线程(目标=捕获)
child_t.setDaemon(True)
child_t.start()
而(一):
a=[]
ret,frame=cap.read()
img1=cv2.cvt颜色(边框,cv2.COLOR\u bgr2灰色)
_,img2=cv2.threshold(img1,127255,cv2.THRESH_二进制)
(u,contornos,u)=cv2.查找对象(img2,cv2.RETR\u列表,cv2.链近似\u简单)
ln=len(续)
对于范围(0,ln)内的i:
cn=contornos[i]
x、 y,w,h=cv2.boundingRect(cn)
面积=2*(宽+高)
如果面积大于60且面积小于1000:
cv2.矩形(框架,(x,y),(x+w,y+h),(0,255,0),2)
a、 附加(区域)
ln2=len(a)
打印ln2
#这里我想调用capture()函数
cv2.imshow(“网络摄像头”,画面)
如果cv2.waitKey(1)&0xFF==ord('x'):
打破
child_t.join()
第1章释放()
cv2.destroyAllWindows()

给你。请注意,我使用的是
threading.Timer
,而不是
threading.Thread
,后跟
time.sleep

另外,您说过需要保存至少包含20个轮廓且面积大于60像素的帧,但代码中的相关
if
语句没有这样做。所以我也加了这个

消息NameError:global name frame,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)
导入线程
进口cv2
writeToFile=False
退出任务=False
def threadTask():
全局框架
如果没有退出任务:
threading.Timer(3.0,threadTask.start())
如果写入文件:
imwrite(“Threads.jpg”,frame)
打印“写入文件”
cap=cv2.视频捕获(0)
threadTask()
虽然(正确):
区域列表=[]
尝试:
ret,frame=cap.read()
img1=cv2.cvt颜色(边框,cv2.COLOR\u bgr2灰色)
_,img2=cv2.threshold(img1,127255,cv2.THRESH_二进制)
(u,等高线,u)=cv2.查找到的多边形(img2,cv2.RETR_列表,cv2.链近似值\u简单值)
nContours=len(等高线)
对于等高线中的等高线:
x、 y,w,h=cv2.boundingRect(轮廓)
面积=2*(宽+高)
#如果面积大于60且面积小于1000:
如果(面积>10)和(面积>20):
cv2.矩形(框架,(x,y),(x+w,y+h),(0,255,0),2)
区域列表。附加(区域)
writeToFile=True
其他:
writeToFile=False
#打印透镜(区域列表)
cv2.imshow(“网络摄像头”,画面)
如果cv2.waitKey(1)&0xFF==ord('x'):
升起键盘中断
除键盘中断外:
exitTask=True
第1章释放()
cv2.destroyAllWindows()
出口(0)

给你。请注意,我使用的是
threading.Timer
,而不是
threading.Thread
,后跟
time.sleep

另外,您说过需要保存至少包含20个轮廓且面积大于60像素的帧,但代码中的相关
if
语句没有这样做。所以我也加了这个

消息NameError:global name frame,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)
导入线程
进口cv2
writeToFile=False
退出任务=False
def threadTask():
全局框架
如果没有退出任务:
threading.Timer(3.0,threadTask.start())
如果写入文件:
imwrite(“Threads.jpg”,frame)
打印“写入文件”
cap=cv2.视频捕获(0)
threadTask()
虽然(正确):
区域列表=[]
尝试:
ret,frame=cap.read()
img1=cv2.cvt颜色(边框,cv2.COLOR\u bgr2灰色)
_,img2=cv2.threshold(img1,127255,cv2.THRESH_二进制)
(u,等高线,u)=cv2.查找到的多边形(img2,cv2.RETR_列表,cv2.链近似值\u简单值)
nContours=len(等高线)
对于等高线中的等高线:
x、 y,w,h=cv2.boundingRect(轮廓)
面积=2*(宽+高)
#如果面积大于60且面积小于1000:
如果(面积>10)和(面积>20):
cv2.矩形(框架,(x,y),(x+w,y+h),(0,255,0),2)
区域列表。附加(区域)
writeToFile=True
其他:
writeToFile=False
#打印透镜(区域列表)
cv2.imshow(“网络摄像头”,画面)
如果cv2.waitKey(1)&0xFF==ord('x'):
升起键盘中断
除键盘中断外:
exitTask=True
第1章释放()
cv2.destroyAllWindows()
出口(0)

今天我还在喝我的第一杯咖啡,但我看不到你将globals列为顶级产品。只有在函数中。您需要在函数之外执行此操作