Image blending is a technique to combine two images with a weighted sum or through advanced techniques like pyramids. OpenCV provides multiple ways to blend images effectively, whether for basic overlaying or advanced image morphing.
What You’ll Learn
1. Introduction to Image Blending
Blending involves combining two images using weights or masks. The basic formula for blending is:
Blended Image=α⋅Image1+β⋅Image2+γ\text{Blended Image} = \alpha \cdot \text{Image1} + \beta \cdot \text{Image2} + \gamma
Where:
- alpha: Weight for the first image.
- beta: Weight for the second image.
- gamma: Scalar added to the result.
2. Simple Weighted Blending
The function cv2.addWeighted() blends two images using the formula above.
Example: Simple Weighted Blending
import cv2 # Load two images of the same size image1 = cv2.imread("image1.jpg") image2 = cv2.imread("image2.jpg") # Blend images with equal weights blended = cv2.addWeighted(image1, 0.5, image2, 0.5, 0) # Display the result cv2.imshow("Blended Image", blended) cv2.waitKey(0) cv2.destroyAllWindows()
Adjusting Weights
# Blend with different weights blended = cv2.addWeighted(image1, 0.7, image2, 0.3, 0)
3. Blending with Masks
Masks allow blending specific regions of two images.
Example: Blending with a Circular Mask
import cv2 import numpy as np # Load two images of the same size image1 = cv2.imread("image1.jpg") image2 = cv2.imread("image2.jpg") # Create a circular mask rows, cols, _ = image1.shape mask = np.zeros((rows, cols), dtype="uint8") center = (cols // 2, rows // 2) radius = min(rows, cols) // 4 cv2.circle(mask, center, radius, 255, -1) # Blend the images using the mask blended = cv2.bitwise_and(image1, image1, mask=mask) inverse_mask = cv2.bitwise_not(mask) blended += cv2.bitwise_and(image2, image2, mask=inverse_mask) # Display the result cv2.imshow("Masked Blended Image", blended) cv2.waitKey(0) cv2.destroyAllWindows()
4. Pyramid-Based Image Blending
Pyramid blending uses multi-scale image decomposition (Gaussian and Laplacian pyramids) to blend images seamlessly.
Steps for Pyramid Blending
- Create Gaussian pyramids for both images and the mask.
- Create Laplacian pyramids from Gaussian pyramids.
- Blend the Laplacian pyramids using the mask.
- Reconstruct the final image from the blended pyramid.
Example: Pyramid Blending
import cv2 import numpy as np def blend_images_pyramid(image1, image2, mask, levels=4): # Generate Gaussian pyramids for images and mask gp_image1 = [image1] gp_image2 = [image2] gp_mask = [mask] for _ in range(levels): image1 = cv2.pyrDown(image1) image2 = cv2.pyrDown(image2) mask = cv2.pyrDown(mask) gp_image1.append(image1) gp_image2.append(image2) gp_mask.append(mask) # Generate Laplacian pyramids lp_image1 = [gp_image1[-1]] lp_image2 = [gp_image2[-1]] lp_mask = [gp_mask[-1]] for i in range(levels, 0, -1): laplacian_image1 = cv2.subtract(gp_image1[i-1], cv2.pyrUp(gp_image1[i])) laplacian_image2 = cv2.subtract(gp_image2[i-1], cv2.pyrUp(gp_image2[i])) lp_image1.append(laplacian_image1) lp_image2.append(laplacian_image2) # Blend pyramids blended_pyramid = [] for la1, la2, gm in zip(lp_image1, lp_image2, gp_mask): blended = cv2.add(la1 * gm / 255, la2 * (1 - gm / 255)) blended_pyramid.append(blended) # Reconstruct the blended image blended_image = blended_pyramid[0] for i in range(1, levels+1): blended_image = cv2.pyrUp(blended_image) blended_image = cv2.add(blended_image, blended_pyramid[i]) return blended_image # Load two images and a mask image1 = cv2.imread("image1.jpg") image2 = cv2.imread("image2.jpg") rows, cols, _ = image1.shape mask = np.zeros((rows, cols), dtype="uint8") cv2.rectangle(mask, (cols // 2, 0), (cols, rows), 255, -1) # Blend the images using pyramid blending blended = blend_images_pyramid(image1, image2, mask, levels=4) # Display the result cv2.imshow("Pyramid Blended Image", blended) cv2.waitKey(0) cv2.destroyAllWindows()
5. Practical Examples
5.1 Combine Two Images Horizontally
import cv2 import numpy as np # Load images image1 = cv2.imread("image1.jpg") image2 = cv2.imread("image2.jpg") # Resize images to the same height height = min(image1.shape[0], image2.shape[0]) image1 = cv2.resize(image1, (int(image1.shape[1] * height / image1.shape[0]), height)) image2 = cv2.resize(image2, (int(image2.shape[1] * height / image2.shape[0]), height)) # Blend horizontally blended = np.hstack((image1, image2)) cv2.imshow("Combined Image", blended) cv2.waitKey(0) cv2.destroyAllWindows()
5.2 Create a Fade Transition Between Two Images
import cv2 import numpy as np # Load images image1 = cv2.imread("image1.jpg") image2 = cv2.imread("image2.jpg") # Ensure both images are the same size image1 = cv2.resize(image1, (500, 500)) image2 = cv2.resize(image2, (500, 500)) # Create a fade effect for alpha in np.linspace(0, 1, 50): blended = cv2.addWeighted(image1, alpha, image2, 1 - alpha, 0) cv2.imshow("Fade Transition", blended) if cv2.waitKey(50) & 0xFF == ord('q'): # Press 'q' to exit break cv2.destroyAllWindows()
5.3 Blend Multiple Images
import cv2 import numpy as np # Load images images = ["image1.jpg", "image2.jpg", "image3.jpg"] loaded_images = [cv2.imread(img) for img in images] # Resize all images to the same size size = (500, 500) loaded_images = [cv2.resize(img, size) for img in loaded_images] # Blend all images equally blended = np.zeros_like(loaded_images[0], dtype="float32") for img in loaded_images: blended += img.astype("float32") / len(loaded_images) # Convert back to uint8 blended = np.clip(blended, 0, 255).astype("uint8") cv2.imshow("Blended Multiple Images", blended) cv2.waitKey(0) cv2.destroyAllWindows()
6. Summary
Key Functions
- cv2.addWeighted(): Perform weighted blending.
- cv2.bitwise_and() / cv2.bitwise_not(): Blend with masks.
- Pyramid Blending: Advanced blending for seamless results.
Best Practices
- Ensure images are the same size for blending.
- Use masks to blend specific regions.
- Leverage pyramid blending for smooth transitions.
By mastering these techniques, you can create stunning image blends for animations, overlays, or seamless image combinations using OpenCV