Предложите алгоритм сопоставления цветовых шаблонов с большим известным набором

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

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

Пример:

Допустим, нам дан набор из трех значений цвета RGB, двух синих и оранжевого:

Пример набора:

Цвет 1: 81 177 206 (синий)

Цвет 2: 36, 70, 224 (синий)

Цвет 3: 255, 132, 0 (оранжевый)

Этот набор из 3 значений цвета должен быть сопоставлен с гораздо большим набором значений цвета, чтобы увидеть, существует ли этот набор в нем, либо с одинаковыми точными значениями RGB для каждого из 3 цветов, либо - существует ли какой-либо шаблон, где значение RGB цветов варьируется в приемлемой степени. Предположим, что любой из компонентов RGB может быть до 3 цифр выше или ниже по значению.

Допустим, наш большой набор известных значений цвета, по которым мы будем искать, выглядит так:

Известный набор:

            Color 1          Color 2       Color 3
Sample A: [25, 25, 25],    [10, 10, 10], [100, 100, 100] 

Sample B: [125, 125, 125], [10, 10, 10], [200, 200, 200] 

Sample C: [13, 87, 255],   [10, 10, 10], [100, 100, 100] 

Sample D: [67, 111, 0],    [10, 10, 10], [200, 200, 200] 

Sample E: [255, 255, 255], [10, 10, 10], [100, 100, 100] 

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

Sample F: [81,177,206], [36, 70, 224], [255, 132, 0]

Если бы образец F существовал с этими значениями в известном наборе, мы получили бы положительное совпадение, потому что это точные значения RGB в качестве цвета 1 в нашем наборе образцов. Кроме того, нам нужно принять разную степень различий в значениях RGB, поэтому следующее также вернет положительные совпадения, поскольку каждое значение RGB находится в пределах 3 цифр от значений цвета 1 из набора образцов:

Положительные совпадения: (помните, что цвет 1: 81 177 206)

Образец F: 80 177 206 (красный канал находится на расстоянии 1 цифры)

Пример F: 81,175,204 (зеленый и синий каналы на расстоянии 2 цифры)

Образец F: 82 179 208 (все три канала в пределах 3 цифр)

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

Отрицательные обращения:

Образец F: 85,177,206 (красный канал находится на расстоянии 4 цифр)

Образец F: 81,170, 206 (зеленый канал находится на расстоянии 7 цифр)

Образец F: 81 177,200 (синий канал находится на расстоянии 6 цифр)

До сих пор мы учитывали только цвет 1 из набора образцов. Однако требование требует учета всего набора образцов. Таким образом, если для цвета 1 не удается найти положительных совпадений, мы предполагаем, что совпадений нет вообще, и не рассматриваем цвета 2 и 3 из набора образцов.

Однако, если мы находим положительный результат для Цвета 1, скажем, 80 177 206, что всего на 1 цифру меньше в красном канале 80 против 81, тогда мы делаем продолжение обработки Цвета 2, и если мы находим положительный соответствует этому, затем мы обрабатываем Color 3 и так далее.

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

Я подумал об использовании хеш-таблиц, по одной на каждый цвет, для построения известного набора. Таким образом, я мог проверить совпадение для цвета 1 и, если оно было найдено, проверить хэш-таблицу для цвета 2 и остановиться, когда совпадений больше не было. Если бы я прошел через все 3 цвета/хеш-таблицы с положительными совпадениями, то у меня было бы общее положительное совпадение, в противном случае — нет. Однако этот подход не учитывает дисперсию, необходимую для каждого из каналов RGB для каждого цвета. Было бы слишком много комбинаций, чтобы можно было построить хеш-таблицы, чтобы хранить все это.

Заранее спасибо и спасибо, что дочитали до конца!


