Что означает результат «список (контур)»? - PullRequest
3 голосов
/ 30 января 2012

Я просто пытался понять, что означает контур и какие значения хранятся, когда мы создаем контур с помощью функции cv.FindContours в OpenCV (я использую OpenCV 2.3.1 и Python).Я использовал следующее простое изображение для теста:

enter image description here

После нахождения контура я применил следующие команды в ipython:

In [8]: contour
Out[8]: <cv2.cv.cvseq at 0x90a31a0>

In [10]: list(contour)
Out[10]: 
 [(256, 190),
  (255, 191),
  (112, 191),
  (255, 191),
  (256, 190),
  (257, 191),
  (257, 190)]

Первая команда говорит, что контур являетсяОбъект cvSeq.

Я отметил эти точки на изображении, которые дают мне следующее изображение (отмеченные красным кружком точки):

enter image description here

Я непонять, что это значит.

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


РЕДАКТИРОВАТЬ : Ниже приведен код, который я использовал.

import cv
img = cv.LoadImage('simple.jpeg')
imgg = cv.LoadImage('simple.jpeg',cv.CV_LOAD_IMAGE_GRAYSCALE)
storage = cv.CreateMemStorage(0)
contours = cv.FindContours(imgg,storage,cv.CV_RETR_TREE,cv.CV_CHAIN_APPROX_SIMPLE,(0,0))
print list(contours)
for i in list(contours):
    cv.Circle(img,i,5,(0,0,255),1)
cv.ShowImage('img',img)
cv.WaitKey(0)

Ответы [ 2 ]

3 голосов
/ 30 января 2012

Я выполнил еще несколько работ по выводу list(contour), чтобы получить представление о контуре на основе ответа, предоставленного выше математическим файлом.

1) Я сделал ошибку на моем тестовом изображении. Я думал, что это было двоичное изображение, в то время как на самом деле это было изображение в градациях серого с некоторыми другими цветами. (Спасибо математическому кофе) Поэтому я изменил изображение на чисто черно-белое изображение, чтобы получить только один контур и снова протестировать. На этот раз list(contour) дал результат 4 значений, которые при рисовании на изображении были четырьмя углами этого поля.

New output of image in question

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

2) Чтобы проверить снова, я взял другое изображение, которое имеет Т-образную форму.

test-image-2

Для этого я ожидаю список из 8 значений, которые являются 8 углами T.

Output of image 2

`list (contour) 'печатает следующий список, который содержит 10 значений. (2 дополнительных значения могут быть из-за ошибок в моем рисунке)

[(92, 58), (92, 108), (174, 108), (175, 109), (175, 239), (225, 239), (225, 109), (226, 108), (285, 108), (285, 58)]

Это означает, что cv.FindContours создает объект cvseq. Внутри него хранятся значения, как я предполагал выше.

3) Приведенные выше примеры находят только один контур. В каком состоянии будут обнаружены несколько контуров? Я не совсем понимал концепцию множественных связанных последовательностей , как объяснил математический. Чтобы проверить это, я взял третье изображение.

test image 3

Теперь cv.FindContours находит три контура. Помните, что каждый контур представляет собой список из 4 углов коробок. Эти три списка хранятся в одном объекте cvseq, и указатель указывает только на первый контур, т. Е. На список вершин только первого блока. Таким образом, с помощью приведенного выше кода, углы только одного прямоугольника.

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

Итак, я добавил простой цикл while:

while contours:
   print list(contours)
   for i in list(contours):
       cv.Circle(img,i,5,(0,0,255),3)
   contours = contours.h_next()

И я получил три списка, соответствующих углам трех ящиков:

[(196, 237), (196, 279), (357, 279), (357, 237)]
[(141, 136), (141, 201), (346, 201), (346, 136)]
[(33, 39), (33, 92), (206, 92), (206, 39)]

И выводимое изображение:

Output of image 3

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

Ну, теперь все просто. Я не мог понять контурные значения. Вот почему все это безобразие. Спасибо.

ОБНОВЛЕНИЕ - 1:

Более подробную информацию о контуре в новом cv2 модуле можно найти здесь: Контуры -1: Начало работы

ОБНОВЛЕНИЕ - 2:

Все эти объяснения верны в отношении cv2.CHAIN_APPROX_SIMPLE. Но если вместо этого мы используем cv2.CHAIN_APPROX_NONE, мы получим все точки на контуре. Это подробно объясняется примерами в этой статье: Контуры - 5: Иерархия

3 голосов
/ 30 января 2012

Хорошо, я посмотрел на вашу фотографию, и вы получаете вершины каждой области. Мне потребовалось некоторое время, чтобы потренироваться, потому что я использую интерфейс cv2, а не cv.

Несколько вещей:

  • ваше входное изображение simple.jpeg содержит несколько значений оттенков серого, кроме 0 и 255, скорее всего из-за сжатия jpeg.
  • следовательно, вы получаете несколько областей из вашего FindContours для различных уровней серого.
  • cv.FindContours возвращает несколько связанных последовательностей , и вам нужно пройти через них , чтобы получить все эконтур.
  • Контур, который вы получаете для вашего примера, является одним из граничных.

Для демонстрации давайте нарисуем все контуры.

contours = cv.FindContours(imgg,storage,cv.CV_RETR_TREE,cv.CV_CHAIN_APPROX_SIMPLE,(0,0))
colours = [ (0,255,0,0),   # green
            (255,0,0,0),   # blue
            (255,255,0,0), # cyan
            (0,255,255,0), # yellow
            (255,0,255,0), # magenta
            (0,0,255,0)]   # red 
i=0
while contours:
    cv.DrawContours(img, contours, colours[i], colours[i], 0, thickness=-1)
    i = (i+1) % len(colours)
    contours = contours.h_next() # go to next contour
cv.ShowImage('img',img)
cv.WaitKey(0)

contours drawn

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

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

Извлеченные уроки:

  • cv.FindContours действительно дает "вершины" каждого контура
  • вам нужно contours = contours.h_next() для перебора каждого контура
  • если вы сохраняете в формате JPEG, ожидайте артефактов! Вместо этого используйте TIFF / PNG / что-то без потерь!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...