Image Effects How to Replace Colors in an Image How to Combine Two Images in Python 12 Tips for Effective HTML Image Optimization Restore Image: Common Issues and How to Fix Them Using Image Enhancement for Better Visual Content FLV vs WEBM: Which Video Format Should You Choose in 2025? A Beginner’s Guide to Image Comparison in Python Python Image Analysis Tools and Techniques: Where to Start Understanding How to Change the Aspect Ratio of an Image Unleashing the Power of Image Organizers in 2025 How to Make a Low-Quality Image Look Better Understanding Lossless Image Compression How to Set Up Image Registration in Python 8 Different Image Processing Techniques You Can Use 4 Ways to Make an Image Larger without Losing Quality 3 Easy Ways to Eliminate Duplicate Images The Basics of Face Detection in Python How to Implement Multiple File Upload in PHP Like a Pro Creating Custom Image Cropping Interfaces in Android How to Create Simple Yet Effective PHP Overlay Understanding Real-Time Image Recognition How to add a shadow effect to an image with CSS How to crop an image in Flutter with Cloudinary How To Rotate an Image with Java Image Processing with Python Rotating an image with CSS Enhancing User Experience with a Responsive Image Slider Building a Python Image Recognition System Building an Interactive JavaScript Image Manipulation Tool Image Align Centering with HTML and CSS Efficient Image Cropping Techniques with Angular and Cloudinary Ultimate Guide to Photo Gallery on Android A Comprehensive Guide to Adding Text to Images on Android Mastering Background Changes in React Applications Comprehensive Guide on Changing Background on Android Devices Mastering Image Rotation in Java A Guide to Adding Text to Images with Python A Guide to Converting Images to Grayscale with Python Introduction Creating an Image Overlay with JavaScript Rotating an Image in Python Creating a Dynamic Photo Gallery with jQuery Creating An Interactive Photo Gallery Using JavaScript Mastering Overlay in Android Mastering Angular Overlay: A Comprehensive Guide Comprehensive Guide to Overlay in Flutter Mastering Overlay React for Responsive Design Solutions Create a Blurred Image with PHP: A Comprehensive Guide Guide to Using Blur Image in Flutter Mastering Blur Image in React Native Mastering Image Blurring in Python Mastering the Art of Image Blurring Mastering the Art of Image Blurring in Java The Ultimate Guide to Blurring Images on Android Understanding and Implementing Blur Image in JQuery An Extensive Walkthrough of Blurring Images with JavaScript How to Use HTML, CSS, and JavaScript to Make an Image Slider HTML Image Tag How to Crop GIFs? How to Align Images with CSS Ken Burns Effect – Complete Guide and How to Apply It Cartoonify – Complete Guide on Cartoonify Image Effect Mastering Web Aesthetics: A Comprehensive Guide to Gradient Fades Sepia Effect: The Ultimate Guide to the Sepia Photo Effect What is Vignette? Guide to Vignette Image Editing Pixelate – The Ultimate Guide to the Pixelation Effect How to Outline an Image: Enhancing Visual Appeal and Depth Make Your Photos Pop with Image Effects Upscale Image – Developers guide to AI-driven image upscaling Image Manipulation: History, Concepts and a Complete Guide A Full Guide to Object-aware Cropping Simplify Your Life with Automatic Image Tagging How To Resize Images In WordPress How To Create a Progress Bar For Asset Uploads Animated GIFs – What They Are And How To Create Them How To Automatically Improve Image Resolution AI Drop Shadow Get Image Dimensions From URLs Automatically Add Sepia Effect To Images Automatically Make an Image a Cartoon Automatically Add Blur Faces Effect To Images Automatically Add Background Removal Effect to an Image How to Resize an Image with React How to Easily Resize an Image with React Native

How to Combine Two Images in Python

Modern applications, including social media filters, computer vision, and digital art, rely heavily on image processing. One common task is combining two images, seamlessly merging them for overlays, adding watermarks, or creating other artistic effects. Whether you’re blending images for artistic effects or layering graphics for branding, Python offers powerful libraries to achieve this with ease.

