Jak mogę obliczyć różnicę między dwoma obrazami?

Oto co chciałbym zrobić:

Robię zdjęcia kamerką w regularnych odstępach czasu. Coś w stylu poklatkowego. Jeśli jednak nic się tak naprawdę nie zmieniło, czyli zdjęcie wygląda tak samo, nie chcę zapisywać najnowszej migawki.

Wyobrażam sobie, że jest jakiś sposób na oszacowanie różnicy i musiałbym empirycznie określić próg.

Szukam prostoty, a nie doskonałości. Używam Pythona.

Author: Jav_Rock, 2008-10-10

20 answers

Idea Ogólna

Opcja 1: załaduj oba obrazy jako tablice (scipy.misc.imread) i Oblicz różnicę elementów (piksel po pikselu). Oblicz normę różnicy.

Opcja 2: Załaduj oba obrazy. Oblicz jakiś wektor funkcji dla każdego z nich (jak histogram). Oblicz odległość między wektorami funkcji, a nie obrazami.

Są jednak pewne decyzje, które należy podjąć najpierw.

Pytania

Powinieneś odpowiedzieć na te pytania pierwszy:

  • Czy obrazy mają ten sam kształt i wymiar?

    Jeśli nie, może być konieczna zmiana ich rozmiaru lub przycinanie. Biblioteka PIL pomoże to zrobić w Pythonie.

    Jeśli są zrobione z tymi samymi ustawieniami i tym samym urządzeniem, prawdopodobnie są takie same.

  • Czy obrazy są dobrze dopasowane?

    Jeśli nie, możesz najpierw uruchomić korelację krzyżową, aby znaleźć najlepsze wyrównanie. SciPy ma do tego zadania.

    Jeśli aparat i sceny są nieruchome, obrazy prawdopodobnie będą dobrze wyrównane.

  • Czy ekspozycja obrazów jest zawsze taka sama? (Czy jasność / kontrast jest taki sam?)

    Jeśli nie, możesz chcieć znormalizować obrazy.

    [18]}ale bądź ostrożny, w niektórych sytuacjach może to zrobić więcej zła niż dobra. Na przykład pojedynczy jasny piksel na ciemnym tle sprawi, że znormalizowany obraz będzie bardzo różny.
  • Czy informacje o kolorze są ważne?

    Jeśli chcesz aby zauważyć zmiany kolorów, będziesz mieć wektor wartości kolorów na punkt, a nie wartość skalarną, jak na obrazie w skali szarości. Potrzebujesz więcej uwagi przy pisaniu takiego kodu.

  • Czy na obrazie są wyraźne krawędzie? Czy mogą się ruszyć?

    Jeśli tak, możesz najpierw zastosować algorytm wykrywania krawędzi (np. obliczyć gradient transformacją Sobela lub Prewitta, zastosować jakiś próg), a następnie porównać krawędzie na pierwszym obrazie z krawędziami na drugi.

  • Czy na obrazie jest szum?

    Wszystkie czujniki zanieczyszczają obraz pewną ilością szumu. Tanie czujniki mają więcej hałasu. Przed porównaniem obrazów warto zastosować redukcję szumów. Rozmycie jest tu najprostszym (ale nie najlepszym) podejściem.

  • Jakie zmiany chcesz zauważyć?

    Może to wpłynąć na wybór normy do wykorzystania dla różnicy między obrazami.

    Rozważ użycie normy Manhattan (suma wartości bezwzględnych) lub zero norm (liczba elementów nie równa zero), aby zmierzyć, jak bardzo obraz się zmienił. Pierwszy powie Ci, jak bardzo obraz jest wyłączony, drugi powie tylko, ile pikseli się różni.

Przykład

Zakładam, że Twoje obrazy są dobrze wyrównane, tego samego rozmiaru i kształtu, prawdopodobnie z inną ekspozycją. Dla uproszczenia konwertuję je do skali szarości, nawet jeśli są to obrazy kolorowe (RGB).

Będziesz potrzebował tych import:

import sys

from scipy.misc import imread
from scipy.linalg import norm
from scipy import sum, average

Główna funkcja, odczyt dwóch obrazów, konwersja do skali szarości, porównywanie i drukowanie wyników:

