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

为何cv2.addWeighted中alpha值不更新,网格矩形透明度一致?

问题描述

我尝试在实时摄像头视频上叠加矩形网格,各矩形需根据normran数组的归一化值呈现不同透明度(本次测试未启用动态效果)。但所有矩形透明度均相同,代码循环执行正常,最终画面仅应用normran最后一个元素对应的alpha值。

原代码

#===========================================================================================================================
# Import Necessary Libraries

import cv2 as cv
import numpy as np
from sklearn import preprocessing
import math
import itertools
  
#===========================================================================================================================
# Define a Video Capture

vid = cv.VideoCapture(0)

#===========================================================================================================================
# Initialize

height = int(input('Define Number of Rows: '))
width = int(input('Define Number of Columns: '))
hxw = height * width

#===========================================================================================================================
# Create a Random Number Array

randnums= np.random.randint(1,30000,(hxw))
normran = (randnums - randnums.min())/((randnums.max() - randnums.min()))
        
print(normran)

#===========================================================================================================================
# Create a Color Map

def colorgrid(img, normran):
    
    h, w, _ = img.shape
    
    dy = h / height
    dx = w / width

    g = np.linspace(0, w-dx, width)
    b = np.linspace(g[1], w, width)
    t = np.linspace(0, h-dy, height)
    k = np.linspace(t[1], h, height)
    
    overlay = img.copy()
    
    thickness = 2
    color3 = (0, 0, 0)
            
    color2 = (0, 0, 255)
    thickness1 = -1
    
    i = -1
    
    for spy, spay in itertools.product(t, k):
        for spx, spax in itertools.product(g, b):
            
            i = i + 1
            alpha = normran[i]
            
            spx = int(round(spx))
            spax = int(round(spax))
            spy = int(round(spy))
            spay = int(round(spay))
                
            startx = (spx, spy)
            stopx = (spax, spay)
            
            print(alpha)
            print(i)
            
            cv.rectangle(overlay, startx, stopx, color2, thickness1)
            imgnew = cv.addWeighted(overlay, normran[i], img, 1, 0)
            cv.rectangle(img, startx, stopx, color3, thickness)
            
            if (i) == (hxw-1):
                i = -1
                break

    return imgnew

#===========================================================================================================================
# Use the Camera

while(True):
    
    # the 'q' button is set as the
    # quitting button you may use any
    # desired button of your choice
    if cv.waitKey(1) & 0xFF == ord('q'):
        break
      
    # Capture the video frame
    # by frame

    ret, frame = vid.read()
    
    frame = cv.flip(frame,1)

    clr = colorgrid(frame, normran)

    # Display the resulting frame
    cv.imshow('Test', clr)
      
# After the loop release the cap object
vid.release()
# Destroy all the windows
cv.destroyAllWindows()

输入3行3列时的输出示例

0.90409176345848
0
0.07855800279531544
1
0.4564557328064003
2
0.9938310280013495
3
0.0
4
0.16005590630873778
5
1.0
6
0.9541182707600366
7
0.1760566774302376
8
0.90409176345848
0
0.07855800279531544
1
0.4564557328064003
2
0.9938310280013495
3
0.0
4
0.16005590630873778
5
1.0
6
0.9541182707600366
7
0.1760566774302376
8

^^ this repeats infinitely

问题原因与修复方案

问题根源

原代码中每次循环都在同一个overlay图层上绘制矩形,然后调用cv.addWeighted将整个overlay与原图混合。这会导致后续矩形的绘制覆盖之前的透明度设置,最终只有最后一次混合操作的效果会保留在输出画面中。

修复后的代码

重点修改colorgrid函数,让每个矩形的透明度独立生效:

#===========================================================================================================================
# Import Necessary Libraries

import cv2 as cv
import numpy as np
from sklearn import preprocessing
import math
import itertools
  
#===========================================================================================================================
# Define a Video Capture

vid = cv.VideoCapture(0)

#===========================================================================================================================
# Initialize

height = int(input('Define Number of Rows: '))
width = int(input('Define Number of Columns: '))
hxw = height * width

#===========================================================================================================================
# Create a Random Number Array

randnums= np.random.randint(1,30000,(hxw))
normran = (randnums - randnums.min())/((randnums.max() - randnums.min()))
        
print(normran)

#===========================================================================================================================
# Create a Color Map

def colorgrid(img, normran):
    h, w, _ = img.shape
    dy = h / height
    dx = w / width

    # 生成所有网格的坐标,简化计算逻辑
    grid_coords = []
    for row in range(height):
        for col in range(width):
            x1 = int(col * dx)
            x2 = int((col + 1) * dx)
            y1 = int(row * dy)
            y2 = int((row + 1) * dy)
            grid_coords.append((x1, y1, x2, y2))
    
    # 初始化结果图为原图副本
    result = img.copy()
    thickness = 2
    color3 = (0, 0, 0)
    color2 = (0, 0, 255)
    thickness1 = -1
    
    # 遍历每个网格,独立计算透明度叠加
    for i, (x1, y1, x2, y2) in enumerate(grid_coords):
        alpha = normran[i]
        # 创建临时图层,绘制当前矩形
        temp_overlay = result.copy()
        cv.rectangle(temp_overlay, (x1, y1), (x2, y2), color2, thickness1)
        # 将当前矩形按alpha值混合到结果图
        result = cv.addWeighted(temp_overlay, alpha, result, 1 - alpha, 0)
        # 绘制矩形边框
        cv.rectangle(result, (x1, y1), (x2, y2), color3, thickness)
    
    return result

#===========================================================================================================================
# Use the Camera

while(True):
    if cv.waitKey(1) & 0xFF == ord('q'):
        break
      
    ret, frame = vid.read()
    frame = cv.flip(frame,1)
    clr = colorgrid(frame, normran)
    cv.imshow('Test', clr)
      
vid.release()
cv.destroyAllWindows()

修改说明

  1. 简化坐标计算:用行列循环直接生成每个网格的坐标,避免原代码中itertools.product和linspace导致的坐标重复或计算冗余问题
  2. 独立叠加每个矩形:为每个矩形创建临时图层,混合后更新结果图,确保每个矩形的透明度设置不会被后续操作覆盖
  3. 优化循环逻辑:去掉原代码中多余的i变量重置逻辑,用enumerate直接遍历网格坐标和normran数组

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:01:33