Wie Sie effizient Lesen und speichern von video von einer IP-Kamera?

Habe ich ein python-script, das ich verwenden, um schnappen Sie Bilder von einer ip-Kamera über mein home-Netzwerk und fügen Sie Datum-Zeit-Informationen. In einem 12-Stunden-Frist greift es sich rund 200.000 Bilder. Aber wenn zoneminder (Kamera-überwachung-software) auf der Kamera verwaltet 250.000 in einem Zeitraum von 7 Stunden.

Ich Frage mich, wenn jemand helfen könnte mich zu verbessern mein Skript Effizienz habe ich versucht, mit der threading-Modul zu erstellen, 2 threads, aber es hat nicht geholfen, ich bin mir nicht sicher, ob ich es umgesetzt haben, ist es falsch oder nicht. Unten ist der code, den ich momentan verwende:

#!/usr/bin/env python

# My First python script to grab images from an ip camera

import requests
import time
import urllib2
import sys
import os
import PIL
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
import datetime
from datetime import datetime
import threading

timecount = 43200
lock = threading.Lock()

wdir = "/workdir/"

y = len([f for f in os.listdir(wdir) 
     if f.startswith('Cam1') and os.path.isfile(os.path.join(wdir, f))])

def looper(timeCount):
   global y
   start = time.time()
   keepLooping = True
   while keepLooping:
    with lock:
        y += 1
    now = datetime.now()
    dte = str(now.day) + ":" +  str(now.month) + ":" + str(now.year)
    dte1 = str(now.hour) + ":" + str(now.minute) + ":" + str(now.second) + "." + str(now.microsecond)
    cname = "Cam1:"
    dnow = """Date: %s """ % (dte)
    dnow1 = """Time: %s""" % (dte1)
    buffer = urllib2.urlopen('http://(ip address)/snapshot.cgi?user=uname&pwd=password').read()
    img = str(wdir) + "Cam1-" + str('%010d' % y) + ".jpg"
    f = open(img, 'wb')
    f.write(buffer) 
    f.close()
    if time.time()-start > timeCount:
           keepLooping = False
    font = ImageFont.truetype("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",10)
    img=Image.open(img)
    draw = ImageDraw.Draw(img)
    draw.text((0, 0),cname,fill="white",font=font)
    draw.text((0, 10),dnow,fill="white",font=font)
    draw.text((0, 20),dnow1,fill="white",font=font)
    draw = ImageDraw.Draw(img)
    draw = ImageDraw.Draw(img)
    img.save(str(wdir) + "Cam1-" + str('%010d' % y) + ".jpg")

for i in range(2):
        thread = threading.Thread(target=looper,args=(timecount,))
        thread.start()
        thread.join()

wie könnte ich das verbessern, dieses Skript oder wie öffne ich einen stream von der Kamera, dann schnappen Sie Bilder aus dem stream? würde, dass auch die Steigerung der Effizienz /capture-rate?

Edit:

Dank kobejohn Hilfe ich habe mit der folgenden Umsetzung. laufen für einen 12-Stunden-Zeitraum, es ist mittlerweile über 420.000 Bilder aus 2 separaten Kameras (zur gleichen Zeit), von denen jedes für Ihre eigenen thread in der gleichen Zeit, im Vergleich zu etwa 200.000 von meine ursprüngliche Implementierung vor. Der folgende code wird ausgeführt 2 Kamera parallel (oder nahe genug), und fügen Sie text zu Ihnen:

import base64
from datetime import datetime
import httplib
import io
import os
import time

from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw

import multiprocessing

wdir = "/workdir/"
stream_urlA = '192.168.3.21'
stream_urlB = '192.168.3.23'
usernameA = ''
usernameB = ''
password = ''

y = sum(1 for f in os.listdir(wdir) if f.startswith('CamA') and os.path.isfile(os.path.join(wdir, f)))
x = sum(1 for f in os.listdir(wdir) if f.startswith('CamB') and os.path.isfile(os.path.join(wdir, f)))

def main():
    time_count = 43200
