OpenCV批量加水印工具调用addWeighted时报输入参数尺寸不匹配如何解决
报错根本原因
cv2.addWeighted 要求参与运算的两个矩阵必须满足完全相同的宽高尺寸、完全相同的通道数,你遇到的报错就是两个输入参数不满足这个要求导致的。
排查步骤
- 先验证尺寸是否匹配:批量处理的图片中存在尺寸小于logo的图片,你计算的roi切片坐标会超出原图边界,最终切出来的roi宽高和logo不一致。比如logo尺寸是200200,原图只有150150,切片得到的roi最大只有150*150,和logo尺寸不匹配。
- 再验证通道数是否匹配:存在两种可能,一是logo是带透明通道的4通道PNG,和3通道的原图roi通道数不一致;二是批量处理的图片中包含单通道灰度图,和3通道的logo通道数不一致。
修复方案
1. 尺寸适配逻辑
在切片roi前新增logo自动缩放、坐标边界校验逻辑,确保roi和参与运算的logo尺寸完全一致。
2. 通道统一逻辑
强制统一logo和所有待处理图片为3通道BGR格式,避免通道数不一致问题。
修复后完整代码
import cv2 import numpy as np import glob import os ## 导入并处理Logo,强制读取为3通道,忽略透明通道 logo = cv2.imread("logo.png", cv2.IMREAD_COLOR) h_logo, w_logo = logo.shape[:2] images_path = glob.glob("/Users/kylebaptist/Desktop/images/saved/*.*") # 提前创建输出目录避免报错 os.makedirs("/Users/kylebaptist/Desktop/images/saved/watermarked", exist_ok=True) for img_path in images_path: img = cv2.imread(img_path) # 单通道灰度图转3通道 if len(img.shape) == 2: img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) h_img, w_img = img.shape[:2] # 原图比logo小的话,等比缩小logo适配原图 current_logo = logo.copy() cur_h_logo, cur_w_logo = h_logo, w_logo if h_img < cur_h_logo or w_img < cur_w_logo: scale = min(h_img / cur_h_logo, w_img / cur_w_logo) cur_w_logo = int(cur_w_logo * scale) cur_h_logo = int(cur_h_logo * scale) current_logo = cv2.resize(current_logo, (cur_w_logo, cur_h_logo), interpolation=cv2.INTER_AREA) # 计算水印居中坐标,增加边界校验防止越界 center_y = int(h_img / 2) center_x = int(w_img / 2) top_y = max(0, center_y - int(cur_h_logo / 2)) left_x = max(0, center_x - int(cur_w_logo / 2)) bottom_y = min(h_img, top_y + cur_h_logo) right_x = min(w_img, left_x + cur_w_logo) # 裁剪roi和logo到完全相同的尺寸 roi = img[top_y: bottom_y, left_x: right_x] logo_cropped = current_logo[0: bottom_y - top_y, 0: right_x - left_x] # 水印融合 result = cv2.addWeighted(roi, 1, logo_cropped, 0.3, 0) img[top_y: bottom_y, left_x: right_x] = result filename = os.path.basename(img_path) # 输出到单独的watermarked目录,避免和原图混淆 cv2.imwrite(f"/Users/kylebaptist/Desktop/images/saved/watermarked/watermark_{filename}", img)
额外优化点
- 新增了输出目录自动创建逻辑,避免目录不存在导致的保存报错
- 输出文件单独保存在watermarked子目录,避免覆盖原图,也不会出现遍历的时候把已经生成的带水印的图再次加水印的问题
- logo缩放用了copy操作,不会修改原始logo的尺寸,适配不同大小的原图
内容的提问来源于stack exchange,提问作者Kyle
相关产品推荐
相关产品推荐

