Oto, co chciałbym zrobić:
Robię zdjęcia kamerą internetową w regularnych odstępach czasu. Coś w rodzaju filmu poklatkowego. Jeśli jednak nic się naprawdę nie zmieniło, to znaczy obraz wygląda prawie tak samo, nie chcę przechowywać najnowszej migawki.
Wyobrażam sobie, że istnieje sposób na ilościowe określenie różnicy i musiałbym empirycznie określić próg.
Szukam raczej prostoty niż perfekcji. Używam Pythona.
Odpowiedzi:
Główny pomysł
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. Obliczyć wektor cech dla każdego z nich (jak histogram). Oblicz odległość między wektorami cech, a nie obrazami.
Jednak najpierw trzeba podjąć pewne decyzje.
pytania
Najpierw powinieneś odpowiedzieć na następujące pytania:
Czy obrazy mają ten sam kształt i wymiary?
Jeśli nie, może być konieczna zmiana ich rozmiaru lub przycięcie. Pomoże w tym biblioteka PIL w Pythonie.
Jeśli są zrobione z tymi samymi ustawieniami i tym samym urządzeniem, prawdopodobnie są takie same.
Czy obrazy są dobrze wyrównane?
Jeśli nie, możesz najpierw przeprowadzić korelację krzyżową, aby najpierw znaleźć najlepsze dopasowanie. SciPy ma funkcje, które to robią.
Jeśli aparat i scena są nieruchome, obrazy prawdopodobnie będą dobrze wyrównane.
Czy ekspozycja obrazów jest zawsze taka sama? (Czy lekkość / kontrast to to samo?)
Jeśli nie, możesz znormalizować obrazy.
Ale bądź ostrożny, w niektórych sytuacjach może to przynieść więcej szkody niż pożytku. Na przykład pojedynczy jasny piksel na ciemnym tle sprawi, że znormalizowany obraz będzie zupełnie inny.
Czy informacje o kolorze są ważne?
Jeśli chcesz zauważyć zmiany kolorów, będziesz mieć wektor wartości kolorów na punkt, zamiast wartości skalarnej, jak na obrazie w skali szarości. Pisząc taki kod, potrzebujesz więcej uwagi.
Czy obraz ma wyraźne krawędzie? Czy prawdopodobnie się ruszą?
Jeśli tak, możesz najpierw zastosować algorytm wykrywania krawędzi (np. Obliczyć gradient za pomocą transformaty Sobela lub Prewitta, zastosować jakiś próg), a następnie porównać krawędzie na pierwszym obrazie z krawędziami na drugim.
Czy na obrazie jest szum?
Wszystkie czujniki zanieczyszczają obraz pewną ilością szumów. Niedrogie czujniki mają większy szum. Przed porównaniem zdjęć warto zastosować pewną redukcję szumów. Rozmycie jest tutaj najprostszym (ale nie najlepszym) podejściem.
Jakie zmiany chcesz zauważyć?
Może to wpłynąć na wybór normy używanej dla różnicy między obrazami.
Rozważ użycie normy Manhattan (suma wartości bezwzględnych) lub normy zerowej (liczba elementów różna od zera), aby zmierzyć, jak bardzo obraz się zmienił. Pierwsza powie ci, jak bardzo obraz jest wyłączony, druga powie tylko, o ile pikseli się różni.
Przykład
Zakładam, że Twoje obrazy są dobrze wyrównane, mają ten sam rozmiar i kształt, prawdopodobnie z różną ekspozycją. Dla uproszczenia konwertuję je na skalę szarości, nawet jeśli są to obrazy kolorowe (RGB).
Będziesz potrzebować tych importów:
Główna funkcja, odczyt dwóch obrazów, konwersja do skali szarości, porównywanie i drukowanie wyników:
Jak porównać.
img1
iimg2
są tutaj tablice 2D SciPy: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ć w przypadku obrazów w skali szarości (np..pgm
):Normalizacja jest trywialna, możesz wybrać normalizację do [0,1] zamiast [0,255].
arr
jest tablicą SciPy, więc wszystkie operacje są oparte na elementach:Uruchom
main
funkcję:Teraz możesz umieścić to wszystko w skrypcie i uruchomić na dwóch obrazach. Jeśli porównamy obraz do samego siebie, nie ma różnicy:
Jeśli rozmyjemy obraz i porównamy z oryginałem, jest pewna różnica:
PS Cały skrypt compare.py .
Aktualizacja: odpowiednie techniki
Ponieważ pytanie dotyczy sekwencji wideo, w której klatki są prawdopodobnie prawie takie same, a szukasz czegoś niezwykłego, chciałbym wspomnieć o kilku alternatywnych podejściach, które mogą być odpowiednie:
Zdecydowanie polecam zajrzeć do książki „Learning OpenCV”, Rozdział 9 (Części obrazu i segmentacja) i 10 (Śledzenie i ruch). Pierwsza uczy metody odejmowania tła, druga podaje pewne informacje o metodach 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 Python.Najprostsza wersja odejmowania tła:
Bardziej zaawansowane wersje uwzględniają szeregi czasowe dla każdego piksela i obsługują sceny niestatyczne (jak ruchome drzewa czy trawa).
Ideą przepływu optycznego jest pobranie dwóch lub więcej klatek i przypisanie wektora prędkości każdemu pikselowi (gęsty przepływ optyczny) lub niektórym z nich (rzadki przepływ optyczny). Aby oszacować rzadki przepływ optyczny, możesz użyć metody Lucas-Kanade (jest również zaimplementowana w OpenCV). Oczywiście, jeśli jest duży przepływ (wysoka średnia powyżej maksymalnych wartości pola prędkości), to coś się porusza w kadrze, a kolejne obrazy są bardziej różne.
Porównanie histogramów może pomóc w wykryciu nagłych zmian między kolejnymi klatkami. Takie podejście zastosowano w Courbon i in., 2010 :
źródło
RuntimeWarning: invalid value encountered in double_scalars
online 44 (return (arr-amin)*255/rng
) iValueError: array must not contain infs or NaNs
online 30 (z_norm = norm(diff.ravel(), 0)
)rng
równa się zero. Po prostu dodaj czek i ustawrng = 1
Proste rozwiązanie:
Zakoduj obraz jako jpeg i poszukaj znaczącej zmiany w rozmiarze pliku .
Zaimplementowałem coś podobnego w przypadku miniatur wideo i odniosłem duży sukces i skalowalność.
źródło
Możesz porównać dwa obrazy za pomocą funkcji z PIL .
Obiekt diff to obraz, w którym każdy piksel jest wynikiem odjęcia wartości koloru tego piksela z drugiego obrazu od pierwszego obrazu. Używając obrazu porównawczego, możesz zrobić kilka rzeczy. Najprostsza to
diff.getbbox()
funkcja. Pokaże Ci minimalny prostokąt zawierający wszystkie zmiany między dwoma obrazami.Prawdopodobnie możesz zaimplementować aproksymacje innych wymienionych tutaj rzeczy, używając również funkcji z PIL.
źródło
Dwie popularne i stosunkowo proste metody to: (a) odległość euklidesowa już zasugerowana 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ą również bardziej wyrafinowane metody, ale wymagają one nieco więcej pracy.
Używając składni podobnej do numpy,
zakładając, że
i1
ii2
są tablice obraz 2D w skali szarości.źródło
Błaha rzecz do wypróbowania:
Ponownie próbkuj oba obrazy do małych miniatur (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. Ta metoda eliminuje szumy, które mogą pojawiać się zwłaszcza w słabo oświetlonych scenach. Może być nawet lepiej, jeśli przejdziesz do skali szarości.
źródło
Odnoszę się konkretnie do pytania, jak obliczyć, jeśli są one „wystarczająco różne”. Zakładam, że możesz dowiedzieć się, jak odejmować piksele jeden po drugim.
Najpierw wziąłbym kilka zdjęć, na których nic się nie zmienia, i ustaliłbym maksymalną wartość, o jaką zmienia się każdy piksel tylko z powodu różnic w przechwytywaniu, szumu w systemie obrazowania, artefaktów kompresji JPEG i chwilowych zmian w oświetleniu. . Być może okaże się, że można się spodziewać różnic 1 lub 2 bitów, nawet jeśli nic się nie porusza.
Następnie do „prawdziwego” testu potrzebujesz takiego kryterium:
Tak więc, być może, jeśli E = 0,02, P = 1000, oznaczałoby to (w przybliżeniu), że byłoby „inne”, gdyby jeden piksel zmienił się o więcej niż ~ 5 jednostek (zakładając obrazy 8-bitowe) lub jeśli więcej niż 1000 piksele miały w ogóle jakiekolwiek błędy.
Ma to służyć głównie jako dobra technika „segregacji” umożliwiająca szybką identyfikację obrazów, które są wystarczająco blisko, aby nie wymagały dalszego badania. Obrazy, które „zawodzą”, mogą zatem być bardziej skomplikowaną / kosztowną techniką, która nie dawałaby fałszywych alarmów, gdyby na przykład kamera trochę się trzęsła lub była bardziej odporna 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 (właściwie nawet bardziej rozbudowanymi). Nawet jeśli nie chcesz używać tego oprogramowania, możesz zajrzeć do źródła, aby zobaczyć, jak to zrobiliśmy. Jest dość często używany komercyjnie, a ta technika progowania została opracowana, abyśmy mogli mieć zestaw testowy do renderowania i oprogramowania do przetwarzania obrazu, z „obrazami referencyjnymi”, które mogą różnić się w zależności od platformy lub gdy wprowadziliśmy drobne poprawki tha algorytmów, więc chcieliśmy wykonać operację „dopasowanie w granicach tolerancji”.
źródło
Miałem podobny problem w pracy, przerabiałem nasz punkt końcowy transformacji obrazu i chciałem sprawdzić, czy nowa wersja daje takie same lub prawie takie same dane wyjściowe jak stara wersja. Więc napisałem to:
https://github.com/nicolashahn/diffimg
Działający na obrazach o tym samym rozmiarze i na poziomie piksela mierzy różnicę wartości na każdym kanale: R, G, B (, A), bierze średnią różnicę tych kanałów, a następnie uśrednia różnicę wszystkie piksele i zwraca współczynnik.
Na przykład w przypadku obrazu 10x10 białych pikseli i tego samego obrazu, 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 ), a dla wszystkich innych pikseli wynosi 0. Przy 100 pikselach łącznie 0,33 ... / 100 = ~ 0,33% różnicy w obrazie.
Wierzę, że to działałoby idealnie dla projektu OP (zdaję sobie sprawę, że jest to bardzo stary post, ale publikacja dla przyszłych StackOverflowers, którzy również chcą porównać obrazy w Pythonie).
źródło
Większość udzielonych odpowiedzi nie dotyczy poziomów oświetlenia.
Przed dokonaniem porównania normalizowałbym obraz do standardowego poziomu światła.
źródło
Kolejny fajny, prosty sposób na zmierzenie podobieństwa między dwoma obrazami:
Jeśli inni są zainteresowani skuteczniejszym sposobem porównywania podobieństw obrazów, przygotowałem samouczek i aplikację internetową do pomiaru i wizualizacji podobnych obrazów za pomocą Tensorflow.
źródło
skimage
jest naprawdę przyjemny w użyciu dla tej aplikacji. Używamfrom skimage.measure import compare_ssim, compare_mse
dużo. skimage.measure docs .Czy widzieliście już pytanie o algorytm wyszukiwania podobnych obrazów ? Sprawdź to, aby zobaczyć sugestie.
Sugerowałbym transformację falkową twoich ramek (napisałem do tego rozszerzenie C używając transformacji Haara); następnie porównując indeksy największych (proporcjonalnie) współczynników falkowych między dwoma obrazami, powinieneś otrzymać liczbowe przybliżenie podobieństwa.
źródło
Przepraszam, jeśli jest już za późno na odpowiedź, ale ponieważ robię coś podobnego, pomyślałem, że mógłbym w jakiś sposób wnieść swój wkład.
Może z OpenCV mógłbyś użyć dopasowania szablonu. Zakładając, że używasz kamery internetowej, jak powiedziałeś:
Wskazówka: max_val (lub min_val w zależności od użytej metody) zwróci liczby, duże liczby. Aby uzyskać różnicę w procentach, użyj szablonu dopasowanego do tego samego obrazu - wynik będzie 100%.
Pseudo kod na przykładzie:
Mam nadzieję, że to pomoże.
źródło
Odległość poruszających się ziemią może być dokładnie tym, czego potrzebujesz. To może być odrobinę ciężki do realizacji w czasie rzeczywistym chociaż.
źródło
A co z obliczeniem odległości Manhattanu dla dwóch obrazów. To daje n * n wartości. Następnie możesz zrobić coś w rodzaju średniej wiersza, aby zredukować do n wartości i wykonać funkcję, aby uzyskać jedną pojedynczą wartość.
źródło
Miałem dużo szczęścia ze zdjęciami jpg zrobionymi tym samym aparatem na statywie poprzez (1) znaczne uproszczenie (np. Przejście od szerokości 3000 do 100 pikseli lub nawet mniej) (2) spłaszczenie każdej tablicy jpg w jedną wektor (3) parami skorelowane obrazy sekwencyjne z prostym algorytmem korelacji w celu uzyskania współczynnika korelacji (4) współczynnik korelacji do kwadratu, aby uzyskać r-kwadrat (tj. ułamek zmienności na jednym obrazie wyjaśniony zmiennością na następnym) (5) ogólnie w mojej aplikacji jeśli r-kwadrat <0,9, mówię, że te dwa obrazy są różne i coś wydarzyło się pomiędzy.
To jest solidne i szybkie w mojej implementacji (Mathematica 7)
Warto pobawić się częścią obrazu, która Cię interesuje, i skupić się na tym, przycinając wszystkie obrazy do tego małego obszaru, w przeciwnym razie przeoczysz istotną zmianę z dala od aparatu.
Nie wiem, jak używać Pythona, ale czy na pewno robi też korelacje, nie?
źródło
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 wykrycia zmian strzałów w filmie o krykieta (w C przy użyciu openCV)
źródło
Sprawdź, jak Haar Wavelets są implementowane przez isk-daemon . Możesz użyć jego kodu imgdb C ++, aby obliczyć różnicę między obrazami w locie:
źródło
Miałem ten sam problem i napisałem prosty moduł Pythona, który porównuje dwa obrazy tego samego rozmiaru za pomocą ImageChops poduszki, aby utworzyć czarno-biały obraz różnicowy i podsumowuje wartości histogramu.
Możesz uzyskać ten wynik bezpośrednio lub wartość procentową w porównaniu do pełnego porównania czerni i bieli.
Zawiera również prostą funkcję is_equal, z możliwością podania rozmytego progu pod (i włączając) obraz przechodzi jako równy.
Podejście nie jest zbyt wyszukane, ale może być przydatne dla innych osób borykających się z tym samym problemem.
https://pypi.python.org/pypi/imgcompare/
źródło
Nieco bardziej pryncypialnym podejściem jest użycie globalnego deskryptora do porównywania obrazów, takich jak GIST lub CENTRIST. Funkcja skrótu, jak opisano tutaj , również zapewnia podobne rozwiązanie.
źródło
wynik:
Fałsz
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.jpg image1 \ 1012 .jpg
przykładowe zdjęcia:
815.jpg
5.jpg
źródło
Myślę, że można po prostu obliczyć odległość euklidesową (tj. Sqrt (suma kwadratów różnic, piksel po pikselu)) między luminancją dwóch obrazów i uznać je za równe, jeśli mieści się poniżej jakiegoś empirycznego progu. I lepiej zrób to opakowując funkcję C.
źródło
Istnieje wiele wskaźników służących do oceny, czy dwa obrazy wyglądają / jak wyglądają.
Nie będę się tutaj rozpisywał, bo myślę, że powinien to być problem naukowy inny niż techniczny.
Ogólnie rzecz biorąc, pytanie dotyczy postrzegania obrazów przez człowieka, więc każdy algorytm ma swoje wsparcie dla cech ludzkiego układu wzrokowego.
Klasyczne podejścia to:
Predyktor widocznych różnic: algorytm oceny wierności obrazu ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- assessment-of / 10.1117 / 12.135952.short? SSO = 1 )
Ocena jakości obrazu: od widoczności błędów do podobieństwa strukturalnego ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )
FSIM: indeks podobieństwa funkcji do oceny jakości obrazu ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )
Wśród nich SSIM (ocena jakości obrazu: od widoczności błędów do podobieństwa strukturalnego) jest najłatwiejszy do obliczenia, a jego narzut jest również niewielki, jak podano w innym artykule „Ocena jakości obrazu w oparciu o podobieństwo gradientu” ( https: //www.semanticscholar .org / papier / Ocena-jakości-obrazu-na-podstawie-gradientu-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).
Istnieje wiele innych podejść. Spójrz na Google Scholar i wyszukaj coś takiego jak „różnica wizualna”, „ocena jakości obrazu” itp., Jeśli jesteś zainteresowany / naprawdę zależy Ci na sztuce.
źródło
Istnieje proste i szybkie rozwiązanie za pomocą numpy, obliczając średni kwadratowy błąd:
źródło