Как я могу сравнить два NSImages для различий? - PullRequest
4 голосов
/ 02 августа 2011

Я пытаюсь измерить разницу в процентах между двумя изображениями.

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

  1. Простота кодирования
  2. Производительность.

Методы, которые я видел:

Не зависит от языка - академический Сравнение изображений - быстрый алгоритм и прямой доступ к пикселям для Mac http://www.markj.net/iphone-uiimage-pixel-color/

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

Ответы [ 5 ]

4 голосов
/ 14 августа 2011

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

Ниже приводится обзор алгоритма, который я использовал:

  1. Преобразование изображений воттенки серого - сравните один канал вместо трех.
  2. Разделите каждое изображение на n * n сетку «субизображений».Затем для пары подизображений:
    1. Рассчитайте их гистограммы цветовой композиции.
    2. Рассчитайте абсолютную разницу между двумя гистограммами.
  3. Максимальная найденная разница междудва изображения - это мера различия двух изображений.Другие метрики также могут быть использованы (например, средняя разница между подизображениями).

Как отметил Цкуцци в своем ответе, если ваша конечная цель - двоичный файл "да, эти два изображения (примерно) одинаковы"или" нет, это не так ", вам нужно какое-то значимое пороговое значение.Вы можете получить такое значение, передавая изображения в алгоритм и настраивая пороговое значение, основываясь на его выводе и на том, насколько похожи вы думаете изображения.Я полагаю, что это форма машинного обучения .

Я недавно написал сообщение в блоге на эту тему, хотя и как часть более широкой цели.Я также создал простое приложение для iPhone, чтобы продемонстрировать алгоритм.Вы можете найти источник на GitHub ;возможно это поможет?

2 голосов
/ 09 августа 2011

Это какой-то старый мерзкий Фортран, но он должен дать вам базовый подход. Это совсем не сложно. В связи с тем, что я делаю это на двухцветной палитре, вы должны выполнить эту операцию для R, G и B. То есть вычислить интенсивности или значения в каждой ячейке / пикселе, сохранить их в некотором массиве. Сделайте то же самое для другого изображения и вычтите один массив из другого, это оставит вас с каким-то прекрасным изображением вычитания. Я бы посоветовал сделать так, как предлагают парни выше, вычислить величину суммы компонентов R, G и B, чтобы вы просто получили одно значение. Запишите это в массив, сделайте то же самое для другого изображения, затем вычтите. Затем создайте новый диапазон для R, G или B и сопоставьте полученный вычтенный массив с этим, в результате получится намного более четкое изображение.

* =============================================================
      SUBROUTINE SUBTRACT(FNAME1,FNAME2,IOS)
*     This routine writes a model to files
* =============================================================
*    Common :
      INCLUDE 'CONST.CMN'
      INCLUDE 'IO.CMN'
      INCLUDE 'SYNCH.CMN'
      INCLUDE 'PGP.CMN'
*    Input :
      CHARACTER fname1*(sznam),fname2*(sznam)
*    Output :
      integer IOS
*    Variables:
       logical glue
       character fullname*(szlin)
       character dir*(szlin),ftype*(3)
       integer i,j,nxy1,nxy2
       real si1(2*maxc,2*maxc),si2(2*maxc,2*maxc)
* =================================================================

       IOS = 1
       nomap=.true.

       ftype='map'
       dir='./pictures'

!    reading first image
       if(.not.glue(dir,fname2,ftype,fullname))then
           write(*,31) fullname
           return
       endif

       OPEN(unit2,status='old',name=fullname,form='unformatted',err=10,iostat=ios)

       read(unit2,err=11)nxy2
       read(unit2,err=11)rad,dxy
       do i=1,nxy2
          do j=1,nxy2
             read(unit2,err=11)si2(i,j)
          enddo
       enddo

       CLOSE(unit2)


!    reading second image
       if(.not.glue(dir,fname1,ftype,fullname))then
           write(*,31) fullname
           return
       endif

       OPEN(unit2,status='old',name=fullname,form='unformatted',err=10,iostat=ios)

       read(unit2,err=11)nxy1
       read(unit2,err=11)rad,dxy
       do i=1,nxy1
          do j=1,nxy1
             read(unit2,err=11)si1(i,j)
          enddo
       enddo

       CLOSE(unit2)

!    substracting images 
       if(nxy1.eq.nxy2)then 
           nxy=nxy1
           do i=1,nxy1
              do j=1,nxy1
                 si(i,j)=si2(i,j)-si1(i,j)
              enddo
           enddo
       else
          print *,'SUBSTRACT: Different sizes of image arrays'
          IOS=0 
          return
       endif

*  normal finishing
       IOS=0 
       nomap=.false.
       return

*  exceptional finishing
10     write (*,30) fullname
       return
11     write (*,32) fullname
       return

30     format('Cannot open file   ',72A)
31     format('Improper filename   ',72A)
32     format('Error reading from file   ',72A)

      end
! =============================================================

Надеюсь, это пригодится. Всего наилучшего.

2 голосов
/ 09 августа 2011

Действительно сложно что-то предложить, если вы не расскажете нам больше об изображениях или вариациях.Они формы?Это разные объекты, и вы хотите знать, какой класс объектов?Являются ли они одним и тем же объектом, и вы хотите различить экземпляр объекта?Это лица?Это отпечатки пальцев?Находятся ли объекты в одной позе?Под таким же освещением?

Когда вы говорите «производительность», что именно вы имеете в виду?Насколько велики изображения?В общем, это действительно зависит.Исходя из того, что вы сказали, если это только простота кодирования и производительность, я бы предложил просто найти абсолютную величину разницы пикселей.Это очень легко кодировать и примерно так же быстро, как и получается, но на самом деле вряд ли будет работать для чего-либо, кроме самых синтетических примеров.

При этом я хотел бы указать вам: DHOG, GLOH, SURFи SIFT.

2 голосов
/ 09 августа 2011

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

Первый показывает изображение из моделирования в некоторый момент времени t. Второе изображение было вычтено из первого, которое было снято через некоторое время (симуляция) t + dt. Вычтенное изображение (черно-белое для ясности) показывает, как изменилось моделирование за это время. Это было сделано, как описано выше, и является очень мощным и легко кодируемым.

Надеюсь, это поможет вам в некотором роде

Image of simulated syncrotron emission from the Crab Nebula

Subtraction of one image from another taken 109 days of simulated time later

1 голос
/ 08 августа 2011

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

Чтобы реализовать метод гистограммы, я бы сделал следующее:

  1. Вычисление красной, зеленой и синей гистограмм каждого изображения
  2. Суммируйте различия между каждым ведром
  3. Если разница превышает определенный порог, то процент составляет 0%
  4. В остальном цвета на изображениях одинаковы. Так что сделайте сравнение пикселей за пикселем и конвертируйте разницу в процент.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...