person znelson    schedule 19.04.2015    source источник
comment
Допустимо ли 3 совокупное отклонение или оно для каждого из значений R, G, B?   -  person Anshul Goyal    schedule 19.04.2015
comment
Это для каждого из значений RGB в каждом из цветов в наборе. Это не кумулятивное отклонение, хотя, возможно, неплохо иметь его в качестве дополнительной защиты.   -  person znelson    schedule 19.04.2015
comment
Использование OpenCV с С#? Я полагаю, используя EmguCV?   -  person Failed Scientist    schedule 19.04.2015
comment
Что это у вас есть несколько наборов по известному набору цветов, которые соответствуют критериям? Как часто меняется известный набор по сравнению с частотой выполнения этого алгоритма? Фиксирован ли размер допустимого отклонения или он может меняться со временем?   -  person Zohar Peled    schedule 19.04.2015
comment
@TalhaIrfan В идеале да. Я пытался использовать демо-версию SurfFeature в качестве отправной точки. Но в этом примере изображение A сравнивается с изображением B, тогда как мне нужно сравнить особенности изображения A со всем известным набором в базе данных. Мне не удалось изменить пример SurfFeature для этого. Если бы вы могли указать мне в правильном направлении, я был бы чрезвычайно благодарен.   -  person znelson    schedule 19.04.2015
comment
@ZoharPeled Пока один образец в известном наборе соответствует (или находится в пределах отклонения на одном или нескольких каналах RGB для тестируемого цвета), это общий успех. Известный набор со временем будет только расти. Отклонение может быть немного изменено в большую или меньшую сторону для устранения ложных срабатываний/отрицательных результатов. Однако отклонение не меняется с точки зрения запуска алгоритма. Другими словами, если отклонение равно 3, оно всегда равно 3 для каждого теста цвета/образца, пока однажды я не решу изменить его.   -  person znelson    schedule 19.04.2015
comment
Ваши цветовые наборы всегда будут содержать 3 цвета или это может быть любое количество цветов? (например, если вы сохраните его в базе данных, будет ли у вас таблица из 9 столбцов tinyint? (каждый цвет имеет 3 столбца tinyint)   -  person Zohar Peled    schedule 19.04.2015
comment
@ZoharPeled да, в наборе всегда будет одинаковое количество цветов. С точки зрения SQL вы правы.   -  person znelson    schedule 19.04.2015
comment
Что ж, дорогой, я полагаю, ты мало использовал EmguCV. Просто просмотрите его веб-сайт, и вы получите всю информацию. Там же есть примеры проектов :)   -  person Failed Scientist    schedule 19.04.2015
comment
@TalhaIrfan Я просмотрел сайт и у меня есть все образцы. Пожалуйста, укажите мне тот, который использует GpuMat для эталонных изображений, загружаемых из базы данных. Проблема заключается в том, как настроить его так, чтобы он сравнивал не изображение A с изображением B, а скорее изображение A с n-изображениями, и все они использовали графический процессор.   -  person znelson    schedule 19.04.2015
comment
Я перенес логику в Cudafy и запустил ее на своем графическом процессоре. Оказывается, это на 50% медленнее на GPU по сравнению с PLINQ на CPU. Перейдите к stackoverflow .com/questions/29739044/, если вам интересно узнать, как это возможно!   -  person znelson    schedule 20.04.2015


Ответы (3)


Держите один отсортированный список. Отсортируйте его три раза стабильной сортировкой, сначала по B, затем по G, затем по R. Это оставит его отсортированным в порядке RGB. Учитывая ваш ввод, найдите индексы для первого и последнего допустимых R с помощью двоичного поиска. Затем найдите в этом диапазоне приемлемые G, а затем найдите снова сокращенный диапазон на предмет B. Все это должно быть O (lgN).

-- Если я что-то не упустил, это решение обобщается для сопоставления набора из 3 цветов, 10 цветов или k цветов. Создайте массив индексов в свой список наборов цветов. Для подготовки стабильно отсортируйте индексы 3*k раз, как указано выше. Для поиска выполните 3*k бинарных поисков в обратном порядке.

(Это предполагает, что цвета зафиксированы в столбцах. Если это не так, вы все равно можете использовать этот метод, но ваш индексный список будет иметь размер N * k: ему нужна запись для A1, A2, A3. И в конце добавьте убедитесь, что вы сопоставили по одному из каждого столбца.)

person AShelly    schedule 19.04.2015
comment
Спасибо - это решает только один цвет в наборе образцов. В приведенных выше примерах это будет работать, скажем, для цвета 1, но мне придется повторить это для цветов 2 и 3. Что произойдет, если мне нужно протестировать 10 цветов в наборе образцов? - person znelson; 19.04.2015
comment
Итак, у вас есть большой список из N наборов, где каждый набор имеет размер k, и вы хотите найти набор, в котором все значения k достаточно близки? - person AShelly; 19.04.2015
comment
У меня есть большой список из N наборов, где каждый набор состоит из подмножеств фиксированного размера («цвета» в приведенном выше примере). В каждом из этих подмножеств есть три значения int (r, g, b). Мне нужно найти, какие наборы из большого списка имеют подмножества, каждое значение RGB которых находится в пределах n цифр выборочного набора, но на основе цвета для цвета. - person znelson; 19.04.2015

В конце концов, после экспериментов с SQL и программированием на графическом процессоре (Cudafy), самым быстрым, простым и поддающимся отладке решением было просто перебирать данные с помощью Parallel.For(). Этот подход позволил обработать 1,5 млн сэмплов (всего 90 млн байтов) за 18 мс.

