Обработка изображений: улучшение алгоритма для распознавания "Coca-Cola Can"

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

Template matching

Некоторые ограничения на проект:

  • Фон может быть очень шумным.
  • У банки может быть любой масштаб или вращение или даже ориентация (в разумных пределах).
  • Изображение может иметь некоторую степень размытости (контуры могут быть не совсем прямыми).
  • На изображении могут быть бутылки с кока-колой, а алгоритм должен определять только банку!
  • Яркость изображения может сильно различаться (поэтому вы не можете слишком полагаться на распознавание цвета).
  • Банка может быть частично спрятана по бокам или в середине и, возможно, частично спрятана за бутылкой.
  • На изображении может не быть банок, и в этом случае вам ничего не нужно найти и написать сообщение, в котором говорится об этом.

Таким образом, вы можете получить такие хитрые вещи, которые (в этом случае мой алгоритм полностью провалился):

Total fail

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

Язык: Выполнено в C++ с использованием библиотеки OpenCV.

Предварительная обработка: Для предварительной обработки изображения, т.е. преобразования изображения в более сырую форму, чтобы придать алгоритму, я использовал 2 метода:

  1. Изменение цветовой области с RGB на HSV и фильтрация по "красному" оттенку, насыщенность выше определенного порога, чтобы избежать появления оранжевых цветов, и фильтрация низкого значения, чтобы избежать темных тонов. Конечным результатом было двоичное черно-белое изображение, где все белые пиксели будут представлять пиксели, которые соответствуют этому порогу. Очевидно, что на изображении все еще много дерьма, но это уменьшает количество измерений, с которыми вам приходится работать. Binarized image
  2. Шумовая фильтрация с использованием медианной фильтрации (принимая значение медианного пикселя всех соседей и заменяя пиксель на это значение), чтобы уменьшить шум.
  3. С помощью фильтра Canny Edge Detection Filter можно получить контуры всех элементов после 2 предыдущих шагов. Contour detection

Алгоритм: сам алгоритм, который я выбрал для этой задачи, был взят из этой удивительной книги по извлечению признаков и называется Обобщенное преобразование Хафа (довольно сильно отличается от обычного преобразования Хафа). В основном это говорит о нескольких вещах:

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

В конце концов, вы получите тепловую карту голосов, например, здесь все пиксели контура банки будут голосовать за ее гравитационный центр, так что у вас будет много голосов в одном пикселе, соответствующем в центре, и вы увидите пик на тепловой карте, как показано ниже:

GHT

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

Результаты: теперь, хотя этот подход работал в основных случаях, в некоторых областях его не хватало:

  • Это очень медленно ! Я недостаточно подчеркиваю это. Почти 30 дней понадобилось для обработки 30 тестовых изображений, очевидно, потому что у меня был очень высокий коэффициент масштабирования для поворота и перемещения, поскольку некоторые банки были очень маленькими.
  • Он был полностью утерян, когда на изображении были бутылки, и по какой-то причине почти всегда находил бутылку вместо банки (возможно, потому что бутылки были больше, таким образом, имели больше пикселей, таким образом, больше голосов)
  • Нечеткие изображения также были бесполезны, так как голоса оказались в пикселях в случайных местах вокруг центра, что привело к очень шумной тепловой карте.
  • Была достигнута разница в перемещении и повороте, но не в ориентации, что означало, что банка, которая не была обращена непосредственно к объективу камеры, не была распознана.

Можете ли вы помочь мне улучшить мой конкретный алгоритм, используя исключительно функции OpenCV, для решения четырех указанных проблем?

Я надеюсь, что некоторые люди также узнают что-то из этого, ведь я думаю, что не только люди, которые задают вопросы, должны учиться. :)

+1518
источник поделиться
27 ответов

Альтернативный подход заключается в извлечении объектов (ключевых точек) с использованием масштабно-инвариантного преобразования объектов (SIFT) или ускоренных надежных объектов (SURF).

Это реализовано в OpenCV 2.3.1.

Вы можете найти хороший пример кода, используя функции в Features2D + Homography, чтобы найти известный объект

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

Enter image description here

Источник изображения: учебный пример

Обработка занимает несколько сотен мсек для SIFT, SURF немного быстрее, но не подходит для приложений реального времени. ORB использует FAST, который слабее относительно инвариантности вращения.

Оригинальные документы

+617
источник

