为什么网络摄像头捕获无法在python中刷新?

问题描述

我不知道,因为我的视频捕获不会在每个浏览器中刷新... 我使用cv2开始网络摄像头拍摄,但是图像没有更新。为什么?它可以依靠什么? 目的是从身体框架区域的运动中检测呼吸频率。但是网络摄像头不会更新,仅显示第一帧。 我在python中的代码是:

import cv2
import queue
import threading
import datetime
import matplotlib
import http.server
import socketserver
import math
from urllib.parse import urlparse,parse_qs
from io import BytesIO
import numpy as np
import PIL.Image as PImage
matplotlib.use('Agg')
import matplotlib.pyplot as plt

DocRoot = "./"
ImgQueue = queue.Queue(3)
ims = None


def calcMotion(region0,region1):
    """
    Calculates motion based on Lucas/Kanade optical flow method.
    Returns veLocities in x,y
    """
    ra0 = np.diff(region0,axis=0)
    dyi = (ra0[:,:-1] + ra0[:,1:])

    ra1 = np.diff(region0,axis=1)
    dxi = (ra1[:-1,:] + ra1[1:,:])

    diff = region1 - region0
    s1 = diff[:-1,:] + diff[1:,:]
    dt = s1[:,1:] + s1[:,:-1:]
    x2 = (dxi * dxi).sum()
    xy = (dxi * dyi).sum()
    y2 = (dyi * dyi).sum()
    tx = (dxi * dt).sum()
    ty = (dyi * dt).sum()
    det = x2 * y2 - xy * xy
    det *= 0.5
    if abs(det) < 1E-3:
        return 0,0
    u = (tx * y2 - ty * xy) / det
    v = (x2 * ty - xy * tx) / det
    mod = math.sqrt(u * u + v * v)
    if mod == 0:
        return 0,0
    return u,v


