Подтвердить что ты не робот

Сравните два изображения: путь python/linux

Попытка решить проблему предотвращения дублирования изображений для загрузки.

У меня есть два JPG. Глядя на них, я вижу, что они на самом деле идентичны. Но по какой-то причине они имеют разный размер файла (один извлекается из резервной копии, другой - другая загрузка), и поэтому у них есть другая контрольная сумма md5.

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

Пример: http://static.peterbe.com/a.jpg и http://static.peterbe.com/b.jpg

Обновить

Я написал этот script:

import math, operator
from PIL import Image
def compare(file1, file2):
    image1 = Image.open(file1)
    image2 = Image.open(file2)
    h1 = image1.histogram()
    h2 = image2.histogram()
    rms = math.sqrt(reduce(operator.add,
                           map(lambda a,b: (a-b)**2, h1, h2))/len(h1))
    return rms

if __name__=='__main__':
    import sys
    file1, file2 = sys.argv[1:]
    print compare(file1, file2)

Затем я загрузил два визуально идентичных изображения и запустил script. Выход:

58.9830484122

Может ли кто-нибудь сказать мне, что должно быть подходящим отключением?

Обновление II

Разница между a.jpg и b.jpg заключается в том, что вторая была сохранена с PIL:

b=Image.open('a.jpg')
b.save(open('b.jpg','wb'))

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

4b9b3361

Ответ 1

Существует проект OSS, который использует WebDriver для снятия снимков экрана, а затем сравнивает изображения, чтобы увидеть, есть ли какие-либо проблемы (http://code.google.com/p/fighting-layout-bugs/)). Он делает это, открывая файл в поток, а затем сравнивая каждый бит.

Возможно, вы сможете сделать что-то подобное с PIL.

EDIT:

После большего количества исследований я нашел

h1 = Image.open("image1").histogram()
h2 = Image.open("image2").histogram()

rms = math.sqrt(reduce(operator.add,
    map(lambda a,b: (a-b)**2, h1, h2))/len(h1))

on http://snipplr.com/view/757/compare-two-pil-images-in-python/ и http://effbot.org/zone/pil-comparing-images.htm

Ответ 2

От здесь

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

import ImageChops

def equal(im1, im2):
    return ImageChops.difference(im1, im2).getbbox() is None

Ответ 3

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

С PIL и Numpy вы можете сделать это довольно легко:

import Image
import numpy
import sys

def main():
    img1 = Image.open(sys.argv[1])
    img2 = Image.open(sys.argv[2])

    if img1.size != img2.size or img1.getbands() != img2.getbands():
        return -1

    s = 0
    for band_index, band in enumerate(img1.getbands()):
        m1 = numpy.array([p[band_index] for p in img1.getdata()]).reshape(*img1.size)
        m2 = numpy.array([p[band_index] for p in img2.getdata()]).reshape(*img2.size)
        s += numpy.sum(numpy.abs(m1-m2))
    print s

if __name__ == "__main__":
    sys.exit(main())

Это даст вам числовое значение, которое должно быть очень близко к 0, если изображения совершенно одинаковые.

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

Ответ 4

Используя ImageMagick, вы можете просто использовать в своей оболочке [или вызывать через библиотеку ОС изнутри программы]

compare image1 image2 output

Это создаст выходное изображение с отличиями, отмеченными

compare -metric AE -fuzz 5% image1 image2 output

Дает вам коэффициент нечеткости 5%, чтобы игнорировать незначительные различия пикселей. Более подробную информацию можно приобрести у здесь

Ответ 5

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

  • если ваша проблема заключается в том, чтобы увидеть, есть ли перелистывание бит в ваших JPEG файлах, а затем попытаться отобразить разностное изображение (возможно, небольшое редактирование локально?),

  • чтобы увидеть, являются ли изображения глобально одинаковыми, используйте расстояние Kullback Leibler для сравнения ваших гистограмм,

  • чтобы увидеть, есть ли у вас какие-то качественные изменения, прежде чем применять другие ответы, отфильтруйте свое изображение, используя приведенные ниже функции, чтобы повысить важность высокочастотных частот:

код:

def FTfilter(image,FTfilter):
    from scipy.fftpack import fft2, fftshift, ifft2, ifftshift
    from scipy import real
    FTimage = fftshift(fft2(image)) * FTfilter
    return real(ifft2(ifftshift(FTimage)))
    #return real(ifft2(fft2(image)* FTfilter))


#### whitening
def olshausen_whitening_filt(size, f_0 = .78, alpha = 4., N = 0.01):
    """
    Returns the whitening filter used by (Olshausen, 98)

    f_0 = 200 / 512

    /!\ you will have some problems at dewhitening without a low-pass

    """
    from scipy import mgrid, absolute
    fx, fy = mgrid[-1:1:1j*size[0],-1:1:1j*size[1]]
    rho = numpy.sqrt(fx**2+fy**2)
    K_ols = (N**2 + rho**2)**.5 * low_pass(size, f_0 = f_0, alpha = alpha)
    K_ols /= numpy.max(K_ols)

    return  K_ols

def low_pass(size, f_0, alpha):
    """
    Returns the low_pass filter used by (Olshausen, 98)

    parameters from Atick (p.240)
    f_0 = 22 c/deg in primates: the full image is approx 45 deg
    alpha makes the aspect change (1=diamond on the vert and hor, 2 = anisotropic)

    """

    from scipy import mgrid, absolute
    fx, fy = mgrid[-1:1:1j*size[0],-1:1:1j*size[1]]
    rho = numpy.sqrt(fx**2+fy**2)
    low_pass = numpy.exp(-(rho/f_0)**alpha)

    return  low_pass

(бесстыдная копия http://www.incm.cnrs-mrs.fr/LaurentPerrinet/Publications/Perrinet08spie)

Ответ 6

Во-первых, я должен отметить, что theyre не идентичен; b было повторно сжато и потеряно качество. Вы можете это увидеть, если внимательно посмотреть на хороший монитор.

Чтобы определить, что они субъективно "одинаковы", вам нужно будет сделать что-то вроде того, что предложил fortran, хотя вам придется произвольно установить порог для "одинаковости". Чтобы сделать s независимым от размера изображения и обрабатывать каналы немного более разумно, я бы подумал о выполнении RMS (среднеквадратичного) евклидова расстояния в цветовом пространстве между пикселями двух изображений. У меня нет времени, чтобы написать код прямо сейчас, но в основном для каждого пикселя, вы вычисляете

(R_2 - R_1) ** 2 + (G_2 - G_1) ** 2 + (B_2 - B_1) ** 2

добавив в

(A_2 - A_1) ** 2

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

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

Ответ 7

Я тестировал это, и он работает лучше всех методов и очень быстро!

def rmsdiff_1997(im1, im2):
    "Calculate the root-mean-square difference between two images"

    h = ImageChops.difference(im1, im2).histogram()

    # calculate rms
    return math.sqrt(reduce(operator.add,
        map(lambda h, i: h*(i**2), h, range(256))
    ) / (float(im1.size[0]) * im1.size[1]))

здесь ссылка для справки

Ответ 8

Вы можете сравнить его с помощью PIL (итерация по пикселям/сегментам изображения и сравнение) или если вы смотрите для полного сравнения идентичных копий, попробуйте сравнить хэш MD5 обоих файлов.