Чтобы ускорить процесс, я бы воспользовался тем, что вас не просят найти произвольный образ/объект, но, в частности, логотип Coca-Cola. Это важно, потому что этот логотип очень свойственен, и он должен иметь характерную, масштабно-инвариантную сигнатуру в частотной области, особенно в красном канале RGB. Другими словами, чередующийся рисунок красно-белого-красного цвета, встречаемый горизонтальной линией развертки (обученный на горизонтально выровненном логотипе), будет иметь отличительный "ритм", проходящий через центральную ось логотипа. Этот ритм будет "ускоряться" или "замедляться" в разных масштабах и ориентациях, но будет оставаться пропорционально эквивалентным. Вы могли бы определить/определить несколько десятков таких строк сканирования, как по горизонтали, так и по вертикали через логотип и еще несколько по диагонали, по шаблону звездообразования. Назовите эти "строки сканирования подписи".

Signature scan line

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

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

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

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

+356
источник
другие ответы

Связанные вопросы


Похожие вопросы

Интересная проблема: когда я взглянул на изображение бутылки, я подумал, что это тоже может быть. Но, как человек, я сделал, чтобы сказать разницу, что я тогда заметил, что это тоже бутылка...

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

Не слишком сложно реализовать, если вы уже делаете банки. Реальный недостаток - это удвоение времени обработки. (Но, думая заранее о реальных приложениях, вы все равно захотите делать бутылки; -)

+146
источник

Не трудно ли даже для людей различить бутылку и банку на втором изображении (при условии, что прозрачная область бутылки скрыта)?

Они почти одинаковы, за исключением очень маленькой области (то есть ширина в верхней части банки немного мала, в то время как обертка бутылки имеет одинаковую ширину, но небольшие изменения не так ли?)

Первое, что пришло мне в голову, это проверить красный верх бутылки. Но это все еще проблема, если нет бутылки для бутылки, или если она частично скрыта (как упомянуто выше).

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

Особо посмотрите на это, чтобы увидеть, насколько точно они обнаруживают стекло:

Смотрите результат их реализации:

Enter image description here

Говорят, что это реализация статьи "Геодезическая структура активного контура для поиска стекла" К. МакГенри и Дж. Понсе, CVPR 2006.

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

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

Enter image description here

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

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

  1. Это работает, только если ваша бутылка пуста. В этом случае вам придется искать красную область между двумя черными цветами (если жидкость Coca Cola черная).
  2. Еще одна проблема, если прозрачная часть покрыта.

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

+117
источник

Мне очень нравятся ответы Даррена Кука и укладчика на эту проблему. Я был в состоянии бросить свои мысли в комментарии к ним, но я считаю, что мой подход слишком сформирован, чтобы не уходить отсюда.

Вкратце, вы определили алгоритм для определения того, что логотип Coca-Cola присутствует в определенном месте в пространстве. Теперь вы пытаетесь определить для произвольных ориентаций и произвольных масштабных коэффициентов эвристику, подходящую для различения банок Coca-Cola от других объектов, включая бутылки, рекламные щиты, рекламные объявления и атрибуты Coca-Cola, связанные с этим символическим логотипом. Вы не упоминали многие из этих дополнительных случаев в своем заявлении о проблеме, но я чувствую, что они жизненно важны для успеха вашего алгоритма.

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

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

Для этого наиболее правильными критериями выбора банок являются следующие:

  • Правильна ли форма силуэта объекта, как вы набросали в своем вопросе? Если так, +1.
  • Если мы предполагаем наличие естественного или искусственного света, обнаруживаем ли мы хромированный контур бутылки, который указывает на то, сделан ли он из алюминия? Если так, +1.
  • Определяем ли мы, что зеркальные свойства объекта являются правильными по отношению к нашим источникам света (иллюстративная видеосвязь по обнаружению источника света)? Если так, +1.
  • Можем ли мы определить какие-либо другие свойства объекта, которые идентифицируют его как банку, включая, но не ограничиваясь этим, перекос логотипа топологического изображения, ориентацию объекта, сопоставление объекта (например, на плоской поверхности как таблица или в контексте других банок), а наличие вкладки? Если так, для каждого, +1.

Ваша классификация может выглядеть следующим образом:

  • Для каждого совпадения кандидатов, если обнаружен логотип Coca Cola, нарисуйте серую рамку.
  • Для каждого совпадения по +2 нарисуйте красную рамку.

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

