5 Best Ways to Join Two Images Horizontally and Vertically Using OpenCV Python

πŸ’‘ Problem Formulation: In image processing, it’s often necessary to combine images to create a collage or to analyze image data side by side. For instance, joining two digital photographs or merging pieces of a panoramic scene. Using OpenCV in Python, there are methods to concatenate images both horizontally and vertically. This article will solve the problem by presenting various OpenCV functions capable of joining images seamlessly.

Method 1: Using OpenCV’s hconcat() and vconcat() for Simple Stacking

The opencv module in Python provides cv2.hconcat() for horizontal stacking and cv2.vconcat() for vertical stacking of images. These functions are specifically designed for the purpose of joining images by concatenating them along the specified axis. The only prerequisite is that for hconcat(), the images must have the same height, and for vconcat(), the same width.

Here’s an example:

import cv2

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

# Horizontal concatenation
horizontally_combined = cv2.hconcat([image1, image2])

# Vertical concatenation
vertically_combined = cv2.vconcat([image1, image2])

cv2.imwrite('horizontally_combined.jpg', horizontally_combined)
cv2.imwrite('vertically_combined.jpg', vertically_combined)

The output are the images saved as ‘horizontally_combined.jpg’ and ‘vertically_combined.jpg’.

This code snippet loads two images, then horizontally concatenates them using cv2.hconcat(), and vertically concatenates using cv2.vconcat(). The results are written back to the disk as new image files.

Method 2: Using NumPy’s Concatenation Function

Alternatively, since OpenCV images are NumPy arrays, you can directly use NumPy methods to concatenate images. NumPy’s np.concatenate() function is versatile and can be used to join images along any axis. We just need to make sure that dimensions (besides the one along we are concatenating) match between images.

Here’s an example:

import cv2
import numpy as np

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

# Horizontal concatenation
horizontally_combined = np.concatenate((image1, image2), axis=1)

# Vertical concatenation
vertically_combined = np.concatenate((image1, image2), axis=0)

cv2.imwrite('horizontally_combined.jpg', horizontally_combined)
cv2.imwrite('vertically_combined.jpg', vertically_combined)

The output are the images saved as ‘horizontally_combined.jpg’ and ‘vertically_combined.jpg’.

This example demonstrates the use of NumPy’s np.concatenate() method to combine images horizontally and vertically by setting the axis parameter to 1 and 0, respectively. The resulting images are saved to disk.

Method 3: Manipulating Image Shape with Resizing

If the images do not share the same dimensions, you can resize them using OpenCV’s cv2.resize() function before concatenation. This method provides the flexibility to handle images of different sizes, albeit with the tradeoff of distorting aspect ratios if needed.

Here’s an example:

import cv2
import numpy as np

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

# Resize image2 to match image1's dimensions
image2_resized = cv2.resize(image2, (image1.shape[1], image1.shape[0]))

# Now concatenate
horizontally_combined = np.concatenate((image1, image2_resized), axis=1)

cv2.imwrite('horizontally_combined.jpg', horizontally_combined)

The output is the image saved as ‘horizontally_combined.jpg’.

This snippet resizes the second image to match the first image’s dimensions before horizontally concatenating them. It’s a fast way to make images compatible for joining but careful attention should be given to maintain aspect ratios.

Method 4: Using the copyMakeBorder() Method

The copyMakeBorder() function can be creatively used to join images by first creating a border around an image and then placing another image adjacent to it. This technique can be particularly useful when you want to include padding between the images.

Here’s an example:

import cv2

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

# Create a border around image1
bordered_image1 = cv2.copyMakeBorder(image1, 0, 0, 0, image2.shape[1], cv2.BORDER_CONSTANT)

# Stack both images
stacked_images = np.vstack((bordered_image1, image2))

cv2.imwrite('stacked_images.jpg', stacked_images)

The output is the image saved as ‘stacked_images.jpg’.

In this method, copyMakeBorder() is used to create a right-hand side border to image1 which is as wide as image2. Then, both images are stacked vertically using np.vstack(). This method can be appreciated for creating a spacing between images.

Bonus One-Liner Method 5: Simple One-liner with Slicing

For a quick and dirty one-liner, you can create a blank canvas and place both images onto it using slicing. This method is less conventional but works well for quickly placing two images side by side.

Here’s an example:

import cv2
import numpy as np

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

# Create a black canvas
canvas = np.zeros((max(image1.shape[0], image2.shape[0]), image1.shape[1]+image2.shape[1], 3), dtype='uint8')

# Place both images on the canvas
canvas[:image1.shape[0], :image1.shape[1]] = image1
canvas[:image2.shape[0], image1.shape[1]:image1.shape[1]+image2.shape[1]] = image2

cv2.imwrite('combined_canvas.jpg', canvas)

The output is the image saved as ‘combined_canvas.jpg’.

This one-liner creates a black canvas large enough for both images and then uses slicing to lay the images side by side on the canvas.

Summary/Discussion

  • Method 1: OpenCV’s hconcat() and vconcat(). Strengths: straightforward and designed for the task. Weaknesses: Requires images of compatible dimensions.
  • Method 2: NumPy’s concatenate function. Strengths: Uses the power of NumPy and is versatile. Weaknesses: Still requires images to have matching dimensions on axes not being concatenated along.
  • Method 3: Resizing before joining. Strengths: Overcomes dimension mismatch. Weaknesses: Can distort the aspect ratio which might not be desirable.
  • Method 4: Using copyMakeBorder for padding. Strengths: Useful for adding spacing; creative use of padding. Weaknesses: Requires additional steps and an aesthetic judgement on spacing.
  • Method 5: One-liner with Slicing. Strengths: Quick and easy; no need for dimension matching. Weaknesses: Not as clean or straightforward as the others; manual placement on a canvas.