Як можна кількісно визначити різницю між двома зображеннями?


179

Ось що я хотів би зробити:

Я регулярно фотографуюсь веб-камерою. Начебто річ, що проміжок часу. Однак якщо нічого насправді не змінилося, тобто картина майже виглядає однаково, я не хочу зберігати останні знімки.

Я думаю, що існує певний спосіб кількісної оцінки різниці, і мені доведеться емпірично визначити поріг.

Я шукаю простоту, а не досконалість. Я використовую python.


Відповіді:


269

Загальна ідея

Варіант 1: Завантажте обидва зображення у вигляді масивів ( scipy.misc.imread) та обчисліть різницю по елементах (піксель на піксель). Обчисліть норму різниці.

Варіант 2: Завантажте обидва зображення. Обчисліть деякий вектор функції для кожного з них (як гістограма). Обчисліть відстань між функціональними векторами, а не зображеннями.

Однак деякі рішення потрібно прийняти першими.

Запитання

Спершу слід відповісти на ці запитання:

  • Чи є зображення однакової форми та розміру?

    Якщо ні, то вам може знадобитися змінити розмір або обрізати їх. Бібліотека PIL допоможе зробити це в Python.

    Якщо вони приймаються з тими самими налаштуваннями і одним і тим же пристроєм, вони, ймовірно, однакові.

  • Чи добре вирівнюються зображення?

    Якщо ні, то, можливо, спочатку потрібно запустити перехресну кореляцію, щоб знайти найкраще вирівнювання. SciPy має функції для цього.

    Якщо камера та сцена нерухомі, зображення, ймовірно, будуть добре вирівняні.

  • Чи експозиція зображень завжди однакова? (Чи легкість / контраст однакова?)

    Якщо ні, можливо, ви захочете нормалізувати зображення.

    Але будьте обережні, в деяких ситуаціях це може зробити більше неправильного, ніж корисного. Наприклад, один яскравий піксель на темному тлі зробить нормалізоване зображення дуже різним.

  • Чи важлива інформація про колір?

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

  • Чи є на зображенні чіткі краї? Вони ймовірно рухаються?

    Якщо так, ви можете застосувати алгоритм виявлення ребер спочатку (наприклад, обчислити градієнт за допомогою трансформації Собеля або Превітта, застосувати деякий поріг), а потім порівняти ребра на першому зображенні з ребрами на другому.

  • Чи є шум у зображенні?

    Всі датчики забруднюють зображення деякою кількістю шуму. Датчики з низькими витратами мають більше шуму. Можливо, ви бажаєте застосувати деяке зниження шуму, перш ніж порівнювати зображення. Тут розмиття - найпростіший (але не найкращий) підхід.

  • Які зміни ви хочете помітити?

    Це може вплинути на вибір норми, яка використовується для різниці між зображеннями.

    Розглянемо використання норми Манхеттена (сума абсолютних значень) або нульової норми (кількість елементів, не рівних нулю), щоб виміряти, наскільки зображення змінилося. Перший скаже вам, на скільки вимкнене зображення, а другий - лише на скільки пікселів.

Приклад

Я припускаю, що ваші зображення добре вирівняні, однакового розміру та форми, можливо, з різною експозицією. Для простоти я перетворюю їх у масштаби сірого, навіть якщо вони є кольоровими (RGB) зображеннями.

Вам знадобиться такий імпорт:

import sys

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

Основна функція, прочитати два зображення, перетворити в масштаб сірого, порівняти та надрукувати результати:

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

Як порівнювати img1і img2є 2D масиви SciPy тут:

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)