def main():
    file1, file2 = sys.argv[1:1+2]
    # read images as 2D arrays (convert to grayscale for simplicity)
    img1 = to_grayscale(imread(file1).astype(float))
    img2 = to_grayscale(imread(file2).astype(float))
    # compare
    n_m, n_0 = compare_images(img1, img2)
    print "Manhattan norm:", n_m, "/ per pixel:", n_m/img1.size
    print "Zero norm:", n_0, "/ per pixel:", n_0*1.0/img1.size

Jak porównywać. img1 i img2 są macierzami 2D SciPy tutaj:

def compare_images(img1, img2):
    # normalize to compensate for exposure difference, this may be unnecessary
    # consider disabling it
    img1 = normalize(img1)
    img2 = normalize(img2)
    # calculate the difference and its norms
    diff = img1 - img2  # elementwise for scipy arrays
    m_norm = sum(abs(diff))  # Manhattan norm
    z_norm = norm(diff.ravel(), 0)  # Zero norm
    return (m_norm, z_norm)

Jeśli plik jest obrazem kolorowym, imread zwraca tablicę 3D, średnie kanały RGB (ostatnia oś tablicy)w celu uzyskania intensywności. Nie trzeba tego robić dla obrazów w skali szarości (np. .pgm):

def to_grayscale(arr):
    "If arr is a color image (3D array), convert it to grayscale (2D array)."
    if len(arr.shape) == 3:
        return average(arr, -1)  # average over the last axis (color channels)
    else:
        return arr

Normalizacja jest trywialna, możesz wybrać normalizację do [0,1] zamiast [0,255]. arr jest Tablica SciPy tutaj, więc wszystkie operacje są elementowe:

def normalize(arr):
    rng = arr.max()-arr.min()
    amin = arr.min()
    return (arr-amin)*255/rng

Uruchom funkcję main:

if __name__ == "__main__":
    main()

Teraz możesz umieścić to wszystko w skrypcie i uruchomić na dwóch obrazkach. Jeśli porównamy obraz do siebie, nie ma różnicy:

$ python compare.py one.jpg one.jpg
Manhattan norm: 0.0 / per pixel: 0.0
Zero norm: 0 / per pixel: 0.0

Jeśli rozmyjemy obraz i porównamy z oryginałem, jest pewna różnica:

$ python compare.py one.jpg one-blurred.jpg 
Manhattan norm: 92605183.67 / per pixel: 13.4210411116
Zero norm: 6900000 / per pixel: 1.0

P. S. całość compare.py skrypt.

Aktualizacja: odpowiednie techniki

Ponieważ pytanie dotyczy sekwencji wideo, jeśli ramki są prawdopodobnie prawie takie same, a ty szukasz czegoś niezwykłego, chciałbym wspomnieć o kilku alternatywnych podejściach, które mogą być istotne: {]}

    Odejmowanie i segmentacja tła (wykrywanie obiektów pierwszoplanowych) [36]}
  • Rzadki przepływ optyczny (do wykrywania ruchu)
  • porównywanie histogramów lub innych statystyk zamiast obrazów

Zdecydowanie polecam zajrzenie do książki "Learning OpenCV", rozdziały 9 (Części obrazów i segmentacja) i 10 (śledzenie i ruch). Pierwszy uczy korzystania z metody odejmowania tła, drugi podaje pewne informacje na temat metod przepływu optycznego. Wszystkie metody są zaimplementowane w bibliotece OpenCV. Jeśli używasz Pythona, sugeruję użycie OpenCV ≥ 2.3 i jego cv2 modułu Pythona.

Najprostsza wersja odejmowania tła:

  • poznaj średnią wartość μ i odchylenie standardowe σ dla każdego piksela tła
  • porównaj bieżące wartości pikseli z zakresem (μ-2σ,μ+2σ) lub (μ-σ,μ+σ)

Bardziej zaawansowane wersje uwzględniają szeregi czasowe dla każdego piksela i obsługują niestatyczne sceny (takie jak poruszające się drzewa lub trawa).

Idea przepływu optycznego polega na pobraniu dwóch lub więcej klatek i przypisaniu wektora prędkości każdemu pikselowi (gęsty przepływ optyczny) lub niektórym z nich (Rzadki przepływ optyczny). Aby oszacować niewielki przepływ optyczny, możesz użyć metody Lucas-Kanade (jest ona również zaimplementowana w OpenCV). Oczywiście, jeśli jest dużo flow (high average over max values of the velocity field), wtedy coś porusza się w kadrze, a kolejne obrazy są bardziej różne.

