使用 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)
...
使用 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)
...