Of course! The function you're looking for is cv2.copyMakeBorder() from the OpenCV library in Python. It's a very useful function for adding padding or borders around an image.

Here’s a complete guide covering what it does, its parameters, different border types, and practical examples.
What is cv2.copyMakeBorder()?
This function creates a new image by copying an existing image and adding a specified border around it. This is often done for various reasons, such as:
- Kernel Operations: When applying convolutional kernels (like in blurring or edge detection), the kernel might extend beyond the image's edges. Padding solves this problem.
- Aesthetics: Simply adding a decorative frame around an image.
- Image Mosaics: Creating a grid of images where each image needs a uniform border.
Function Syntax
dst = cv2.copyMakeBorder(src, top, bottom, left, right, borderType, value, dst)
Parameters Explained
Let's break down each parameter:
| Parameter | Type | Description |
|---|---|---|
src |
numpy.ndarray |
Source image. This is the input image you want to add a border to. |
top |
int |
The width of the border in pixels at the top of the image. |
bottom |
int |
The width of the border in pixels at the bottom of the image. |
left |
int |
The width of the border in pixels on the left side of the image. |
right |
int |
The width of the border in pixels on the right side of the image. |
borderType |
int |
The type of border to create. This is a crucial parameter. We'll cover the common types below. |
value |
int, tuple, or list |
The color of the border. The type depends on the image: - For a grayscale image ( uint8), it's a single integer (e.g., 0 for black). - For a BGR color image, it's a 3-element tuple/list like [255, 0, 0] for blue. Note: This parameter is only used for cv2.BORDER_CONSTANT. |
dst |
numpy.ndarray |
Destination image. This is an optional parameter where you can pre-allocate the output array. If not provided, it's created automatically. |
Border Types (borderType)
This is the most important part. The type of border determines how the pixels outside the original image are determined.

| Border Type | Constant | Description | Use Case |
|---|---|---|---|
| Constant | cv2.BORDER_CONSTANT |
The border pixels have a constant value, specified by the value parameter. |
Creating a solid color frame (e.g., black, white, blue). |
| Replicate | cv2.BORDER_REPLICATE |
The border pixels are the same as the edge pixels of the image. It replicates the pixel values at the border. | When you want the border to look like a simple extension of the image. |
| Reflect | cv2.BORDER_REFLECT |
The border pixels are a reflection of the image pixels. The pattern is fedcba|abcdefgh|hgfedcb. |
Good for natural-looking padding without introducing sharp edges. |
| Reflect101 | cv2.BORDER_REFLECT_101 |
Similar to BORDER_REFLECT, but the edge pixel is not repeated. The pattern is gfedcb|abcdefgh|gfedcba. |
Often preferred over BORDER_REFLECT as it looks more natural. |
| Wrap | cv2.BORDER_WRAP |
The image is "tiled" to fill the border. The pattern is cdefgh|abcdefgh|abcdefg. |
Specialized effects, simulating a repeating pattern. |
Complete Python Code Examples
Let's see these border types in action.
Step 1: Installation
If you don't have OpenCV installed, open your terminal or command prompt and run:
pip install opencv-python
Step 2: The Code
import cv2
import numpy as np
import matplotlib.pyplot as plt
# --- Helper Function to Display Images ---
def show_images(images, titles):
"""Displays a list of images with their titles using matplotlib."""
n = len(images)
fig, axes = plt.subplots(1, n, figsize=(5 * n, 5))
if n == 1:
axes = [axes]
for ax, img, title in zip(axes, images, titles):
# Convert BGR (OpenCV) to RGB (Matplotlib) for color display
if len(img.shape) == 3 and img.shape[2] == 3:
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
ax.imshow(img_rgb)
else: # Grayscale image
ax.imshow(img, cmap='gray')
ax.set_title(title)
ax.axis('off')
plt.tight_layout()
plt.show()
# --- 1. Load an Image ---
# We use a small image to make the border effect very visible
# If you don't have an image, you can create one
# image = np.zeros((100, 100, 3), dtype=np.uint8) # A black 100x100 BGR image
# image[:] = [255, 0, 0] # Fill it with blue
# Or load from a file
try:
image = cv2.imread('your_image.jpg') # Replace with your image path
if image is None:
raise FileNotFoundError
except FileNotFoundError:
print("Image not found. Creating a sample image instead.")
# Create a sample image with a gradient to see the effect clearly
image = np.zeros((200, 200, 3), dtype=np.uint8)
for i in range(200):
image[:, i, :] = [i, 0, 200-i] # Gradient from blue to red
# --- 2. Define Border Properties ---
border_width = 50
border_color = [0, 255, 0] # Green border
# --- 3. Apply Different Border Types ---
# a) BORDER_CONSTANT: A solid color border
constant_border = cv2.copyMakeBorder(image, border_width, border_width, border_width, border_width,
cv2.BORDER_CONSTANT, value=border_color)
# b) BORDER_REPLICATE: Replicate the edge pixels
replicate_border = cv2.copyMakeBorder(image, border_width, border_width, border_width, border_width,
cv2.BORDER_REPLICATE)
# c) BORDER_REFLECT: Mirror the image pixels
reflect_border = cv2.copyMakeBorder(image, border_width, border_width, border_width, border_width,
cv2.BORDER_REFLECT)
# d) BORDER_REFLECT_101: Mirror without duplicating the edge pixel (most common)
reflect101_border = cv2.copyMakeBorder(image, border_width, border_width, border_width, border_width,
cv2.BORDER_REFLECT_101)
# --- 4. Display the Results ---
show_images(
[image, constant_border, replicate_border, reflect_border, reflect101_border],
["Original Image", "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_REFLECT_101"]
)
Practical Example: Padding for Convolution
A very common use case for copyMakeBorder is before applying a filter (like a Gaussian blur) to avoid artifacts at the image borders.
import cv2
import numpy as np
# Load an image
image_path = 'your_image.jpg' # Replace with your image path
image = cv2.imread(image_path)
if image is None:
print(f"Could not load image from {image_path}. Skipping convolution example.")
else:
# Define a kernel size (must be odd)
kernel_size = (15, 15)
sigma = 10 # Standard deviation for Gaussian blur
# --- Method 1: Blurring without padding (can cause artifacts) ---
blurred_no_pad = cv2.GaussianBlur(image, kernel_size, sigma)
# --- Method 2: The correct way - add padding first ---
# Calculate padding needed (half the kernel size)
pad_x = kernel_size[1] // 2
pad_y = kernel_size[0] // 2
# Add a border using BORDER_REFLECT_101 (common choice)
padded_image = cv2.copyMakeBorder(image, pad_y, pad_y, pad_x, pad_x,
cv2.BORDER_REFLECT_101)
# Now, apply the blur on the padded image
blurred_with_pad = cv2.GaussianBlur(padded_image, kernel_size, sigma)
# Crop the image back to its original size
final_blurred_image = blurred_with_pad[pad_y:-pad_y, pad_x:-pad_x]
# Display the comparison
show_images(
[image, blurred_no_pad, final_blurred_image],
["Original", "
