OpenCV (Python) VideoCapture.read() 丢失帧

OpenCV (Python) VideoCapture.read() on missing frames

python 的新手,OpenCV 的新手,我将在我的硕士论文中使用它,并且在使用 OpenCV 的 VideoCapture 对象时已经遇到了一些问题。

情况: 我得到了 2 个包含相应图像的文件夹(使用 RGB 和红外相机拍摄)。我想使用 while 循环在 Window 中并排显示它们。当其中一个图像序列中缺少一些图像时,问题就出现了(由于录制时出现问题或其他原因,我真的不知道,但这应该不重要)。我的想法是使用 .read() 函数的布尔返回值来检查是否有要读取的帧,如果没有,则将图像替换为黑色图像。这就是我所做的:

代码:

import cv2
import numpy as np

pathRGB = "Bilder/RGB"
pathIR = "Bilder/IR"
# the paths to the folders containing the images

capRGB = cv2.VideoCapture(pathRGB + "/frame_%06d.jpg")
capIR = cv2.VideoCapture(pathIR + "/frame_%06d.jpg")
# setting up the VideoCapture-elements with the according format

shapeRGB = capRGB.read()[1].shape
shapeIR = capIR.read()[1].shape
# get the shape of the first image in each folder to later create the black
# dummy-image

dtypeRGB = capRGB.read()[1].dtype
dtypeIR = capIR.read()[1].dtype
# get the type of the first image in each folder to later create the black
# dummy-image

if (capRGB.isOpened() is False):
    print("Error opening RGB images")
if (capIR.isOpened() is False):
    print("Error opening IR images")

cv2.namedWindow("frames", cv2.WINDOW_NORMAL)

while capRGB.isOpened() and capIR.isOpened() is True:
    retRGB, imgRGB = capRGB.read()
    retIR, imgIR = capIR.read()
    # read both images

    if retRGB is True and retIR is False:
        imgIR = np.zeros(shapeIR, dtype=dtypeIR)
    # if there is no IR image, crate a dummy one
    if retIR is True and retRGB is False:
        imgRGB = np.zeros(shapeRGB, dtype=dtypeRGB)
    # if there is no RGB image, crate a dummy one
    if retRGB is False and retIR is False:
        break

    imgCombined = np.hstack((imgRGB, imgIR))
    # put both images together
    cv2.imshow("frames", imgCombined)
    k = cv2.waitKey(1)
    if k == ord("q"):
        break

capRGB.release()
capIR.release()
cv2.destroyAllWindows()

问题: 根据我的理解,问题的出现是因为 capIR.read() 试图读取丢失的图像(在我的例子中是第 527 张)而不是仅仅返回 false/None 它试图一遍又一遍地读取相同的图像。直到丢失的帧,一切正常,正确的“IR”图像甚至变黑,但随后视频播放开始变慢,而我仍然可以通过按 'q'、spyder [=] 关闭 window 34=] 冻结,如果我等待“太久”,我什至不得不将其关闭。控制台一遍又一遍地发出“[image2 @ 000002a7af8f0480] 无法打开文件:Bilder/IR/frame_000527.jpg”,以至于我无法滚动到顶部。 我想我想问的是:有没有什么方法可以让 .read() 函数只尝试读取 1 次并在失败后继续下一帧?

此致,并在此先致谢!

假设 directory1 中的图像与 directory2 中的图像具有相同的名称,但我们知道某些图像可能不存在于两个目录中...

import glob,os,cv2

path1 = "folder1/"
path2 = "folder2/"

#change directory to path1 
os.chdir(path1)
l1 = glob.glob("*.jpg")   #get a list of images names 

os.chdir("../")  #go one directory up


blackimg = cv2.imread("blackimg.jpg")

for fname in l1:

    #check if image1 exists , then read it .  otherwise im1 = blackimg
    if os.path.isfile(path1+fname):
        im1=cv2.imread(path1+fname)
    else:
        im1=blackimg
    
    #check if image2 exists , then read it .  otherwise im2 = blackimg
    if os.path.isfile(path2+fname):
        im2=cv2.imread(path2+fname)
    else:
        im2=blackimg

    imgCombined = np.hstack((im1, im2))


    cv2.imshow("Combined", imgCombined)
    print("press any key to continue, q to exit")
    k = cv2.waitKey(0) 
    if k == ord("q"):break


cv2.destroyAllWindows()

模拟以使用不同的文件和目录名称进行测试。

将从两个目录中检索最大的帧号,然后遍历所有帧号以从两个目录中读取文件。

import os
import cv2
import re
import glob

image_dir1 = 'test1'
image_dir2 = 'test2'

# retrieve all frames in both directories
frames_cap1 = glob.glob(os.path.join(image_dir1, "frame_*.jpg"))
frames_cap2 = glob.glob(os.path.join(image_dir2, "frame_*.jpg"))

# sort inscending
frames_cap1.sort()
frames_cap2.sort()

# retrieve last frame No for both directories
last_frame_cap1 = frames_cap1[-1]
last_frame_cap2 = frames_cap2[-1]

# extract integer counter as a group
# modify regex to match file name if required 
match_cap1 = re.search('frame_(\d+).jpg', last_frame_cap1)
match_cap2 = re.search('frame_(\d+).jpg', last_frame_cap2)
last_frame_no_cap1 = int(match_cap1.group(1))
last_frame_no_cap2 = int(match_cap2.group(1))

# retrieve max frame No
max_frame_no = max(last_frame_no_cap1, last_frame_no_cap2)

for i in range(max_frame_no + 1):
    # adapt formatting of frame number to digit count in file name
    # here: 6 digits with leading zeros
    image_path_cap1 = os.path.join(image_dir1, f"frame_{i:06d}.jpg")
    image_path_cap2 = os.path.join(image_dir2, f"frame_{i:06d}.jpg")
    
    if not os.path.isfile(image_path_cap1):
        print(f"handle missing file: '{image_path_cap1}'")
        # ...
    else:
        img1 = cv2.imread(image_path_cap1)
        # …

    if not os.path.isfile(image_path_cap2):
        print(f"handle missing file: '{image_path_cap2}'")
        # ...
    else:
        img2 = cv2.imread(image_path_cap2)
        # …
# …