Как читать все кадры в видео без остановки с помощью opencv - PullRequest
0 голосов
/ 14 июня 2019

Iv 'написал этот код, чтобы извлечь все кадры из видео и сохранить как изображения. Но почему-то VideoCapture.read () возвращает false, даже если он не достиг конечного кадра.

Как я могу это исправить и прочитать все кадры?

Я пробовал ловить исключение, но оно ничего не возвращает.

Я следовал исходному коду и обнаружил, что VideoCaputre.read () вызывает VideoCapture.grab и он называется icap-> grabFrame (), но не может получить подробную информацию о icap-> grabFrame ().

python3.6.7 (по умолчанию, 22 октября 2018 г., 11:32:17) Opencv 3.4.3 Колаборатория Google

Информация о видео 'coded_width': 4000 'coded_height': 3000 'r_frame_rate': '30000/1001' 'avg_frame_rate': '30000/1001'

import os
import ffmpeg
import json
import cv2
import sys


base_dir = './gdrive/My Drive/'
files = os.listdir(base_dir)    

# only videos
mp4s =[]
mp4s = [file for file in files if 'MP4' in file ]

# get metadata
file_list = []

for video in mp4s:
  video_dir = base_dir + '/' + video
  video_info = ffmpeg.probe(video_dir)
  time = video_info['streams'][0]['tags']['creation_time']
  slice_str = time.find('T')
  slice_end = time.find('.')

  file_list.append({
      'file_name':video,
      'start_rec':time[slice_str + 1:slice_end],
      'end_rec':video_info['streams'][0]['tags']['timecode'],
      'duration':video_info['streams'][0]['duration'],
      'nb_frames':video_info['streams'][0]['nb_frames'],
      'coded_width':video_info['streams'][0]['coded_width'],
      'coded_height':video_info['streams'][0]['coded_height'],
      'r_frame_rate':video_info['streams'][0]['r_frame_rate'],
      'avg_frame_rate':video_info['streams'][0]['avg_frame_rate']
  }) 

#sort by recording start time
list_sorted = sorted(file_list, key=lambda x:x['start_rec'])
print(list_sorted)

#opencv extract all frames and save as png
dir_path = base_dir + '/' + 'images'
basename ='intervention'
ext = 'png'
n = 0

for dic in list_sorted:
  print('start', dic['file_name'])
  video_path = base_dir + '/' + dic['file_name']
  cap = cv2.VideoCapture(video_path)

  if not cap.isOpened():
    print('not opened')
    sys.exit()

  os.makedirs(dir_path, exist_ok=True)
  base_path = os.path.join(dir_path, basename)

  digit = len(str(int(cap.get(cv2.CAP_PROP_FRAME_COUNT))))


# below this code ret supposed to be true until the end frame but did't reach the end

  while True:
    ret, frame = cap.read()
    print('ret=', ret)
    print(cap.get(cv2.CAP_PROP_POS_FRAMES), '/', cap.get(cv2.CAP_PROP_FRAME_COUNT))

    if ret:
      cv2.imwrite('{}_{}.{}'.format(base_path, str(n).zfill(digit), ext), frame)
      n += 1

    else:
      print('done', dic['file_name'])
      cap.release()
      cv2.destroyAllWindows()
      break 

это возвращается

start GX010223.MP4 ret = True 1,0 / 96,0 ~ ret = True 96,0 / 96,0 ret = False 96,0 / 96,0 сделано GX010223.MP4 начать GX010224.MP4 ret = True 1,0 / 105,0 ~ ret = True 105,0 / 105,0 ret = False 105,0 / 105,0 сделано GX010224.MP4

start GX010225.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX010225.MP4

start GX020225.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX020225.MP4

start GX030225.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX030225.MP4

start GX040225.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX040225.MP4

start GX050225.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX050225.MP4

start GX060225.MP4 ret = True 1,0 / 539,0 ~ ret = True 29,0 / 539,0 ret = False 29,0 / 539,0 сделано GX060225.MP4

start GX010226.MP4 ret = True 1,0 / 282,0 ~ ret = True 29,0 / 282,0 ret = False 29,0 / 282,0 сделано GX010226.MP4

start GX010227.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX010227.MP4

start GX020227.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX020227.MP4

start GX030227.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX030227.MP4

start GX040227.MP4 ret = True 1.0 / 15960.0 ~ ret = True 29,0 / 15960,0 ret = False 29,0 / 15960,0 сделано GX040227.MP4

start GX050227.MP4 ret = True 1.0 / 2514.0 ~ ret = True 29,0 / 2514,0 ret = False 29,0 / 2514,0 сделано GX050227.MP4

Я пытался проверить «пусто или нет» по этому коду

while True:

      ret, frame = cap.read()
      print('ret=', ret)
      print(cap.get(cv2.CAP_PROP_POS_FRAMES), '/', cap.get(cv2.CAP_PROP_FRAME_COUNT))
      cv2.imwrite('{}_{}.{}'.format(base_path, str(n).zfill(digit), ext), frame)
      n += 1

      if ret == False:
        if frame == None:
          print('done', dic['file_name'])
          cap.release()
          cv2.destroyAllWindows()
          break

но когда cap.read () не удалось, он возвращает объект None, поэтому он не работал должным образом.

1 Ответ

0 голосов
/ 14 июня 2019
VideoCapture cap("your_video.avi");
if(!cap.isOpened())  // check if we succeeded
    return -1;

Mat frame;
while(1) // looply reading frames from the video file
{
    cap >> frame; // try to get an image frame

    if (frame.empty())
    {
        // reach to the end of the video file
        break;
    }
}

frame.empty () решит вашу проблему. это в C ++, но может быть таким же в Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...