In this article, we’ll explore how to combine two images in Python using popular libraries like OpenCV and Pillow. We’ll walk through different methods, including alpha blending, masking, and pasting, to help you seamlessly merge images for various applications.

In this article:

Using Pillow to Merge Images

When working with images in Python, Pillow is one of the most popular and flexible libraries for image processing. It provides an easy-to-use interface for performing operations such as resizing, cropping, rotating, filtering, and merging images.

Pillow simplifies image manipulation—whether you’re making collages, combining screenshots, or merging images for analysis—with only a few lines of code. Now, let’s explore how Pillow can merge two images side by side, perfectly aligned despite size differences.

To begin, make sure that Pillow is installed in your Python virtual environment. If it’s not already installed, you can add it using:

pip install pillow

Next, create a Python file in your project directory, import the module, and load the images:

from PIL import Image

# Open the two images
image1 = Image.open("image1.jpg")
image2 = Image.open("image2.jpg")

Before merging, it’s important to check whether the images have the same dimensions. If they don’t, we should adjust their sizes to ensure they align properly. The easiest way to do this is to resize both images to match the height of the smaller one while preserving their aspect ratios:

# Get the height of the smaller image
min_height = min(image1.height, image2.height)

# Resize images to have the same height while maintaining the aspect ratio
image1 = image1.resize((int(image1.width * min_height / image1.height), min_height))
image2 = image2.resize((int(image2.width * min_height / image2.height), min_height))

This ensures that both images have the same height, making them easier to merge seamlessly. Now, we need a blank canvas that can accommodate both images side by side:

# Create a blank image with the combined width
combined_width = image1.width + image2.width
combined_image = Image.new("RGB", (combined_width, min_height))

Once we have the blank canvas, we can paste both images onto it, positioning them next to each other, and finally, we can display and save the merged image. Here is what our code looks like:

from PIL import Image

# Open the two images
image1 = Image.open("image1.jpg")
image2 = Image.open("image2.jpg")

# Get the height of the smaller image
min_height = min(image1.height, image2.height)

# Resize images to have the same height while maintaining the aspect ratio
image1 = image1.resize((int(image1.width * min_height / image1.height), min_height))
image2 = image2.resize((int(image2.width * min_height / image2.height), min_height))

# Create a blank image with combined width
combined_width = image1.width + image2.width
combined_image = Image.new("RGB", (combined_width, min_height))

# Paste images side by side
combined_image.paste(image1, (0, 0))
combined_image.paste(image2, (image1.width, 0))

# Show and save the final merged image
combined_image.show()
combined_image.save("merged_image.jpg")

How to Combine Two Images in Python with OpenCV

OpenCV is another Python library that allows you to combine images easily. It is one of the most widely used libraries for computer vision, image processing, and machine learning tasks. It provides a comprehensive set of tools for manipulating images, detecting objects, applying transformations, and performing real-time processing. OpenCV is highly optimized for performance and supports various image operations, such as blending, masking, and overlays, making it an excellent choice for combining images efficiently.

To use OpenCV to merge your images, start by making sure OpenCV is installed in your Python environment. If you haven’t installed it yet, you can do so using the following pip command:

pip install opencv-python

Next, we’ll load two images and display them using OpenCV:

import cv2

# Load the two images
image1 = cv2.imread("image1.jpg")
image2 = cv2.imread("image2.jpg")

# Display images (optional)
cv2.imshow("Image 1", image1)
cv2.imshow("Image 2", image2)
cv2.waitKey(0)
cv2.destroyAllWindows()

Here, the cv2.imread() function loads images as NumPy arrays, which allows us to manipulate them easily. The cv2.imshow() function is used to display the images, and cv2.waitKey(0) ensures the windows stay open until a key is pressed.

Before we merge our images, we need to make sure both images have the same dimensions. If they have differences in dimensions, we can resize the second image to match the first one using cv2.resize():

# Resize second image to match the first image
image2 = cv2.resize(image2, (image1.shape[1], image1.shape[0]))

Now that both images are the same size, we can merge them using OpenCV’s cv2.addWeighted() function, which allows us to control the blending ratio by adjusting alpha values:

