Python OpenCV crops the image and modifies the corresponding Labelme annotation file

Python OpenCV crops the image and modifies the corresponding Labelme annotation file

  • Preface
  • Prerequisites
  • Related introduction
  • lab environment
  • Crop the image and modify the corresponding Labelme annotation file
    • 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 enter the Python Daily Operation Column, OpenCV-Python Small Application Column, YOLO Series Column, Natural Language Processing Column or my personal homepage to view
  • 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.
  • OpenCV is a cross-platform computer vision and machine learning software library released under the Apache2.0 license (open source) and can run on Linux, Windows, Android and Mac OS operating systems. It is lightweight and efficient – it consists of a series of C functions and a small number of C++ classes. It also provides interfaces in Python, Ruby, MATLAB and other languages, and implements many common algorithms in image processing and computer vision.
  • OpenCV is written in C++ language. It has C++, Python, Java and MATLAB interfaces and supports Windows, Linux, Android and Mac OS. OpenCV is mainly geared towards real-time vision applications and takes advantage of MMX and SSE instructions when available.

Experimental environment

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

Crop the image and modify the corresponding Labelme annotation file

  • Background: In some scenarios, the annotated image data obtained has a black border. The purpose of this article is to remove the black border from the image data and remove it. strong>Synchronically modify the Labelme annotation file corresponding to the labeled image data to facilitate subsequent use.
  • Project structure
    This is a quote


Code implementation

import os
import cv2
import json
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 xyxy2xminyminxmaxymax(rect):
    xmin = min(rect[0],rect[2])
    ymin = min(rect[1],rect[3])
    xmax = max(rect[0],rect[2])
    ymax = max(rect[1],rect[3])
    return [xmin,ymin,xmax,ymax]

def alter_json(img_name,in_json_path,out_json_path,crop_x,crop_y,crop_height,crop_width,pad):
    '''
    in_json_path: json file input path
    out_json_path: json file saving path
    crop_x: x of crop matrix coordinates
    crop_y: y of crop matrix coordinates
    crop_height: Height after cropping
    crop_width: width after cropping
    pad: picture padding number
    '''
    file_in = open(in_json_path, "r", encoding='utf-8')
    # json.load data to variable json_data
    json_data = json.load(file_in)
    # Modify the content in json
    json_data["imageHeight"] = crop_height
    json_data["imageWidth"] = crop_width + 2*pad
    json_data["imagePath"] = img_name
    json_data["imageData"] = None
    # Read [[x1,y1],[x2,y2]] of original jsons
    for LabelBox in json_data['shapes']:
        points = LabelBox['points']
        points[0][0] = points[0][0] - crop_x + pad
        points[0][1] =points[0][1] - crop_y
        points[1][0] = points[1][0] - crop_x + pad
        points[1][1] = points[1][1] - crop_y
    file_in.close()

    #Create a write file
    file_out = open(out_json_path, "w", encoding='utf-8')
    #Write the modified data to the file
    file_out.write(json.dumps(json_data))
    file_out.close()

#Image display function
def show(name, img):
    cv2.namedWindow(name, 0) # Used to create a window with the specified name, 0 means CV_WINDOW_NORMAL
    # cv2.resizeWindow(name, img.shape[1], img.shape[0]); # Set the width and height to 640*480
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

def crop_largest_img(image):
    '''
    parameter:
        image is an array of color images.
    '''
    #Convert to grayscale image
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Binarization
    _, binary = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY)
    # show('binary',binary)

    # Find contours
    contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
    '''
    retval = cv2.boundingRect( cnt )

    parameter:
        cnt is a grayscale image or contour.
    return value:
        retval represents the coordinate value of the upper left corner vertex of the returned rectangular boundary and the width and height of the rectangular boundary, that is, x, y, w, h
    '''
    for cnt in contours:
        x,y,w,h = cv2.boundingRect(cnt) # Get the contour vertices and side lengths
        if w*h<600*600: # Filter out rectangular boxes smaller than 600*600
            continue
        # print(x,y,w,h) # 570 126 1039 728 Upper left corner x Upper left corner y Frame width Frame height
        # cv2.rectangle(image,(x,y),(x + w,y + h),(255,0,0),10) # xmin, ymin, xmax, ymax
    # show('image',image)
    return x,y,w,h


if __name__=="__main__":
    #The folder where the output image is located
    out_imgs_dir = 'out_images/'
    # Output the folder where jsons is located
    out_jsons_dir = 'out_jsons/'
    if not os.path.exists(out_imgs_dir):
        os.mkdir(out_imgs_dir)
    if not os.path.exists(out_jsons_dir):
        os.mkdir(out_jsons_dir)

    # Enter the folder where the image is located
    in_imgs_dir = 'images/'
    # Enter the folder where jsons is located
    in_jsons_dir = 'jsons/'
    # Enter a list of image names
    file_name_list = os.listdir(in_imgs_dir)
    img_name_list = [i for i in file_name_list if i.endswith('.png')]
    # Enter the jsons file name list
    file_name_list = os.listdir(in_jsons_dir)
    json_name_list = [i for i in file_name_list if i.endswith('.json')]
    # print(img_name_list,json_name_list)

    # Define the number of left and right padding for cropped images
    pad = 0

    for img_name,json_name in zip(img_name_list,json_name_list):
        in_img_path = os.path.join(in_imgs_dir,img_name)
        out_img_path = os.path.join(out_imgs_dir,img_name)
        in_json_path = os.path.join(in_jsons_dir,json_name)
        out_jsons_path = os.path.join(out_jsons_dir,json_name)
        # print(in_img_path,in_json_path)
        # Read pictures
        image = cv2.imread(in_img_path)
        # Get the maximum clipping rectangle coordinates (x, y, w, h)
        x,y,w,h = crop_largest_img(image)
        # print(x,y,w,h)
        # Read and modify json files
        alter_json(img_name,in_json_path,out_jsons_path,x,y,h,w,pad=pad)
        # Save cropped image
        crop_img = image[y:y + h,x-pad:x + w + pad] # h,w

        cv2.imwrite(out_img_path,crop_img)




  • Due to my limited level, errors and omissions are inevitable. Please criticize and correct me.
  • For more exciting content, you can click to enter the Python Daily Operation Column, OpenCV-Python Small Application Column, YOLO Series Column, Natural Language Processing Column or my personal homepage to view
  • 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, and ECA attention mechanisms
  • 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