Обнаружение каждого свойства несет в себе очень разную временную и пространственную сложность, и для каждого подхода быстрый переход по адресу http://dsp.stackexchange.com более чем разумен для определения наиболее правильного и наиболее эффективного алгоритма для ваших целей. Моя цель здесь состоит в том, чтобы просто и просто подчеркнуть, что обнаружение, если что-то может, путем признания недействительной небольшой части пространства обнаружения кандидата, не является наиболее надежным или эффективным решением этой проблемы, и в идеале вы должны предпринять соответствующие действия. соответственно.

И, эй, поздравляю с публикацией новостей Хакера! В целом, это довольно потрясающий вопрос, достойный той рекламы, которую он получил. :)

+47
источник

Глядя на форму

Возьмите гусак в форме красной части банки/бутылки. Обратите внимание на то, как консервная банка слегка сужается на самом верху, а этикетка бутылки - прямо. Вы можете различать эти два, сравнивая ширину красной части по ее длине.

Глядя на основные моменты

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

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

+39
источник

Пожалуйста, посмотрите на трекер Zdenek Kalal Predator. Требуется некоторое обучение, но он может активно изучать, как отслеживаемый объект выглядит в разных ориентациях и масштабах, и делает это в режиме реального времени!

Исходный код доступен на его сайте. Это в MATLAB, но, возможно, есть реализация Java, уже сделанная членом сообщества. Я успешно повторно внедрил часть трекера TLD в С#. Если я правильно помню, TLD использует Папоротники в качестве детектора ключевых точек. Вместо этого я использую SURF или SIFT (уже предложенный @stacker) для повторного получения объекта, если он был потерян трекером. Обратная связь с трекером позволяет легко со временем построить динамический список шаблонов просеивания/сёрфинга, которые со временем позволяют повторно захватывать объект с очень высокой точностью.

Если вы заинтересованы в моей реализации С# трекера, не стесняйтесь спрашивать.

+35
источник

Если вы не ограничены только камерой, которая не была в одном из ваших ограничений, возможно, вы можете перейти к использованию датчика дальности, такого как Xbox Kinect. С помощью этого вы можете выполнить согласованную сегментацию изображения на основе глубины и цвета. Это позволяет быстрее разделять объекты на изображении. Затем вы можете использовать сопоставление ICP или аналогичные методы, чтобы даже соответствовать форме, а не просто ее контуру или цвет, и учитывая, что она является цилиндрической, это может быть допустимым вариантом для любой ориентации, если у вас есть предыдущее 3D-сканирование цели. Эти методы часто бывают довольно быстрыми, особенно когда они используются для такой конкретной цели, которая должна решить вашу проблему скорости.

Также я мог бы предложить, не обязательно для точности или скорости, но для удовольствия вы могли бы использовать обученную нейронную сеть на своем сегментированном изображении с оттенком, чтобы идентифицировать форму банки. Они очень быстрые и часто могут быть точными до 80/90%. Тренировка будет немного долгим процессом, хотя вам придется вручную идентифицировать банку в каждом изображении.

+30
источник

Я бы обнаружил красные прямоугольники: RGB → HSV, фильтр red → двоичное изображение, закрыть (расширение затем размывается, называемое imclose в matlab)

Затем просмотрите прямоугольники от самых больших до самых маленьких. Прямоугольники, которые имеют меньшие прямоугольники в известном положении/масштабе, могут быть удалены (при условии, что пропорции бутылки постоянны, меньший прямоугольник будет крышкой для бутылок).

Это оставит вас с красными прямоугольниками, тогда вам нужно каким-то образом обнаружить логотипы, чтобы узнать, красные ли они прямоугольники или кокс. Как OCR, но с известным логотипом?

+21
источник

Это может быть очень наивная идея (или может вообще не работать), но размеры всех кокса могут быть исправлены. Так может быть, если одно и то же изображение содержит как банку, так и бутылку, тогда вы можете рассказать их отдельно по соображениям размера (бутылки будут больше). Теперь из-за недостающей глубины (т.е. 3D-сопоставление для двумерного отображения) возможно, что бутылка может казаться сжатой и не существует разницы в размерах. Вы можете восстановить некоторую информацию о глубине с помощью стереоизображения, а затем восстановить исходный размер.

+20
источник

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

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

Что вокруг логотипа? Для банки можно увидеть металл, который, несмотря на эффекты освещения, не меняет своего основного цвета. Пока мы знаем угол метки, мы можем сказать, что прямо над ним, поэтому мы смотрим на разницу между ними:

tqB8d.jpg

