Обнаружение лиц на видеопотоке падает после перехода на много - PullRequest
0 голосов
/ 01 декабря 2019

Я создал видеопоток, который принимает данные с камеры, рисует прямоугольники на лицах и рисует данные о времени и погоде в верхней части кадра. Этот кадр показан в приложении wxPython. Большую часть времени он зависает после нескольких секунд работы. Если он не останавливается при запуске, он часто зависает и вылетает при перемещении в кадре, снятом камерой. Можно ли этого избежать или процесс распознавания лица слишком сложен для запуска Python? код:

import wx
from PIL import Image
import cv2
import numpy as np
import requests
import time
import json
from datetime import datetime

SIZE = (1280, 720)

CapDev = cv2.VideoCapture(0)

# THIS PART HAS BEEN DELETED, CONTAINED PRIVATE API KEYS
req = None
appid = ''
api_url = ''
city_id = 

haar_cascade_face = cv2.CascadeClassifier('data/haarcascade_frontalface_default.xml')

starttime = time.time()
dispcount = 0

size = CapDev.read()[1].shape[:2]
size = size[:2]
size = size[::-1]
print(size)

font = cv2.FONT_HERSHEY_SIMPLEX
white = (255, 255, 255)
left_bot_text = (0, size[1] - 50)
left_top_text = (0, 25)


def get_image():
    global req, appid, api_url, city_id, font, size

    frame = CapDev.read()[1]
    if not req:
        req = [requests.get(url=api_url, params=dict(q='Ghent,be', APPID=appid)), time.time()]

    req = getweatherinfo(req)
    weatherinfo = processweatherinfo(req)
    localtime = gettime()
    # detecting faces using opencv2 cascades
    frame = detect_faces(haar_cascade_face, frame)
    # drawing weather info + rectangle around it
    cv2.putText(frame, weatherinfo, left_top_text, font, 1, white, 2, cv2.LINE_AA)
    rightbot, thikness = cv2.getTextSize(weatherinfo, font, 1, 2)
    cv2.rectangle(frame, (rightbot[0], rightbot[1]+thikness+10), (0, 0),  white, 2)

    # drawing the current time + rectangle around it
    cv2.putText(frame, localtime, left_bot_text, font, 1, white, 2, cv2.LINE_AA)
    rightbot2, thikness2 = cv2.getTextSize(localtime, font, 1, 2)
    cv2.rectangle(frame, (rightbot2[0], size[1]-50 + thikness2), (0, size[1]-80), white, 2)


    totimg = frame
    totimage = convertToRGB(totimg)
    image = Image.fromarray(totimage)
    return image


def getweatherinfo(weatherreq):
    if int(time.time() - weatherreq[1]) > 1:
        wetreq = [requests.get(url=api_url, params=dict(q='Ghent', APPID=appid)), time.time()]
        print('New Request ')
    else:
        wetreq = weatherreq
    return wetreq


def convertToRGB(image):
    return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)


def detect_faces(cascade, test_img, scaleFactor = 1.1):
    img_copy = test_img.copy()

    gray_img = cv2.cvtColor(img_copy, cv2.COLOR_BGR2GRAY)

    faces_rects = cascade.detectMultiScale(gray_img, scaleFactor = scaleFactor, minNeighbors = 5)
    for (x, y, w, h) in faces_rects:
        cv2.rectangle(img_copy, (x, y), (x + w, y + h), (255, 0, 0), 2)

    return img_copy


def processweatherinfo(reqresp):
    datastore = json.loads(reqresp[0].text)
    global starttime
    global dispcount
    weather = datastore['weather'][0]['main'] + ': ' + datastore['weather'][0]['description']
    temp = str(datastore['main']['temp']) + 'K, '+str(round(float(datastore['main']['temp'])-273.15, 2))+" deg. Celsius"
    wind = 'wind speed ' + str(datastore['wind']['speed']) + 'm/s'  # + str(datastore['wind']['deg']) + ' degrees'
    cycle = [weather, temp, wind]
    if starttime-time.time() < -3 and dispcount != 2:
        dispcount += 1
        starttime = time.time()
    elif starttime - time.time() < -3 and dispcount == 2:
        dispcount = 0
        starttime = time.time()
    return cycle[dispcount]


def unixtodatetime(unix_stamp):
    dt_object = datetime.fromtimestamp(unix_stamp)
    dt_object = str(dt_object).split()
    return dt_object[1], dt_object[0]


def gettime():
    timestamp = unixtodatetime(time.time())[0]
    return timestamp[:11]


def pil_to_wx(image):
    width, height = image.size
    buffer = image.convert('RGB').tobytes()
    bitmap = wx.Bitmap.FromBuffer(width, height, buffer)
    return bitmap


class HUDPanel(wx.Panel):
    def __init__(self, parent):
        super(HUDPanel, self).__init__(parent, -1)
        self.SetInitialSize(size)
        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.Bind(wx.EVT_PAINT, self.on_paint)
        self.update()

    def update(self):
        self.Refresh()
        self.Update()
        wx.CallLater(15, self.update)

    def create_bitmap(self):
        image = get_image()
        bitmap = pil_to_wx(image)
        return bitmap

    def on_paint(self, event):
        bitmap = self.create_bitmap()
        dc = wx.AutoBufferedPaintDC(self)
        dc.DrawBitmap(bitmap, 0, 0)


class ExtraPanel(wx.Panel):
    def __init__(self, parent):
        super(ExtraPanel, self).__init__(parent, -1)
        self.SetInitialSize(size)
        self.SetBackgroundColour(wx.SystemSettings.GetColour(0))
        My_Button = wx.Button(self, label="STOP")
        My_Button.Bind(wx.EVT_BUTTON, self.stop_on_press)

    def stop_on_press(self, event):
        print("TestButton was used")
        wx.Exit()


class Frame(wx.Frame):
    def __init__(self):
        style = wx.DEFAULT_FRAME_STYLE & ~wx.RESIZE_BORDER & ~wx.MAXIMIZE_BOX
        super(Frame, self).__init__(None, -1, 'Camera Viewer', style=style)

        my_sizer = wx.BoxSizer(wx.HORIZONTAL)

        campanel = HUDPanel(self)
        campanel.SetSize(size)
        my_sizer.Add(campanel, wx.CENTER, 0)

        widgetpanel = ExtraPanel(self)
        widgetpanel.SetSize(size)
        my_sizer.Add(widgetpanel, 0, wx.ALL | wx.CENTER, 5)

        self.SetSizer(my_sizer)
        self.SetSize((size[0]*2,size[1]))


def main():
    app = wx.App()
    frame = Frame()

    frame.Show()
    app.MainLoop()


if __name__ == '__main__':
    main()

Извините за грязный код. Любые улучшения в кодировании / подсказка для перестановки кода приветствуются

...