Сравнение изображений не работает с изображениями, снятыми камерой

[![введите описание изображения здесь][1]][1][![введите описание изображения здесь][2]][2]Я работаю над сравнением двух изображений на наличие различий.
Проблема в том, что он отлично работает, когда я загружаю какое-то изображение из Интернета, но не работает, когда я пытаюсь сравнить изображения, снятые с камеры телефона. Любая идея, где я делаю это неправильно?

Я работаю в Google Colab. Я пробовал использовать метод «structural_similarity» и dilate и findContours, оба не работают с изображениями с камеры.

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

Как вы видите на картинке - он показывает все нит n битов различий, но не показывает больший объект как разницу.

Изображение с телефона1:
enter image description here

Захваченное телефоном изображение2:
enter image description here

Вот мой код:

import cv2
from skimage.metrics import structural_similarity
import imutils

ref = cv2.imread('/content/drive/My Drive/Image Comparison/1.png')
target = cv2.imread('/content/drive/My Drive/Image Comparison/2.png')
gray_ref = cv2.cvtColor(ref, cv2.COLOR_BGR2GRAY)
gray_compare = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)

(score, diff) = structural_similarity(gray_ref,gray_compare, full=True)
diff = (diff * 255).astype("uint8")
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)

no_of_differences = 0

for c in contours:
    (x, y, w, h) = cv2.boundingRect(c)
    rect_area = w*h
    
    if rect_area > 10:
        no_of_differences +=1
        cv2.rectangle(ref, (x, y), (x + w, y + h), (0, 0, 255), 2)
        cv2.rectangle(target, (x, y), (x + w, y + h), (0, 0, 255), 2)

print("# of differences = ", no_of_differences)
scale_percent = 60 # percent of original size
width = int(ref.shape[1] * scale_percent / 100)
height = int(target.shape[0] * scale_percent / 100)
dim = (width, height)
  
# resize image
resized_ref = cv2.resize(ref, dim, interpolation = cv2.INTER_AREA)
resized_target = cv2.resize(target, dim, interpolation = cv2.INTER_AREA)
cv2_imshow(resized_ref)
cv2_imshow(resized_target)
cv2.waitKey(0)

Пожалуйста, покажите нам свою работу, чтобы воспроизвести проблему. См. минимальный воспроизводимый пример и Как спросить. Кроме того, «не работает» недостаточно для диагностики вашей проблемы. Уточните, пожалуйста, ошибки, с которыми вы столкнулись.

rayryeng 22.04.2022 18:49

не просто сбрасывайте код в вопросе. по крайней мере, убедитесь, что он правильно оформлен.

Christoph Rackwitz 22.04.2022 20:50

приносим извинения за неудобства - в следующий раз будем внимательнее

SauZ Khan 23.04.2022 21:58
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
0
3
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем решении есть две основные проблемы:

  • structural_similarity возвращает положительные и отрицательные значения (в диапазоне [-1, 1]).
    Преобразование: diff = (diff * 255).astype("uint8") применяет диапазон [0, 1], но для диапазона [-1, 1] мы можем использовать следующее преобразование:

     diff = ((diff+1) * 127.5).astype("uint8")  # Convert from range [-1, 1] to [0, 255].
    
  • Использование cv2.threshold с автоматическим порогом cv2.THRESH_OTSU недостаточно для пороговой обработки изображения (по крайней мере, когда применяется после structural_similarity).
    Вместо этого мы можем заменить его на адаптивный порог - адаптивный порог Гаусса.
    (Мое предложенное решение по-прежнему не является оптимальным, потому что мне пришлось вручную настраивать аргументы, но найти общее решение кажется слишком сложным).
    Замените thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] на:

     thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30)  # Use adaptive gaussian threshold instead of cv2.THRESH_OTSU
    

Пример кода (без использования Google Colb):

import cv2
from skimage.metrics import structural_similarity
import imutils

ref = cv2.imread('1.png')
target = cv2.imread('2.png')

ref = ref[(ref.shape[0]-480):(ref.shape[0]+480), (ref.shape[1]-768):(ref.shape[1]+768), :]
target = target[(target.shape[0]-480):(target.shape[0]+480), (target.shape[1]-768):(target.shape[1]+768), :]

gray_ref = cv2.cvtColor(ref, cv2.COLOR_BGR2GRAY)
gray_compare = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)

(score, diff) = structural_similarity(gray_ref, gray_compare, full=True)

#diff = (diff * 255).astype("uint8")
diff = ((diff+1) * 127.5).astype("uint8")  # Support negative values (range of diff is [-1, 1])

#thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30)  # Use adaptive gaussian threshold instead of cv2.THRESH_OTSU

contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)

no_of_differences = 0

for c in contours:
    (x, y, w, h) = cv2.boundingRect(c)
    rect_area = w*h

    if rect_area > 10:
        no_of_differences +=1
        cv2.rectangle(ref, (x, y), (x + w, y + h), (0, 0, 255), 2)
        cv2.rectangle(target, (x, y), (x + w, y + h), (0, 0, 255), 2)

print("# of differences = ", no_of_differences)
scale_percent = 60 # percent of original size
width = int(ref.shape[1] * scale_percent / 100)
height = int(target.shape[0] * scale_percent / 100)
dim = (width, height)
  
# resize image
resized_ref = cv2.resize(ref, dim, interpolation = cv2.INTER_AREA)
resized_target = cv2.resize(target, dim, interpolation = cv2.INTER_AREA)
cv2.imshow('diff', diff)
cv2.imshow('thresh', thresh)
cv2.imshow('resized_ref', resized_ref)
cv2.imshow('resized_target', resized_target)
cv2.waitKey()
cv2.destroyAllWindows()

Оригинал diff = (diff * 255).astype("uint8"):
enter image description here
Как видите, происходит переполнение данных.

diff = ((diff+1) * 127.5).astype("uint8"):
enter image description here

Оригинал thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]:
enter image description here Как видите, около половины thresh — белые.

Результат thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30):
enter image description here


resized_target:
enter image description here

resized_ref:
enter image description here

Примечание:
Изображения, которые вы разместили, содержат маркировку и имеют разный размер.
В следующий раз попробуй выкладывать чистые картинки вместо скриншотов...

Большое спасибо - все работает - ценю вашу помощь - Не могли бы вы помочь еще в одном вопросе - Что, если я не хочу отмечать крошечные различия и хочу показать только более крупные. Поскольку столько красных меток - я даже не понимаю, в чем собственно разница. заранее спасибо

SauZ Khan 23.04.2022 21:52

Конечно, замените if rect_area > 10 на if rect_area > 1000 (например). Вы также можете отфильтровать по cv2.contourArea(c) или проверить if (w > 30) And (h > 30)...

Rotem 23.04.2022 22:35

Спасибо за вашу помощь, но он все еще не работает с реальными фотографиями проекта. Я так запутался, потому что он работает с другими снимками, но не с фотографиями проекта. Загрузка фактического изображения, где оно не обнаруживает датчик. Не могли бы вы помочь снова с этим.

SauZ Khan 25.04.2022 15:41

Никакого волшебства... В случае с трубами это не работает, потому что два изображения сняты с немного разных позиций и углов - два изображения не идеально выровнены. Вы можете попробовать методы выравнивания изображений перед проверкой сходства (например, разместить изображение одно поверх другого). В случае с образцом труб выравнивание изображения не будет работать так хорошо, потому что есть проблемы с 3D. Мой ответ пришел с предупреждением: «найти общее решение кажется слишком сложным». Извини...

Rotem 25.04.2022 19:37

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