Здесь, что выше и ниже логотипа полностью темное, непротиворечивое по цвету. Относительно легко в этом отношении.

witbV.jpg

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

u9w9i.jpg

И, наконец, сложный. Но не так сложно, как только мы пойдем только по тому, что мы можем видеть непосредственно над (и ниже) красной оберткой. Его прозрачность, что означает, что она покажет все, что стоит за ней. Это хорошо, потому что вещи, которые стоят за ним, вряд ли будут такими же последовательными по цвету, как серебряный круговой металл банки. За этим может быть много разных вещей, которые говорят нам, что это пустая (или наполненная прозрачной жидкостью) бутылка или постоянный цвет, который может означать, что он заполнен жидкостью или что бутылка просто перед сплошной цвет. Мы работаем с тем, что ближе всего к вершине и дну, и шансы на правильные цвета в правильном месте относительно тонкие. Мы знаем, что это бутылка, потому что у нее нет такого ключевого визуального элемента банки, который относительно упрощен по сравнению с тем, что может быть за бутылкой.

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

В редких случаях, когда подобный оттенок серебра стоит за бутылкой, даже после абстракции пластика, или бутылка каким-то образом заполнена тем же оттенком серебристой жидкости, мы можем отбросить то, что мы можем приблизительно оценить как форма серебра - как я уже упоминал, круглая и следует за формой банки. Но даже если мне не хватает знаний в обработке изображений, это звучит медленно. Еще лучше, почему бы не вывести это за однократную проверку сторон логотипа, чтобы убедиться, что там нет ничего такого же серебряного цвета? Ах, но что, если там есть такой же оттенок серебра за банкой? Затем мы действительно должны уделять больше внимания формам, снова глядя на верхнюю и нижнюю часть банки.

В зависимости от того, насколько безупречно это все должно быть, это может быть очень медленным, но я полагаю, что моя основная концепция - сначала проверить самые простые и самые близкие вещи. Идите по цветовым различиям вокруг уже подобранной формы (которая, кажется, самая тривиальная часть этого в любом случае), прежде чем приступить к разработке формы других элементов. Для его перечня:

  • Найдите основную привлекательность (красный фон логотипа и, возможно, логотип для ориентации, хотя в случае отказа банки можно сосредоточиться только на красном).
  • Проверьте форму и ориентацию, еще раз через очень своеобразную покраснение.
  • Проверьте цвета вокруг формы (так как это быстро и безболезненно)
  • Наконец, при необходимости проверьте форму этих цветов вокруг главной притяжения для правильной округлости.

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

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


Как отказ от ответственности, у меня нет опыта и никогда не думал об обработке изображений за пределами этого вопроса, но это так интересно, что я подумал об этом довольно глубоко, и, прочитав все остальные ответы, я считаю это возможно, самый простой и наиболее эффективный способ сделать это. Лично я просто рад, что мне не нужно думать о программировании этого!

ИЗМЕНИТЬ

bad drawing of a can in MS paint Кроме того, посмотрите на этот рисунок, который я сделал в MS Paint... Это абсолютно ужасно и довольно неполно, но, основываясь только на форме и цветах, вы можете догадаться, что это будет. По сути, это единственные вещи, которые нужно искать для сканирования. Когда вы смотрите на эту очень своеобразную форму и сочетание цветов настолько близко, что еще может быть? Бит, который я не рисовал, на белом фоне, должен считаться "чем-то непоследовательным". Если бы у него был прозрачный фон, он мог бы переходить практически на любое другое изображение, и вы все равно могли бы его видеть.

+18
источник

Я не знаю OpenCV, но, глядя на проблему логически, я думаю, что вы можете различать бутылку и можете, изменив изображение, которое вы ищете, например, Coca Cola. Вы должны включить до верхней части банки, так как в случае может быть серебряная подкладка наверху кока-колы, а в случае бутылки такой серебряной подкладки не будет.

Но очевидно, что этот алгоритм потерпит неудачу в тех случаях, когда вершина can скрыта, но в этом случае даже человек не сможет отличить два (если видна только часть кока-колы бутылки/банки)

+15
источник

Мне нравится вызов и я хочу дать ответ, который решает проблему, я думаю.

  • Извлечь функции (ключевые точки, дескрипторы, такие как SIFT, SURF) логотипа
  • Совместите точки с образцом модели логотипа (используя Matcher, например Brute Force)
  • Оцените координаты твердого тела (проблема PnP - SolvePnP)
  • Оцените положение крышки в соответствии с жестким корпусом
  • Сделайте обратную проекцию и вычислите положение пикселя изображения (ROI) крышки бутылки (я предполагаю, что у вас есть внутренние параметры камеры)
  • Проверьте, существует ли кепка или нет. Если есть, то это бутылка