#    time_count = 1
    procs = list()
    for i in range(1):
        p = multiprocessing.Process(target=CameraA, args=(time_count, y,))
        q = multiprocessing.Process(target=CameraB, args=(time_count, x,))
        procs.append(p)
        procs.append(q)
        p.start()
        q.start()
    for p in procs:
        p.join()

def CameraA(time_count, y):
    y = y
    h = httplib.HTTP(stream_urlA)
    h.putrequest('GET', '/videostream.cgi')
    h.putheader('Authorization', 'Basic %s' % base64.encodestring('%s:%s' % (usernameA, password))[:-1])
    h.endheaders()
    errcode, errmsg, headers = h.getreply()
    stream_file = h.getfile()
    start = time.time()
    end = start + time_count
    while time.time() <= end:
    y += 1
        now = datetime.now()
        dte = str(now.day) + "-" + str(now.month) + "-" + str(now.year)
        dte1 = str(now.hour) + ":" + str(now.minute) + ":" + str(now.second) + "." + str(now.microsecond)
        cname = "Cam#: CamA"
        dnow = """Date: %s """ % dte
        dnow1 = """Time: %s""" % dte1
        # your camera may have a different streaming format
        # but I think you can figure it out from the debug style below
        source_name = stream_file.readline()    # '--ipcamera'
        content_type = stream_file.readline()    # 'Content-Type: image/jpeg'
        content_length = stream_file.readline()   # 'Content-Length: 19565'
        #print 'confirm/adjust content (source?): ' + source_name
        #print 'confirm/adjust content (type?): ' + content_type
        #print 'confirm/adjust content (length?): ' + content_length
        # find the beginning of the jpeg data BEFORE pulling the jpeg framesize
        # there must be a more efficient way, but hopefully this is not too bad
        b1 = b2 = b''
        while True:
            b1 = stream_file.read(1)
            while b1 != chr(0xff):
                b1 = stream_file.read(1)
            b2 = stream_file.read(1)
            if b2 == chr(0xd8):
                break
        # pull the jpeg data
        framesize = int(content_length[16:])
        jpeg_stripped = b''.join((b1, b2, stream_file.read(framesize - 2)))
        # throw away the remaining stream data. Sorry I have no idea what it is
        junk_for_now = stream_file.readline()
        # convert directly to an Image instead of saving /reopening
        # thanks to SO: http://stackoverflow.com/a/12020860/377366
        image_as_file = io.BytesIO(jpeg_stripped)
        image_as_pil = Image.open(image_as_file)
        draw = ImageDraw.Draw(image_as_pil)
        draw.text((0, 0), cname, fill="white")
        draw.text((0, 10), dnow, fill="white")
        draw.text((0, 20), dnow1, fill="white")
        img_name = "CamA-" + str('%010d' % y) + ".jpg"
        img_path = os.path.join(wdir, img_name)
        image_as_pil.save(img_path)