def flatten(xs,ys):
    """
    Substracts linear fit from values ys and
    returns result and the value at the middle of the fitted values,ie the avg.
    """
    fitted = np.polyval(np.polyfit(xs,ys,1),xs)
    return ys - fitted,fitted[len(xs) // 2]


def countCrossing(arr,avg):
    """
    Counts how many times the values cross the average.
    Only counts when going down.
    Returns the count
    """
    state = 0
    cnt = 0
    for i in arr:
        if state == 1 and i < avg:
            state = 2
            cnt += 1
        elif state == 2 and i > avg:
            state = 1
        elif state == 0:
            if i > avg:
                state = 1
            else:
                state = 2
    return cnt


"""
Use a global variable so we can do running average.
"""
BRate = 0


def genStripChart(figSize,xs,flags):
    """
    Creates a strip char using matplotlib.
    First flattens the values and then counts the zero crossings.
    Returns the chart as PNG in binary form,which is then sent to the browser.
    """
    global BRate
    fig = plt.figure(figsize=figSize)
    ax = fig.add_subplot(111)
    xlen = len(xs)
    dxs = [0] * xlen
    for i in range(1,len(xs)):
        dxs[i] = (xs[i] - xs[0]).total_seconds()
    ys,avg = flatten(dxs,ys)
    cnt = countCrossing(ys,avg)

    if dxs[-1] > 0:
        cnt = cnt * 60.0 / dxs[-1]
    BRate = BRate + (cnt - BRate) * 0.3
    ax.plot(dxs,flags)
    ax.set_ylim(-1.5,1.5)
    ax.grid()
    ax.set_title("Breathing Rate = %.0f per min" % (BRate))
    ax.set_xlabel("seconds")
    plt.close()

    out = BytesIO()
    fig.savefig(out,format='png')
    out.seek(0)
    return out.read()


class ImageServerHandler(http.server.SimpleHTTPRequestHandler):
    """
    This class handles the HTTP request from clients.
    """

    def do_GET(self):
        global ImgQueue
        try:
            # ignore request to favicon
            if self.path.endswith('favicon.ico'):
                return
            parts = urlparse(self.path)
            qs = parse_qs(parts.query)
            req = parts.path[1:]
            reqHandler = self.handlerTable.get(req)
            if reqHandler != None:
                out,contype = reqHandler(self,req,qs)
            else:
                out,contype = self.serveFile(req,qs)
            self.send_response(200,"OK")
            self.send_header("Cache-Control","no-cache,must-revalidate")
            self.send_header("Content-Type",contype)
            self.end_headers()
            self.wfile.write(out)
        except Exception as e:
            try:
                self.send_response(503,"Error")
                self.end_headers()
                self.send_header("Content-Type",contype)
                self.wfile.write(bytes(out,"UTF-8"))
            except:
                print("Error",e)

    def getMimeType(self,fname):
        table = [['.js','text/javascript'],['.html','text/html'],['.css','text/css']]
        for suf,mtype in table:
            if fname.endswith(suf):
                return mtype
        return 'text/html'

    def serveFile(self,qs):
        global DocRoot
        req = req if len(req) > 0 else "breathingMonitor.html"
        contype = self.getMimeType(req)
        with open(DocRoot + req,"r") as fh:
            content = fh.read()
        return bytes(content,"UTF-8"),contype

    def log_message(self,format,*args):
        return

    def getimage(self,qstr):
        """
        Gets image from the queue for display.
        Returns image data and mime type
        """
        im = ImgQueue.get()
        temp = BytesIO()
        im.save(temp,format="JPEG")
        return temp.getvalue(),"image/jpeg"

    def clicked(self,qstr):
        global ims
        x = float(qstr['inpx'][0])
        y = float(qstr['inpy'][0])
        t = float(qstr['sigma'][0])
        t = min(1,max(0,t))
        ims.startMeasurement(x,y,t)
        s = "start measurement at x %.0f y %.0f t %.2f" % (x,t)
        out = bytes(s,"UTF-8")
        contype = "text/plain"
        return out,contype

    def getChart(self,qstr):
        global ims
        try:
            contype = "image/png"
            return genStripChart((5,2.4),ims.tData,ims.mData,"r-"),contype
        except KeyboardInterrupt:
            return "Aborted","text/plain"

    """
    Class table
    """
    handlerTable = {
        'get': getimage,'clicked': clicked,'chart': getChart
    }

    #
    # End of ImageServerHandler
    #


class ImageServer:
    """
    This class runs the camera thread and the HTTP request hanlder thread.
    """

    def __init__(self):
        """
        Initializes the camera connection
        """
        self.cam = cv2.VideoCapture(0)
        self.cam.set(cv2.CAP_PROP_FRAME_WIDTH,160)
        self.cam.set(cv2.CAP_PROP_FRAME_HEIGHT,120)

        self.nlen = 256
        self.mData = np.array([0.0] * self.nlen)
        self.tData = [datetime.datetime.Now()] * self.nlen
        self.measureX = 0
        self.measureY = 0
        self.first = True
        self.runAvg = 0
        self.runAvg1 = 0
        self.sigma = 0.3
        self.BoxSize = 35
        self.imgWidth,self.imgHeight = 0,0

    def camLoop(self):
        """
        Reads image from the camera stream and
        puts image in the queue.
        """
        global ImgQueue
        while True:
            ret,frame = self.cam.read()

            frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
            img = PImage.fromarray(frame)
            try:
                if ImgQueue.full():
                    print("full")
                    ImgQueue.get()
                ImgQueue.put_Nowait(img)
            except Exception:
                print("Queue error")

    def processingLoop(self):
        global ImgQueue
        while True:
            img = ImgQueue.get()
            w,h = img.size
            bwImg = np.array(img.convert("L").getdata()).reshape((h,w))
            self.digestimage(bwImg)

    def startMeasurement(self,x,t):
        size = self.BoxSize
        x = min(max(0,x - size / 2),self.imgWidth - size - 1)
        y = min(max(0,y - size / 2),self.imgHeight - size - 1)
        self.measureX = int(x)
        self.measureY = int(y)
        self.sigma = t
        self.first = True

    def digestimage(self,imgBW):
        self.imgWidth,self.imgHeight = imgBW.shape
        if self.measureX == 0 or self.measureY == 0:
            self.measureX = int(self.imgWidth / 2)
            self.measureY = int(self.imgHeight / 2)
        size = self.BoxSize
        x = self.measureX
        y = self.measureY
        region = imgBW[x:x + size,y:y + size]

        if self.first:
            self.first = False
            self.runAvg = 0
            self.runAvg1 = 0
            self.lastRegion = region
            self.mData = np.array([0.0] * self.nlen)

        u,col = calcMotion(region,self.lastRegion)
        self.lastRegion = region

        t1 = self.sigma
        t11 = 0.3
        self.runAvg1 = (col - self.runAvg1) * t1 + self.runAvg1
        col = self.runAvg = (self.runAvg1 - self.runAvg) * t11 + self.runAvg
        self.mData[0:-1] = self.mData[1:]
        self.tData[0:-1] = self.tData[1:]
        self.mData[-1] = col
        self.tData[-1] = datetime.datetime.Now()

    def startCamera(self):
        thr = threading.Thread(target=self.camLoop)
        thr.daemon = True
        thr.start()

    def startProcessing(self):
        thr = threading.Thread(target=self.processingLoop)
        thr.daemon = True
        thr.start()

    def start(self,port):
        print("Open http://localhost:%d" % port)
        try:
            httpd = socketserver.Tcpserver(("0.0.0.0",port),ImageServerHandler)
            try:
                httpd.serve_forever()
                httpd.shutdown()
            except KeyboardInterrupt:
                return
        except:
            print("Failed to start HTTP Server")
            return


#
# main
#
if __name__ == "__main__":
    ims = ImageServer()
    ims.startCamera()
    ims.startProcessing()
    ims.start(5010)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)