使用 openCV 保存图像时颜色错误

wrong colors when saving image with openCV

使用 openCV,当我使用 openCV 以 .png 格式保存处理后的图像时,我得到的颜色与在屏幕上显示时的颜色不同。

(代码在消息末尾)

这是我通过 cv2.imshow('after', after) 在屏幕上显示图像得到的结果(这就是我想要的):

这是我用 cv2.imwrite("debug.png", after) 将相同图像保存为 .png 得到的结果(这不是我想要的):

盒子和中心好像是透明的,因为当我在vs code上打开.png时,它们是黑色的像vs code背景(见上图),但是当我在windows Photos中打开它时软件,它们是白色的(见下图)

这是我的代码,它是 this post and this post 之间的一种融合。它在两个图像之间的差异周围绘制绿色框,并绘制每个差异的中心:

def find_diff(before, after):
    before = np.array(before)
    after = np.array(after)

    # 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((cY,cY)) 
            cv2.circle(after, (cX, cY), 2, (320, 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)
    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)

我不知道是哪一步出错了。调用 .circle().rectangle().

时,我确实给出了绿色和蓝色

正如@fmw42 在问题评论部分指出的那样, 我在 mss ScreenShot 对象上调用 np.array() 并期望它们开箱即用。 事实证明 ScreenShot class 以特定格式存储图像数据,并且当 np.array() 操作实例对象时,它使用不同的格式来管理图像通道,特别是 alpha 通道。

所以解决方案是首先转换 Image 对象中的 mss ScreenShot 对象以兼容的方式保存图像数据,以便 np.array() 处理它们:

def find_diff(before, after):
    before = Image.frombytes("RGB", before.size, before.bgra, "raw", "BGRX")
    after = Image.frombytes("RGB", after.size, after.bgra, "raw", "BGRX")
    before = np.array(before)
    after = np.array(after)
    ...