Porównywanie histogramów może pomóc wykryć nagłe zmiany między kolejnymi klatkami. Podejście to zostało wykorzystane w Courbon et al, 2010:

podobieństwo kolejnych klatek. odległość między dwoma kolejnymi klatkami jest mierzona. Jeśli jest zbyt wysoka, oznacza to, że druga klatka jest uszkodzona, a tym samym obraz został wyeliminowany. Odległość Kullbacka–Leiblera (50), czyli wzajemna Entropia na histogramach obu klatek:

$$ D (P, q) = \ sum_i p (I) \log (P (i) / q(i)) $$

Gdzie p i q są histogramami ramek. Próg jest ustalony na 0,2.

 215
Author: sastanin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-21 17:15:21

Proste rozwiązanie:

Zakoduj obraz jako jpeg i poszukaj znaczącej zmiany w Rozmiar pliku .

Zaimplementowałem coś podobnego z miniaturkami wideo i miałem wiele sukcesów i skalowalności.

 67
Author: keparo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-10 04:44:19

Możesz porównać dwa obrazy za pomocą funkcji z PIL .

import Image
import ImageChops

im1 = Image.open("splash.png")
im2 = Image.open("splash2.png")

diff = ImageChops.difference(im2, im1)

Obiekt diff jest obrazem, w którym każdy piksel jest wynikiem odejmowania wartości kolorów tego piksela na drugim obrazie od pierwszego obrazu. Używając obrazu diff możesz zrobić kilka rzeczy. Najprostszą z nich jest funkcja diff.getbbox(). Pokaże Ci minimalny prostokąt, który zawiera wszystkie zmiany między dwoma obrazami.

Możesz prawdopodobnie zaimplementować przybliżenia innych rzeczy wymienione tutaj przy użyciu funkcji z PIL, jak również.

 48
Author: gooli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-13 06:50:17

Dwie popularne i stosunkowo proste metody to: (a) odległość euklidesowa już sugerowana lub (b) znormalizowana korelacja krzyżowa. Znormalizowana korelacja krzyżowa wydaje się być zauważalnie bardziej odporna na zmiany oświetlenia niż prosta korelacja krzyżowa. Wikipedia podaje wzór na znormalizowaną korelację krzyżową . Istnieją też bardziej wyrafinowane metody, ale wymagają one nieco więcej pracy.

Używając składni numpy,

dist_euclidean = sqrt(sum((i1 - i2)^2)) / i1.size

dist_manhattan = sum(abs(i1 - i2)) / i1.size

dist_ncc = sum( (i1 - mean(i1)) * (i2 - mean(i2)) ) / (
  (i1.size - 1) * stdev(i1) * stdev(i2) )

Zakładając, że i1 i i2 są 2D tablice obrazów w skali szarości.

 19
Author: Mr Fooz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-10 03:47:44

Trywialna rzecz do wypróbowania:

Porównuj oba obrazy do małych miniaturek (np. 64 x 64) i porównaj miniatury piksel po pikselu z określonym progiem. Jeśli oryginalne obrazy są prawie takie same, ponownie próbkowane miniatury będą bardzo podobne lub nawet dokładnie takie same. Metoda ta zajmuje się hałasem, który może wystąpić zwłaszcza w scenach przy słabym oświetleniu. Może nawet lepiej, jeśli przejdziesz do skali szarości.

 13
Author: Ates Goral,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-10 03:49:32

Zwracam się konkretnie do pytania, jak obliczyć, czy są one "wystarczająco różne". Zakładam, że możesz wymyślić, jak odjąć piksele jeden po drugim.

Po Pierwsze, chciałbym wziąć kilka obrazów z nic zmienia się, i dowiedzieć się maksymalną ilość, że każdy piksel zmienia tylko z powodu zmian w przechwytywaniu, szum w systemie obrazowania, artefakty kompresji JPEG, i moment za moment zmiany w oświetleniu. Być może przekonasz się, że różnice 1 lub 2 bitowe są można się spodziewać, nawet gdy nic się nie rusza.

Następnie dla" prawdziwego " testu, chcesz kryterium jak to:

  • to samo, jeśli do P pikseli różnią się nie więcej niż E.