def CameraB(time_count, x):
    x = x
    h = httplib.HTTP(stream_urlB)
    h.putrequest('GET', '/videostream.cgi')
    h.putheader('Authorization', 'Basic %s' % base64.encodestring('%s:%s' % (usernameB, password))[:-1])
    h.endheaders()
    errcode, errmsg, headers = h.getreply()
    stream_file = h.getfile()
    start = time.time()
    end = start + time_count
    while time.time() <= end:
    x += 1
        now = datetime.now()
        dte = str(now.day) + "-" + str(now.month) + "-" + str(now.year)
        dte1 = str(now.hour) + ":" + str(now.minute) + ":" + str(now.second) + "." + str(now.microsecond)
        cname = "Cam#: CamB"
        dnow = """Date: %s """ % dte
        dnow1 = """Time: %s""" % dte1
        # your camera may have a different streaming format
        # but I think you can figure it out from the debug style below
        source_name = stream_file.readline()    # '--ipcamera'
        content_type = stream_file.readline()    # 'Content-Type: image/jpeg'
        content_length = stream_file.readline()   # 'Content-Length: 19565'
        #print 'confirm/adjust content (source?): ' + source_name
        #print 'confirm/adjust content (type?): ' + content_type
        #print 'confirm/adjust content (length?): ' + content_length
        # find the beginning of the jpeg data BEFORE pulling the jpeg framesize
        # there must be a more efficient way, but hopefully this is not too bad
        b1 = b2 = b''
        while True:
            b1 = stream_file.read(1)
            while b1 != chr(0xff):
                b1 = stream_file.read(1)
            b2 = stream_file.read(1)
            if b2 == chr(0xd8):
                break
        # pull the jpeg data
        framesize = int(content_length[16:])
        jpeg_stripped = b''.join((b1, b2, stream_file.read(framesize - 2)))
        # throw away the remaining stream data. Sorry I have no idea what it is
        junk_for_now = stream_file.readline()
        # convert directly to an Image instead of saving /reopening
        # thanks to SO: http://stackoverflow.com/a/12020860/377366
        image_as_file = io.BytesIO(jpeg_stripped)
        image_as_pil = Image.open(image_as_file)
        draw = ImageDraw.Draw(image_as_pil)
        draw.text((0, 0), cname, fill="white")
        draw.text((0, 10), dnow, fill="white")
        draw.text((0, 20), dnow1, fill="white")
        img_name = "CamB-" + str('%010d' % x) + ".jpg"
        img_path = os.path.join(wdir, img_name)
        image_as_pil.save(img_path)

if __name__ == '__main__':
    main()

BEARBEITEN (26/05/2014):

Ich verbrachte den besseren Teil von 2 Monaten zu aktualisieren versuchen das script /Programm für die Arbeit mit python 3, aber war völlig unfähig, es zu bekommen, etwas zu tun. würde jeder in der Lage sein zu zeigen Sie mich in die richtige Richtung?

Habe ich versucht das 2to3-Skript, aber es wurde nur ein paar Einträge und ich war noch nicht in der Lage, es zu bekommen, um überhaupt funktionieren kann.

Eine änderung oder klein sein mögen, zu verbessern, verwenden genratar Ausdruck und Summe (anstelle von len, müssen Reihenfolge): sum(1 for f in os.listdir(wdir) if f.startswith('CamFront') and os.path.isfile(os.path.join(wdir, f)))
gut, das Teil ist nur zu prüfen, wenn es die Bilder schon im Arbeitsverzeichnis, um herauszufinden, ob der Zähler beginnt bei 1 oder unter einer anderen Nummer. es ist mehr die rate der Erfassung ich versuche mich zu verbessern in der looper-Funktion. und für die Verbesserung areyou sagen, ersetzen Sie den gesamten y = Teil nur mit y = Summe(1 für f in os.listdir(wdir eingesetzt) falls f ein.startswith('CamFront') ?
Ich bin auch neue Python-Anfänger. Gerade lese ich einige, wo sun(genrator expression) besser ist, dann len([listcompresion]). Natürlich ist dies nicht die Antwort auf Ihre Frage. Ich wünschte, ich könnte, aber in diesem Stadium ich bin nicht in der Lage zu tragen 🙁 🙁
Die wichtigste Frage ist - was ist derzeit die meisten Ressourcen. Ist es schlapp auf system calls? Oder Vernetzung? Oder Festplatte? Oder CPU? Definitionen Ihrer hardware und wie ist die Last auf jedem Stück ist es viel hilfreicher, als nur zu zeigen, uns etwas code, ohne jeden Versuch einer Profilierung der Frage und der Hoffnung, dass jemand es für Sie tun.
nun, ich glaube nicht, dass die Festplatte oder die cpu das problem sein würde, wie es läuft auf einem i7 930 cpu, ubuntu-server-os auf einer pcie-ssd, die Bilder gehen an einen sata3-hdd. wie für die cpu-Last nie scheint sehr hoch zu sein, wenn das Skript ausgeführt wird, die ich gerade lief es für 30 Sekunden und die höchste cpu-Auslastung lag bei 18% auf 1 Kern beim greifen von 2 Kamera.

InformationsquelleAutor | 

Schreibe einen Kommentar