Проверьте, есть ли точно такое же изображение, как входное изображение

Я хочу знать, как я могу найти изображение в массиве данных (в папке много изображений), и я хочу найти изображение, которое точно совпадает с входным изображением (учитывая входное изображение из другой папки, отсутствующей в данных папку) и сравните входное изображение со всеми массивными данными, если оно обнаружило точно такое же изображение, а затем отобразите его имя в качестве выходного (имя того же изображения в папке, а не входное имя) (например, dafs.jpg)

используя питон

Я думаю о сравнении точного значения пикселей RGB и вычитания пикселя входного изображения из каждого изображения в папке

но я не знаю, как это сделать в Python

1 ответ

Решение

Сравнение значений пикселей RGB

Вы можете использовать модуль подушки, чтобы получить доступ к данным пикселей определенного изображения. Имейте в виду, что pillow поддерживает эти форматы изображений.

Если мы сделаем несколько предположений о том, что значит идентифицировать 2 изображения, основываясь на вашем описании, оба изображения должны:

  • Имеют одинаковые размеры (высота и ширина)
  • Иметь одинаковые значения пикселей RGB (значения пикселей RGB [x, y] во входном изображении должны совпадать со значениями пикселей RGB [x, y] в выходном изображении)
  • Быть одинаковой ориентации (в связи с предыдущим предположением изображение считается не идентичным по сравнению с тем же изображением, повернутым на 90 градусов)

тогда, если у нас есть 2 изображения, используя pillow модуль

from PIL import Image

original = Image.open("input.jpg")
possible_duplicate = Image.open("output.jpg")

следующий код сможет сравнить 2 изображения, чтобы увидеть, были ли они идентичны

def compare_images(input_image, output_image):
  # compare image dimensions (assumption 1)
  if input_image.size != output_image.size:
    return False

  rows, cols = input_image.size

  # compare image pixels (assumption 2 and 3)
  for row in range(rows):
    for col in range(cols):
      input_pixel = input_image.getpixel((row, col))
      output_pixel = output_image.getpixel((row, col))
      if input_pixel != output_pixel:
        return False

  return True

позвонив

compare_images(original, possible_duplicate)

Используя эту функцию, мы могли бы пройти через набор изображений

from PIL import Image

def find_duplicate_image(input_image, output_images):
  # only open the input image once
  input_image = Image.open(input_image)

  for image in output_images:
    if compare_images(input_image, Image.open(image)):
      return image

Собрав все вместе, мы могли бы просто позвонить

original = "input.jpg"
possible_duplicates = ["output.jpg", "output2.jpg", ...]

duplicate = find_duplicate_image(original, possible_duplicates)

Обратите внимание, что приведенная выше реализация найдет только первый дубликат и вернет его. Если дубликат не найден, None будет возвращен.

Нужно иметь в виду, что сравнение каждого пикселя может оказаться дорогостоящим. Я использовал это изображение и побежал compare_images используя это как вход и выход 100 раз, используя модуль timeit, и взял среднее значение всех этих запусков

num_trials = 100
trials = timeit.repeat(
    repeat=num_trials,
    number=1,
    stmt="compare_images(Image.open('input.jpg'), Image.open('input.jpg'))",
    setup="from __main__ import compare_images; from PIL import Image"
)
avg = sum(trials) / num_trials

print("Average time taken per comparison was:", avg, "seconds")

# Average time taken per comparison was 1.3337286046380177 seconds

Обратите внимание, что это было сделано на изображении, которое было только 600 на 600 пикселей. Если вы сделали это с "массивным" набором возможных дубликатов изображений, где я буду принимать "массивный", чтобы обозначить как минимум 1M изображений одинакового размера, это может занять ~15 дней (1 000 000 * 1,28 с / 60 секунд / 60 минут / 24 часа), чтобы пройти и сравнить каждое выходное изображение с входным, что не является идеальным.

Также имейте в виду, что эти показатели будут различаться в зависимости от машины и используемой операционной системы. Числа, которые я предоставил, являются скорее для иллюстративных целей.

Альтернативная реализация

Хотя я не полностью исследовал эту реализацию сам, одним из способов, который вы могли бы попробовать, было бы предварительное вычисление хеш-значения данных пикселей каждого из ваших изображений в вашей коллекции с использованием хеш-функции. Если вы сохранили их в базе данных, где каждый хеш содержит ссылку на исходное изображение или имя изображения, то все, что вам нужно будет сделать, - это вычислить хеш входного изображения, используя ту же функцию хеширования, и сравнить хэши. Это потребовало бы много времени вычислений и сделало бы гораздо более эффективный алгоритм.

Этот блог описывает одну реализацию для этого.

Обновление - 2018-08-06

Согласно запросу OP, если вам дали каталог возможных дублированных изображений, а не самих явных путей к изображениям, то вы могли бы использовать os а также ntpath модули вроде так

import ntpath
import os

def get_all_images(directory):
  image_paths = []

  for filename in os.listdir(directory):
    # to be as careful as possible, you might check to make sure that
    # the file is in fact an image, for instance using
    # filename.endswith(".jpg") to check for .jpg files for instance
    image_paths.append("{}/{}".format(directory, filename))

  return image_paths

def get_filename(path):
  return ntpath.basename(path)

Используя эти функции, обновленная программа может выглядеть

possible_duplicates = get_all_images("/path/to/images")
duplicate_path = find_duplicate_image("/path/to/input.jpg", possible_duplicates)
if duplicate_path:
  print(get_filename(duplicate_path))

Выше будет напечатано имя дублированного изображения только в том случае, если дубликат был, иначе ничего не будет напечатано.

Другие вопросы по тегам