杰瑞科技汇

Python OpenCV如何实现图像裁剪?

Of course! Here’s a comprehensive guide on how to crop an image using Python and OpenCV, from the basic concept to practical examples with code.

Python OpenCV如何实现图像裁剪?-图1
(图片来源网络,侵删)

What is Cropping?

Cropping is the process of removing unwanted outer areas of an image to enhance framing, highlight a subject, or change the aspect ratio. In OpenCV, this is done by slicing the image array.

An image in OpenCV is represented as a NumPy array. The dimensions are structured as [rows, columns, channels]. You can think of it like a grid:

  • Rows: The height of the image (Y-axis).
  • Columns: The width of the image (X-axis).
  • Channels: The color components (e.g., 3 for BGR, 1 for Grayscale).

To crop an image, you simply select a rectangular slice of this array.


The Basic Syntax: Array Slicing

The core of cropping in OpenCV is NumPy array slicing. The syntax is:

Python OpenCV如何实现图像裁剪?-图2
(图片来源网络,侵删)
cropped_image = original_image[y_start:y_end, x_start:x_end]

Important Note: The slicing is exclusive of the end index. So, if you write image[0:100, 0:200], the slice will include rows 0 to 99 and columns 0 to 199.

Let's break it down with a visual example:

Imagine you have a 600x400 image.

(0,0) ------------------------ (599, 0)
  |                            |
  |                            |
  |   (y_start, x_start)       |
  |        +-----------------+  |
  |        |                 |  |
  |        |   CROPPED        |  |
  |        |   REGION        |  |
  |        |                 |  |
  |        +-----------------+  |
  |                            |
  |                            |
(0, 399) ----------------------- (599, 399)

To crop the region defined by (x_start, y_start) and (x_end, y_end), you would use:

Python OpenCV如何实现图像裁剪?-图3
(图片来源网络,侵删)
cropped = image[y_start:y_end, x_start:x_end]

Step-by-Step Example: Cropping a Face

Let's write a complete, runnable script to load an image, crop a specific region, and display both the original and cropped images.

Prerequisites

First, make sure you have OpenCV and NumPy installed:

pip install opencv-python numpy

You'll also need an image. For this example, let's use the standard lena.jpg or download a sample image and save it as sample.jpg in the same directory as your script.

Code

import cv2
import numpy as np
# 1. Read the image
# Make sure 'sample.jpg' is in the same directory or provide the full path
image_path = 'sample.jpg'
original_image = cv2.imread(image_path)
# Check if the image was loaded successfully
if original_image is None:
    print(f"Error: Could not read image from {image_path}")
    exit()
# 2. Define the cropping coordinates
# Format: [y_start, y_end, x_start, x_end]
# Let's say we want to crop a 200x200 pixel region from the top-left corner
y_start = 50
y_end = 250
x_start = 50
x_end = 250
# 3. Crop the image using array slicing
cropped_image = original_image[y_start:y_end, x_start:x_end]
# 4. Display the original and cropped images
cv2.imshow('Original Image', original_image)
cv2.imshow('Cropped Image', cropped_image)
# 5. Wait for a key press to close the windows
# The '0' means it will wait indefinitely until any key is pressed
cv2.waitKey(0)
# 6. Close all OpenCV windows
cv2.destroyAllWindows()

Explanation

  1. cv2.imread(image_path): Reads the image from the specified file path and loads it as a NumPy array.
  2. Define Coordinates: We manually set the y_start, y_end, x_start, and x_end values to define our desired crop box.
  3. Slicing: original_image[y_start:y_end, x_start:x_end] extracts the portion of the array corresponding to our crop box.
  4. Display: cv2.imshow() creates windows to display the images.
  5. cv2.waitKey(0): Pauses the script execution until a key is pressed. This is crucial; without it, the windows would appear and disappear instantly.
  6. cv2.destroyAllWindows(): Cleans up and closes all the windows created by OpenCV.

Interactive Cropping with Mouse Events

Hardcoding coordinates is not practical. A more useful approach is to let the user draw a rectangle on the image with their mouse to select the crop area.

Here's how to do it using OpenCV's mouse event callback functions.

Code

