解压后视频帧是上下颠倒的

问题描述 投票:0回答:5

我的问题是,当我使用 opencv 将视频提取到帧中时,有时我得到的帧会翻转,这在我的机器(窗口)和 VM(ubuntu)上都发生过,但是我测试的一些视频,帧不翻转。所以,我想知道应该在我的代码中更改/添加哪些因素或哪些内容,以使提取内容无需翻转即可修复

def extract_frame(video,folder):
   global fps

   os.mkdir('./green_frame/{folder}/'.format(folder=folder))
   vidcap = cv2.VideoCapture(video)
   success,image = vidcap.read()
   fps = vidcap.get(cv2.CAP_PROP_FPS)
   count = 0
   success = True
   while success:  #os.path.join(pathOut,(name+'.png'))
      cv2.imwrite(os.path.join('./green_frame/{folder}/'.format(folder=folder),"frame%d.png" % count), image)
      success,image = vidcap.read()
      print('Read a new frame: ', success) 
      count += 1

这是我从这段代码中获得的框架示例。 我原来用的视频是这样颠倒的:

所以,就我而言,我必须改变什么才能使它不像我的第一张照片那样翻转。与视频的分辨率或帧率有关吗?我用 1280x720 分辨率的视频进行测试,提取的所有帧都上下翻转,但 568x320 视频中的帧是正常的

谢谢你

编辑: 所以,我查看了视频的信息,发现在元数据中,它为提取到颠倒帧的视频旋转了180度 但是当我检查产生非颠倒框架的普通视频时,它没有旋转:180

那么,我该如何处理具有旋转的视频呢?

python opencv video-processing
5个回答
28
投票

2022 年 9 月 28 日更新

现在只需更新到 OpenCV v4.5 及以上版本即可解决此问题。

如果升级出现问题,请按照下面的旧答案进行操作。


对于仍在研究这个问题的人来说,我只是陷入了同样的问题。事实证明,一些 Android 手机和 iPhone 会横向拍摄图像/帧,并根据 exif“旋转”标签即时转换它们以显示图像/帧。

OpenCV 中奇怪的设计选择是

cv2.imread(img_file)
已经通过读取图像的
rotate
标签以正确的方向读取图像,但
cv2.VideoStream
read()
方法不会执行此操作。

因此,为了解决这个问题,我使用

ffmpeg
来读取“旋转”标签并将视频帧旋转到正确的方向。(非常感谢上面的评论,为我指明了正确的方向👍)

以下是代码:

  • 确保您有用于Python的

    ffmpeg
    。 (
    pip install ffmpeg-python
    )

  • 创建一个方法来检查 video_file 是否需要旋转:

     import ffmpeg    
    
     def check_rotation(path_video_file):
         # this returns meta-data of the video file in form of a dictionary
         meta_dict = ffmpeg.probe(path_video_file)
    
         # from the dictionary, meta_dict['streams'][0]['tags']['rotate'] is the key
         # we are looking for
         rotateCode = None
         if int(meta_dict['streams'][0]['tags']['rotate']) == 90:
             rotateCode = cv2.ROTATE_90_CLOCKWISE
         elif int(meta_dict['streams'][0]['tags']['rotate']) == 180:
             rotateCode = cv2.ROTATE_180
         elif int(meta_dict['streams'][0]['tags']['rotate']) == 270:
             rotateCode = cv2.ROTATE_90_COUNTERCLOCKWISE
    
         return rotateCode
    
  • 创建一个方法来校正视频文件中帧的旋转:

     def correct_rotation(frame, rotateCode):  
         return cv2.rotate(frame, rotateCode) 
    
  • 最后,在主循环中执行此操作:

     # open a pointer to the video file stream
     vs = cv2.VideoCapture(video_path)
    
     # check if video requires rotation
     rotateCode = check_rotation(video_path)
    
     # loop over frames from the video file stream
     while True:
         # grab the frame from the file
         grabbed, frame = vs.read()
    
         # if frame not grabbed -> end of the video
         if not grabbed:
             break
    
         # check if the frame needs to be rotated
         if rotateCode is not None:
             frame = correct_rotation(frame, rotateCode)
    
         # now your logic can start from here
    

希望这有帮助🍻


3
投票

有时以下方法可以解决某些视频打开颠倒的问题。

cap = cv2.VideoCapture(path, apiPreference=cv2.CAP_MSMF)

3
投票

当我最近遇到这个问题时,我发现所需要的只是更新到 OpenCV v4.5:


1
投票

rotate 标签是可选的,因此 check_rotation 将会失败, 此代码修复它:

def check_rotation(path_video_file):
    # this returns meta-data of the video file in form of a dictionary
    meta_dict = ffmpeg.probe(path_video_file)
    # from the dictionary, meta_dict['streams'][0]['tags']['rotate'] is the key
    # we are looking for
    rotate_code = None
    rotate = meta_dict.get('streams', [dict(tags=dict())])[0].get('tags', dict()).get('rotate', 0)
    return round(int(rotate) / 90.0) * 90

0
投票

我会在你的帧处理循环中执行此操作:

frame = cv2.flip(frame,0)

0 垂直翻转,请参阅 Open CV 文档了解更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.