Więc, być może, jeśli E = 0.02, P = 1000, to oznacza (w przybliżeniu), że będzie "inaczej", jeśli każdy pojedynczy piksel zmieni się o więcej niż ~5 jednostek (zakładając obrazy 8-bitowe), lub jeśli więcej niż 1000 pikseli ma jakiekolwiek błędy w ogóle.

Jest to przeznaczona głównie jako dobra technika "triage", aby szybko zidentyfikuj obrazy, które są wystarczająco blisko, aby nie wymagały dalszej analizy. Obrazy, które "nie" może następnie bardziej do bardziej skomplikowanej / kosztownej techniki, która nie miałaby fałszywych alarmów, gdyby aparat potrząsnął trochę, na przykład, lub był bardziej wytrzymały na zmiany oświetlenia.

Prowadzę projekt open source, OpenImageIO , który zawiera narzędzie o nazwie "idiff", które porównuje różnice z takimi progami (nawet bardziej rozbudowanymi). Nawet jeśli nie chcesz używać tego oprogramowania, może zajrzysz do źródła, żeby zobaczyć, jak to zrobiliśmy. Jest używany komercyjnie dość dużo i ta technika progowania została opracowana tak, że możemy mieć zestaw testów dla renderowania i przetwarzania obrazu oprogramowania ,z "obrazów referencyjnych", które mogą mieć małe różnice od platformy do platformy lub jak zrobiliśmy drobne poprawki do algorytmów tha, więc chcieliśmy" dopasowanie w tolerancji " operacji.

 7
Author: Larry Gritz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-14 16:10:21

Większość udzielonych odpowiedzi Nie dotyczy poziomów oświetlenia.

Chciałbym najpierw normalizować obraz do standardowego poziomu światła przed wykonaniem porównania.

 5
Author: Loren Pechtel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-10 03:55:20

Czy widziałeś algorytm wyszukiwania podobnych obrazów pytanie? Sprawdź, aby zobaczyć sugestie.

Sugerowałbym transformację falkową Twoich ramek (napisałem do tego rozszerzenie C za pomocą transformacji Haara); następnie, porównując indeksy największych (proporcjonalnie) współczynników falkowych między dwoma obrazami, powinieneś uzyskać numeryczne przybliżenie podobieństwa.

 2
Author: tzot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:53

Miałem podobny problem w pracy, przepisywałem nasz punkt końcowy transformacji obrazu i chciałem sprawdzić, czy nowa wersja produkuje to samo lub prawie to samo wyjście co stara wersja. Więc napisałem to:

Https://github.com/nicolashahn/diffimg

, który działa na obrazach o tej samej wielkości i na poziomie piksela, mierzy różnicę wartości w każdym kanale: R, G, B (, A), bierze średnią różnicę tych kanałów, a następnie uśrednia różnica w stosunku do wszystkich pikseli i Zwraca współczynnik.

Na przykład, przy obrazie 10x10 białych pikseli i tym samym obrazie, ale jeden piksel zmienił się na czerwony, różnica w tym pikselu wynosi 1/3 lub 0,33... (RGB 0,0,0 vs 255,0,0) i dla wszystkich innych pikseli wynosi 0. Razem 100 pikseli, 0,33.../ 100 = a ~ 0,33% różnicy w obrazie.

Wierzę, że to będzie działać idealnie dla projektu OP (zdaję sobie sprawę, że jest to bardzo stary post teraz, ale post dla przyszłych StackOverflowers, którzy również chcą porównać obrazy w Pythonie).

 2
Author: nicolashahn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-27 15:27:49

Przepraszam, jeśli jest za późno, aby odpowiedzieć, ale ponieważ robię coś podobnego, pomyślałem, że mogę się jakoś przyczynić.

Może w OpenCV przydałoby się dopasowanie szablonu. Zakładając, że używasz kamery internetowej, jak powiedziałeś:

  1. Uprość obrazy (może?)
  2. Zastosuj dopasowanie szablonu i sprawdź max_val za pomocą minMaxLoc

Wskazówka: max_val (lub min_val w zależności od użytej metody) da ci liczby, duże liczby. Aby uzyskać różnicę w procentach użyj dopasowania szablonu z tym samym obrazem - wynik będzie twój 100%.

Pseudo kod na przykładzie:

previous_screenshot = ...
current_screenshot = ...

# simplify both images somehow

# get the 100% corresponding value
res = matchTemplate(previous_screenshot, previous_screenshot, TM_CCOEFF)
_, hundred_p_val, _, _ = minMaxLoc(res)

