Python OpenCV image cropping tool

Project introduction

In image processing, sometimes pictures need to be cropped for better display or analysis. Python’s OpenCV library provides many image processing functions, including image cropping. This article will introduce how to use Python and OpenCV to implement a simple image cropping tool.

Program writing steps:
  1. Import necessary libraries
    In this program we need to use OpenCV and os libraries. OpenCV is a widely used computer vision library for image and video processing. The os library provides functions to access operating system functions.
    import cv2
    import os
  2. Set input and output folder paths
    In this program, we need to specify the path to the input and output folders. The input folder should contain the images that need to be cropped, and the output folder should be used to save the cropped images.
    input_folder = ""
    output_folder = ""
    
  3. Get all image files that need to be cropped
    Use the listdir function in the os library to obtain all image files in the input folder. Here we only consider files in jpg and png format.
    image_files = [f for f in os.listdir(input_folder) if f.endswith('.jpg') or f.endswith('.png')]
    
  4. Load the first image and create a copy
    In order to facilitate users to crop pictures, we need to display the first picture in the window and crop it based on this. Here we use OpenCV’s imread function to read the first image and create a copy.
    first_image_path = os.path.join(input_folder, image_files[0])
    first_image = cv2.imread(first_image_path)
    image_display = first_image.copy()
  5. Create a window and bind a callback function
    Use OpenCV’s namedWindow function to create a window named “image”, and use the setMouseCallback function to bind the callback function draw_rectangle to this window.
    cv2.namedWindow('image')
    cv2.setMouseCallback('image', draw_rectangle)
    
  6. Define callback function
    The callback function draw_rectangle is used to draw a rectangular frame in the window so that the user can select the area that needs to be cropped. When the left mouse button is pressed, the initial coordinates are recorded and the rectangular frame is drawn. When the left mouse button is released, the rectangular frame is drawn and the end point coordinates are recorded.
    def draw_rectangle(event, x, y, flags, param):
        global x_init, y_init, drawing, top_left_pt, bottom_right_pt, first_image
    
        if event == cv2.EVENT_LBUTTONDOWN:
            drawing=True
            x_init, y_init = x, y
    
        elif event == cv2.EVENT_LBUTTONUP:
            drawing=False
            top_left_pt = (min(x_init, x), min(y_init, y))
            bottom_right_pt = (max(x_init, x), max(y_init, y))
            hex_color = '#FFFFCC'
            rgb_color = tuple(int(hex_color[i:i + 2], 16) for i in (1, 3, 5))
            cv2.rectangle(first_image, top_left_pt, bottom_right_pt, rgb_color, 2)
    
        cv2.imshow('image', first_image)
    
  7. Display the first image and wait for the user to draw the cropping box
    Use the imshow function to display the first image and wait for the user to draw the cropping box. When the user presses the ‘c’ key, the program jumps out of the loop and starts cropping; when the user presses the ‘r’ key, the cropping frame is reset; when the user presses the ‘esc’ key, the program exits program.
    cv2.imshow('image', image_display)
    while True:
        key = cv2.waitKey(1) & 0xFF
    
        if key == ord('r'):
            first_image = cv2.imread(first_image_path)
            top_left_pt = (-1, -1)
            bottom_right_pt = (-1, -1)
    
        elif key == ord('c') and top_left_pt != (-1, -1) and bottom_right_pt != (-1, -1):
            break
    
        elif key == 27:
            cv2.destroyAllWindows()
            exit()
    
  8. Traverse each image file for cropping
    Use a for loop to loop through all the image files that need to be cropped, crop them one by one, and save the cropped images to the output folder.
    for filename in image_files:
        image_path = os.path.join(input_folder, filename)
    
        #Load images
        image = cv2.imread(image_path)
    
        #Crop based on the coordinates of the first clipping
        cropped_img = image[top_left_pt[1]:bottom_right_pt[1], top_left_pt[0]:bottom_right_pt[0]]
    
        # Save the cropped image
        output_path = os.path.join(output_folder, filename)
        cv2.imwrite(output_path, cropped_img)
        print("The picture has been successfully cropped and saved:", output_path)
    

    Complete code:

    import cv2
    import os
    
    # Set the path of the input folder and output folder
    input_folder = ""
    output_folder = ""
    while True:
        print("-----------------Welcome to use Lijiang picture cropping tool------------------" )
        print("a.Start program")
        print("b.Exit program")
        ans = input("Please select:")
        if ans == "a":
            print("*******Operation Guide: Program usage tutorial: Keyboard "esc" key to exit the window, keyboard "c" key to save the cropped picture, keyboard "r" key to reset the cropping frame")
            print("******* Tip: When entering the file saving path, it is recommended to enter a relative path. For example, you can just write the folder name directly. At this time, the picture will be saved in the same directory as the program!")
            print("******* Tips: Please note that Chinese characters cannot appear when entering the path, otherwise the program will report an error or execution error!")
            input_folder = input("Please enter the file path:")
            output_folder = input("Please enter the output file path (save):")
            break
        elif ans == "b":
            break
        else:
            print("Please enter a valid answer!")
    
    # Make sure the output folder exists, if not create it
    os.makedirs(output_folder, exist_ok=True)
    
    # Get all image files in the input folder
    image_files = [f for f in os.listdir(input_folder) if f.endswith('.jpg') or f.endswith('.png')]
    
    # Load the first image and create a copy
    first_image_path = os.path.join(input_folder, image_files[0])
    first_image = cv2.imread(first_image_path)
    image_display = first_image.copy()
    
    #Create a window and bind a callback function
    cv2.namedWindow('image')
    cv2.setMouseCallback('image', draw_rectangle)
    
    # Record the coordinates of the first cropping
    top_left_pt = (-1, -1)
    bottom_right_pt = (-1, -1)
    
    drawing=False
    
    
    def draw_rectangle(event, x, y, flags, param):
        global x_init, y_init, drawing, top_left_pt, bottom_right_pt, first_image
    
        # Record the initial coordinates when the left mouse button is pressed and start drawing a rectangular frame
        if event == cv2.EVENT_LBUTTONDOWN:
            drawing=True
            x_init, y_init = x, y
    
        # End drawing the rectangular frame when the left mouse button is released, and record the end point coordinates
        elif event == cv2.EVENT_LBUTTONUP:
            drawing=False
            top_left_pt = (min(x_init, x), min(y_init, y))
            bottom_right_pt = (max(x_init, x), max(y_init, y))
            hex_color = '#FFFFCC'
            rgb_color = tuple(int(hex_color[i:i + 2], 16) for i in (1, 3, 5))
            cv2.rectangle(first_image, top_left_pt, bottom_right_pt, rgb_color, 2)
    
        cv2.imshow('image', first_image) # Refresh the image window
    
    
    # Display the first image and wait for the user to draw the cropping box
    cv2.imshow('image', image_display)
    while True:
        key = cv2.waitKey(1) & 0xFF
    
        # Press 'r' to reset the cropping frame
        if key == ord('r'):
            first_image = cv2.imread(first_image_path)
            top_left_pt = (-1, -1)
            bottom_right_pt = (-1, -1)
    
        # Press 'c' to confirm the cropping frame and start cropping
        elif key == ord('c') and top_left_pt != (-1, -1) and bottom_right_pt != (-1, -1):
            break
    
        # Press 'esc' to exit the program
        elif key == 27:
            cv2.destroyAllWindows()
            exit()
    
    # Traverse each image file for cropping
    
    for filename in image_files:
        image_path = os.path.join(input_folder, filename)
    
        #Load images
        image = cv2.imread(image_path)
    
        #Crop based on the coordinates of the first clipping
        cropped_img = image[top_left_pt[1]:bottom_right_pt[1], top_left_pt[0]:bottom_right_pt[0]]
    
        # Save the cropped image
        output_path = os.path.join(output_folder, filename)
        cv2.imwrite(output_path, cropped_img)
        print("The picture has been successfully cropped and saved:", output_path)
    
    cv2.destroyAllWindows()
    
Notes:
  1. The input path and output path cannot contain Chinese characters, otherwise the program will report an error or execute an error.
  2. This program only supports image files in jpg and png formats.
  3. The operation guide and prompt information can be modified according to the actual situation.
Conclusion:

This article describes how to implement a simple image cropping tool using Python and OpenCV. Through this program, users can easily select the area that needs to be cropped and save the cropped picture to a designated folder. This program can play an important role in image processing, data analysis and other fields.