You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenCV与Python实现两张图像的中心对齐

Align Image 2 to Image 1's Center Using OpenCV

Got it, let's walk through how to get Image 2 perfectly centered on Image 1 using the center coordinates you've already calculated (or can calculate with a modified version of your existing code).

First, let's make sure we're on the same page: you need the (x,y) center for both images. Your current code collects centers for all contours in Image 1, but I'll assume you want the center of the main object (so we'll tweak that to pick the largest contour, which is usually the one you care about).

Step 1: Get Center Coordinates for Both Images

First, refactor your code into a reusable function to get the center of an image's main object:

def get_image_center(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 120, 255, 1)
    contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # Pick the largest contour (adjust this if you need a specific one)
    main_contour = max(contours, key=cv2.contourArea)
    M = cv2.moments(main_contour)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    return (cX, cY)

Use this function on both Image 1 and Image 2 to get center1 and center2 as tuples (e.g., (200, 300)).

Step 2: Calculate How Much to Shift Image 2

To align Image 2's center with Image 1's, compute the offset (dx, dy) that moves Image 2's center to match Image 1's:

dx = center1[0] - center2[0]
dy = center1[1] - center2[1]

Positive values mean shift right/down; negative values mean shift left/up.

Step 3: Apply the Translation

Use OpenCV's warpAffine to shift Image 2. First, create the transformation matrix:

translation_matrix = np.float32([[1, 0, dx], [0, 1, dy]])

Then apply it to Image 2, setting the output size to match Image 1 so the result fits perfectly:

aligned_img2 = cv2.warpAffine(img2, translation_matrix, (img1.shape[1], img1.shape[0]))

This gives you Image 2 shifted so its center matches Image 1's. If Image 2 is larger than Image 1, parts of it will be cropped (which aligns with your desired effect).

Alternative: Overlay Image 2 Centered on Image 1

If you want to keep Image 1 as the background and paste Image 2 centered on top (instead of just shifting Image 2), use this method:

# Get dimensions of Image 2
rows2, cols2 = img2.shape[:2]

# Calculate top-left corner of Image 2 when centered on Image 1
x_offset = center1[0] - cols2 // 2
y_offset = center1[1] - rows2 // 2

# Ensure we don't go outside Image 1's bounds
x1 = max(0, x_offset)
y1 = max(0, y_offset)
x2 = min(img1.shape[1], x_offset + cols2)
y2 = min(img1.shape[0], y_offset + rows2)

# Calculate the corresponding region to take from Image 2
img2_x1 = max(0, -x_offset)
img2_y1 = max(0, -y_offset)
img2_x2 = cols2 - max(0, x_offset + cols2 - img1.shape[1])
img2_y2 = rows2 - max(0, y_offset + rows2 - img1.shape[0])

# Paste Image 2 onto Image 1
overlay_result = img1.copy()
overlay_result[y1:y2, x1:x2] = img2[img2_y1:img2_y2, img2_x1:img2_x2]

This overlays Image 2 centered on Image 1, clipping any parts that go outside Image 1's edges.

Full Working Code

Here's the complete script putting it all together:

import cv2
import numpy as np
import os

def get_image_center(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 120, 255, 1)
    contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    main_contour = max(contours, key=cv2.contourArea)
    M = cv2.moments(main_contour)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    return (cX, cY)

# Load your images
img1 = cv2.imread(os.path.expanduser('~\\Desktop\\c1.png'))
img2 = cv2.imread(os.path.expanduser('~\\Desktop\\c2.png'))  # Replace with your Image 2 path

# Get centers
center1 = get_image_center(img1)
center2 = get_image_center(img2)

# Option 1: Shift Image 2 to align its center with Image 1's
dx = center1[0] - center2[0]
dy = center1[1] - center2[1]
translation_matrix = np.float32([[1, 0, dx], [0, 1, dy]])
aligned_img2 = cv2.warpAffine(img2, translation_matrix, (img1.shape[1], img1.shape[0]))

# Option 2: Overlay Image 2 centered on Image 1
rows2, cols2 = img2.shape[:2]
x_offset = center1[0] - cols2 // 2
y_offset = center1[1] - rows2 // 2
x1, y1 = max(0, x_offset), max(0, y_offset)
x2, y2 = min(img1.shape[1], x_offset + cols2), min(img1.shape[0], y_offset + rows2)
img2_x1, img2_y1 = max(0, -x_offset), max(0, -y_offset)
img2_x2, img2_y2 = cols2 - max(0, x_offset + cols2 - img1.shape[1]), rows2 - max(0, y_offset + rows2 - img1.shape[0])
overlay_result = img1.copy()
overlay_result[y1:y2, x1:x2] = img2[img2_y1:img2_y2, img2_x1:img2_x2]

# Save or display results
cv2.imwrite('aligned_image2.png', aligned_img2)
cv2.imwrite('overlay_result.png', overlay_result)
cv2.imshow('Aligned Image 2', aligned_img2)
cv2.imshow('Overlay Result', overlay_result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Quick Notes

  • Contour Selection: If your image has multiple contours and you don't want the largest one, adjust the get_image_center function to pick the right contour (e.g., filter by area, shape, etc.).
  • Coordinate System: Remember OpenCV uses top-left as (0,0), so positive dy shifts down, positive dx shifts right.
  • Cropping: The first option (warpAffine) will crop Image 2 if it's larger than Image 1. The overlay option does the same but keeps Image 1 as the background.

内容的提问来源于stack exchange,提问作者Luca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:30:17