python - 使用 RSTP 的 DNN OpenCV Python 总是在几分钟后崩溃

标签 python opencv ffmpeg video-streaming

描述:
我想使用 DNN 创建一个人员计数器。我使用的模型是 MobileNetSSD。我使用的摄像头是海康威视的 IPCam。 Python 使用 RSTP 协议(protocol)与 IPCam 通信。
我制作的程序很好,没有错误,在运行示例视频时,程序运行良好。但是当我用 IPcam 替换它时,出现了一个未知错误。
错误:
有时 错误 是:

[h264 @ 000001949f7adfc0] error while decoding MB 13 4, bytestream -6
[h264 @ 000001949f825ac0] left block unavailable for requested intra4x4 mode -1
[h264 @ 000001949f825ac0] error while decoding MB 0 17, bytestream 762
有时 不出现错误程序被杀死。

更新错误
之后 修改代码 ,我发现了错误。发现的错误是
[h264 @ 0000019289b3fa80] error while decoding MB 4 5, bytestream -25
现在我不知道该怎么办,因为错误是不是 在谷歌。
源代码:
旧代码
这是我最早的代码在得到建议之前从评论字段。
import time
import cv2
import numpy as np
import math
import threading

print("Load MobileNeteSSD model")

prototxt = "MobileNetSSD_deploy.prototxt"
model = "MobileNetSSD_deploy.caffemodel"

CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
           "bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
           "dog", "horse", "motorbike", "person", "pottedplant", "sheep",
           "sofa", "train", "tvmonitor"]

net = cv2.dnn.readNetFromCaffe(prototxt, model)

pos_line = 0
offset = 50
car = 0
detected = False
check = 0
prev_frame_time = 0


def detect():
    global check, car, detected
    check = 0
    if(detected == False):
        car += 1
        detected = True


def center_object(x, y, w, h):
    cx = x + int(w / 2)
    cy = y + int(h / 2)
    return cx, cy


