python - VideoCapture()读取多个视频和帧分辨率问题

标签 python opencv video-processing

根据这个article的回答这是指将单个图像组合成4面的方式。从那里开始,我想从仅使用单个视频更改为使用 4 个视频作为输入。

这是我的代码,它使用单个视频作为输入

import cv2
import numpy as np


def make4side(image, scale=0.5):

   # image = cv2.imread(image)
   h = int((scale*image.shape[0])) #height
   w = int((scale*image.shape[1])) #width
   image = cv2.resize(image, (w,h ), interpolation = cv2.INTER_AREA) #shrink image to half

   output = np.zeros((w+h+h , w + h + h, 3), dtype="uint8")

   # top 
   output[0:h, h:h+w] = image 
   # left >> rotate 90
   output[h:h+w, 0:h] = np.rot90(image,1) 
   # right >> rotate 270
   output[h:h + w, h + w:h +w +h] = np.rot90(image,3)  
   # bottom >> rotate 180
   output[h+w:h+w+h, h:h+w] = np.rot90(image,2) 

   return output
   #cv2.imwrite('test.jpg', output)

def process(video):
   cap = cv2.VideoCapture(video)
   fourcc = cv2.VideoWriter_fourcc(*'XVID')
   holo = None
   ret = False
   while(not ret):
    ret, frame = cap.read()
    if ret:
        frame = cv2.resize(frame, (640, 480), interpolation = cv2.INTER_AREA)
        holo = make4side(frame)
   out = cv2.VideoWriter('hologram640x480.avi',fourcc, 23.98, (holo.shape[0],holo.shape[1]))
   total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
   count = 0
   print("Processing %d frames"%(total_frames))
   while(True):
       # Capture frame-by-frame
       ret, frame = cap.read()
       if ret:
           frame = cv2.resize(frame, (640, 480), interpolation = cv2.INTER_AREA)
           holo = make4side(frame)
           out.write(holo)
           count += 1
           print("Total:%d of %d"%(count,total_frames))
       if(count>=total_frames-1):
           break

   cap.release()
   out.release()
   return

process('g.mov')

结果是这样的

4 sided video from single video

在这段代码中,整个帧的高度和宽度仅基于我也关注的单个视频的输入,因为我使用了 4 个视频,当然帧分辨率不相同(但都是横向的) ).函数 make4side() 中的变量 h 和 w 是帮助定位每个小框架的主要部分。那么对于这种情况,大帧(可变输出)分辨率应该是多少?

我必须读取 4 个视频并将其写入一个,因此我如何使用 VideoCapture 对象来实现此目的

为了明确我的问题,我想要一个由 4 个输入视频组成的视频,每个视频都将放置在每个位置(顶部、底部、左侧和右侧)。我的大帧分辨率有问题,如果我有 4 个视频而不是一个,我不知道该用什么。另一个问题是关于 VideoCapture 对象。如何同时读取所有视频的帧或以任何其他方式执行此操作?

谢谢

编辑: top 顶面

left 左侧

back 背面

right 右侧

这些不是我将要使用的真实帧,而只是我将要用于我的视频的简单想法。另一件事,输入文件可能不具有相同的分辨率。我如何使用多个视频捕获对象来读取它们中的每一个并将其放置在大框架的每一侧以编写单个视频

最佳答案

所以一切都取决于你想做什么,所以它会取决于你要处理什么类型的图像。首先,您始终可以拥有 4 个 VideoCapture 类实例,每个实例都加载一个新视频,例如:

videoTop = cv2.VideoCapture(videoTopFileName)
videoLeft = cv2.VideoCapture(videoLeftFileName)
videoRight = cv2.VideoCapture(videoRightFileName)
videoBottom = cv2.VideoCapture(videoBottomFileName)

readCorrect = True
while( readCorrect ):
  readCorrect , topFrame = videoTop.read()
  ret, leftFrame = videoLeft.read()
  readCorrect = readCorrect and ret
  ret, rightFrame = videoRight.read()
  readCorrect  = readCorrect and ret
  ret, bottomFrame = videoBottom.read()
  readCorrect = readCorrect and ret
  if readCorrect :
     holo = make4side(topFrame, leftFrame, rightFrame, bottomFrame )

您可以在此循环中将图像保存在 VideoWriter 中。

