Проблема с глобальной переменной при использовании потокового видео с python и opencv - PullRequest
0 голосов
/ 06 февраля 2020

Я пытаюсь транслировать видео и создать систему распознавания движения. Я использую многопоточность, потому что считаю ее более стабильной и чистой с параллельными кадрами. Я застрял в том, как объявить кадр 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)

1 Ответ

0 голосов
/ 06 февраля 2020

Пожалуйста, посмотрите на ваш код:

            (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.

Удачи

Andreas

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...