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

OpenCV保存PNG图像时颜色与imshow显示不一致且区域透明问题

问题原因
  • mss库grab方法返回的图像为带alpha通道的BGRA四通道格式,你直接转换为numpy数组后,调用cv2.circle、cv2.rectangle时传入的是三通道BGR颜色值,OpenCV会默认将绘制区域的alpha通道赋值为0(全透明)。PNG格式支持透明通道,保存后不同查看工具的背景色不同,就会出现VSCode中显黑、系统照片应用中显白的差异;而cv2.imshow默认忽略alpha通道,所以显示效果符合预期。
  • 调用cv2.circle时传入的颜色值(320, 159, 22)存在超范围问题:8位图像的单通道颜色取值范围为0-255,320会被自动截断为64,实际绘制颜色和你预期的不一致。
  • 代码存在笔误:centers.append((cY,cY)) 错误,应该存储(cX, cY)才能拿到正确的中心点坐标。
修复方案

优先选择去掉alpha通道的方案,不需要透明效果的话更稳定,修改后的代码如下:

import numpy as np
import cv2
from skimage.metrics import structural_similarity
import mss
from time import sleep

def find_diff(before, after):
    # mss返回的是BGRA四通道,先转为BGR三通道,移除alpha通道
    before = np.array(before)
    before = cv2.cvtColor(before, cv2.COLOR_BGRA2BGR)
    after = np.array(after)
    after = cv2.cvtColor(after, cv2.COLOR_BGRA2BGR)

    # Convert images to grayscale
    before_gray = cv2.cvtColor(before, cv2.COLOR_BGR2GRAY)
    after_gray = cv2.cvtColor(after, cv2.COLOR_BGR2GRAY)

    # Compute SSIM between two images
    (score, diff) = structural_similarity(before_gray, after_gray, full=True)
    diff = (diff * 255).astype("uint8")

    # Threshold the difference image, followed by finding contours to
    # obtain the regions of the two input images that differ
    thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
    contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]

    centers = []
    for c in contours:
        area = cv2.contourArea(c)
        if area > 40:
            # Find centroid
            M = cv2.moments(c)
            cX = int(M["m10"] / M["m00"])
            cY = int(M["m01"] / M["m00"])
            # 修复坐标存储错误
            centers.append((cX,cY)) 
            # 修复颜色值超范围问题,BGR三个通道取值都控制在0-255之间
            cv2.circle(after, (cX, cY), 2, (220, 159, 22), -1) 
            
            #draw boxes on diffs
            x, y, w, h = cv2.boundingRect(c)
            cv2.rectangle(after, (x, y), (x + w, y + h), (36, 255, 12), 2)

    cv2.imwrite("debug.png", after)
    cv2.imshow('after', after)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    return centers


before = mss.mss().grab((466, 325, 1461, 783))
sleep(3)
after = mss.mss().grab((466, 325, 1461, 783))
relative_diffs = find_diff(before, after)

如果需要保留alpha通道,只需要将绘图的颜色值改为四通道,比如(36, 255, 12, 255),最后一位255代表完全不透明即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:24:02