Python OpenCV – 在基于特定对象条件保存视频时,并非所有符合条件的帧都被保存

我在Python中使用OpenCV,试图仅在视频帧中出现特定类型的对象/标签时(例如“雨伞”)录制/保存这些帧。

问题:

它正确地从首次在帧中发现所述对象/标签的实例开始保存帧,但如果在接下来的几帧中没有该对象/标签,并且在几帧之后才出现,那么这些帧不会被保存到我正在保存的mp4文件中。

它只保存了带有所述对象的第一组连续帧,而不保存后续的帧。

在阅读了此链接中的建议后,我通过将帧写入步骤放入for循环中来编辑代码,如下所示: OpenCV – 基于特定条件保存视频片段

我尝试改进的帧写入代码片段

# 逐帧保存视频
for frame_numb in range(total_frames):
    if i == '':
        pass
    else:
        if "umbrella" in label:
            print("umbrella in labels")
            # 可能需要更改的导致问题的部分
            out_vid.write(frame[frame_numb])

上述代码更改的结果:

它只创建了一个256kb的文件,并且文件无法打开/未写入任何内容

如果我在代码中进行以下更改,那么它只会保存视频中满足条件的第一帧,并在整个时间内重复播放同一帧

    # 逐帧保存视频
    for frame_numb in range(total_frames):
        if i == '':
            pass
        else:
            if "umbrella" in label:
                print("umbrella in labels")
                # 可能需要更改的导致问题的部分
                out_vid.write(frame)

为参考提供更大块的代码如下:

def vid_objects_detection(type=0, confidence_threshold=0.5, image_quality=416):
    classes = []
    # 从coco文本文件中读取类别名称并插入到classes列表中
    with open("coco.names", "r") as f:
        classes = [line.strip() for line in f.readlines()]
    net = cv2.dnn.readNet("yolov3-tiny.weights", "yolov3-tiny.cfg") # 使用tiny版本的权重和配置文件
    layer_names = net.getLayerNames()
    
    output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
    # 加载视频
    cap = cv2.VideoCapture(type)  # 使用0表示网络摄像头
    _, frame = cap.read()
    height, width, channels = frame.shape
    # 提供编解码器以将帧写入视频
    fourcc = cv2.VideoWriter_fourcc(*'MP4V')
    # 以名称和大小写入视频。应与原始视频的尺寸(宽度,高度)相同
    out_vid = cv2.VideoWriter('obj_detect4_'+str(type), fourcc, 20.0, (width,height))
    font = cv2.FONT_HERSHEY_COMPLEX_SMALL 
    starting_time = time.time()
    frame_id = 0
    while True:
        _, frame = cap.read()
        frame_id +=1
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        height, width, channels = frame.shape

        blob = cv2.dnn.blobFromImage(frame, 0.00392, (image_quality, image_quality), (0, 0, 0), True, crop=False)
        net.setInput(blob)
        outs = net.forward(output_layers)
        # 用于在屏幕上显示信息
        class_ids = []
        confidences = []
        boxes = []
        for out in outs:
            for detection in out:
                # 计算分数,类别ID,置信度
                if confidence > confidence_threshold:
                    # 计算中心_x,中心_y,宽度,高度,x,y
                    boxes.append([x, y, w, h])
                    confidences.append(float(confidence))
                    class_ids.append(class_id)
                    print("confidences:", confidences)
                    print(class_ids)
                    print("boxes", boxes)
        indexes = cv2.dnn.NMSBoxes(boxes, confidences, confidence_threshold, 0.4)
        for i in range(len(boxes)):
            if i in indexes:
                x, y, w, h = boxes[i]
                label = str(classes[class_ids[i]])
        elapsed_time = time.time() - starting_time
        fps = frame_id / elapsed_time
        time_display = time.strftime("%a, %d%b%Y %H:%M:%S", time.localtime())
        cv2.putText(frame,"|FPS: " + str(round(fps,3)), (10, 40), font, 1, (0,255,0), 1)
        print(fps)
        # 逐帧保存视频
        if i == '':
            pass
        else:
            if 'umbrella' in label:
                out_vid.write(frame)
        key = cv2.waitKey(5)
        if key == 27:
            break
    cap.release()
    out_vid.release()
    cv2.destroyAllWindows()
# 调用函数
vid_objects_detection("walking.mp4")

我已经修剪了代码中的一些次要计算,并插入注释以减少代码长度


回答:

有时视频编解码器会执行所谓的关键帧压缩。这意味着,每隔10帧会完全存储一帧,而中间的所有其他帧则作为变化或增量存储。在这种情况下,当你尝试仅保存这些中间帧时,它们可能不会被保存。但是在这些情况下,如果你按顺序遍历每一帧,保存帧是有效的。

你可以注释掉行 out_vid = cv2.VideoWriter('obj_detect4_'+str(type), fourcc, 20.0, (width,height)),并尝试仅根据你的条件从网络摄像头流中保存帧。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注