Python OpenCV LoadDatasetList函数,最后两个参数分别代表什么?

3
我目前正在尝试使用OpenCV 4.2.2训练一个数据集,我搜索了网络但只找到了两个参数的示例。OpenCV 4.2.2 loadDatasetList需要4个参数,但存在一些缺陷,我尽力克服了这些缺陷,并通过以下代码进行了尝试。我最初尝试了一个数组,但是loadDatasetList抱怨该数组不可迭代,然后我尝试下面的代码,但没有成功。感谢您的时间,希望每个人都安全健康。
之前的错误是传递了一个未经iter()处理的数组。
当前的错误是:
PS E:\MTCNN> python kazemi-train.py Traceback (most recent call last): File "kazemi-train.py", line 35, in status, images_train, landmarks_train = cv2.face.loadDatasetList(args.training_images,args.training_annotations, iter(imageFiles), iter(annotationFiles)) SystemError: returned NULL without setting an error
import os
import time
import cv2
import numpy as np
import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Training of kazemi facial landmark algorithm.')
    parser.add_argument('--face_cascade', type=str, help="Path to the cascade model file for the face detector",
                        default=os.path.join(os.path.dirname(os.path.realpath(__file__)),'models','haarcascade_frontalface_alt2.xml'))
    parser.add_argument('--kazemi_model', type=str, help="Path to save the kazemi trained model file",
                        default=os.path.join(os.path.dirname(os.path.realpath(__file__)),'models','face_landmark_model.dat'))
    parser.add_argument('--kazemi_config', type=str, help="Path to the config file for training",
                        default=os.path.join(os.path.dirname(os.path.realpath(__file__)),'models','config.xml'))
    parser.add_argument('--training_images', type=str, help="Path of a text file contains the list of paths to all training images",
                        default=os.path.join(os.path.dirname(os.path.realpath(__file__)),'train','images_train.txt'))
    parser.add_argument('--training_annotations', type=str, help="Path of a text file contains the list of paths to all training annotation files",
                        default=os.path.join(os.path.dirname(os.path.realpath(__file__)),'train','points_train.txt'))

    parser.add_argument('--verbose', action='store_true')
    args = parser.parse_args()

    start = time.time()
    facemark = cv2.face.createFacemarkKazemi()
    if args.verbose:
        print("Creating the facemark took {} seconds".format(time.time()-start))
    start = time.time()
    imageFiles = []
    annotationFiles = []
    for file in os.listdir("./AppendInfo"):
        if file.endswith(".jpg"):
            imageFiles.append(file)
        if file.endswith(".txt"):
            annotationFiles.append(file)
    status, images_train, landmarks_train = cv2.face.loadDatasetList(args.training_images,args.training_annotations, iter(imageFiles), iter(annotationFiles))
    assert(status == True)
    if args.verbose:
        print("Loading the dataset took {} seconds".format(time.time()-start))

    scale  = np.array([460.0, 460.0])
    facemark.setParams(args.face_cascade,args.kazemi_model,args.kazemi_config,scale)

    for i in range(len(images_train)):
        start = time.time()
        img = cv2.imread(images_train[i])
        if args.verbose:
            print("Loading the image took {} seconds".format(time.time()-start))

        start = time.time()
        status, facial_points = cv2.face.loadFacePoints(landmarks_train[i])
        assert(status == True)
        if args.verbose:
            print("Loading the facepoints took {} seconds".format(time.time()-start))

        start = time.time()
        facemark.addTrainingSample(img,facial_points)
        assert(status == True)
        if args.verbose:
            print("Adding the training sample took {} seconds".format(time.time()-start))

    start = time.time()
    facemark.training()
    if args.verbose:
        print("Training took {} seconds".format(time.time()-start))

如果我只使用2个参数,会引发以下错误:

文件“kazemi-train.py”的第37行,在 status、images_train、landmarks_train = cv2.face.loadDatasetList(args.training_images,args.training_annotations) 中出现 TypeError: loadDatasetList()缺少必要参数'images'(pos 3)

如果我尝试使用3个参数,则会引发以下错误:

Traceback (最新调用的最后一次): File "kazemi-train.py", line 37, in status, images_train, landmarks_train = cv2.face.loadDatasetList(args.training_images,args.training_annotations, iter(imagePaths)) TypeError: loadDatasetList()缺少必要参数'annotations'(pos 4)

loadDatasetList的文档:

OpenCV documentation on loadDatasetList


检查形状 - Sivaram Rasathurai
您只需要提供训练图像和注释。 - Sivaram Rasathurai
我删除了我的回答,因为它没有起作用。 - Sivaram Rasathurai
rcvaram,非常感谢您的帮助。 - Levon Ravel
2个回答

4
你提供的图片描述了 loadDatasetList() 的 C++ API,而在很多情况下无法将其参数映射到 Python API。原因之一是 Python 函数可以返回多个值,而 C++ 不行。在 C++ API 中,第三个和第四个参数用于存储函数的输出。它们分别存储从 imageList 文件读取图像后的路径以及从 annotationList 文件读取标注后的路径。

回到你的问题,我找不到 Python 版本的该函数参考文档。并且我相信 OpenCV 4 中的 API 已经改变。经过多次尝试,我确定 cv2.face.loadDatasetList 仅返回一个布尔值,而不是元组。这就是为什么即使你填写了四个参数,仍然遇到了第一个错误 TypeError: cannot unpack non-iterable bool object

毫无疑问,cv2.face.loadDatasetList 应该生成两个文件路径列表。因此,第一部分的代码应该像这样:

images_train = []
landmarks_train = []
status = cv2.face.loadDatasetList(args.training_images, args.training_annotations, images_train, landmarks_train)

我期望 images_trainlandmarks_train 应该包含图像和关键点注释的文件路径,但它并没有按照预期工作。

在全面了解程序之后,我编写了一个新函数 my_loadDatasetList 来替换(损坏的)cv2.face.loadDatasetList

def my_loadDatasetList(text_file_images, text_file_annotations):
    status = False
    image_paths, annotation_paths = [], []
    with open(text_file_images, "r") as a_file:
        for line in a_file:
            line = line.strip()
            if line != "":
                image_paths.append(line)
    with open(text_file_annotations, "r") as a_file:
        for line in a_file:
            line = line.strip()
            if line != "":
                annotation_paths.append(line)
    status = len(image_paths) == len(annotation_paths)
    return status, image_paths, annotation_paths

现在,您可以替换

status, images_train, landmarks_train = cv2.face.loadDatasetList(args.training_images,args.training_annotations, iter(imageFiles), iter(annotationFiles))

status, images_train, landmarks_train = my_loadDatasetList(args.training_images, args.training_annotations)

我已经测试过,可以使用来自这里的数据通过cv2.imreadcv2.face.loadFacePoints分别加载images_trainlandmarks_train


1
谢谢您为深入解释和提高答案水平而授予您赏金。我非常确定这将帮助许多其他人。 - Levon Ravel

2

从文档中可以看出,代码行cv2.face.loadDatasetList仅返回一个布尔值。其次,请从参数中删除iter。函数loadDatasetList接受一个列表作为第三个和第四个参数。

因此,请在您的代码中进行以下更改:

原始代码:

status, images_train, landmarks_train = cv2.face.loadDatasetList(args.training_images,args.training_annotations, iter(imageFiles), iter(annotationFiles))

致:

status = cv2.face.loadDatasetList(args.training_images,args.training_annotations, imageFiles, annotationFiles)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接