Как реализовать пакетирование по папкам на основе папок - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть скрипт, который использует библиотеку распознавания лиц MTCNN, которая перебирает достаточное количество каталогов, насчитывающих тысячи изображений. Проблема, с которой я столкнулся при использовании этого сценария, - это чрезмерное использование памяти при обработке всех этих изображений, что в конечном итоге приведет к исчерпанию памяти моего MacBook (16 ГБ ОЗУ). То, что я хочу сделать, - это реализовать пакетную обработку для папок по папкам вместо указанного предела c, поскольку ни одна из папок не содержит достаточно изображений по отдельности, чтобы в системе не хватало памяти.

# open up the csv file
with open(csv_path, 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerow(['Index', 'Threshhold', 'Path'])

for path, subdirs, files in os.walk(path):
    for name in files:
        if name == '.DS_Store':
            print("Skipping .DS_Store")
            continue
        else:
            try:
                image = os.path.join(path, name)
                pixels = pyplot.imread(image)

                print("Processing " + image)
                print("Count: " + str(inc))

                # calculate the area of the image
                total_height = pixels.shape[0]
                total_width = pixels.shape[1]

                total_area = total_height * total_width

                # create the detector, using default weights
                detector = MTCNN()
                faces = detector.detect_faces(pixels)

                ax = pyplot.gca()

                face_total_area = 0

                if faces == []:
                    print("No faces detected.")
                    # pass in 0 for the threshold becuase there's no faces
                    #write_to_csv(inc, 0, image)
                    print()
                else:
                    for face in faces:
                        # get dimensions from the face
                        x, y, width, height = face['box']

                        # calculate the area of the face
                        face_area = width * height
                        face_total_area += face_area

                    threshold = face_total_area / total_area

                    # write to csv only if the threshold is less than the limit 
                    # change back to this eventually ^^^^^^^^^
                    if threshold > threshhold_limit:
                        print("Facial area is over the threshold - writing file path to csv.")
                        write_to_csv(inc, threshold, image)
                    else:
                        print("Image threshold is under the limit - good")

                    print(threshold)
                    print()

                inc += 1
            except:
                print("Processing error - skipping image")

Можно ли что-то подобное сделать? Или это должно быть сделано по-другому? Идея состоит в том, что пакетирование, подобное этому, позволит mtcnn освободить память, на которой он хранится, когда завершит обработку этой папки.

1 Ответ

0 голосов
/ 13 апреля 2020

Использование памяти не должно увеличиваться с этой программой, потому что она не накапливает данные от одного изображения к следующему. Итак, то, что вы просите, не будет иметь никакого эффекта. Вы пробовали запустить этот же код за пределами Python ноутбука? Как отдельная программа? Возможно, что в блокноте хранятся ссылки на все прочитанные изображения. Либо так, либо найдите вызов, который действительно сбросил бы внутреннее состояние pyplot внутри самого внутреннего l oop. (возможно pyplot.clf()).

«Пакетирование», как вы говорите, - это то, что происходит внутри первого for l oop, который будет запускаться один раз для каждой папки в вашем дереве. Единственное, что вам может пригодиться, - это сбросить внутреннее состояние внутри первого l oop, но за пределами второго для (for name in ...) вам нужно будет найти точно такой же вызов для сброса внутреннего состояния.

(кроме того, вы заметили, что в своем блоке with вы создаете csv-модуль записи, который становится недействительным в конце блока - вам следует реорганизовать этот код, чтобы повторно не открывать файл CSV для каждого нового строка - (что происходит в непоказанной функции write_to_csv))

...