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

Python实现图像旋转后填充黑边区域的技术方案问询

图像旋转后黑色区域的自内容填充方案

需求:对图像执行旋转操作后,用图像自身的内容填充旋转产生的黑色空白区域。

用户现有代码(已实现旋转并提取黑区Mask):

# 读取图像
img = cv2.imread("input.png")

# 获取图像尺寸
h, w = img.shape[:2]

# 定义旋转矩阵
M = cv2.getRotationMatrix2D((w/2, h/2), 30, 1)

# 执行旋转
rotated = cv2.warpAffine(img, M, (w, h))

mask = np.zeros(rotated.shape[:2], dtype=np.uint8)
mask[np.where((rotated == [0, 0, 0]).all(axis=2))] = 255
img_show(mask)

以下是两种更优的填充方案:

方案1:预扩展画布+旋转裁剪(高效简便)

核心思路:先将原图扩展为足够大的画布(确保旋转后不会出现黑边),在扩展画布上平铺原图内容,旋转后再裁剪回原尺寸,空白区域会被原图的重复内容自动填充。

实现代码:

import cv2
import numpy as np

# 读取图像
img = cv2.imread("input.png")
h, w = img.shape[:2]

# 计算原图对角线长度,作为扩展画布的最小边长
diag_len = int(np.sqrt(h**2 + w**2))
# 创建扩展画布,平铺原图内容(多铺一圈避免边缘空白)
extended = np.tile(img, (diag_len//h + 2, diag_len//w + 2, 1))
ext_h, ext_w = extended.shape[:2]

# 以扩展画布中心为旋转点生成旋转矩阵
M = cv2.getRotationMatrix2D((ext_w//2, ext_h//2), 30, 1)
# 旋转扩展后的图像
rotated_ext = cv2.warpAffine(extended, M, (ext_w, ext_h))

# 裁剪回原图像尺寸,取扩展画布的中心区域
x_start = (ext_w - w) // 2
y_start = (ext_h - h) // 2
final_img = rotated_ext[y_start:y_start+h, x_start:x_start+w]

# 展示结果
cv2.imshow("Final Result", final_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

方案2:基于Mask的反向映射填充(精准对应)

核心思路:利用旋转矩阵的逆矩阵,对每个黑区像素反向计算其在原图中的对应位置,用原图像素直接填充黑区,保证内容的映射连续性。

实现代码:

import cv2
import numpy as np

img = cv2.imread("input.png")
h, w = img.shape[:2]

# 生成旋转矩阵并执行旋转
M = cv2.getRotationMatrix2D((w/2, h/2), 30, 1)
rotated = cv2.warpAffine(img, M, (w, h))

# 获取黑区域Mask
mask = np.zeros(rotated.shape[:2], dtype=np.uint8)
mask[np.where((rotated == [0, 0, 0]).all(axis=2))] = 255

# 计算旋转矩阵的逆矩阵,用于反向映射
M_inv = cv2.invertAffineTransform(M)

# 遍历黑区像素,填充对应原图内容
for y in range(h):
    for x in range(w):
        if mask[y, x] == 255:
            # 计算该点在原图中的坐标
            orig_x = M_inv[0,0]*x + M_inv[0,1]*y + M_inv[0,2]
            orig_y = M_inv[1,0]*x + M_inv[1,1]*y + M_inv[1,2]
            # 坐标边界裁剪,避免超出原图范围
            orig_x_clamped = np.clip(int(round(orig_x)), 0, w-1)
            orig_y_clamped = np.clip(int(round(orig_y)), 0, h-1)
            rotated[y, x] = img[orig_y_clamped, orig_x_clamped]

# 展示结果
cv2.imshow("Final Result", rotated)
cv2.waitKey(0)
cv2.destroyAllWindows()

方案对比

  • 方案1:代码简洁、执行效率高,填充效果为原图平铺,适合对填充速度要求高、无需精准映射的场景。
  • 方案2:填充内容与原图旋转映射严格对应,效果更自然,但需要遍历像素,速度略慢,适合对填充连续性有要求的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:35:18