Обнаружение крышки - еще одна проблема. Это может быть сложным или простым. Если бы я был вами, я бы просто проверил цветную гистограмму в ROI для простого решения.

Пожалуйста, дайте отзыв, если я ошибаюсь. Благодарю.

+13
источник

Существует множество цветовых дескрипторов, используемых для распознавания объектов, в приведенной ниже статье сравниваются многие из них. Они особенно эффективны в сочетании с SIFT или SURF. Только SURF или SIFT не очень полезны для изображения кока-колы, потому что они не распознают множество точек интереса, вам нужна информация о цвете, чтобы помочь. Я использую BIC (Border/Interior Pixel Classi fiation) с SURF в проекте, и он отлично работал для распознавания объектов.

Цветовые дескрипторы для поиска веб-изображений: сравнительное исследование

+10
источник

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

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

Вы можете переучить начальную v3 модель на Tensorflow:

Как восстановить начальный финальный слой для новых категорий.

В этом случае вы будете обучать сверточную нейронную сеть классифицировать объект как кока-колу или нет.

+10
источник

Я несколько лет опаздываю, отвечая на этот вопрос. Поскольку в последние 5 лет современное искусство подтолкнуло CNN к своим пределам, я бы не стал использовать OpenCV для выполнения этой задачи сейчас! (Я знаю, что вам особенно нужны функции OpenCv в вопросе). Я считаю, что алгоритмы обнаружения объектов, такие как Faster-RCNN, YOLO, SSD и т.д., будут иметь эту проблему со значительным запасом по сравнению с функциями OpenCV. Если бы я решил решить эту проблему сейчас (через 6 лет!!), я бы определенно использовал Faster-RCNN.

+10
источник

Мне нравится ваш вопрос, независимо от того, не зависит от него: P

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

Нам пришлось разработать робот, который использовал Xbox Kinect для обнаружения коксовых бутылок и банок на любой ориентации в различных условиях освещения и окружающей среды. Наше решение включало использование полосового фильтра на канале Hue в сочетании с преобразованием окружности hough. Мы смогли немного ограничить окружающую среду (мы могли бы выбрать, где и как расположить робота и датчик Kinect), иначе мы собирались использовать преобразования SIFT или SURF.

Вы можете прочитать о нашем подходе на моем сообщении в блоге по теме:)

+9
источник

Глубокое обучение

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

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

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

OpenCV и Google Net: http://docs.opencv.org/trunk/d5/de7/tutorial_dnn_googlenet.html

OpenCV и SVM: http://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html

+8
источник

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

Полезно извлекать только банки и их можно комбинировать с обнаружением прозрачных объектов.

+6
источник

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

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

+3
источник

Ответы на этой странице действительно равны:

  • "использовать SIFT"

  • "использовать Kinect"

Если вас не интересует фактическая информатика распознавания образов, и вы просто хотите "использовать" что-то (например, SIFT или Kinect),

сегодня повсеместно просто использовать общедоступные системы распознавания образов.

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

Вы больше не сядете и (попробуете) добиться распознавания образов с нуля, чем сядете и начнете собирать и отображать карты, или что вы начнете рендеринг HTML с нуля или напишите базу данных SQL с нуля.

Вы просто используете тензометр Google (они достигли точки построения чипов, ради всего прочего, быстрее обрабатывать тензорный поток), Clarifai, Bluemix или что-то еще.

AWS только что выпустила хороший для распознавания изображений (2018).

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

func isItACokeCan() {

    jds.headers = ["Accept-Language":"en"]
    let h = JustOf<HTTP> ...use your favorite http library

    let u: String =
        "https://gateway-a.watsonplatform.net/visual-recognition/api/v3/classify"
        + "?api_key= ... your API key ..."
        + "&version=2016-05-20"
        + "&classifier_ids= ... your Classifier name ..."

    h.post( u,
        files: ["x.jpeg": .data("x.jpeg", liveImageData!, "image/jpeg")]

    ) { r in
        if r.ok { DispatchQueue.main.async { self.processResult(r.json) } }
        else { DispatchQueue.main.async { self.doResults("network woe?") } }
    }
}

func processResult(_ rr: Any?){
    let json = JSON(rr!)
    print("\(json)")
}