# hundred_p_val is now the 100%

res = matchTemplate(previous_screenshot, current_screenshot, TM_CCOEFF)
_, max_val, _, _ = minMaxLoc(res)

difference_percentage = max_val / hundred_p_val

# the tolerance is now up to you
Mam nadzieję, że to pomoże.
 2
Author: zanfranceschi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-15 16:08:16

Odległość od Ziemi może być dokładnie tym, czego potrzebujesz. Może to być abit ciężki do wdrożenia w czasie rzeczywistym.

 1
Author: shoosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-10 02:48:35

A co z obliczeniem odległości Manhattanu dwóch obrazów? To daje wartości n * N. Następnie możesz zrobić coś takiego jak średnia wiersza, aby zmniejszyć do wartości n i funkcji nad tym, aby uzyskać jedną pojedynczą wartość.

 1
Author: Tobias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-10 02:53:30

[[0]] mam sporo szczęścia ze zdjęciami jpg zrobionymi tym samym aparatem na statywie przez (1) znaczne uproszczenie (jak przejście z 3000 pikseli szerokości do 100 pikseli szerokości lub nawet mniej) (2) spłaszczenie każdej tablicy jpg w jeden wektor (3) parami korelujące obrazy sekwencyjne z prostym algorytmem korelacji, aby uzyskać współczynnik korelacji (4) kwadratowy współczynnik korelacji, aby uzyskać R-kwadrat (tj. ułamek zmienności w jednym obrazie wyjaśniony zmiennością w następnym) (5) ogólnie w moja aplikacja jeśli R-kwadrat

To jest solidne i szybkie w mojej implementacji (Mathematica 7)

Warto pobawić się tą częścią obrazu, którą jesteś zainteresowany i skupić się na tym, przycinając Wszystkie zdjęcia do tego małego obszaru, w przeciwnym razie pominięta zostanie odległa od kamery, ale ważna zmiana.

Nie wiem jak używać Pythona, ale jestem pewien, że też nie?

 1
Author: Roman Dial,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-19 21:28:00

Możesz obliczyć histogram obu obrazów, a następnie obliczyć współczynnik Bhattacharyya , jest to bardzo szybki algorytm i użyłem go do wykrywania zmian ujęć w filmie krykieta (w C za pomocą openCV)

 1
Author: vishalv2050,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-24 20:44:46

Zobacz jak Haar-daemon jest zaimplementowany przez ISK-daemon . Możesz użyć kodu Imgdb C++, aby obliczyć różnicę między obrazami w locie:

ISK-daemon jest serwerem bazodanowym typu open source, który umożliwia dodawanie obrazów opartych na treści (wizualnych)do dowolnej strony internetowej lub oprogramowania.

Ta technologia pozwala użytkownikom dowolnej strony internetowej lub oprogramowania związanego z obrazem na szkic w widżecie, który obraz chcą znaleźć i na który strona internetowa odpowiada im najbardziej podobne obrazy lub po prostu poprosić o Więcej podobnych zdjęć na każdej stronie szczegółów obrazu.

 1
Author: Ricardo Cabral,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-16 21:11:08

Miałem ten sam problem i napisałem prosty moduł Pythona, który porównuje dwa obrazy tej samej wielkości za pomocą ImageChops pillow ' a do utworzenia czarno-białego obrazu różnicowego i podsumowania wartości histogramu.

Możesz uzyskać ten wynik bezpośrednio lub wartość procentową w porównaniu do pełnego porównania czerń i biel.

Zawiera również prostą funkcję is_equal, z możliwością podania rozmytego progu pod (i włącznie) obrazem przechodzi jako równy.

Podejście nie jest bardzo rozbudowany, ale może jest przydatny dla innych, którzy zmagają się z tym samym problemem.

Https://pypi.python.org/pypi/imgcompare/

 1
Author: datenhahn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-21 00:23:54

Nieco bardziej pryncypialnym podejściem jest użycie globalnego deskryptora do porównywania obrazów, takich jak GIST lub CENTRIST. Funkcja hash, jak opisano tutaj, również dostarcza podobnego rozwiązania.

 1
Author: Felix Goldberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-29 00:53:36

Kolejny ładny, prosty sposób na zmierzenie podobieństwa między dwoma obrazami:

import sys
from skimage.measure import compare_ssim
from skimage.transform import resize
from scipy.ndimage import imread

