【问题标题】:Opencv fails to save video when cropped using numpy slicing使用 numpy 切片裁剪时,Opencv 无法保存视频
【发布时间】:2020-12-04 14:54:11
【问题描述】:

我正在使用 OpenCV (3.4.6) 从 Raspberry Pi HQ 摄像头捕获视频,该摄像头连接到运行 Raspbian 10 的 Raspberry Pi 4。然后将对象检测算法建议的边界框绘制到捕获的帧上,然后输出保存到视频文件中。

一切都很好,除非我尝试将视频裁剪到我感兴趣的区域。

使用以下行成功裁剪图像(由cv2.imshow 确认):

frame = frame[0:720, 280:1000]

但是,它也阻止了 out.write 保存的输出 - 我只是得到一个空文件,并且对 Python 和 OpenCV 都是新手,我正在努力找出原因。

我已将代码精简到下面的相关部分(抱歉 - 它仍然有点长 - 我不完全确定什么可能是重要的):

# begin video capture
    try:
        vid = cv2.VideoCapture(int(video_path), cv2.CAP_V4L2)
        
    except:
        vid = cv2.VideoCapture(video_path)

    out = None
    
    # set capture resolution     
    inputcodec = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') # forces MJPG codec
    vid.set(6, inputcodec) # sets inputcodec for video capture
    vid.set(3, 1280) # sets video capture width
    vid.set(4, 720) # sets video capture height
    
    if FLAGS.output:
        # by default VideoCapture returns float instead of int
        width = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
        fps = int(vid.get(cv2.CAP_PROP_FPS))
        codec = cv2.VideoWriter_fourcc(*FLAGS.output_format)
        out = cv2.VideoWriter(FLAGS.output, codec, fps, (width, height))

    while True:
        return_value, frame = vid.read()
        frame = frame[0:720, 280:1000] # crop video to square region of interest
        if return_value:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            image = Image.fromarray(frame)
        else:
            print('Video has ended or failed, try a different video format!')
            break
    
        frame_size = frame.shape[:2]
        image_data = cv2.resize(frame, (input_size, input_size))
        image_data = image_data / 255.
        image_data = image_data[np.newaxis, ...].astype(np.float32)
        start_time = time.time()

        if FLAGS.framework == 'tflite':
            interpreter.set_tensor(input_details[0]['index'], image_data)
            interpreter.invoke()
            pred = [interpreter.get_tensor(output_details[i]['index']) for i in range(len(output_details))]
            if FLAGS.model == 'yolov3' and FLAGS.tiny == True:
                boxes, pred_conf = filter_boxes(pred[1], pred[0], score_threshold=0.25,
                                                input_shape=tf.constant([input_size, input_size]))
            else:
                boxes, pred_conf = filter_boxes(pred[0], pred[1], score_threshold=0.25,
                                                input_shape=tf.constant([input_size, input_size]))
        else:
            batch_data = tf.constant(image_data)
            pred_bbox = infer(batch_data)
            for key, value in pred_bbox.items():
                boxes = value[:, :, 0:4]
                pred_conf = value[:, :, 4:]

        boxes, scores, classes, valid_detections = tf.image.combined_non_max_suppression(
            boxes=tf.reshape(boxes, (tf.shape(boxes)[0], -1, 1, 4)),
            scores=tf.reshape(
                pred_conf, (tf.shape(pred_conf)[0], -1, tf.shape(pred_conf)[-1])),
            max_output_size_per_class=50,
            max_total_size=50,
            iou_threshold=FLAGS.iou,
            score_threshold=FLAGS.score
        )
        pred_bbox = [boxes.numpy(), scores.numpy(), classes.numpy(), valid_detections.numpy()]
        image = utils.draw_bbox(frame, pred_bbox)
        fps = 1.0 / (time.time() - start_time)
        print("FPS: %.2f" % fps)
        result = np.asarray(image)
        cv2.namedWindow("result", cv2.WINDOW_AUTOSIZE)
        result = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
        
        if not FLAGS.dont_show:
            cv2.imshow("result", result)
        
        if FLAGS.output:
            out.write(result)
        if cv2.waitKey(1) & 0xFF == ord('q'): break
    cv2.destroyAllWindows()

任何有关如何解决此问题的建议将不胜感激。

【问题讨论】:

  • 框架的尺寸是多少?您可以使用frame.shape 进行检查
  • 我会强烈建议在您对vid.set 的调用中使用命名常量,而不是没有明显意义的数字。您已经在对 vid.get 的调用中使用了这些命名常量。

标签: python opencv raspberry-pi


【解决方案1】:

您创建 VideoWriter 并将其宽度和高度设置为 1280 x 720。

以后您希望它节省 720 x 720 作物吗?那就是问题所在。 frame = frame[0:720, 280:1000] 是一个 720 x 720 数组。

确定您的视频应具有的尺寸,并始终如一地使用它们。视频流无法更改分辨率。

【讨论】:

  • 谢谢,但也许我仍然缺少一些东西。我在打开流后进行裁剪的原因是无法将 VideoWriter 设置为 720 x 720。指定 720 x 720 会导致图像损坏。我相信这是因为(或者至少我读过一些书)OpenCV 只允许 32 的倍数作为维度(除非维度是标准的,例如 1080 或 720)。如果我确实将其设置为 32 的倍数,那么我得到了一个矩形框架,其高度等于指定的值,但宽度更大,尽管将宽度和高度设置为相等?
  • 为什么 1280x720 工作时 720x720 会失败?你有一个两个维度的工作长度。如果出现故障或损坏,您需要对此进行调查,或者打开另一个帖子并进行讨论。不要只是猜测并完成它。仍然,您给视频编写器的帧大小与创建它的大小不同。这是一个错误。
猜你喜欢
  • 2021-08-28
  • 2016-03-18
  • 2017-03-10
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 2019-05-27
  • 2019-11-21
  • 1970-01-01
相关资源
最近更新 更多