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

OpenCV视频添加Logo呈现透明,需保留原始色彩的技术问题

问题描述

我有一个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()
解决方案

问题根源:

  1. cv2.addWeighted 中给overlay设置了0.25的权重,导致Logo与视频帧混合,产生透明效果;
  2. 冗余的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 21:45:29