Машинный анализатор. Часть 4. Классификатор


    В предыдущей статье я описывал память волновых нейронов.В данной статье мы рассмотрим классификатор изображений.


    Что такое классификатор


    Классификатор(лат. classis— разряд и facere— делать) — систематизированный перечень наименованных объектов, каждому из которых в соответствие дан уникальный код.


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


    Теория


    Мы должны взять два цветных изображения, разрушить их на набор бинарных изображений, так, как это описано в части 1.Потом, для каждого бинарного изображения найти волновую память, как описано в части 3, и сравнить массив волновой памяти одного изображения с массивом волновой памяти другого изображения. Поскольку разные изображения имеют разное количество цветов, мы ограничим число, на которое мы будем разбирать изображение. Назовем это число DEFMINCOLOR.


    Мы имеем два вектора строк(массивы волновой памяти, которые записаны в виде строк) с одинаковой размерностью, равной DEFMINCOLOR.Для того, чтобы найти максимальное совпадение среди этих строк, необходимо сдвигать на DEFMINCOLOR раз один вектор, забирая из последнего элемента значение, выталкивая это значение из вектора и размещая его в начале этого же вектора, и сравнить этот вектор с вторым. Если значения первого вектора совпадают со вторым, добавляем в булевый вектор единичку. В противном случае добавляем нолик. Суммируем все значения в булевым векторе и делим это значение на размерность булевого массива, и умножаем на 100.Получаем процент совпадений волновой памяти. В цикле сдвига на DEFMINCOLOR раз мы находим максимальный процент совпадения волновой памяти.


    То есть, классификатором двух изображений я буду называть процент максимального совпадения волновой памяти этих двух изображений.


    Работа программы


    Я снял видео и разбил его на фрагменты изображений. Осторожно, изображения в 144p.


    Ступеньки

    Изображение, похожее на ступеньки

    Дверь

    Компьютер

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

    Вот результаты для 255-цветных gif изображений.


    Результаты для gif изображений.

    Ступеньки и изображение, похожее на ступеньки
    Ограничитель цветов( DEFMINCOLOR ) равен 255
    Процент совпадения волновой памяти 1.9685%
    1.9685/100*255=5 общих описателей контуров


    Ступеньки и компьютер
    Ограничитель цветов( DEFMINCOLOR ) равен 255
    Процент совпадения волновой памяти 1.9685%
    1.9685/100*255=5 общих описателей контуров


    Ступеньки и дверь
    Ограничитель цветов( DEFMINCOLOR ) равен 255
    Процент совпадения волновой памяти 2.3622%
    2.3622/100*255=6 общих описателей контуров.


    Когда я только начинал измерения, я обрадовался том, что у разных изображений имеются какие-либо общие черты, какое-то общее количество описателей контуров(волновой памяти), отличное от нуля. Однако я увидел, что программа дает одинаковые код разным парам изображения. Следовательно, этот код не является уникальным, и наша программа не является классификатором. Это провал.


    Да, первое время я так и думал. Однако я решил взять не гиф изображения с количеством цветов 255, а png изображения, у которых было от 7 до 15 тысяч цветов. И начал проводить эксперименты над этими изображениями.


    Результаты для png изображений

    Ступеньки и изображение, похожее на ступеньки
    Ограничитель цветов( DEFMINCOLOR ) равен 700
    Процент совпадения волновой памяти 29.4286%
    29.4286/100*700=206 общих описателей контуров


    Ступеньки и компьютер
    Ограничитель цветов( DEFMINCOLOR ) равен 700
    Процент совпадения волновой памяти 11.8571%
    11.8571/100*700=83 общих описателей контуров


    Ступеньки и дверь
    Ограничитель цветов( DEFMINCOLOR ) равен 700
    Процент совпадения волновой памяти 12.1429%
    12.1429/100*700=85 общих описателей контуров.


    Здесь мы видим, что программа дает разный код разной паре изображений. Продолжим увеличивать DEFMINCOLOR


    Результаты для png изображений

    Ступеньки и изображение, похожее на ступеньки
    Ограничитель цветов( DEFMINCOLOR ) равен 2000
    Процент совпадения волновой памяти 18.3%
    18.3/100*2000=366 общих описателей контуров


    Ступеньки и компьютер
    Ограничитель цветов( DEFMINCOLOR ) равен 2000
    Процент совпадения волновой памяти 14.1%
    14.1/100*2000=282 общих описателей контуров


    Ступеньки и дверь
    Ограничитель цветов( DEFMINCOLOR ) равен 2000
    Процент совпадения волновой памяти 11.75%
    11.75/100*2000=235 общих описателей контуров.


    Теперь я решил уменьшить значение DEFMINCOLOR и приравнял его 255, такому же значению, как и для gif изображения. И был немного удивлен.


    Результаты для png изображений

    Ступеньки и изображение, похожее на ступеньки
    Ограничитель цветов( DEFMINCOLOR ) равен 255
    Процент совпадения волновой памяти 45.8824%
    45.8824/100*255=117 общих описателей контуров


    Ступеньки и компьютер
    Ограничитель цветов( DEFMINCOLOR ) равен 255
    Процент совпадения волновой памяти 15.2941%
    15.2941/100*255=39 общих описателей контуров


    Ступеньки и дверь
    Ограничитель цветов( DEFMINCOLOR ) равен 255
    Процент совпадения волновой 14.76%
    14.76/100*255=36 общих описателей контуров.


    Изображение классификатора


    Изображение

    Выводы: Получается, что классификатор работает, однако  гиф изображения не подходят для классификации ввиду сильного сжатия.


    Спасибо за чтение статьи.

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 16

      0
      Резюмируя. Для пары практически не отличающихся изображений оценка совпадения 0,45. Произвольная пара изображений даёт ложно-положительный ответ в 0,15.

      однако  гиф изображения не подходят для классификации ввиду сильного сжатия
      Они-то как раз и показывают реальное совпадение/различие (0,02), которое даёт алгоритм. А когда затем стали использовать не по одному изображению, а цветные изображения, бинаризованные способом из первой статьи, то фактически стали сравнивать крупные «низкочастотные» пятна на них. Вот и выросло «совпадение» с 0,02 до 0,15.
        0
        Согласен с VDG.
        Странный подход, по идее любой машинный классификатор изображений должен удовлетворительно справляться с классификацией того, что легко классифицирует человек(иначе не стоит и браться). В данном случае, человеку похожие изображения сопоставить не то что не проблема, а даже не задача. Даже простой попиксельный подсчёт дистанции даст однозначный результат.
        Если я правильно понял, волна начинает формироваться из области с интенсивностью выше некоторого порога, по идее это для двух случайно зашумлённых изображений даст, в общем случае, случайный результат, который в волнах высших порядков может быть сойдётся к чему-то более-менее общему. Звучит как-то не очень надёжно.
        Вывод, предложенный метод не работает.(А как он может работать вообще, без хотя какой-то нормализации входных данных, мне не понятно.)
          0
          Что вы подразумеваете под «попиксельным подсчетом дистанции»?
            0
            Переводим изображение в RGB и по каждому каналу для каждого пикселя считаем корень из модуля разности квадратов значений для двух изображений(либо просто модуль разности). Полученные таким образом расстояния по всем каналам и всем пикселям просто складываем. Получаем одно число, которое тем меньше, чем изображения более схожи.
            Для большей ясности. Изображение 1 назовём P1, А изображение 2 — P2.
            Пиксель имеет координаты XYС, где C это цветовой канал R,G или B, а X Y это положение. Ниже алгоритм на питоне, в предположении, что изображение это трёхмерный массив.
            def PicDist(P1,P2)
              sum =0
              for x in range(X):
                for y in range(Y):
                  for C in ['R','G','B']:
                    sum += sqrt(abs(P1[x][y][C]**2 - P2[x][y][C]**2))
            return sum
              0
              gif-это 8 битное изображение, которое сдержит палитру цветов.Если взять пару немного отличающихся изображений, например с 15 и 14 тысячами цветов, и преобразовать их в 255-цветное gif изображение, палитры для одного и другого изображения будут различны.Ваш алгоритм «попиксельного подсчета дистанции» работать не будет, поскольку при обратном преобразовании из палитры gif-а в RGB изображения будут искажения цветов.
                0
                От чего же не будет? Специально только что попробовал(в GIMP). Взял RGB изображение из стандартных виндовых, сохранил как gif, открыл и преобразовал обратно в RGB. Искажения есть, но они небольшие. Разница между изображениями мизерная (Самое яркое искажение не больше 20 по каждому каналу, различимых глазом точек не много). Соответственно и расстояние будет небольшое. Как и должно для сильно схожих изображений. Поэтому должно сработать
                  0
                  Хорошо.Сфотографируйте два похожих объекта(не одинаковых, а похожих) преобразуйте их оба в гиф, потом преобразуйте их обратно в RGB, сравните их своей программой, и сообщите здесь.
          0
          image
          image
          image
          тестовые изображения.
          Тестовый код на питоне:
          import pygame
          import os
          import numpy as np
          #from math import sqrt
          
          P1 = pygame.surfarray.array3d(pygame.image.load(os.path.join("Pictures","TestImage1.png")))
          P2 = pygame.surfarray.array3d(pygame.image.load(os.path.join("Pictures","TestImage2.png")))
          P3 = pygame.surfarray.array3d(pygame.image.load(os.path.join("Pictures","TestImage3.png")))
          
          (R,G,B) = (0,1,2)
          Sum12 = Sum13 = Sum23 = 0
          for x in range(512):
              for y in range(512):
                  for color in (R,G,B):
                      Sum12 += abs(float(P1[x][y][color]) - float(P2[x][y][color]))
                      Sum13 += abs(float(P1[x][y][color]) - float(P3[x][y][color]))
                      Sum23 += abs(float(P2[x][y][color]) - float(P3[x][y][color]))
          Norma = 255*3*(512**2)
          N12 = Sum12/Norma
          N13 = Sum13/Norma
          N23 = Sum23/Norma
          
          def makeMono(Array):
                  New_Array = np.zeros(Array.shape)
                  for x,row in enumerate(Array):
                      for y,(R,G,B) in enumerate(row):
                          New_Array[x][y] = int((0.299*R**2 + 0.587*G**2 + 0.114*B**2)**0.5)
                  return New_Array[:,:,0]
          
          Pm1 = makeMono(P1)
          Pm2 = makeMono(P2)
          Pm3 = makeMono(P3)
          
          SumM12 = SumM13 = SumM23 = 0
          for x in range(512):
              for y in range(512):
                  SumM12 += abs(float(Pm1[x][y]) - float(Pm2[x][y]))
                  SumM13 += abs(float(Pm1[x][y]) - float(Pm3[x][y]))
                  SumM23 += abs(float(Pm2[x][y]) - float(Pm3[x][y]))
          Norma = 255*(512**2)
          Nm12 = SumM12/Norma
          Nm13 = SumM13/Norma
          Nm23 = SumM23/Norma


          Результаты при сохранении цвета N11,N12 и N23 (расстояния между соотв. изображениями):
          N11 = 0.144
          N12 = 0.191
          N23 = 0.176
          Не ахти, но два ближайшие показаны верно и это метод «в лоб»

          Результаты при обесцвечивании Nm11,Nm12 и Nm23:
          Nm11 = 0.141
          Nm12 = 0.180
          Nm23 = 0.152
          Суть та же, результат верный. Метод элементарный «в лоб».
          Если надо, могу исходные гифки выложить.
          PS исправил ошибку в коде. N от Nm теперь почти не отличаются.
          PSPS. Подскажите как это можно свернуть, чтоб простынёй не висело? ))
            0
            Я к чему, мой пример можно использовать как референс того, хуже чего работать не должно в принципе. И Gif — не Gif реально совершенно не важно.
              0
              Хорошо.Моя программа создает процент совпадения волновой-контурной памяти.При одинаковых изображениях процент совпадения равен 100%.Объясните пожалуйста, как можно использовать ваши цифры 0.141,0.180, и 0.152, и как их преобразовать в проценты? Я понял, что если изображения абсолютно похожи, ваша программa выдаст нули.Как найти процент совпадения изображений вашим способом?
                0
                как их преобразовать в проценты?
                * 100
                  0
                  Наверно это неправильно, потому что если бы это было так, то для одинаковых картинок процент совпадения был бы 100%.Однако, процент совпадения одинаковых изображений равен нулю.Следовательно, правильной была бы формула (1-число)*100.В этом случае мы получаем следующий результат.Для 0.141 получаем (1-0.141)*100=85,9%, для 0.180 получаем (1-0.180)*100=82%, а для 0.152 мы получаем(1-0.152)*100=84,8%.Это как то подозрительно одинаково как для разных картинок, так и для одинаковых.Следовательно, на 100 умножать неправильно.
                    0
                    Картинки именно что похожи(третью специально по цветам подбирал), поэтому результат близкий. Ниже пример непохожей картинки, результат явный.
                    если для «похожих» мера сходства около 85%, то от них с явно непохожей -2… 5%.
                    Я не говорю что простое определение расстояния хороший метод классификации(см. «похожие» картинки), но он даёт стабильный и предсказуемый результат, при этом метод простой как грабли. К тонкостям качества картинки он тоже умерено чувствителен(считай робастный). Поэтому задумывая классификатор и распознавание изображений, надо добиваться результата не хуже.
              0
              image
              Четвёртое изображение специально контрастное прошлым.
              Результаты:
              N14 = 1.021
              N24 = 0.97
              N34 = 0.95
              Nm14 = 0.290
              Nm24 = 0.266
              Nm34 = 0.216
                0

                Хм. NumPy умеет в векторизованные операции. Первые 3 цикла заменяются строкой наподобие [N1,N2,N3] = np.average(np.abs(np.subtract(a,b)),axis=(0,1)) / 255 и т.д., это будет работать быстрее.

                  0
                  Не вопрос, но это надо было подумать)) В данном конкретном случае скорость безразлична. Плюс так любой, в том числе не знакомый с питоном, разберётся что именно тут написано.
                  Но да, можно оптимизировать.

              Only users with full accounts can post comments. Log in, please.