Как я могу ускорить процесс поиска дубликатов изображений, чем joblib?

#python #joblib

Вопрос:

У меня есть почти 300 довольно больших изображений. и найдите, какое изображение дублируется. Итак, откройте все изображения и сделайте их меньшим изображением(64,64) и преобразуйте в массив numpy. и, наконец, сравнение всех массивов numpy, и если сумма массива пар() равна нулю, то эта пара дублируется.

Все очень просто. Но проблема в скорости.

Поэтому я пытаюсь использовать joblib в качестве пакета распараллеливания.

но это происходит чрезвычайно медленно.

Я думаю, что маринованные данные слишком велики, поэтому накладные расходы делают все медленнее.

Как я могу сделать этот код параллельным по эффективности? Ниже приведен весь код.

 import pandas as pd
from PIL import Image
import os
import numpy as np
from tqdm import tqdm
import joblib
from joblib import Parallel, delayed
from itertools import combinations
 

импорт пакетов

 data = pd.DataFrame(os.listdir("git"), columns=["dir"])
data["dir"] = "git/" data["dir"]
tqdm.pandas()
data["image"] = data["dir"].progress_apply(Image.open)
 

загрузка данных

введите описание изображения здесь

 data["small_image"] = data["image"].progress_apply(lambda x: x.resize((64,64)))
 

сделайте изображение меньшего размера для скорости

 data["small_image"] = data["small_image"].progress_apply(np.array)
 

преобразуйте изображение в массив np.

введите описание изображения здесь

 def test(i, j):
    tmp = data["small_image"][i]-data["small_image"][j]
    if tmp.sum() == 0:
        print("DUPLICATE!")
        return (i, j)
    else:
        return 0
 

это функция определения того, какая пара изображений дублируется.

и, наконец,,

 set(Parallel(n_jobs=1)(delayed(test)(i,j) for i, j in combinations(range(4), 2)))
# Wall time: 2.93 ms
set(Parallel(n_jobs=2)(delayed(test)(i,j) for i, j in combinations(range(4), 2))) # 2,3, -1, -2 almost same time
# Wall time: 49.2 s
 

Комментарии:

1. Изменение размера изображений звучит как объезд. Если вы ищете точные дубликаты, простое сравнение изображений пиксель за пикселем, вероятно, быстрее, чем первая нормализация каждого из них.

2. @tripleee Я согласен. но вопрос в том, чтобы распараллелить.

3. Чтение всех изображений и последующее распараллеливание означает, что вы копируете все изображения во все параллельные задания. Старайтесь делиться как можно меньшим количеством данных между процессами, т. е. загружайте изображения только после распараллеливания. Это приведет к гораздо большему объему работы (каждое изображение должно быть прочитано и обработано в каждой задаче, которая хочет получить к нему доступ), но если у вас ограниченное количество параллельных задач, это все равно может быть лучше, чем совместное использование всех данных между всеми задачами.

4. Еще большее улучшение могло бы быть, если бы вы еще больше нормализовали изображения, а затем просто сравнили полученные отпечатки пальцев (SHA256 или что-то еще) на этапе уменьшения.