Python merges rectangular boxes of the same category and intersecting

Python merges intersecting rectangular boxes of the same category

  • Preface
  • Prerequisites
  • Related introduction
  • lab environment
  • Python merges rectangular boxes of the same category and intersecting
    • Code

Foreword

  • Due to my limited level, errors and omissions will inevitably occur. Please criticize and correct me.
  • For more exciting content, you can click to view the Python daily operations column, YOLO series column, natural language processing column or my personal homepage.
  • Face disguise detection based on DETR
  • YOLOv7 trains its own data set (mask detection)
  • YOLOv8 trains its own data set (football detection)
  • YOLOv5: TensorRT accelerates YOLOv5 model inference
  • YOLOv5: IoU, GIoU, DIoU, CIoU, EIoU
  • Playing with Jetson Nano (5): TensorRT accelerates YOLOv5 target detection
  • YOLOv5: Add SE, CBAM, CoordAtt, ECA attention mechanism
  • YOLOv5: Interpretation of yolov5s.yaml configuration file and adding small target detection layer
  • Python converts COCO format instance segmentation data set to YOLO format instance segmentation data set
  • YOLOv5: Use version 7.0 to train your own instance segmentation model (instance segmentation of vehicles, pedestrians, road signs, lane lines, etc.)
  • Use Kaggle GPU resources to experience the Stable Diffusion open source project for free

Prerequisite

  • Familiar with Python

Related introduction

  • Python is a cross-platform computer programming language. It is a high-level scripting language that combines interpretation, compilation, interactivity and object-oriented. It was originally designed for writing automated scripts (shells). As the version is constantly updated and new language features are added, it is increasingly used for the development of independent, large-scale projects.

Experimental environment

  • Python 3.x (object-oriented high-level language)

Python merges intersecting rectangular boxes of the same category

Code implementation

import os
import cv2
import json
from collections import deque
import numpy as np

def xyxy2xywh(rect):
    '''
    (x1,y1,x2,y2) -> (x,y,w,h)
    '''
    return [rect[0],rect[1],rect[2]-rect[0],rect[3]-rect[1]]

def xywh2xyxy(rect):
    '''
    (x,y,w,h) -> (x1,y1,x2,y2)
    '''
    return [rect[0],rect[1],rect[0] + rect[2],rect[1] + rect[3]]


def is_RecA_RecB_interSect(RecA, RecB): # Rec = [xmin,ymin,xmax,ymax]
    # Get [xmin, ymin, xmax, ymax] of the intersection area
    x_A_and_B_min = max(RecA[0], RecB[0])
    y_A_and_B_min = max(RecA[1], RecB[1])
    x_A_and_B_max = min(RecA[2], RecB[2])
    y_A_and_B_max = min(RecA[3], RecB[3])
    # Calculate the area of the intersection. When (xmax - xmin) is negative, it means that the A and B boxes have no intersection and are set to 0 directly. (ymax - ymin)Similarly.
    interArea = max(0, x_A_and_B_max - x_A_and_B_min) * max(0, y_A_and_B_max - y_A_and_B_min)
    return interArea > 0

def merge_RecA_RecB(RecA, RecB): # Rec = [xmin,ymin,xmax,ymax]
    # Get [xmin,ymin,xmax,ymax] of the merged area
    xmin = min(RecA[0], RecB[0])
    ymin = min(RecA[1], RecB[1])
    xmax = max(RecA[2], RecB[2])
    ymax = max(RecA[3], RecB[3])
    return [xmin,ymin, xmax,ymax]

'''
Recursion is a way for a procedure or function to call itself directly or indirectly in its definition or specification.
It usually transforms a large and complex problem into a smaller problem similar to the original problem to solve.
Therefore, the most important thing in the recursive process is to see whether the original problem can be decomposed into smaller sub-problems. This is the key to using recursion.


    Termination condition: The number of rectangular boxes is 1 or empty.
    Return value: The newly merged rectangular box
    Tasks at this level: What you need to do at each level is to traverse the subsequent rectangles starting from it and look for rectangles that can be merged with it.

'''
def merge_rect(box,labels):
    '''
    Merge overlapping boxes

    Input parameters: box :[[xmin,ymin,xmax,ymax],...]
            labels :['0', '0', '1', '1', '1', '2', '2', '2' ]

    return:
        Merged box:[[xmin,ymin,xmax,ymax],...]
        Merged labels:['0', '1', '2']
    '''
    if len(box) == 1 or len(box) == 0 : # The number of rectangular boxes is 1 or empty
        return box,labels

    for i in range(len(box)):
        RecA_xyxy = box[i]
        labelA = labels[i]
        for j in range(i + 1, len(box)):
            RecB_xyxy = box[j]
            labelB = labels[i]
            if is_RecA_RecB_interSect(RecA_xyxy, RecB_xyxy) and labelA==labelB:
                rect_xyxy = merge_RecA_RecB(RecA_xyxy, RecB_xyxy)
                # Use remove(elem) to remove elements
                box.remove(RecA_xyxy)
                box.remove(RecB_xyxy)
                box.append(rect_xyxy)
                labels.pop(i)
                labels.pop(j-1)
                labels.append(labelA)
                merge_rect(box,labels)
                # Return to the previous loop to avoid repeated processing of merged rectangles
                return box,labels
    return box,labels

        

if __name__ == "__main__":
    color = {<!-- -->
        '0' : (255,0,0),
        '1' : (0,255,0),
        '2' : (0,0,255),
    }

    box = [[71, 32, 81, 109], [70, 80, 81, 111], [77, 221, 86, 240], [76, 220, 87, 258],
           [76, 240, 87, 258], [150, 379, 160, 400], [151, 380, 160, 418], [151, 400, 160, 416]]
    labels = ['0', '0', '1', '1', '1', '2', '2', '2' ]
    print(labels,box,sep='\\
')


    img = cv2.imread('res.png')
    for (xmin,ymin,xmax,ymax),label in zip(box,labels):
        img = cv2.rectangle(img, (xmin,ymin), (xmax,ymax), color[label], 1)
    cv2.imwrite('origin.jpg', img)


    merged_box,merged_labels = merge_rect(box,labels)
    print(merged_labels,merged_box,sep='\\
')

    merged_img = cv2.imread('res.png')
    for (xmin,ymin,xmax,ymax),label in zip(merged_box,merged_labels):
        merged_img = cv2.rectangle(merged_img, (xmin,ymin), (xmax,ymax), color[label], 1)
    cv2.imwrite('merged.jpg', merged_img)

  • Due to my limited level, errors and omissions will inevitably occur. Please criticize and correct me.
  • For more exciting content, you can click to view the Python daily operations column, YOLO series column, natural language processing column or my personal homepage.
  • Face disguise detection based on DETR
  • YOLOv7 trains its own data set (mask detection)
  • YOLOv8 trains its own data set (football detection)
  • YOLOv5: TensorRT accelerates YOLOv5 model inference
  • YOLOv5: IoU, GIoU, DIoU, CIoU, EIoU
  • Playing with Jetson Nano (5): TensorRT accelerates YOLOv5 target detection
  • YOLOv5: Add SE, CBAM, CoordAtt, ECA attention mechanism
  • YOLOv5: Interpretation of yolov5s.yaml configuration file and adding small target detection layer
  • Python converts COCO format instance segmentation data set to YOLO format instance segmentation data set
  • YOLOv5: Use version 7.0 to train your own instance segmentation model (instance segmentation of vehicles, pedestrians, road signs, lane lines, etc.)
  • Use Kaggle GPU resources to experience the Stable Diffusion open source project for free