def process_frame_MobileNetSSD(next_frame):
    global car, check, detected

    rgb = cv2.cvtColor(next_frame, cv2.COLOR_BGR2RGB)
    (H, W) = next_frame.shape[:2]

    blob = cv2.dnn.blobFromImage(next_frame, size=(300, 300), ddepth=cv2.CV_8U)
    net.setInput(blob, scalefactor=1.0/127.5, mean=[127.5, 127.5, 127.5])
    detections = net.forward()

    for i in np.arange(0, detections.shape[2]):
        confidence = detections[0, 0, i, 2]

        if confidence > 0.5:

            idx = int(detections[0, 0, i, 1])
            if CLASSES[idx] != "person":
                continue

            label = CLASSES[idx]

            box = detections[0, 0, i, 3:7] * np.array([W, H, W, H])
            (startX, startY, endX, endY) = box.astype("int")

            center_ob = center_object(startX, startY, endX-startX, endY-startY)
            cv2.circle(next_frame, center_ob, 4, (0, 0, 255), -1)

            if center_ob[0] < (pos_line+offset) and center_ob[0] > (pos_line-offset):
                # car+=1
                detect()

            else:
                check += 1
                if(check >= 5):
                    detected = False

            cv2.putText(next_frame, label+' '+str(round(confidence, 2)),
                        (startX, startY-10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            cv2.rectangle(next_frame, (startX, startY),
                          (endX, endY), (0, 255, 0), 3)

    return next_frame


def PersonDetection_UsingMobileNetSSD():
    cap = cv2.VideoCapture()
    cap.open("rtsp://admin:Admin12345@192.168.100.20:554/Streaming/channels/2/")

    global car,pos_line,prev_frame_time

    frame_count = 0

    while True:
        try:
            time.sleep(0.1)
            new_frame_time = time.time()
            fps = int(1/(new_frame_time-prev_frame_time))
            prev_frame_time = new_frame_time

            ret, next_frame = cap.read()
            w_video = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
            h_video = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
            pos_line = int(h_video/2)-50

            if ret == False: break

            frame_count += 1
            cv2.line(next_frame, (int(h_video/2), 0),
                     (int(h_video/2), int(h_video)), (255, 127, 0), 3)
            next_frame = process_frame_MobileNetSSD(next_frame)

            cv2.rectangle(next_frame, (248,22), (342,8), (0,0,0), -1)
            cv2.putText(next_frame, "Counter : "+str(car), (250, 20),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
            cv2.putText(next_frame, "FPS : "+str(fps), (0, int(h_video)-10),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
            cv2.imshow("Video Original", next_frame)
            # print(car)

        except Exception as e:
            print(str(e))

        if cv2.waitKey(1) & 0xFF == ord('q'): 
            break


    print("/MobileNetSSD Person Detector")


    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    t1 = threading.Thread(PersonDetection_UsingMobileNetSSD())
    t1.start()
新代码
我已经修改了我的代码,但程序仍然停止取帧。我刚刚修改了 PersonDetection_UsingMobileNetSSD() 功能。我还删除了我正在使用的多线程。代码已经运行了大约 30 分钟,但是 破框后 ,代码将永远不要重新执行程序 block if ret == True .
def PersonDetection_UsingMobileNetSSD():
    cap = cv2.VideoCapture()
    cap.open("rtsp://admin:Admin12345@192.168.100.20:554/Streaming/channels/2/")

    global car,pos_line,prev_frame_time

    frame_count = 0

    while True:
        try:
            if cap.isOpened():
                ret, next_frame = cap.read()
                if ret:
                    new_frame_time = time.time()
                    fps = int(1/(new_frame_time-prev_frame_time))
                    prev_frame_time = new_frame_time
                    w_video = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
                    h_video = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
                    pos_line = int(h_video/2)-50

                    # next_frame = cv2.resize(next_frame,(720,480),fx=0,fy=0, interpolation = cv2.INTER_CUBIC)

                    if ret == False: break

                    frame_count += 1
                    cv2.line(next_frame, (int(h_video/2), 0),
                            (int(h_video/2), int(h_video)), (255, 127, 0), 3)
                    next_frame = process_frame_MobileNetSSD(next_frame)

                    cv2.rectangle(next_frame, (248,22), (342,8), (0,0,0), -1)
                    cv2.putText(next_frame, "Counter : "+str(car), (250, 20),
                                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
                    cv2.putText(next_frame, "FPS : "+str(fps), (0, int(h_video)-10),
                                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
                    cv2.imshow("Video Original", next_frame)
                    # print(car)
                else:
                    print("Crashed Frame")
            else:
                print("Cap is not open")

        except Exception as e:
            print(str(e))

        if cv2.waitKey(1) & 0xFF == ord('q'): 
            break


    print("/MobileNetSSD Person Detector")


    cap.release()
    cv2.destroyAllWindows()
需求:
硬件:英特尔 i5-1035G1,内存 8 GB,NVIDIA GeForce MX330
软件:Python 3.6.2、OpenCV 4.5.1、Numpy 1.16.0
问题:
  • 我应该怎么做才能修复这个错误?
  • 是什么导致这种情况发生?

  • 此致,

    谢谢

    最佳答案

    这里的主要问题是 RSTP 中总是有一些损坏的帧。解决方案是在线程 1 上运行视频捕获,在线程 2 上运行视频处理。
    例如:

    import cv2
    import threading
    import queue
    
    q=queue.Queue()
    
    def this_receive(q):
        cap = cv2.VideoCapture("rtsp://admin:Admin12345@192.168.10.20:554/Streaming/channels/2/")
        cap.set(cv2.CAP_PROP_FPS, 5)
        ret, next_frame = cap.read()
        q.put(next_frame)
        while ret:
            ret, next_frame = cap.read()
            w_video = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
            h_video = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
            q.put(next_frame)
    
    def main_program(q):
        while True:
            try:
                if q.empty() != True:
                    next_frame=q.get()
            except Exception as e:
                print(str(e))
    
            if cv2.waitKey(1) & 0xFF == ord('q'): 
                break
    
    if __name__ == "__main__":
        print("Main Program")
        p2 = threading.Thread(target=this_receive,args=((q),))
        p2.start()
        p1 = threading.Thread(target=main_program,args=((q),))
        p1.start()
    
    此示例将根据您遇到的情况起作用。框架的损坏不会影响数据处理的质量。只是这种方法会导致处理延迟。视频时间和实时时间最多有 10 分钟的延迟。想知道什么样的延迟?去尝试一下!

    关于python - 使用 RSTP 的 DNN OpenCV Python 总是在几分钟后崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72795190/

    相关文章:

    c++ - OpenCV 分水岭分割遗漏了一些对象

    python - OpenCV Python将图像的某些部分复制到另一部分

    Android 使用 FFmpeg 的位图系列和 mp3 创建 MP4(我需要最小的 ffmpeg 配置来构建)

    python - 如何使用 ffmpeg-python 将视频剪切到一定长度并添加介绍视频?

    HTML5 视频 Chrome - ffmpeg - mp4 在除 Chrome 之外的所有工作

    Python Seg Fault 对我来说毫无意义

    python - 错误 ModuleNotFoundError : No module named 'azure.keyvault.secrets' although I installed the package

    c++ - 在 opencv 中保存图像的奇怪行为

    python - 带进度条的 Tkinter GUI

    python - 如何有效地计算运行标准差