Якщо файл є кольоровим зображенням, imreadповертає 3D-масив, середні RGB-канали (остання вісь масиву) для отримання інтенсивності. Не потрібно робити це для зображень у масштабах сірого (наприклад .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

Нормалізація є тривіальною, ви можете обрати нормування до [0,1] замість [0,255]. arrтут є масив SciPy, тому всі операції є елементарними:

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

Запустіть mainфункцію:

if __name__ == "__main__":
    main()

Тепер ви можете скласти це все в сценарій і бігти проти двох зображень. Якщо ми порівнюємо зображення із самим собою, то різниці немає:

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

Якщо ми розмиваємо зображення і порівнюємо з оригіналом, є деяка різниця:

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

PS Весь скрипт сравнение.py .

Оновлення: відповідні методи

Оскільки питання стосується відео послідовності, де кадри, ймовірно, будуть майже однаковими, і ви шукаєте щось незвичне, я хотів би зазначити кілька альтернативних підходів, які можуть бути актуальними:

  • віднімання та сегментація фону (для виявлення об'єктів переднього плану)
  • розріджений оптичний потік (для виявлення руху)
  • порівняння гістограм або іншої статистики замість зображень

Я настійно рекомендую переглянути книгу «Навчання OpenCV», глави 9 (частини зображення та сегментація) та 10 (відстеження та рух). Перший вчить використовувати метод віднімання фону, другий дає деяку інформацію про методи оптичного потоку. Усі методи реалізовані в бібліотеці OpenCV. Якщо ви використовуєте Python, я пропоную використовувати OpenCV ≥ 2.3 та його cv2модуль Python.

Найпростіша версія віднімання фону:

  • дізнатися середнє значення μ та стандартне відхилення σ для кожного пікселя фону
  • порівняти значення поточних пікселів до діапазону (μ-2σ, μ + 2σ) або (μ-σ, μ + σ)

Більш вдосконалені версії враховують часовий ряд для кожного пікселя та обробляють нестатичні сцени (наприклад, переміщення дерев чи траву).

Ідея оптичного потоку полягає у прийнятті двох або більше кадрів і призначенні вектора швидкості кожному пікселю (щільний оптичний потік) або деякому з них (розріджений оптичний потік). Для оцінки розрідженого оптичного потоку можна скористатися методом Лукаса-Канаде (він також реалізований у OpenCV). Очевидно, якщо велика кількість потоку (висока середня величина над максимальними значеннями поля швидкості), то в кадрі щось рухається, і наступні зображення є більш різними.

Порівняння гістограм може допомогти виявити раптові зміни між послідовними кадрами. Цей підхід був використаний у Courbon et al, 2010 :

Подібність послідовних кадрів. Вимірюється відстань між двома послідовними кадрами. Якщо вона занадто висока, це означає, що другий кадр пошкоджений і таким чином зображення усувається. Відстань Куллбека - Лейблера або взаємна ентропія на гістограмах двох кадрів:

$$ d (p, q) = \ sum_i p (i) \ log (p (i) / q (i)) $$

де p і q використовуються гістограми кадрів. Поріг фіксується на 0,2.


Я отримую RuntimeWarning: invalid value encountered in double_scalarsна лінії 44 ( return (arr-amin)*255/rng) і ValueError: array must not contain infs or NaNsна лінії 30 ( z_norm = norm(diff.ravel(), 0))
BioGeek,

@BioGeek, тобто rngдорівнює нулю. Просто додайте чек і встановітьrng = 1
haisi

76

Просте рішення:

Кодуйте зображення як jpeg і шукайте істотні зміни у розмірі файлів .

Я реалізував щось подібне з ескізами відео і мав багато успіху та масштабованості.


3
Це дуже просте, просте рішення і набагато краще, ніж будь-яке порівняння пікселів. Якщо у зображенні вашої веб-камери трохи шуму або якщо зображення зміщене навіть на один піксель, пряме порівняння підбере всі ці безглузді зміни. Більш надійним підходом було б обчислення дискретного косинусного перетворення, а потім порівняння зображень у частотній області. Використання подібного стиснення JPEG отримує більшу частину переваг без занурення в теорію Фур'є.
AndrewF

Люблю це. Хоча інші рішення також працюють, це має велику перевагу для загальної ситуації: що робити, якщо ви не хочете зберегти "базовий" образ? просто збережіть розмір файлів як хеш, а потім порівняйте просто числа з відніманням. У моєму випадку у мене є 4 зображення, одне з них дуже подібне, а інші 3 абсолютно різні. Просто масштабуйте до однакових розмірів, до jpg та субстрату. Дійсно приємно.
Дієго Андрес Діас Еспіноза

60

Можна порівняти два зображення за допомогою функцій PIL .

import Image
import ImageChops

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

diff = ImageChops.difference(im2, im1)

Об'єкт diff - це зображення, в якому кожен піксель є результатом віднімання значень кольорів цього пікселя у другому зображенні від першого зображення. Використовуючи зображення diff, ви можете зробити кілька речей. Найпростіша - diff.getbbox()функція. Він покаже вам мінімальний прямокутник, який містить усі зміни між вашими двома зображеннями.

Ви можете, можливо, реалізувати наближення інших згаданих тут матеріалів, використовуючи також функції з PIL.


2
Я хочу зберегти зображення різниці. означає об'єкт diff, який містить різницю зображень. завдяки чому я його зберігаю?
Сагар

2
@Anthony ви можете зателефонувати save () на об'єкт diff, вказавши ім'я зображення. так: diff.save ("diff.png") це збереже зображення різниці для вас.
Сагар

20

Два популярні і відносно прості методи: (а) евклідова відстань, що вже пропонується, або (б) нормалізована перехресна кореляція. Нормалізована перехресна кореляція, як правило, помітно міцніша до змін освітлення, ніж проста перехресна кореляція. Вікіпедія дає формулу для нормалізованої перехресної кореляції . Існують і більш досконалі методи, але вони вимагають трохи більше роботи.

Використовуючи синтаксис, схожий на нуме,

dist_euclidean = sqrt (сума ((i1 - i2) ^ 2)) / i1.size

dist_manhattan = сума (abs (i1 - i2)) / i1.size

dist_ncc = сума ((i1 - означає (i1)) * (i2 - означає (i2))) / (
  (i1.size - 1) * stdev (i1) * stdev (i2))

припускаючи, що це i1і i2є двовимірні масиви зображень у градаціях сірого.


3
Функції перехресної кореляції зображень вбудовані в SciPy ( docs.scipy.org/doc/scipy/reference/generated/… ), а швидка версія за допомогою FFT доступна в stsci python ( stsci.edu/resources/software_hardware/pyraf/ stsci_python )
ендоліти

14

Тривіальна річ, яку слід спробувати:

Перекомпонуйте обидва зображення на невеликі ескізи (наприклад, 64 x 64) та порівняйте мініатюри пікселів на піксель із певним порогом. Якщо оригінальні зображення майже однакові, перекомпоновані мініатюри будуть дуже схожими або навіть абсолютно однаковими. Цей метод опікується шумом, який може виникати особливо в умовах низької освітленості. Це може бути навіть краще, якщо ви перейдете до сірого.


але як би ви порівняли пікселі?
перевізник

Коли у вас є мініатюри, ви можете просто порівняти пікселі по черзі. Ви б обчислили "відстань" значень RGB, якщо ви працюєте за кольором або просто різницею між сірими тонами, якщо ви маєте відтінки сірого.
Атес Горал

1
"порівняти пікселі по черзі". Що це означає? Якщо тест не вдасться, якщо ONE з 64 ^ 2 тестів на піксель не вдається?
Федеріко А. Рампоні

Що я мав на увазі під «порівнянням мініатюр пікселів за пікселем з певним порогом», - це придумати нечіткий алгоритм порівняння пікселів. Якщо розрахована різниця (залежить від вашого нечіткого алгоритму) перевищує певний поріг, зображення "не однакові".
Атес Горал

1
Дуже простий приклад, без "нечіткого алгоритму": паралельний цикл через кожен піксель (порівняйте піксель № n зображення №1 з пікселем № н зображення №2), а різницю значення додайте до змінної
mk12

7

Я звертаюсь конкретно до питання, як зробити обчислення, якщо вони "досить різні". Я припускаю, що ви можете зрозуміти, як віднімати пікселі по черзі.

По-перше, я б сфотографував купу зображень, що нічого не змінюється, і з’ясував би максимальну кількість, що змінюється будь-яким пікселем саме через зміни в захваті, шумі в системі візуалізації, артефактах стиснення JPEG та моментальних моментах змін освітлення . Можливо, ви побачите, що 1 або 2 бітових відмінностей можна очікувати навіть тоді, коли нічого не рухається.

Тоді для "справжнього" тесту потрібно такий критерій:

  • те саме, якщо до P пікселів відрізняються не більше ніж E.

Тож, можливо, якщо E = 0,02, P = 1000, це означатиме (приблизно), що було б "інакше", якщо будь-який один піксель змінюється більш ніж на ~ 5 одиниць (припускаючи 8-бітні зображення), або якщо більше 1000 пікселі взагалі мали помилки.

Це, головним чином, як хороша техніка "тріади" для швидкого виявлення зображень, які є досить близькими, щоб не потребувати подальшого вивчення. Зображення, які "провалюються", можуть згодом перетворитись на більш складну / дорогу техніку, яка не мала б помилкових позитивів, якби, наприклад, камера трясла біт або була більш міцною до змін освітлення.

Я запускаю проект з відкритим кодом, OpenImageIO , який містить утиліту під назвою "idiff", яка порівнює різниці з такими порогами (ще більш детально, власне). Навіть якщо ви не хочете користуватися цим програмним забезпеченням, ви можете подивитися джерело, щоб побачити, як ми це зробили. Він використовується в комерційних технологіях зовсім небагато, і ця методика визначення порогових значень була розроблена так, що ми могли мати тестовий набір для програмного забезпечення візуалізації та обробки зображень із "еталонними зображеннями", які можуть мати невеликі відмінності від платформи до платформи або коли ми робимо незначні зміни алгоритми, тому ми хотіли операцію "відповідність толерантності".


6

У мене була схожа проблема на роботі, я переписував нашу кінцеву точку перетворення зображення і хотів перевірити, що нова версія виробляє той самий або майже той самий вихід, що і стара. Тому я написав це:

https://github.com/nicolashahn/diffimg

Що працює на зображеннях однакового розміру, і на рівні пікселя вимірює різницю значень на кожному каналі: R, G, B (, A), приймає середню різницю цих каналів, а потім усереднює різницю всіх пікселів і повертає відношення.

Наприклад, із зображенням білих пікселів розміром 10x10 і тим самим зображенням, але один піксель змінився на червоний, різниця в цьому пікселі становить 1/3 або 0,33 ... (RGB 0,0,0 проти 255,0,0 ), а в усіх інших пікселів - 0. Зі 100 пікселів 0,33 ... / 100 = a ~ 0,33% різниці у зображенні.

Я вважаю, що це було б ідеально підходить для проекту ОП (я розумію, що це вже дуже стара публікація, але публікація для майбутніх StackOverflowers, які також хочуть порівнювати зображення в python).


5

Більшість наданих відповідей не стосується рівня освітленості.

Я б спершу нормалізував зображення до стандартного рівня освітлення, перш ніж робити порівняння.


Якщо ви робите періодичні зображення та відрізняєтесь суміжними парами, ви, ймовірно, можете дозволити собі зберегти перше, коли хтось увімкне фари.
walkytalky

5

Ще один приємний, простий спосіб вимірювання подібності двох зображень:

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)

Якщо інших цікавить більш потужний спосіб порівняння подібності зображень, я склав підручник та веб- додаток для вимірювання та візуалізації подібних зображень за допомогою Tensorflow.


3
Так, skimageце дуже приємно використовувати для цього додатка. Я from skimage.measure import compare_ssim, compare_mseбагато використовую . skimage.мір мір .
ximiki

3

Ви бачили Алгоритм пошуку подібних зображень ? Перевірте це, щоб побачити пропозиції.

Я б запропонував вейвлет-перетворення ваших кадрів (я написав розширення C для цього, використовуючи перетворення Хаар); тоді, порівнюючи показники найбільших (пропорційно) вейвлет-коефіцієнтів між двома картинками, слід отримати приблизне числове схожість.


2

Прошу вибачення, якщо це занадто пізно, щоб відповісти, але оскільки я робив щось подібне, я думав, що можу якось зробити свій внесок.

Можливо, з OpenCV ви могли б використовувати шаблони відповідності. Припустимо, що ви використовуєте веб-камеру, як ви сказали:

  1. Спростіть зображення (можливо порогове значення?)
  2. Застосовуйте відповідність шаблонів і перевіряйте max_val за допомогою minMaxLoc

Порада: max_val (або min_val залежно від використовуваного методу) дасть вам числа, великі цифри. Щоб отримати різницю у відсотках, використовуйте відповідність шаблону з тим самим зображенням - результат буде вашим 100%.

Псевдокод для прикладу:

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

Сподіваюся, це допомагає.


1

Відстань від земляних рушіїв може бути саме тим, що вам потрібно. Це може бути ABIT важко реалізувати в реальному часі , хоча.


Я не відчуваю, що ця відповідь гарно відповідає: "Я шукаю простоту, а не досконалість. Я використовую python".
PilouPili

Я думаю, оскільки ця тема запитів отримує багато трафіку, а заголовок, який малює у більшості глядачів, стосується того, як кількісно визначити різницю між двома зображеннями, тут вона має значення.
Данорам

1

Як щодо обчислення відстані двох зображень на Манхеттені . Це дає вам n * n значень. Тоді ви можете зробити щось на зразок середнього рядка для зменшення до n значень і функції над цим, щоб отримати одне єдине значення.


1

Мені пощастило з зображеннями jpg, зробленими однаковою камерою на штативі, шляхом (1) значно спрощення (наприклад, від 3000 пікселів в ширину до 100 пікселів або навіть менше) (2) вирівнювання кожного масиву jpg в єдиний вектор (3) попарно співвіднесення послідовних зображень за допомогою простого кореляційного алгоритму, щоб отримати коефіцієнт кореляції (4) квадратичний коефіцієнт кореляції, щоб отримати r-квадрат (тобто частка мінливості в одному зображенні, пояснена варіацією в наступному) (5), як правило, в моєму додатку якщо r-квадрат <0,9, я кажу, що два зображення різні, і щось сталося між ними.

Це надійно і швидко в моєму виконанні (Mathematica 7)

Варто пограти з тією частиною зображення, яка вас зацікавила, і зосередитись на цьому, обрізаючи всі зображення на тій маленькій ділянці, інакше віддалену від камери, але важливу зміну не буде пропущено.

Я не знаю, як використовувати Python, але впевнений, що він також відповідає, ні?


1

ви можете обчислити гістограму обох зображень, а потім обчислити коефіцієнт Бхаттачарія , це дуже швидкий алгоритм, і я використовував його для виявлення змін знімків у відео для крикету (в C за допомогою openCV)


Не могли б ви обчислити коефіцієнт на самих зображеннях?
ендоліт

Вам доведеться обчислити гістограми для зображень (з розміром відрізка гістограми відповідно до вимог).
vishalv2050

1

Перевірте, як іск-демон демонструє реалізацію Haar Wavelets . Ви можете використовувати код imgdb C ++ для обчислення різниці між зображеннями на ходу:

isk-daemon - сервер баз даних з відкритим кодом, здатний додавати контент (візуальні) зображення на пошук до будь-якого веб-сайту чи програмного забезпечення, пов'язаного із зображеннями.

Ця технологія дозволяє користувачам будь-якого веб-сайту чи програмного забезпечення, що зображує зображення, накреслити на віджет, яке зображення вони хочуть знайти, і запросити веб-сайт відповісти на них найбільш схожими зображеннями або просто запитати більше подібних фотографій на кожній сторінці детальних зображень.


1

У мене була така ж проблема, і я написав простий модуль python, який порівнює два зображення однакового розміру за допомогою ImageChops подушки для створення чорно-білого розрізненого зображення та підсумовує значення гістограми.

Ви можете отримати або цей показник безпосередньо, або відсоткове значення порівняно з повною чорною та білою різницею.

Він також містить просту функцію is_equal, з можливістю подавати нечіткий поріг під (і включаючи) зображення проходить як рівне.

Підхід не дуже досконалий, але, можливо, він корисний для інших, хто бореться з тим же питанням.

https://pypi.python.org/pypi/imgcompare/


1

Дещо більш принциповий підхід полягає у використанні глобального дескриптора для порівняння зображень, таких як GIST або CENTRIST. Хеш-функція, як описано тут , також забезпечує подібне рішення.


1
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', 7))
    r = compare_image_dir_with_hash('image1\\', 'image2\\', 10)
    for k in r.keys():
        print(k, r.get(k))


if __name__ == '__main__':
    main()
  • вихід:

    Помилкові
    Правда
    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

  • приклади зображень:

    • 815.jpg
      815.jpg

    • 5.jpg
      5.jpg


0

Я думаю, ви могли просто обчислити евклідову відстань (тобто sqrt (сума квадратів різниць, піксель за пікселем)) між яскравістю двох зображень і вважати їх рівними, якщо це потрапляє під якийсь емпіричний поріг. І вам краще зробити це, обернувши функцію C.


0

Існує багато показників для оцінки того, як два зображення виглядають / як вони виглядають.

Я не буду тут вникати в будь-який код, бо вважаю, що це має бути наукова проблема, крім технічної.

Як правило, питання пов'язане із сприйняттям людиною зображень, тому кожен алгоритм має підтримку щодо рис зорової системи людини.

Класичні підходи:

Прогноз видимих ​​відмінностей: алгоритм оцінки вірності зображення ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- оцінка / 10,1117 / 12,135952.короткий? SSO = 1 )

Оцінка якості зображення: від видимості помилок до структурної подібності ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )

FSIM: Індекс подібності функцій для оцінки якості зображення ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )

Серед них SSIM (Оцінка якості зображення: від видимості помилок до структурної подібності) є найпростішим для обчислення, а його накладні витрати також невеликі, про що повідомляється в іншій статті "Оцінка якості зображення на основі схожості з градієнтом" ( https: //www.semanticscholar .org / paper / Image-Assessment-Based-on-Gradient-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).

Є ще багато інших підходів. Погляньте на Google Академію та знайдіть щось на зразок "візуальна різниця", "оцінка якості зображення" тощо, якщо ви зацікавлені / дійсно піклуєтесь про мистецтво.


0

Існує просте і швидке рішення з використанням numpy шляхом обчислення середньої помилки в квадраті:

before = np.array(get_picture())
while True:
    now = np.array(get_picture())
    MSE = np.mean((now - before)**2)

    if  MSE > threshold:
        break

    before = now
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.