# get two images - resize both to 1024 x 1024
img_a = resize(imread(sys.argv[1]), (2**10, 2**10))
img_b = resize(imread(sys.argv[2]), (2**10, 2**10))

# score: {-1:1} measure of the structural similarity between the images
score, diff = compare_ssim(img_a, img_b, full=True)
print(score)

Jeśli inni są zainteresowani bardziej wydajnym sposobem porównywania podobieństwa obrazów, przygotowałemtutorial i webapp do pomiaru i wizualizacji podobnych obrazów za pomocą Tensorflow.

 1
Author: duhaime,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-30 16:29:02
import os
from PIL import Image
from PIL import ImageFile
import imagehash

#just use to the size diferent picture
def compare_image(img_file1, img_file2):
    if img_file1 == img_file2:
        return True
    fp1 = open(img_file1, 'rb')
    fp2 = open(img_file2, 'rb')

    img1 = Image.open(fp1)
    img2 = Image.open(fp2)

    ImageFile.LOAD_TRUNCATED_IMAGES = True
    b = img1 == img2

    fp1.close()
    fp2.close()

    return b





#through picturu hash to compare
def get_hash_dict(dir):
    hash_dict = {}
    image_quantity = 0
    for _, _, files in os.walk(dir):
        for i, fileName in enumerate(files):
            with open(dir + fileName, 'rb') as fp:
                hash_dict[dir + fileName] = imagehash.average_hash(Image.open(fp))
                image_quantity += 1

    return hash_dict, image_quantity

def compare_image_with_hash(image_file_name_1, image_file_name_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.
    recommend to use
    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_1 = None
    hash_2 = None
    with open(image_file_name_1, 'rb') as fp:
        hash_1 = imagehash.average_hash(Image.open(fp))
    with open(image_file_name_2, 'rb') as fp:
        hash_2 = imagehash.average_hash(Image.open(fp))
    dif = hash_1 - hash_2
    if dif < 0:
        dif = -dif
    if dif <= max_dif:
        return True
    else:
        return False


def compare_image_dir_with_hash(dir_1, dir_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.

    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_dict_1, image_quantity_1 = get_hash_dict(dir_1)
    hash_dict_2, image_quantity_2 = get_hash_dict(dir_2)

    if image_quantity_1 > image_quantity_2:
        tmp = image_quantity_1
        image_quantity_1 = image_quantity_2
        image_quantity_2 = tmp

        tmp = hash_dict_1
        hash_dict_1 = hash_dict_2
        hash_dict_2 = tmp

    result_dict = {}

    for k in hash_dict_1.keys():
        result_dict[k] = None

    for dif_i in range(0, max_dif + 1):
        have_none = False

        for k_1 in result_dict.keys():
            if result_dict.get(k_1) is None:
                have_none = True

        if not have_none:
            return result_dict

        for k_1, v_1 in hash_dict_1.items():
            for k_2, v_2 in hash_dict_2.items():
                sub = (v_1 - v_2)
                if sub < 0:
                    sub = -sub
                if sub == dif_i and result_dict.get(k_1) is None:
                    result_dict[k_1] = k_2
                    break
    return result_dict


def main():
    print(compare_image('image1\\815.jpg', 'image2\\5.jpg'))
    print(compare_image_with_hash('image1\\815.jpg', 'image2\\5.jpg', 6))
    r = compare_image_dir_with_hash('image1\\', image2\\', 10)
    for k in r.keys():
        print(k, r.get(k))


if __name__ == '__main__':
    main()
  • Wyjście:

    False
    True
    image2\5.jpg image1\815.jpg
    image2\6.jpg image1\819.jpg
    image2\7.jpg image1\900.jpg
    image2\8.jpg image1\998.jpg
    image2\9.image1\1012.jpg. jpg

  • Przykładowe zdjęcia:

    • 815.. jpg
      815.. jpg

    • 5.. jpg
      5.. jpg

 1
Author: admin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-29 11:34:08

Myślę, że można po prostu obliczyć odległość euklidesową (tj. sqrt (suma kwadratów różnic, piksel po pikselu)) pomiędzy luminancją obu obrazów i uznać je za równe, Jeśli mieści się to pod pewnym empirycznym progiem. I lepiej zrób to zawijając funkcję C.

 0
Author: Federico A. Ramponi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-10 04:08:13