现在到了棘手的部分,你的图片大小不一样......你可以这样做:

import cv2
import numpy as np

# load images, in your case frames from videos
top = cv2.imread("D:\\testing\\1.jpg")
left = cv2.imread("D:\\testing\\2.jpg")
bottom = cv2.imread("D:\\testing\\3.jpg")
right = cv2.imread("D:\\testing\\4.jpg")

targetSize = (200,200)

h = targetSize[1] #height
w = targetSize[0] #width

top = cv2.resize(top,  targetSize )
left = cv2.resize(left,  targetSize )
bottom = cv2.resize(bottom,  targetSize )
right = cv2.resize(right,  targetSize )

output = np.zeros((w+h+h , w + h + h, 3), dtype="uint8")

# top
output[0:h, h:h+w] = top
# left >> rotate 90
output[h:h+w, 0:h] = np.rot90(left,1)
# right >> rotate 270
output[h:h + w, h + w:h +w +h] = np.rot90(bottom,3)
# bottom >> rotate 180
output[h+w:h+w+h, h:h+w] = np.rot90(right,2)

cv2.imshow("frame", output )
cv2.waitKey(0)import cv2
import numpy as np

# load images, in your case frames from videos
top = cv2.imread("D:\\testing\\1.jpg")
left = cv2.imread("D:\\testing\\2.jpg")
bottom = cv2.imread("D:\\testing\\3.jpg")
right = cv2.imread("D:\\testing\\4.jpg")

targetSize = (200,200)

h = targetSize[1] #height
w = targetSize[0] #width

top = cv2.resize(top,  targetSize )
left = cv2.resize(left,  targetSize )
bottom = cv2.resize(bottom,  targetSize )
right = cv2.resize(right,  targetSize )

output = np.zeros((w+h+h , w + h + h, 3), dtype="uint8")

# top
output[0:h, h:h+w] = top
# left >> rotate 90
output[h:h+w, 0:h] = np.rot90(left,1)
# right >> rotate 270
output[h:h + w, h + w:h +w +h] = np.rot90(bottom,3)
# bottom >> rotate 180
output[h+w:h+w+h, h:h+w] = np.rot90(right,2)

cv2.imshow("frame", output )
cv2.waitKey(0)

但这会生成像这样的“坏”图像:

enter image description here

为了使其不变形,您应该找到宽高比并尝试调整它们的大小。如果纵横比不同,则必须填充图像。这是取决于您的任务的部分,您可以裁剪图像或填充图像。

但基本上这是应该做的。希望对您有所帮助。


更新:

只是为了澄清循环部分:

  readCorrect , topFrame = videoTop.read()
  ret, leftFrame = videoLeft.read()
  readCorrect = readCorrect and ret

在第一行中,我将 read 返回的 bool 值分配给了 readCorrect 变量。然后在下一张图片中,我分配给 ret 并用之前的结果做一个逻辑 and 。这样您就可以知道是否所有这些都是真的,或者是否有任何一个是假的。

我还纠正了循环中的一些错误(我输入 while not readCorrect 并且应该没有 not)。

在循环之前还有一件事你应该创建 VideoWriter 对象,你总是可以在阅读之前获取每个视频的大小 get使用参数 CV_CAP_PROP_FRAME_WIDTHCV_CAP_PROP_FRAME_HEIGHT,例如 videoTop.get(CV_CAP_PROP_FRAME_WIDTH)

然后在循环内,特别是在获取图像后的 if 内,您可以将其写入。

关于python - VideoCapture()读取多个视频和帧分辨率问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52278770/

相关文章:

python用正则表达式查找替换字符串中的非拉丁词

python - 在Python OpenCV中将字符串渲染为库属性

c++ - Qt 线程中未检测到信号和插槽

debugging - 如何使用GDB调试OpenCV程序?

python - ModuleNotFoundError : No module named 'libtorrent'

python - 如何检测圆形腐 eclipse /膨胀

python - 如何检查所有值是否都在pivot_table的输入DataFrame中,并创建一些Python Pandas中不存在的值并用0填充?

iOS - 创建多个时间延迟的实时相机预览 View

audio - FFmpeg 输出不准确

video - 为什么ffmpeg-split AVI电影在播放时会卡住