import cv2
# Global variables to store the starting and ending points
cropping = False
x_start, y_start, x_end, y_end = 0, 0, 0, 0
# Mouse callback function
def mouse_crop(event, x, y, flags, param):
    global x_start, y_start, x_end, y_end, cropping
    # If the left mouse button is pressed, record the starting point
    if event == cv2.EVENT_LBUTTONDOWN:
        cropping = True
        x_start, y_start = x, y
        print(f"Start point: ({x}, {y})")
    # If the mouse is moved while the button is pressed, draw a rectangle
    elif event == cv2.EVENT_MOUSEMOVE:
        if cropping:
            # We need to redraw the image to clear the previous rectangle
            image_copy = image.copy()
            cv2.rectangle(image_copy, (x_start, y_start), (x, y), (0, 255, 0), 2)
            cv2.imshow('image', image_copy)
    # If the left mouse button is released, record the ending point
    elif event == cv2.EVENT_LBUTTONUP:
        cropping = False
        x_end, y_end = x, y
        print(f"End point: ({x}, {y})")
        # Draw the final rectangle on the original image
        cv2.rectangle(image, (x_start, y_start), (x_end, y_end), (0, 255, 0), 2)
        cv2.imshow('image', image)
# --- Main script ---
image_path = 'sample.jpg'
image = cv2.imread(image_path)
if image is None:
    print(f"Error: Could not read image from {image_path}")
    exit()
# Clone the image for display purposes
clone = image.copy()
# Create a window and set the mouse callback
cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_crop)
# Display the image and wait for user to draw a rectangle
print("Draw a rectangle on the image with your left mouse button.")
while True:
    cv2.imshow('image', image)
    key = cv2.waitKey(1) & 0xFF # Wait for 1ms
    # If the 'c' key is pressed, crop the image and break the loop
    if key == ord('c'):
        break
# Check if a valid crop was made
if x_start != x_end and y_start != y_end:
    # Ensure coordinates are in the correct order (top-left to bottom-right)
    rect = (min(x_start, x_end), min(y_start, y_end),
            abs(x_end - x_start), abs(y_end - y_start))
    # Crop the image
    roi = image[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]]
    # Display the cropped image
    cv2.imshow('Cropped Image', roi)
    cv2.waitKey(0)
# Close all windows
cv2.destroyAllWindows()

How to Use This Script:

  1. Run the script. A window with your image will appear.
  2. Click and hold the left mouse button at one corner of the area you want to crop.
  3. Drag the mouse to the opposite corner. You will see a green rectangle follow your cursor.
  4. Release the mouse button to finalize the selection.
  5. Press the 'c' key on your keyboard. The script will then display the cropped image in a new window.
  6. Press any key to close the final window and exit the program.

Cropping Based on Contours or Objects

A more advanced use case is to crop an object based on its shape. This typically involves:

  1. Converting the image to grayscale.
  2. Applying a threshold or edge detection (like Canny).
  3. Finding contours in the binary image.
  4. Finding the bounding rectangle of the largest contour.
  5. Cropping the original image using that rectangle.

Example: Cropping the Largest Object

import cv2
import numpy as np
image_path = 'sample.jpg'
image = cv2.imread(image_path)
if image is None:
    print(f"Error: Could not read image from {image_path}")
    exit()
# Convert to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply a Gaussian blur to reduce noise
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# Use Canny edge detection
edges = cv2.Canny(blurred, 50, 150)
# Find contours in the edged image
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Assume the largest contour is the object we want to crop
if contours:
    # Find the largest contour by area
    largest_contour = max(contours, key=cv2.contourArea)
    # Get the bounding rectangle for the largest contour
    # x, y, w, h = cv2.boundingRect(largest_contour)
    # Crop the image using the bounding rectangle coordinates
    # roi = image[y:y+h, x:x+w]
    # A more robust way is to find the minimum area rectangle
    rect = cv2.minAreaRect(largest_contour)
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    # For simplicity, let's stick to the axis-aligned bounding rectangle
    x, y, w, h = cv2.boundingRect(largest_contour)
    cropped_object = image[y:y+h, x:x+w]
    # Draw the bounding rectangle on the original image for visualization
    cv2.drawContours(image, [largest_contour], -1, (0, 255, 0), 3)
    # Display the results
    cv2.imshow('Original with Contour', image)
    cv2.imshow('Cropped Object', cropped_object)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
else:
    print("No contours found.")

This is a powerful technique for isolating objects from their background.

分享:
扫描分享到社交APP
上一篇
下一篇