Это буквально даст вам лучшее, существующее, кокс-распознавание на Земле, в настоящее время достигнутое.

По состоянию на 2018 год вы больше не можете сидеть и "писать лучше распознавания кокса, чем Bluemix", чем вы могли бы "сесть и написать лучшую программу Go, чем AlphaGo".

Системы, такие как Siri, Google Maps, BAAS, основные усилия по обработке изображений - и, очевидно, поиск в тексте google - меняют игру.

Обратите внимание на невероятную разницу только после того, как этот вопрос был задан шесть лет назад.

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

Но этот QA, по-видимому, является скорее обзором технологий.

Так как ответы здесь говорят "использовать библиотеку SIFT" - вы действительно этого не сделали. (Опять же - не более, чем вы по какой-то причине трудолюбиво программируете веб-сервер или базу данных SQL с нуля!)

Вы просто подключаетесь к хорошо известным, вездесущим системам распознавания образов "BAAS" - это строка кода.

+2
источник

Если вы заинтересованы в том, чтобы быть в реальном времени, то вам нужно добавить фильтр предварительной обработки, чтобы определить, что сканируется с помощью тяжелых вещей. Хороший быстрый, очень реальном времени, фильтр предварительной обработки, который позволит вам сканировать вещи, которые, скорее всего, будут кока-колой, может не выглядеть, чем прежде, чем перейти к более случайным вещам, это примерно так: поиск изображения для самых больших патчей цвета, которые являются определенным допуском от sqrt(pow(red,2) + pow(blue,2) + pow(green,2)) вашей кока-колы. Начните с очень строгой цветоустойчивости и проведите свой путь до более мягких цветовых допусков. Затем, когда ваш робот исчерпал выделенное время для обработки текущего кадра, он использует найденные в настоящее время бутылки для ваших целей. Обратите внимание, что вам нужно будет настроить цвета RGB в sqrt(pow(red,2) + pow(blue,2) + pow(green,2)), чтобы получить их в порядке.

Кроме того, это gona кажется действительно тупым, но вы обязательно включили оптимизацию компилятора -oFast при компиляции кода C?

0
источник

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

1: Первая характеристика - цвет, а красный - очень доминирующий. После обнаружения Coca Cola Red есть несколько объектов, представляющих интерес 1A: Насколько велика эта красная область (достаточно ли количества, чтобы определить истинную возможность или нет - 10 пикселей, вероятно, недостаточно), 1B: содержит ли он цвет ярлыка - "Coca-Cola" или волна. 1B1: достаточно ли рассмотреть высокую вероятность того, что это метка.

Пункт 1 - это вид короткого вырезания - предварительный процесс, если этот сотовый объект существует в изображении - двигайтесь дальше.

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

2: Учитывая указанную выше ID области изображения в 1 - проверьте окружающие точки [края] рассматриваемого предмета. A: Есть ли что-то сверху или снизу - серебро? B: Бутылка может казаться прозрачной, но также может быть стеклянный стол - так есть стеклянный стол/полка или прозрачная область - если так, то есть несколько возможных вариантов. Бутылка MIGHT имеет красную крышку, она может и не быть, но должна иметь либо форму винтов/винтов для бутылок, либо колпачок. C: Даже если это не удается A и B, оно все еще может быть частично. Это более сложно, если это частично, потому что частичная бутылка/частичная может выглядеть одинаково, поэтому некоторая дополнительная обработка измерения края красной области до края. Маленькая бутылка может быть похожа по размеру.

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

0
источник

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

Отношение ограничивающего прямоугольника красной области логотипа к общему размеру бутылки/банки отличается. В случае Can, должно быть 1:1, тогда как будет отличаться от бутылки (с крышкой или без нее). Это должно облегчить различие между ними.

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

0
источник

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

ЗДЕСЬ вы можете воспользоваться некоторыми полезными ссылками, которые помогут вам в обучении.

0
источник

Это старый проект, над которым я работал. Изображения MAP очень просты в использовании с JavaScript. Я предлагаю вам объект, вы читаете его и знаете, как его использовать. Нам не нужны JQuery и другие системы для использования изображений MAP.

    //Copyright Cherif yahiaoui, by ELEBAN.FR

//variables de flottement.
var myInstOne = null;
var globalize = null;