# Blend images with alpha transparency
alpha = 0.6  # Weight of the first image
beta = 0.4   # Weight of the second image
blended_image = cv2.addWeighted(image1, alpha, image2, beta, 0)

Here, alpha and beta determine how much of each image is visible in the final result. A higher alpha value makes the first image more dominant, while a higher beta value makes the second image more prominent. The last argument (0) is a scalar that can add brightness, but is left as zero in most cases.

Finally, we display and save the blended image. Here is what our code looks like:

import cv2

# Load the two images
image1 = cv2.imread("image1.jpg")
image2 = cv2.imread("image2.jpg")

# Resize second image to match the first image
image2 = cv2.resize(image2, (image1.shape[1], image1.shape[0]))

# Blend images with alpha transparency
alpha = 0.6  # Weight of the first image
beta = 0.4   # Weight of the second image
blended_image = cv2.addWeighted(image1, alpha, image2, beta, 0)

# Show and save the blended image
cv2.imshow("Blended Image", blended_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite("blended_image.jpg", blended_image)

By adjusting the alpha and beta values, you can control how much each image contributes to the final result.

Automating Image Combination with Cloudinary

Installing and managing image-processing libraries like Pillow and OpenCV can be time-consuming, requiring additional dependencies, manual coding, and system compatibility checks. Handling images locally also consumes storage and processing power, making it difficult to scale for large applications.

Cloudinary eliminates these challenges by providing a cloud-based media management platform that enables dynamic image transformations without any local setup. With Cloudinary, you can overlay, merge, and manipulate images on the fly using simple URL-based transformations or an intuitive Python SDK, making it an excellent solution for scalable web applications.

Instead of writing complex image-processing code, Cloudinary allows you to merge images dynamically using transformation URLs. This makes it an essential option for e-commerce platforms, social media applications, and content delivery networks, where real-time image modifications are constantly needed.

Merging Images Using Cloudinary’s URL-Based API

With Cloudinary’s URL-based transformations, you can overlay one image onto another in a single API call. As an example, we’ll use this image from the Cloudinary demo cloud:

With Cloudinary’s dynamic URL generation, you can overlay one image onto another while setting its width and position:

https://res.cloudinary.com/demo/image/upload/l_docs:logo-semi-opaque,w_1000,x_50,y_50/cld-sample.jpg

This URL overlays docs:logo-semi-opaque onto cld-sample.jpg, setting its width to 1000 pixels and positioning it at (50,50). By adjusting these parameters, you can change the overlay’s size, position, opacity, and blending mode, allowing complete control over how the images are merged. Here is what our image looks like:

For more flexibility, you can integrate Cloudinary’s Python SDK to automate image combinations in your Python applications. The SDK provides an easy way to apply transformations programmatically. To use Cloudinary’s Python SDK, you will first need to install it using pip:

pip install cloudinary

Next, log in to your Cloudinary account and head over to the Programmable Media dashboard. If you don’t have a Cloudinary account, you can sign up for a free account. Now click on the Go to API Keys button to retrieve your API keys.

For this tutorial, we will upload and transform our images. Thankfully, Cloudinary provides a whole host of images that we can use. So, for now, we will be using office_desk.jpg as well as the Cloudinary logo to overlay our images:

Now create a Python file in the project directory of your choosing and start by importing the Cloudinary Python SDK and configuring your Cloudinary credentials:

import cloudinary
import cloudinary.uploader
import cloudinary.api

# Configure Cloudinary with your account details
cloudinary.config(  
    cloud_name="your_cloud_name",  
    api_key="your_api_key",  
    api_secret="your_api_secret"
)

Before overlaying our images, you will first need to upload your images to the Cloudinary cloud. To do this, we will use the .upload() method as follows:

# Upload base image
base_image = cloudinary.uploader.upload('office_desk.jpg', public_id='base_image')

# Upload overlay image
overlay_image = cloudinary.uploader.upload('cloudinary_logo.jpg', public_id='overlay_image')

Finally, you can overlay one image onto another before printing our URL. Here is what our code looks like:

import cloudinary
import cloudinary.uploader
from cloudinary import CloudinaryImage

# Configure Cloudinary with your account details
cloudinary.config(  
    cloud_name="your_cloud_name",  
    api_key="your_api_key",  
    api_secret="your_api_secret"
)

# Upload base image
base_image = cloudinary.uploader.upload('office_desk.jpg', public_id='base_image')

# Upload overlay image
overlay_image = cloudinary.uploader.upload('cloudinary_logo.jpg', public_id='overlay_image')

# Generate URL with overlay and transparency
url = CloudinaryImage('base_image').build_url(
    transformation=[
        {'overlay': 'overlay_image', 'opacity': 50, 'width': 400, 'gravity': 'south_east'}
    ]
)

print(url)

Here is what our image looks like:

Now, if you want to concatenate two images horizontally, first retrieve the width of the first image:

# Retrieve the width of the first image
first_image_info = cloudinary.api.resource('first_image')
first_image_width = first_image_info['width']

Then, use Cloudinary’s transformation API to position the second image to the right of the first image:

# Generate URL with the second image overlaid to the right of the first image
combined_image_url = CloudinaryImage('first_image').build_url(
    transformation=[
        {'overlay': 'second_image', 'x': first_image_width, 'gravity': 'west'}
    ]
)

print("Combined Image URL:", combined_image_url)

Here, we use the x parameter to position the overlay at the width of the first image, followed by using gravity: west to align the second image to the left of the overlay.

Wrapping Up

Whether you need precise local image manipulation with Pillow and OpenCV or want the efficiency of Cloudinary’s dynamic transformation API, these tools offer flexible solutions for various applications. Experiment with these methods based on your specific needs—whether it’s watermarking, compositing, or creating engaging visuals at scale.

Try Cloudinary to simplify and automate your image processing workflows to seamlessly merge, overlay, and transform images with just a few lines of code!

Learn more:

4 Generative AI Trends in the Enterprise

You Won’t Believe Your Eyes: Combining Cloudinary’s Generative AI Transformations

QUICK TIPS
Colby Fayock
Cloudinary Logo Colby Fayock

In my experience, here are tips that can help you get even more out of image merging in Python:

  1. Use Seamless Blending with Poisson Image Editing
    Instead of simple alpha blending, use Poisson image editing (cv2.seamlessClone()) to integrate images naturally, matching lighting and texture. This is especially useful for watermarking or object insertion.
  2. Apply Histogram Matching for Color Consistency
    If the two images have different lighting conditions, use histogram matching (skimage.exposure.match_histograms()) to create a more uniform look before merging.
  3. Optimize Memory Usage for Large Images
    When working with high-resolution images, use cv2.UMat or dask to handle large files efficiently without running into memory issues.
  4. Utilize Transparent Overlays with Alpha Channels
    If merging PNGs with transparency, ensure you handle the alpha channel properly using cv2.addWeighted() or Pillow’s convert("RGBA") to avoid unwanted backgrounds.
  5. Use Feature Matching for Automatic Alignment
    If images need to be aligned before merging, use ORB or SIFT feature detection (cv2.ORB_create() or cv2.SIFT_create()) to find key points and warp one image onto another.
  6. Implement Multi-Scale Blending for Smooth Transitions
    Use Laplacian pyramid blending (cv2.pyrUp() and cv2.pyrDown()) for a seamless gradient transition between images instead of abrupt cuts.
  7. Preprocess Images for Faster Merging
    Convert images to grayscale or LAB color space (cv2.cvtColor()) before processing to speed up computations while preserving important details.
  8. Use Perspective Transformation for Advanced Image Alignment
    If images need to be merged at an angle, use cv2.getPerspectiveTransform() and cv2.warpPerspective() to align them dynamically.
  9. Automate Image Merging in Batch Processing
    If handling bulk images, integrate Pillow or OpenCV with multiprocessing to merge images in parallel, significantly reducing processing time.
  10. Use Cloudinary’s AI-Based Auto Format (f_auto) and Quality (q_auto)
    When automating image merging with Cloudinary, enable f_auto and q_auto in the URL parameters to serve the best format and quality for each user’s device.
Last updated: Mar 7, 2025