首页 > 解决方案 > 使用带有 python 和 opencv 的视频流的全局变量问题

问题描述

我正在尝试流式传输视频并制作运动识别系统。我使用线程是因为我发现并行框架更稳定、更干净。我被困在如何声明第 1 帧和第 2 帧,它们将用于读取运动识别所需的两个图像,这是我的代码:

from threading import Thread
import cv2, time
import os.path
import smtplib
import numpy as np
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

contadorImg = 0


class VideoStreamWidget(object):
    def __init__(self, src='http://192.168.1.78:80'):
        self.capture = cv2.VideoCapture(src)

        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():

                (self.status, self.frame1) = self.capture.read()
                (self.status, self.frame2) = self.capture.read()

                diff = cv2.absdiff(frame1, frame2)
                gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
                blur = cv2.GaussianBlur(gray, (5,5), 0)
                _, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY)
                dilated = cv2.dilate(thresh, None, iterations=3)
                _,contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

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

                    if cv2.contourArea(contour) < 2300: #MIN AREA TO DETECT
                        continue
                    cv2.rectangle(frame1, (x, y), (x+w, y+h), (0, 255, 0), 2)
                    cv2.putText(frame1, "Status: {}".format('Movement'), (10, 20), cv2.FONT_HERSHEY_SIMPLEX,
                                1, (0, 0, 255), 3)
                    contadorImg = contadorImg + 1
                    imagen = 'img' + str(contadorImg) + '.jpg'
                    cv2.imwrite(imagen, frame1)


                if contadorImg%5 == 0 :                          #Sending just 1/5 of the taked images
                    email = '*******'
                    password = '*****'
                    send_to_email = '*****@gmail.com'
                    subject = 'This is the subject'
                    message = 'This is my message'  
                    msg = MIMEMultipart()
                    msg['From'] = email
                    msg['To'] = send_to_email
                    msg['Subject'] = subject

                    msg.attach(MIMEText(message, 'plain'))
                    # Setup the attachment
                    attachment = open(imagen, "rb")
                    part = MIMEBase('application', 'octet-stream')
                    part.set_payload(attachment.read())
                    encoders.encode_base64(part)

                    part.add_header('Content-Disposition', "attachment; filename= %s" % imagen) 
                    print ('i1:', imagen)

                    # Attach the attachment to the MIMEMultipart object
                    msg.attach(part)
                    #time.sleep(1)
                    server = smtplib.SMTP('smtp.gmail.com', 587)
                    server.starttls()
                    server.login(email, password)
                    text = msg.as_string()
                    server.sendmail(email, send_to_email, text)
                    print('Mail Sent')
                    server.quit()


            time.sleep(.01)

    def show_frame(self):
        # Display frames in main program
        cv2.imshow('Surveillance Camera', self.frame1)
        frame1 = frame2
        ret, frame2 = cap.read()
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            cv2.destroyAllWindows()
            exit(1)

if __name__ == '__main__':
    video_stream_widget = VideoStreamWidget()
    while True:
        try:
            video_stream_widget.show_frame()
        except AttributeError:
            pass


这是我在终端上遇到的错误:

Exception in thread Thread-1:
Traceback (most recent call last):

  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()

  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)

  File "master3.py", line 39, in update

    diff = cv2.absdiff(frame1, frame2)

NameError: global name 'frame1' is not defined

init done
opengl support available

Traceback (most recent call last):

  File "master3.py", line 119, in <module>

    video_stream_widget.show_frame()

  File "master3.py", line 100, in show_frame

    frame1 = frame2

UnboundLocalError: local variable 'frame2' referenced before assignment

Segmentation fault (core dumped)

标签: pythonmultithreadingopencv

解决方案


请看一下您的代码:

            (self.status, self.frame1) = self.capture.read()
            (self.status, self.frame2) = self.capture.read()

            diff = cv2.absdiff(frame1, frame2)

但是,self.frame1 和 frame1 不是一回事。如果您将输入图像分配给 self.frame1,那么您也应该通过 self.frame1 访问它。

祝你好运

安德烈亚斯


推荐阅读