var eleban_preload_images = function (name, imgs, url){
try{
    var oThis = this;
    this.images = new Array();
    this.imageshover = new Array();
    this.imagesNames = new Array(imgs.split(";"));


        for(var i=0; i < this.imagesNames[0].length; i++){
            this.images[i] = new Image();
            this.imageshover[i] = new Image();
        }

    this.url = url;

    this.GetAbsoluteurl = function () {

    var img = new Image(); img.src = url;
    url = img.src; img = null; 
        this.url = url; 

    };

    this.Preload = function () {

        for(var i=0; i < this.imagesNames[0].length; i++){
            this.images[i].src = this.url+("btn-"+this.imagesNames[0][i]+".png");
            this.imageshover[i].src = this.url+("btn-"+this.imagesNames[0][i]+"-hover.png");
        }

    };
    this.GetAbsoluteurl();
    this.Preload();
}
finally {return;}
}

var g_preloaderhover = new eleban_preload_images("loaderhover","menu;malette;reservation;cabine;facebook;map;amis","./images/");


//variable arret flottement
var g_stopflo = false;

var myObjfloater = function(name, idname, itop, differ ) {
var oThis = this; // création d'une référence vers l'objet courant
this.name = name;
this.id =idname;
this.xstep= 0.3;
this.itime = 30;
this.obj = null;
this.y = itop;
this.yadd = 0;
this.up = true;
this.pause = false;
this.differ = differ;
this.coordsimage = null;
this.objimg = null;
this.initimages = false;
this.compteur = 0;
this.over = false;
this.timeoutstop = null;
try{
this.initimage = function(){
var img = this.obj.getElementsByTagName('img')[0];
this.coordsimage = new Array(img.width, img.height);
this.objimg = img;
this.initimages = true;
};


this.myMethod = function() {
if(!g_stopflo){
    if(this.differ != 0){ 
this.differ=this.differ-0.1; 
}else{

if(this.obj){
if(this.over == false){
    this.yadd=this.yadd+0.1; this.itime = this.itime + 10;
this.obj.style.visibility = "hidden";
this.y = ((this.up)? this.y - this.yadd : this.y + this.yadd);
this.obj.style.marginTop = this.y +"%" ;
this.obj.style.visibility = "visible";

if (this.yadd > this.xstep){ 
    this.up = (this.up)? false : true;
    this.yadd = -0.1; this.itime=180;
}
}
}else{
    if (document){
        if(document.getElementById) {
         this.obj = document.getElementById(this.id); 
        //this.y = this.obj.offsetTop;
        }else{
        if(document.getElementByTagName) { this.obj = document.getElementByTagName(this.id); this.y = this.obj.offsetTop;}
        }

    }
}
}
this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}    
};

this.callDelayed = function() {
    // utilisation de la référence vers l'objet
if(!g_stopflo){
    this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}
};
}
finally {return;}
};

// special creation des zones AREA
function eleban_createallarea(){
try{
var measur = new Array("w", "h");
measur["w"] = new Array(330,570,185,300,115,390,225);
measur["h"] = new Array(460,570,295,450,100,190,115);
var ititle = new Array("Voir les menus  et nos suggestions","Repas &agrave; emporter","R&eacute;servation d&rsquo;une table","Nous contacter","Nous rejoindre sur FaceBook","Calculer votre trajet","liste des amis");
var ihref = new Array("menus.html","emporter.html","reservation.html","contact.html","likebox.html","google.html","amis.html");
var b_map = new Array(0,1,2,3,4,5,6);
b_map[0] = "71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38";
b_map[1] = "66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92";
b_map[2] = "19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90";
b_map[3] = "60,0,216,1,226,20,225,403,168,421,42,410,45,10";
b_map[4] = "31,7,72,10,82,18,88,45,88,71,76,81,29,80,17,68,16,18";
b_map[5] = "91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94";
b_map[6] = "6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65";

if (document.getElementById){
for (var i=0; i<b_map.length;i++){
var obj = document.getElementById("pc_menu"+i);
    if(obj){
    var ct = '<img class=\"pc_menu\" src=\"'+g_preloaderhover.images[i].src+'\" alt=\"\" width=\"'+measur["w"][i]+'\" height=\"'+measur["h"][i]+'\" usemap=\"#MAP_INDEX'+i+'\" \/>';
    ct+='<map name=\"MAP_INDEX'+i+'\">';
    ct+='<area shape=\"poly\" coords=\"'+b_map[i]+'\" title=\"'+ititle[i]+'\" href=\"'+ihref[i]+'\" \/>';
    ct+='<\/map>';
    obj.innerHTML = ct;
    }
}
}
}
finally {return;}
}

