cv2 和 QPixmap/QImage 中的不同颜色

问题描述 投票:0回答:1

我正在尝试使用 Python 和 PyQt6 构建一个简单的图像编辑器应用程序。目前,TIFF 图像是使用 cv2.imread() 加载的。然后,用户可以进行多项调整(对比度、颜色等)。最后,使用 cv2.imwrite() 保存图像。这部分工作得很好。 对于 GUI,图像先转换为 QImage,然后转换为 QPixmap,然后显示在 GUI 上的 QLabel 上。

问题:导出图像的颜色与 GUI 上显示的图像略有不同。差异是微妙的。但是,显然,对于图像编辑器应用程序,我希望预览图像看起来与最终输出相同。

如果我运行以下代码,问题很容易看出:

image_data = cv2.imread("Color_Adobe.tif")
cv2.imshow("CV2", image_data)

#convert to QImage:
h,w,_ = image_data.shape
bytesPerLine = 3 * w
image = QImage(image_data, w, h, bytesPerLine, QImage.Format.Format_RGB888).rgbSwapped()
pixmap = QPixmap(image)

#set pixmap to QLabel
label.setPixmap(self.pixmap)

此处加载的图像是比色图表的 .TIF 图像。我得到的输出如下:

CV2 与 Pixmap 输出: CV2 vs Pixmap Output

上面是 cv2.imshow() 输出,下面是我的 GUI 中带有 Pixmap 的 QLabel。正如您所看到的,颜色的渲染方式完全不同。一般来说,像素图输出看起来稍微偏红。

查看左下角的红色方块,我在屏幕 (Mac) 上使用 DigitalColorMeter 获得以下读数: CV2:236 56 30 像素图:255 0 0 (RGB)

我认为这与不匹配的色彩空间有关 - 但我只是无法理解到底发生了什么。

如何确保像素图以与 cv2.imshow() 输出相同的方式显示?或者是否有不同/更好的方式在 GUI 中显示图像?

谢谢你。

opencv image-processing pyqt6 qimage qpixmap
1个回答
0
投票

好吧,我终于明白了。事实证明,当您使用 cv2.imshow() 时,图像将使用显示器特定的 ICC 配置文件显示。但是,当通过 Pixmap 显示同一图像(在同一屏幕上)时,将使用标准 sRGB 色彩空间。为了解决这个问题,我首先将图像转换为 PIL 图像,加载 ICC 配置文件(sRGB 和显示器特定)并转换颜色空间。然后转换为 Pixmap 并显示在我的 GUI 上。这样,Pixmap 最终看起来与 imshow() 输出相同。

        image_data = cv2.imread("Color_Adobe.tif")

        #CV2 Output
        cv2.imshow("CV2", image_data)

        image_data = cv2.cvtColor(image_data, cv2.COLOR_RGB2BGR)

        
        PIL_image_sRGB = PIL.Image.fromarray(image_data)

        #Path to sRGB ICC Profile
        src_profile_path = "/Library/ColorSync/Profiles/sRGB.icc"

        # Path to Monitors specific ICC Profile
        dst_profile_path = "/Library/ColorSync/Profiles/Displays/HP U32 4K HDR-11C013E4-4731-AAD9-78F8-9D92871BECD3.icc"

        #Open profiles in PIL
        dst_profile = PIL.ImageCms.getOpenProfile(dst_profile_path)
        src_profile = PIL.ImageCms.getOpenProfile(src_profile_path)

        #convert color spaces to new ICC
        PIL_image_ICC = PIL.ImageCms.profileToProfile(PIL_image_sRGB, src_profile, dst_profile)

        #convert back to numpy array
        image_data = np.array(PIL_image_ICC)


        #convert to QImage
        h,w,_ = image_data.shape
        bytesPerLine = 3 * w
        image = QImage(image_data, w, h, bytesPerLine, QImage.Format.Format_RGB888)
        
        #convert to pixmap
        pixmap = QPixmap(image)    
        label.setPixmap(pixmap)
© www.soinside.com 2019 - 2024. All rights reserved.