person znelson    schedule 21.04.2015

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

CREATE TABLE KnownColorSets (
   KC_1_R tinyint NOT NULL,
   KC_1_G tinyint NOT NULL,
   KC_1_B tinyint NOT NULL,
   KC_2_R tinyint NOT NULL,
   KC_2_G tinyint NOT NULL,
   KC_2_B tinyint NOT NULL,
   KC_3_R tinyint NOT NULL,
   KC_3_G tinyint NOT NULL,
   KC_3_B tinyint NOT NULL
)

CREATE TYPE CompareColorSet As TABLE 
(
   CC_1_R tinyint NOT NULL,
   CC_1_G tinyint NOT NULL,
   CC_1_B tinyint NOT NULL,
   CC_2_R tinyint NOT NULL,
   CC_2_G tinyint NOT NULL,
   CC_2_B tinyint NOT NULL,
   CC_3_R tinyint NOT NULL,
   CC_3_G tinyint NOT NULL,
   CC_3_B tinyint NOT NULL
)



CREATE PROCEDURE stpCompareColorSets 
(
    @Exists bit output,
    @CompareColorSet dbo.CompareColorSet readonly
)
AS
  DECLARE @MaxDiviation tinyint = 3 -- This may be taken from a General params table or added as a parameter to the stored procedure
  SET @Exists = 0
  IF EXISTS (
    SELECT 1
    FROM KnownColorSets KC INNER JOIN
    @CompareColorSet CC ON(
      KC_1_R BETWEEN CC_1_R - @MaxDiviation AND CC_1_R - @MaxDiviation
      AND KC_1_G BETWEEN CC_1_G - @MaxDiviation AND CC_1_G - @MaxDiviation
      AND KC_1_B BETWEEN CC_1_B - @MaxDiviation AND CC_1_B - @MaxDiviation

      AND KC_2_R BETWEEN CC_2_R - @MaxDiviation AND CC_2_R - @MaxDiviation
      AND KC_2_G BETWEEN CC_2_G - @MaxDiviation AND CC_2_G - @MaxDiviation
      AND KC_2_B BETWEEN CC_2_B - @MaxDiviation AND CC_2_B - @MaxDiviation

      AND KC_3_R BETWEEN CC_3_R - @MaxDiviation AND CC_3_R - @MaxDiviation
      AND KC_3_G BETWEEN CC_3_G - @MaxDiviation AND CC_3_G - @MaxDiviation
      AND KC_3_B BETWEEN CC_3_B - @MaxDiviation AND CC_3_B - @MaxDiviation
    )
  ) 
  SET @Exists = 1
person Zohar Peled    schedule 19.04.2015
comment
Спасибо - это именно то, что я сейчас пытаюсь. Я чувствую, что, поскольку общее количество строк в таблице будет составлять несколько миллионов, а SQL-сервер довольно эффективен с планами запросов, у меня гораздо больше шансов на успех с этим маршрутом по сравнению с использованием структур данных в С#, которые я не знаком с. - person znelson; 19.04.2015
comment
Сила sql заключается в работе с большими наборами данных, а порядка нескольких миллионов вряд ли можно назвать завтраком для хорошо проиндексированной таблицы сервера sql. Другое преимущество состоит в том, что вам не нужно самостоятельно писать алгоритм поиска. - person Zohar Peled; 19.04.2015
comment
Выяснилось, что SQL был самым медленным методом, за ним следовал GPU (что удивительно), а самым быстрым методом был PLINQ на CPU. - person znelson; 20.04.2015
comment
@znelson: Если вы имеете в виду свой недавно удаленный вопрос, ваше ядро ​​выглядело так, как будто оно было привязано к памяти, а графический процессор, вероятно, работает медленно, потому что вам нужно копировать данные в графический процессор. Если бы данные находились на графическом процессоре, а не на центральном процессоре, версия на основе графического процессора была бы более эффективной. (также у вас были огромные развернутые циклы и, вероятно, вы тратили впустую инструкции по извлечению пропускной способности памяти) - person ; 20.04.2015
comment
@znelson Были ли у вас какие-либо индексы в вашей таблице и типе? - person Zohar Peled; 20.04.2015
comment
@ZoharPeled Я пробовал тесты с индексами и без них. Они определенно улучшили производительность, но время по-прежнему составляет 250-300 мс по сравнению с PLINQ, который составляет около 180-200 мс. - person znelson; 20.04.2015
comment
@znelson Думаю, тогда PLINQ — лучшее решение :-) - person Zohar Peled; 20.04.2015