2015-09-05 2 views
5

Я использую вычитание фона для анализа движущихся объектов наружной сцены. Когда солнце выходит, у меня проблема с тенями. Я использую контуры для изоляции объектов. В настоящий момент я просто анализирую верхнюю половину контура, поскольку тень обычно находится в нижней половине.Минимальное расположение контура контура OpenCV в python

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

enter image description here

В коде, binary является пороговым изображение движущихся объектов, HIGHT и WIDTH являются высота и ширина изображения, lab одно и то же изображение в цветовом пространстве LAB.

Я хотел бы заменить линию half = int(h/2) функцией, чтобы найти положение y горизонтальной линии, чтобы вырезать «утиную шею».

_,contours,_ = cv2.findContours(binary.copy(), cv2.RETR_EXTERNAL, 
          cv2.CHAIN_APPROX_SIMPLE) 

# loop over the contours 
for i, cnt in enumerate(contours): 

    # compute the bounding box for the contour 
    (x, y, w, h) = cv2.boundingRect(cnt) 

    # reject contours outside size range 
    if w > 250 or w < 30 or h > 250 or h < 30 : 
      continue 

    # make sure the box is inside the frame 
    if x <= 0 or y <= 0 or x+w >= (WIDTH -1) or y+h >= (HIGHT -1): 
      continue 

    # isolate feature 
    half = int(h/2) 
    roi = lab[y:y+half, x:x+w] 
    mask = binary[y:y+half, x:x+w] 

    # calculate the mean of the colour 
    mean = cv2.mean(roi, mask = mask) 
    # note: mean is L a b 
    L = int(mean[0]) 
    a = int(mean[1]) 
    b = int(mean[2]) 
    print L,a,b 

Я использую OpenCV 3 и питона 2,7

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

+3

Добавьте к вашему вопросу несколько изображений с реальными и ожидаемыми результатами. Нажмите ссылку редактирования под тегами. У вас недостаточно репутации, чтобы добавить изображение, но вы можете публиковать общедоступную ссылку от imgur или аналогичного – Miki

+0

Привет Мики, я добавил эскиз, который должен помочь прояснить, пожалуйста, не стесняйтесь спрашивать что-нибудь еще. Я подумал о 3 возможных решениях: 1) как-то использовать моменты, 2) перебирать через список контуров, чтобы найти поворотные точки; 3) строчить строки по горизонтали, чтобы получить профиль, а затем найти поворотные точки профиля. Первые два я понятия не имею о том, что некоторая помощь в том, как использовать моменты или как получить доступ и интерпретировать список контуров, будет очень полезной. Или любое другое предложение было бы очень оценено. – Johno

+0

Прошу прощения за то, что вы пытаетесь сделать так, как просили, но, пожалуйста, избегайте Dropbox/других переходных ссылок, если это вообще возможно, - мы хотим, чтобы эти вопросы помогали людям в течение многих лет, и если вы удалите свой файл Dropbox в будущем, это сделает этот вопрос нет ценный. SO У вас есть договоренность с imgur, чтобы убедиться, что все изображения будут в течение всего времени. Я сделал это для вас в этом случае. Надеюсь, ты найдешь свой ответ! – Basic

ответ

0

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

# loop over the contours 
for i, cnt in enumerate(contours): 

    # compute the bounding box for the contour 
    (x, y, w, h) = cv2.boundingRect(cnt) 

    # reject contours outside size range 
    if w > 250 or w < 30 or h > 250 or h < 30 : 
      continue 

    # make sure the box is inside the frame 
    if x <= 0 or y <= 0 or x+w >= (WIDTH -1) or y+h >= (HIGHT -1): 
      continue 

    # --------------- 
    # create a mask for erosion, you can play with the mask size/shape 
    mask = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) 
    # erode the original image 
    eroded_img = cv2.erode(binary,mask,iterations = 1) 
    cv2.imshow("Eroded image",eroded_img) 
    # find the middle of the two new contours 
    _,new_contours,_ = cv2.findContours(eroded_img, cv2.RETR_EXTERNAL, 
         cv2.CHAIN_APPROX_SIMPLE) 
    (_, y_t, _, h_t) = cv2.boundingRect(new_contours[0]) 
    (_, y_b, _, h_b) = cv2.boundingRect(new_contours[1]) 
    bottom_top_y = max(y_t, y_b) # highest y of bottom part 
    top_bottom_y = min(y_t+h_t, y_b+h_b) # lowest y of top part 
    half = top_bottom_y + (bottom_top_y - top_bottom_y)/2 
    # ------------ 

    # isolate feature 
    roi = lab[y:y+half, x:x+w] 
    mask = binary[y:y+half, x:x+w] 

    # calculate the mean of the colour 
    mean = cv2.mean(roi, mask = mask) 
    # note: mean is L a b 
    L = int(mean[0]) 
    a = int(mean[1]) 
    b = int(mean[2]) 
    print L,a,b 

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

+0

Ike, большое спасибо за ваш вклад. Это определенно один из способов сделать это.Я уже использую erode для уменьшения размера маски, так что сами края объекта не включены в мои вычисления распознавания. Возможно, я разойдусь в цикле, пока не будет 2 контура, а затем верните верхний контур обратно к первоначальному размеру. Приветствия :-) – Johno

Смежные вопросы