//preload, creation et gestion de tous les evenements


var image_resizer = function(g_layer){


    b_org_elm = new Array("w",  "h");
    b_org_elm["w"] = new Array(330,570,185,300,115,390,225);
    b_org_elm["h"] = new Array(460,570,295,450,100,190,115);

    b_map = new Array(0,1,2,3,4,5,6);
    b_map[0] = new Array(71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38);
    b_map[1] = new Array(66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92);
    b_map[2] = new Array(19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90);
    b_map[3] = new Array(60,0,216,1,226,20,225,403,168,421,42,410,45,10);
    b_map[4] = new Array(31,6,70,10,78,18,84,23,88,44,88,70,78,80,75,81,33,82,23,76,18,69,16,22,21,13);
    b_map[5] = new Array(91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94);
    b_map[6] = new Array(6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65);


    b_layer = g_layer;

//gere mouseover
    this.mouseover = function(e){
        if (!e) var e = window.event;
        var tg = (window.event) ? e.srcElement : e.target
            if (tg.nodeName){
                if(tg.nodeName == "AREA"){
                var divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
                    if (divpar){
                        if(divpar.nodeName == "DIV"){
                            var iiobjimg = divpar.getElementsByTagName('img');
                                if (iiobjimg){
                                    ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
                                    iiobjimg[0].src = g_preloaderhover.imageshover[ii].src;
                                }
                        }
                    }
                }
            }
    };

//gere mouseout
    this.mouseout = function(e){
        if (!e) var e = window.event;
        tg = (window.event) ? e.srcElement : e.target
            if (tg.nodeName){
                if(tg.nodeName == "AREA"){
                divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
                    if (divpar){
                        if(divpar.nodeName == "DIV"){
                            var iiobjimg = divpar.getElementsByTagName('img');
                                if (iiobjimg){
                                    ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
                                    iiobjimg[0].src = g_preloaderhover.images[ii].src;
                                }
                        }
                    }
                }
            }
    };

//ajout evenements entree sortie à la page web lors du chargement de la page
    this.init = function () {

        for(var i=0; i<b_org_elm["w"].length;i++){
            w = document.getElementById("pc_menu"+i).offsetWidth;
            h = document.getElementById("pc_menu"+i).offsetHeight;

            xa = w/parseFloat(b_org_elm["w"][i]);
            ya = h/parseFloat(b_org_elm["h"][i]);

            area = document.getElementById("pc_menu"+i).getElementsByTagName('area')[0];

            b_map2 = area.coords.split(",");
            yswitch = true;
                for(m=0; m<b_map2.length;m++){
                b_map2[m] = Math.round(parseFloat(b_map[i][m]) * ((yswitch)? xa: ya));
                yswitch = (yswitch)? false :  true;
                }
            area.coords = b_map2.join(',');
        }
    }; 


    this.resize = function () {
    clearTimeout(myInstOne.timeoutstop);
    g_stopflo=true;

    globalize.init();
    g_stopflo=false;
    myInstOne.obj = null;
    myInstOne.callDelayed();
    };


    nar = document.getElementsByTagName('area').length;

        for(var i=0; i<nar;i++){
            var elem = document.getElementsByTagName('area')[i];
            if (elem.addEventListener){
                    elem.addEventListener("onmouseover",this.mouseover,true);
                elem.addEventListener("onmouseout",this.mouseout,true);
            }else if (elem.attachEvent) {
                    elem.attachEvent("onmouseover", this.mouseover);
                    elem.attachEvent("onmouseout", this.mouseout);
            }else{
                    elem["onmouseover"] = this.mouseover;
                    elem["onmouseout"] = this.mouseout;
            }
        }

            window.onresize = this.resize;
        window.onmouseover = this.mouseover;
        window.onmouseout = this.mouseout;
}


//permet de temporiser et éviter les erreurs de chargement des objets
function temporise_Init(Lastdiv){
if(document.getElementById){
    if(document.getElementById(Lastdiv)){

    eleban_createallarea();

    myInstOne = new myObjfloater('b_menumap11', 'pc_menu1', 1, 0);

    globalize = new image_resizer(document.getElementById('pc_redim'));
    globalize.init();
        globalize.resize();



    }else{
    setTimeout(temporise_Init(Lastdiv), 30);
    }
}
}


window.onload = function () {
temporise_Init("pc_bandeau");
}
0
источник

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

-2

Посмотрите другие вопросы по меткам или Задайте вопрос