skimage.io.imread 与 cv2.imread 的比较

5

我使用并熟悉 cv2,今天我尝试了一下 skimage

我试着用 skimagecv2 读取一张图片。它们都能完美地读取图片,但是当我通过不同的库(skimagecv2)绘制图像的直方图时,直方图显示出了显著的差异。

有人可以帮忙解释一下这两个直方图之间的差异吗?

我的代码:

import cv2
import skimage.io as sk
import numpy as np
import matplotlib.pyplot as plt

path = '../../img/lenna.png'

img1 = sk.imread(path, True)
img2 = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
print(img1.shape)
print(img2.shape)

plt.subplot(2, 2, 1)
plt.imshow(img1, cmap='gray')
plt.title('skimage read')
plt.xticks([])
plt.yticks([])

plt.subplot(2, 2, 2)
plt.imshow(img2, cmap='gray')
plt.title('cv2 read')
plt.xticks([])
plt.yticks([])

plt.subplot(2, 2, 3)
h = np.histogram(img1, 100)
plt.plot(h[0])
plt.title('skimage read histogram')

plt.subplot(2, 2, 4)
h = np.histogram(img2, 100)
plt.plot(h[0])
plt.title('cv2 read histogram')

plt.show()

文本输出:

(512, 512)
(512, 512)

输出:

代码输出



编辑:

这是输入图像:


请问您能否打印出两张图像的 np.mean()np.std() 值,以便我们可以确定差异是在加载和灰度转换中还是在直方图生成和显示中?此外,如果您能分享您使用的实际 Lena 图像,那将会很有帮助。 - Mark Setchell
1
你应该注意到,OpenCVskimage使用基本不同的图像表示方式。OpenCV倾向于使用范围在[0..255]的8位无符号整数,而skimage则倾向于使用范围在[0..1]的浮点数。 - Mark Setchell
非常感谢。正如您所提到的,强度范围差异是原因,我已经理解了。这里有np.meannp.std,它们告诉了很多。skimage mean: 0.4578778306070963 skimage std: 0.19380367354500247 cv2 mean: 123.54518127441406 cv2 std: 47.853738824592234 - Arafat Hasan
计算分位数有大约7种不同的方法。不出所料,不同的库之间的直方图可能会有很大的差异。 - undefined
1个回答

5
这两个 imread 函数只是在读取图像时有不同的默认格式。 skimage.io 的标准使用 64 位浮点数,而 cv2 的标准似乎是无符号字节。
您可以通过将 img1 转换为无符号字节格式来查看这一点。
import skimage as skk
img1 = skk.img_as_ubyte(img1)

现在你将得到相似的直方图。它们不完全相同,因为它们最初是以不同的格式读取的。

img


非常感谢。我想我已经理解了原因。目前还存在差异,这是因为转换时存在精度损失,不是吗? - Arafat Hasan
1
是的,这也是如此。在读取无符号字节(在OpenCV的情况下)或转换为无符号字节(如上所示)时,您将始终丢失一些精度。不同之处在于您如何丢失精度。在OpenCV的情况下,您会丢失精度,因为您正在尝试将.png文件格式表示为字节数组。在使用img_as_ubyte进行转换的scikt中,您会丢失精度,因为您正在从浮点数转换为字节。希望这能让事情更清楚。 - meph
1
关于.png格式的外观,这只是一个想法:https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_format - meph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接