Цель
На этот раз мы изучаем иерархию контуров, то есть отношения родитель-потомок в контурах.
теория
В предыдущих статьях о контурах мы обсуждали несколько функций, связанных с контурами, предоставляемыми OpenCV. но когда мы используемcv.findcontourКогда функция () находит контуры на изображении, мы передали параметр,Режим поиска по контуру. мы обычно проходимcv.RETR_LISTилиcv.RETR_TREE,хорошие результаты. Но что конкретно это означает?
Так же на выходе получаем три массива, первый это изображение, второй контур и еще один мы назвалиhierarchyвывод (проверьте код в предыдущем посте). Но мы никогда и нигде не использовали эту иерархию. Так что же это за иерархия, для чего она используется и как она связана с вышеупомянутыми параметрами функции?
Это то, что мы собираемся обсудить в этой статье.
Что такое иерархия?
Обычно мы используемcv.findcontour() для обнаружения объектов на изображении, верно? Иногда объекты находятся в разных местах. Но в некоторых случаях одни фигуры находятся внутри других фигур. Так же, как вложенные графы. В этом случае мы называем внешнийотец, вызовите внутреннийПодкласс. Таким образом, контуры на изображении находятся в определенной взаимосвязи друг с другом. Мы можем указать, как контур связан друг с другом, например, является ли он дочерним контуром другого контура или родительским контуром и т. д. Представление этого отношения называетсяИерархия.
Ниже приведен пример:
На этом изображении есть несколько фигур, которые я взял из0-5Начать нумерацию.2и2aПредставляет внешний и внутренний контуры самой внешней коробки.
Здесь контуры 0,1,2 находятся навнешний или крайний. Мы можем сказать, что ониУровень-0, или проще говоря, они находятся втот же уровеньсередина.
С последующимcontour-2a. это можно рассматривать какДети контура-2(или наоборот, контур-2 является родителем контура-2а). предположим, что это в1-го уровнясередина. Точно так же контур-3 является потомком контура-2, который находится в следующей иерархии. Наконец, контуры 4,5 являются потомками контура-3а, они находятся на последнем уровне. Судя по нумерации коробок, я думаю, что контур-4 является первым потомком контура-3а (он также может быть контуром-5).
Я упоминаю их, чтобы понять некоторые термины, такие кактот же уровень,Внешний профиль,подконтур,родительский профиль,первый подконтури Т. Д. Теперь давайте перейдем к OpenCV.
Иерархическое представление в OpenCV
Таким образом, каждый профиль имеет свою собственную информацию о том, какой он уровень, кто его дочерний элемент, кто его родитель и т. д. OpenCV представляет его как массив с четырьмя значениями:[Next, Previous, First_Child, Parent]
«Следующий представляет собой следующий контур на том же уровне».
Например, возьмем контур-0 на нашем изображении. Кто следующий контур на том же уровне?Это контур-1. просто сделатьNext = 1
. Точно так же Контур-1 также является Контуром-2. такNext = 2
. А как насчет контура-2?Нет следующей линии контура на той же горизонтальной линии. просто, пустьNext = -1
. А контур-4 находится на том же уровне, что и контур-5. Следующим его контуром является контур-5, поэтомуnext = 5
.
«Предыдущий представляет предыдущие контуры на том же уровне».
то же, что и выше. Контур перед контуром-1 является контуром-0 на том же уровне. Точно так же контур-2 также является контуром-1. Для контура-0 предшествующего элемента нет, поэтому он равен -1.
«First_Child представляет его первый дочерний контур».
Никаких объяснений не требуется. Для контура-2 дочерним элементом является контур-2а. Таким образом, получается значение индекса, соответствующее контуру-2а. А контур-3а у него двое детей. Но мы ориентируемся только на первого ребенка. Это контур-4. ТакFirst_Child = 4
Для контура-3а.
«Родитель представляет индекс своего родительского контура».
это сFirst_ChildНапротив. Для контура-4 и контура-5 родительским контуром является контур-3а. Для контура 3а это контур-3 и так далее.
Уведомление
Если дочерних или родительских элементов нет, поле обрабатывается как -1.
Теперь, когда мы понимаем иерархические стили, используемые в OpenCV, мы можем проверить режим поиска контуров в OpenCV с помощью того же изображения, что и выше. некоторые признаки, какcv.RETR_LIST, cv.RETR_TREE,cv.RETR_CCOMP, cv.RETR_EXTERNALСмысл ожидания.
Режим поиска по контуру
1. RETR_LIST
Это самый простой из четырех флагов (с точки зрения интерпретации). Он просто извлекает все контуры, но не создает никаких отношений родитель-потомок. Согласно этому правилу,Родительский контур и дочерний контур равны, это просто контуры. Все они принадлежат к одному уровню.
Здесь 3-й и 4-й элементы всегда равны -1. Но очевидно, что следующий элемент и предыдущий элемент имеют соответствующие значения. Просто проверьте это сами.
Ниже представлен результат, который у меня получился, каждая строка — это уровень детализации соответствующего контура. Например, первая строка соответствует контуру 0. Следующий контур - контур 1. такNext = 1
. Предыдущего контура нет, поэтомуPrevious=-1
. Остальные два, как уже упоминалось,-1
.
>>> hierarchy
array([[[ 1, -1, -1, -1],
[ 2, 0, -1, -1],
[ 3, 1, -1, -1],
[ 4, 2, -1, -1],
[ 5, 3, -1, -1],
[ 6, 4, -1, -1],
[ 7, 5, -1, -1],
[-1, 6, -1, -1]]])
Это лучший вариант для использования в вашем коде, если вы не используете какие-либо функции иерархии.
2. RETR_EXTERNAL
Если этот флаг используется, он возвращает только крайний внешний флаг. Все детские силуэты остались позади.Можно сказать, что по этому правилу внимание получает только старший сын в каждой семье. На остальных членов семьи плевать :).
Итак, на нашем изображении сколько крайних внешних контуров?На уровне 0?Их 3,т.е. контур 0 1 2, верно?Теперь попробуем найти контур с этим флажком. Здесь присвойте каждому элементу то же значение, что и выше. и сравнить с приведенными выше результатами. Вот что я получаю:
>>> hierarchy
array([[[ 1, -1, -1, -1],
[ 2, 0, -1, -1],
[-1, 1, -1, -1]]])
Вы можете использовать этот флаг, если хотите извлечь только внешние контуры. Это может быть полезно в некоторых ситуациях.
3. RETR_CCOMP
Этот флаг извлекает все контуры и упорядочивает их в двухуровневую иерархию. Внешний контур объекта (т.е. граница объекта) помещается в иерархию-1. Контур отверстия внутри объекта (если есть) помещается в иерархию-2. Если в нем есть какой-либо объект, его контур перемещается только в иерархии 1. и его уязвимости на уровне 2 и так далее.
Просто рассмотрите изображение «белого нуля» на черном фоне. Внешний круг нуля принадлежит первому уровню, а внутренний круг нуля принадлежит второму уровню.
Мы можем объяснить это с помощью простого изображения. Здесь я отметил порядок контуров и слоев, которым они принадлежат, красным и зеленым (1 или 2) в том же порядке, в котором OpenCV определяет контуры.
Рассмотрим первый контур, который является контуром-0. Это иерархия-1. Он имеет два отверстия, Контуры 1 и 2, которые относятся ко второму уровню. Таким образом, для контура-0 следующим контуром на том же уровне будет контур-3. Как и предыдущие. В иерархии-2 его первым дочерним элементом является контур-1. У него нет родительского класса, потому что он находится в иерархии-1. Таким образом, его иерархический массив[3,-1,1,-1]
Теперь контур-1. Он находится на уровне 2. Следующим в той же иерархии (под родителем контура-1) является контур-2. Предыдущего нет. нетchild
,ноparent
контур-0. Итак, массив[2,-1,-1,0]
Аналогичный контур-2: находится в иерархии-2. При контуре-0 в той же иерархии нет следующего контура. тогда нетNext
.previous
контур-1. нетchild
,parent
контур0. Итак, массив[-1,1,-1,0]
контур-3: рядом с уровнем-1 находится контур-5. Раньше это был контур-0.child
контур4, нетparent
. Итак, массив[5,0,4,-1]
контур-4: он находится в иерархии 2 под контуром-3, у него нет братьев и сестер. нетnext
,нетprevious
,нетchild
,parent
контур-3. Итак, массив[-1,-1,-1,3]
Вы можете добавить остальные. Вот окончательный ответ, который я получил:
>>> hierarchy
array([[[ 3, -1, 1, -1],
[ 2, -1, -1, 0],
[-1, 1, -1, 0],
[ 5, 0, 4, -1],
[-1, -1, -1, 3],
[ 7, 3, 6, -1],
[-1, -1, -1, 5],
[ 8, 5, -1, -1],
[-1, 7, -1, -1]]])
4. RETR_TREE
Это последний парень, мистер Перфект. Он извлекает все контуры и создает полный список семейной иерархии.Он даже рассказывает, кто дедушка, отец, сын, внук и многое другое... :).
Например, я взял картинку выше и переписал код для cv. RETR_TREE, переупорядочить контуры и проанализировать их в соответствии с результатами, предоставленными OpenCV. Опять же, красные буквы обозначают количество контуров, а зеленые — порядок иерархии.
Выбиратьcontour-0
: это вhierarchy-0
середина. той же иерархииnext
Контур - контур-7. нетprevious
Контур.child
контур-1, нетparent
. Итак, массив[7,-1,1,-1]
отcontour-2
Например: это вhierarchy-1
середина. Ни один из контуров не находится на одном уровне. нетprevious
.child
даcontour-3
. родителиcontour-1
. Итак, массив[-1,-1,3,1]
В остальном попробуйте сами. Вот полный ответ:
>>> hierarchy
array([[[ 7, -1, 1, -1],
[-1, -1, 2, 0],
[-1, -1, 3, 1],
[-1, -1, 4, 2],
[-1, -1, 5, 3],
[ 6, -1, -1, 4],
[-1, 5, -1, 4],
[ 8, 0, -1, -1],
[-1, 7, -1, -1]]])
Сводная станция блога о технологиях искусственного интеллекта Panchuang: http://docs.panchuang.net/PyTorch, официальная учебная станция на китайском языке: http://pytorch.panchuang.net/OpenCV, официальный китайский документ: http://woshicver.com/