OpenCV Python 网络摄像机实时图像

OpenCV Python IP Camera live image

目前我正在使用以下代码读取网络摄像机实时图像:

def livestream(self):
        print("start")
        stream = urlopen('http://192.168.4.1:81/stream')
        bytes = b''
        while True:
            try:
                bytes += stream.read(1024) 
                a = bytes.find(b'\xff\xd8') 
                b = bytes.find(b'\xff\xd9') 
                if a != -1 and b != -1: 
                    jpg = bytes[a:b+2] 
                    bytes = bytes[b+2:]
                    getliveimage = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
                    livestreamrotated1 = cv2.rotate(getliveimage, cv2.ROTATE_90_CLOCKWISE) #here I am rotating the image
                    print(type(livestreamrotated1)) #type at this point is <class 'numpy.ndarray'>
                    cv2.imshow('video',livestreamrotated1)
                    if cv2.waitKey(1) ==27: # if user hit esc
                        exit(0) # exit program
            except Exception as e:
                print(e)
                print("failed at this point")

现在我想将结果图像集成到 Kivy-GUI 中,并希望摆脱 while 循环,因为它会冻结我的 GUI。不幸的是,循环是逐字节重建图像所必需的。我想改用 cv2.VideoCapture 并每秒安排多次。这根本不起作用,我无法通过这种方式从实时流中捕获图像...我哪里错了?

cap = cv2.VideoCapture('http://192.168.4.1:81/stream?dummy.jpg')
ret, frame = cap.read()
cv2.imshow('stream',frame)

我在其他 post 中读到,此时需要像“dummy.jpg”这样的文件结尾,但它仍然无法正常工作,程序冻结。

请帮忙。提前致谢!

如果您想将阅读循环与 GUI 循环分离,您可以使用多线程来分离代码。你可以有一个线程 运行 你的 livestream 函数并将图像转储到一个全局图像变量中,你的 GUI 循环可以在其中获取它并对其进行任何操作。

我无法真正测试代码的直播部分,但像这样的东西应该可以。读取函数是如何编写将使用此代码的通用循环函数的示例。

import cv2
import time
import threading
import numpy as np

# generic threading class
class Reader(threading.Thread):
    def __init__(self, func, *args):
        threading.Thread.__init__(self, target = func, args = args);
        self.start();

# globals for managing shared data
g_stop_threads = False;
g_lock = threading.Lock();
g_frame = None;

# reads frames from vidcap and stores them in g_frame
def read():
    # grab globals
    global g_stop_threads;
    global g_lock;
    global g_frame;

    # open vidcap
    cap = cv2.VideoCapture(0);

    # loop
    while not g_stop_threads:
        # get a frame from camera
        ret, frame = cap.read();

        # replace the global frame
        if ret:
            with g_lock:
                # copy so that we can quickly drop the lock
                g_frame = np.copy(frame);

        # sleep so that someone else can use the lock
        time.sleep(0.03); # in seconds

# your livestream func
def livestream():
    # grab globals
    global g_stop_threads;
    global g_lock;
    global g_frame;

    # open stream
    stream = urlopen('http://192.168.4.1:81/stream')
    bytes = b''

    # process stream into opencv image
    while not g_stop_threads:
        try:
            bytes += stream.read(1024) 
            a = bytes.find(b'\xff\xd8') 
            b = bytes.find(b'\xff\xd9') 
            if a != -1 and b != -1: 
                jpg = bytes[a:b+2] 
                bytes = bytes[b+2:]
                getliveimage = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
                livestreamrotated1 = cv2.rotate(getliveimage, cv2.ROTATE_90_CLOCKWISE) #here I am rotating the image

                # acquire lock and replace image
                with g_lock:
                    g_frame = livestreamrotated1;

                # sleep to allow other threads to get the lock
                time.sleep(0.03); # in seconds

        except Exception as e:
            print(e)
            print("failed at this point")

def main():
    # grab globals
    global g_stop_threads;
    global g_lock;
    global g_frame;

    # start a thread
    # reader = Reader(read);
    reader = Reader(livestream);

    # show frames from g_frame
    my_frame = None;
    while True:
        # grab lock
        with g_lock:
            # show
            if not g_frame is None:
                # copy # we copy here to dump the lock as fast as possible
                my_frame = np.copy(g_frame);

        # now we can do all the slow manipulation / gui stuff here without the lock
        if my_frame is not None:
            cv2.imshow("Frame", my_frame);

        # break out if 'q' is pressed
        if cv2.waitKey(1) == ord('q'):
            break;

    # stop the threads
    g_stop_threads = True;

if __name__ == "__main__":
    main();