OpenCV
Python
image processing
crop image
tutorial

How to crop an image in OpenCV using Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Cropping in OpenCV is simpler than many beginners expect because you usually do not call a special crop function. In Python, an OpenCV image is a NumPy array, so cropping is done with array slicing, and the only thing you really need to remember is that the order is rows first and columns second.

Crop With NumPy Slicing

Once an image is loaded with OpenCV, you can select a rectangular region with standard slice syntax.

python
1import cv2
2
3image = cv2.imread("input.jpg")
4if image is None:
5    raise FileNotFoundError("input.jpg not found")
6
7crop = image[100:300, 200:500]
8cv2.imwrite("crop.jpg", crop)

The expression image[100:300, 200:500] means:

  • rows from 100 up to but not including 300
  • columns from 200 up to but not including 500

That corresponds to y1:y2, x1:x2, not x1:x2, y1:y2. Mixing those up is the most common mistake.

Work With x, y, width, and height

Bounding boxes are often expressed as x, y, width, and height rather than explicit end coordinates. Convert them carefully before slicing.

python
1import cv2
2
3image = cv2.imread("input.jpg")
4
5x = 150
6y = 80
7width = 250
8height = 180
9
10crop = image[y:y + height, x:x + width]
11cv2.imwrite("crop_box.jpg", crop)

This format is common when boxes come from object detectors, annotation tools, or mouse selections.

Add Bounds Checking for Real Data

Hard-coded crop coordinates are fine for one known image size, but production code should protect itself against out-of-range coordinates.

python
1import cv2
2
3
4def safe_crop(image, x, y, width, height):
5    img_height, img_width = image.shape[:2]
6
7    x1 = max(0, x)
8    y1 = max(0, y)
9    x2 = min(img_width, x + width)
10    y2 = min(img_height, y + height)
11
12    if x1 >= x2 or y1 >= y2:
13        raise ValueError("Crop rectangle is outside the image")
14
15    return image[y1:y2, x1:x2]
16
17
18image = cv2.imread("input.jpg")
19roi = safe_crop(image, 50, 50, 300, 200)
20cv2.imwrite("safe_crop.jpg", roi)

Without these checks, a bad annotation file or a resized source image can silently produce empty outputs.

Center Crop and Batch Cropping

Two common patterns are center cropping and extracting many boxes from one image.

A center crop is useful when you need a consistent region for previews or model input:

python
1import cv2
2
3
4def center_crop(image, crop_width, crop_height):
5    height, width = image.shape[:2]
6    x1 = max((width - crop_width) // 2, 0)
7    y1 = max((height - crop_height) // 2, 0)
8    x2 = x1 + min(crop_width, width)
9    y2 = y1 + min(crop_height, height)
10    return image[y1:y2, x1:x2]
11
12
13image = cv2.imread("input.jpg")
14result = center_crop(image, 256, 256)
15cv2.imwrite("center_crop.jpg", result)

For multiple bounding boxes, loop over them and save or process each crop:

python
1import cv2
2
3image = cv2.imread("input.jpg")
4boxes = [(20, 30, 120, 120), (200, 150, 180, 140)]
5
6for i, (x, y, w, h) in enumerate(boxes, start=1):
7    patch = image[y:y + h, x:x + w]
8    cv2.imwrite(f"crop_{i}.jpg", patch)

That pattern is common in preprocessing pipelines for machine learning datasets.

Displaying the Crop Correctly

If you show the cropped image with OpenCV, you can display it directly. If you use Matplotlib, convert from BGR to RGB first because OpenCV loads color images in BGR order.

python
1import cv2
2import matplotlib.pyplot as plt
3
4image = cv2.imread("input.jpg")
5crop = image[100:250, 100:300]
6
7crop_rgb = cv2.cvtColor(crop, cv2.COLOR_BGR2RGB)
8plt.imshow(crop_rgb)
9plt.axis("off")
10plt.show()

If you skip the conversion, the crop still exists, but the colors will look wrong in Matplotlib.

Common Pitfalls

The first pitfall is mixing up x and y with row and column order. OpenCV images are indexed as image[y, x], so the first slice is vertical position and the second is horizontal position.

Another issue is assuming all images have the same size. Coordinates from one image may be invalid for another unless you clamp them or scale them after resizing.

Developers also sometimes save empty crops without checking dimensions. If the selected region falls outside the image, the result can be unusable while the script continues quietly.

Finally, remember the difference between display libraries. OpenCV and Matplotlib do not use the same default color order.

Summary

  • Crop an OpenCV image in Python with NumPy slicing.
  • Use image[y1:y2, x1:x2], not the other way around.
  • Convert x, y, width, and height into slice endpoints carefully.
  • Add bounds checking when coordinates come from external data.
  • Convert BGR to RGB before showing cropped images with Matplotlib.

Course illustration
Course illustration

All Rights Reserved.