OpenCV视频添加Logo呈现透明,需保留原始色彩的技术问题
问题描述
我有一个Logo,尝试将其添加到视频中。使用下方代码添加后,Logo无法显示原始色彩,呈现透明状态,但我不需要透明度,希望保留Logo的原始色彩格式。
当前显示效果:
我的代码如下:
img_path = 'ap_logo.png' logo = cv2.imread(img_path,cv2.IMREAD_UNCHANGED) # # watermark = image_resize(logo, height=300) watermark = cv2.cvtColor(watermark, cv2.COLOR_BGR2BGRA) watermark_h, watermark_w, watermark_c = watermark.shape ret, frame = cap.read() frame = cv2.flip(frame, 1) frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE) frame_h, frame_w, frame_c = frame.shape # # overlay with 4 channel BGR and Alpha overlay = np.zeros((frame_h, frame_w, 4), dtype='uint8') for i in range(0, watermark_h): print(i) for j in range(0, watermark_w): if watermark[i, j][3] != 0: h_offset = frame_h - watermark_h w_offset = frame_w - watermark_w overlay[h_offset + i, w_offset + j] = watermark[i, j] while(True): ret, frame = cap.read() frame = cv2.flip(frame, 1) frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE) frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA) cv2.addWeighted(overlay, 0.25, frame, 1.0, 0, frame) # Display the resulting frame frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR) if ret: cv2.imshow('Frame', frame) out.write(frame) # file a ilgili frame yazılıyor if cv2.waitKey(1) & 0xFF == ord('q'): break #When everything done, relase the capture cap.release() out.release() # saved cv2.destroyAllWindows()
解决方案
问题根源:
cv2.addWeighted中给overlay设置了0.25的权重,导致Logo与视频帧混合,产生透明效果;- 冗余的BGRA格式转换和Alpha通道处理,进一步弱化了Logo的色彩表现。
修改方案:
- 读取Logo时放弃Alpha通道,用
cv2.IMREAD_COLOR替代cv2.IMREAD_UNCHANGED; - 移除所有与BGRA、Alpha通道相关的代码;
- 直接将Logo像素覆盖到视频帧的对应位置,完全保留原始色彩。
修改后的完整代码:
import cv2 import numpy as np # 补充原代码中未给出的image_resize函数 def image_resize(image, height=None, width=None, inter=cv2.INTER_AREA): dim = None (h, w) = image.shape[:2] if height is None and width is None: return image if height is not None: r = height / float(h) dim = (int(w * r), height) else: r = width / float(w) dim = (width, int(h * r)) return cv2.resize(image, dim, interpolation=inter) img_path = 'ap_logo.png' # 读取Logo时不保留Alpha通道 logo = cv2.imread(img_path, cv2.IMREAD_COLOR) watermark = image_resize(logo, height=300) watermark_h, watermark_w = watermark.shape[:2] # 初始化视频捕获(可替换为本地视频路径) cap = cv2.VideoCapture(0) # 初始化视频写入器(参数根据实际视频尺寸、帧率调整) fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480)) while True: ret, frame = cap.read() if not ret: break frame = cv2.flip(frame, 1) frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE) frame_h, frame_w = frame.shape[:2] # 计算Logo放置位置(右下角) h_offset = frame_h - watermark_h w_offset = frame_w - watermark_w # 直接将Logo覆盖到帧上对应区域 frame[h_offset:h_offset+watermark_h, w_offset:w_offset+watermark_w] = watermark # 显示帧并写入视频文件 cv2.imshow('Frame', frame) out.write(frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放资源 cap.release() out.release() cv2.destroyAllWindows()
如果你的Logo原本带有透明背景,且希望保留背景透明但Logo主体色彩不透明,可以保留Alpha通道处理,但调整cv2.addWeighted的权重为1.0,同时确保Logo的Alpha通道仅控制背景透明。但根据你的需求,直接覆盖像素是最直接保留原始色彩的方式。
内容的提问来源于stack exchange,提问作者CKocar
相关产品推荐
相关产品推荐

