检查一个对象的边界框是否在另一个对象的边界框内

Check to see if a bounding box of an object is inside the bounding box of another object

我有一段视频,人们在不同的房子里走来走去。我在不同的房屋周围创建了一个固定的边界框,并实施了一个跟踪器来跟踪人们的移动。我现在想检查任何人的边界框是否在任何房屋的边界框内。

因为这是一个视频,检查 TrueFalse - 即一个人是否在边界框内会不断随着人们四处走动而改变。例如,我包含了视频 起始帧的图片 。如您所见,Person 0 根本不在任何房屋的边界框内。但是,无论如何它都会打印 True。另外,我还想说的是,我检查了该平台上的多个其他来源和帖子以寻求一些指导,但我找不到任何可以帮助我解决问题的东西。

我得到的输出:

Person 0 : True
Person 1 : True
Person 2 : True
Person 0 : True
Person 1 : True
...

预期输出如下(预期输出的前 3 行对应于下图):

Person 0: False
Person 1: True
Person 2: True
Person 0: False
Person 1: True
...

这是我到目前为止所做的:

# boxes_houses = [(#, #, #, #), (#, #, #, #), ...]

while cap.isOpened():
    success, frame = cap.read()
    if not success:
        break

    # get updated location of objects in subsequent frames
    success, boxes_person = multiTracker.update(frame)
    # boxes_persons = [(#, #, #, #), (#, #, #, #), ...]

    cnt_person = 0
    cnt_house = 0

    for box_person, box_house in zip(boxes_persons, boxes_houses):
        x_p1 = int(box_person[0])
        y_p1 = int(box_person[1])
        x_p2 = int(box_person[2])
        y_p2 = int(box_person[3])
        person_coords = {'x1': x_p1, 'y1': y_p1, 'x2': x_p2, 'y2': y_p2}
        cv2.rectangle(frame, (x_p1, y_p1), (x_p1 + x_p2, y_p1 + y_p2), (0, 0, 0), 2, 1)
        cv2.putText(frame, "House: {}".format(cnt_house), (x1, y1 - 10), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 0, 0), 1)

        x_h1 = int(box_house[0])
        y_h1 = int(box_house[1])
        x_h2 = int(box_house[2])
        y_h2 = int(box_house[3])
        cv2.rectangle(frame, (x_h1 , y_h1), (x_h1 + x_h2, y_h1+ y_h2), (0, 0, 255), 2, 1)
        cv2.putText(frame, "Person: {}".format(cnt_person ), (int(box_house[0]), int(box_house[1] - 5)), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 0, 255), 1)

        ## CHECK TO SEE IF BBOX OF PERSONS ARE INSIDE BBOX OF HOMES ##

        house1 = {'x1': #, 'y1': #, 'x2': #, 'y2': #}
        house2 = {'x1': #, 'y1': #, 'x2': #, 'y2': #}
        house3 = {'x1': #, 'y1': #, 'x2': #, 'y2': #}

        if (person_coords['x1'] < house1['x1'] and person_coords['y1'] < house1['y1'] or person_coords['x2'] < house1['x2'] and person_coords['y2'] < house1['y2']) or (person_coords['x1'] < house2['x1'] and person_coords['y1'] < house2['y1'] or person_coords['x2'] < house2['x2'] and person_coords['y2'] < house2['y2']) or (person_coords['x1'] < house3['x1'] and person_coords['y1'] < house3['y1'] or person_coords['x2'] < house3['x2'] and person_coords['y2'] < house3['y2']):
            print ("Person", num_person, ": True\n")
        
        else:
            print ("Person", num_person, ": False\n")
        
        cnt_house+= 1
        cnt_person+= 1

    # show frame
    cv2.imshow('MultiTracker', frame)

    # quit on ESC button
    if cv2.waitKey(1) & 0xFF == 27:  # Esc pressed
        break

如有任何帮助,我们将不胜感激!

我认为问题来自位置检查(这很难阅读,因为它都在 if 语句中的一行上)。

让我们首先定义一个函数来检查一个人是否在给定的房子里:

def isInside(person, house):
  """
    person is the dict with x1, y1, x2 and y2 for that person
    house is the dict with x1, y1, x2 and y2 for that person
  """
  
  # First we make sure we compare things in the right order
  # You can skip that part if you are sure that in all cases x1 < x2 and y1 < y2
  p_xmin = min(person["x1"], person["x2"])
  p_xmax = max(person["x1"], person["x2"])
  p_ymin = min(person["y1"], person["y2"])
  p_ymax = max(person["y1"], person["y2"])
  
  h_xmin = min(house["x1"], house["x2"])
  h_xmax = max(house["x1"], house["x2"])
  h_ymin = min(house["y1"], house["y2"])
  h_ymax = max(house["y1"], house["y2"])
  
  # Then you perform your checks. From what I understood,
  # you want the result to be true if any corner of the person
  # is inside the house's bounding box.
  
  p_corners = [
    (p_xmin, p_ymin),
    (p_xmin, p_ymax),
    (p_xmax, p_ymin),
    (p_xmax, p_ymax)]

  for corner in p_corners:
    in_range_along_x = corner[0] < h_xmax and corner[0] > h_xmin
    in_range_alond_y = corner[1] < h_ymax and corner[1] > h_ymin
    if in_range_along_x and in_range_along_y:
      return True
  
  # If we get there, then the person is not inside that house
  return False

您还可以修改上面的函数以使用人的边界框的中心而不是角,或者检查所有角是否都在里面。这是作为奖励的中心版本:

def centerIsInside(person, house):
  """
    person is the dict with x1, y1, x2 and y2 for that person
    house is the dict with x1, y1, x2 and y2 for that person
  """
  
  # First we make sure we compare things in the right order
  # You can skip that part if you are sure that in all cases x1 < x2 and y1 < y2

  h_xmin = min(house["x1"], house["x2"])
  h_xmax = max(house["x1"], house["x2"])
  h_ymin = min(house["y1"], house["y2"])
  h_ymax = max(house["y1"], house["y2"])

  # We compute the center of the person:

  p_xcenter = (person["x1"]+person["x2"])/2
  p_ycenter = (person["y1"]+person["y2"])/2

  # Then you perform your checks.

  in_range_along_x = p_xcenter < h_xmax and corner[0] > p_xcenter
  in_range_alond_y = p_ycenter < h_ymax and corner[1] > p_ycenter
  if in_range_along_x and in_range_along_y:
    return True
  else:
    return False

然后您可以使用该函数来执行检查,而不是那个长 if 语句:

# [...]

houses = [house1, house2, house3]
isinside_checks = []
for house in houses:
  isinside_checks.append(isInside(person_coords, house))
if any(inside_checks):
  print ("Person", num_person, ": True\n")
else:
  print ("Person", num_person, ": False\n")

# [...]

您还可以修改 isInside 函数,使其根据参数执行不同类型的检查(任何角、中心、所有角...)