使用 skimage 与 open-cv 的图像的渐变和拉普拉斯

Gradients and Laplacian of an image using skimage vs. open-cv

提问人:user11634 提问时间:11/15/2023 最后编辑:Trenton McKinneyuser11634 更新时间:11/17/2023 访问量:41

问:

我使用 skimage 和 cv2 将图像的垂直和水平渐变以及拉普拉斯渐变与以下代码进行比较:

import sys
import matplotlib.pyplot as plt
from matplotlib.image import imread
import skimage
import cv2

def plot(ax, img, title):
    ax.imshow(img) # cmap = 'gray'
    ax.set_title(title)
    ax.set_xticks([])
    ax.set_yticks([])

img = imread("./strawberry.jpg")
laplacian = cv2.Laplacian(img,cv2.CV_32F)
sobelx = cv2.Sobel(img,cv2.CV_32F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_32F,0,1,ksize=3)

fig1 = plt.figure(figsize=(10, 10))
fig1.suptitle('cv2', fontsize=14, fontweight='bold')
ax = fig1.add_subplot(221)
plot(ax, img, 'Original')
ax = fig1.add_subplot(222)
plot(ax, laplacian, 'Laplacian')
ax = fig1.add_subplot(223)
plot(ax, sobelx, 'Sobel X')
ax = fig1.add_subplot(224)
plot(ax, sobely, 'Sobel Y')
fig1.set_tight_layout(True)

laplacian = skimage.filters.laplace(img,ksize=5)
sobelx = skimage.filters.sobel(img, axis=0)
sobely = skimage.filters.sobel(img, axis=1)

fig2 = plt.figure(figsize=(10, 10))
fig2.suptitle('skimage', fontsize=14, fontweight='bold')
ax = fig2.add_subplot(221)
plot(ax, img, 'Original')
ax = fig2.add_subplot(222)
plot(ax, laplacian, 'Laplacian')
ax = fig2.add_subplot(223)
plot(ax, sobelx, 'Sobel X')
ax = fig2.add_subplot(224)
plot(ax, sobely, 'Sobel Y')
fig2.set_tight_layout(True)

plt.show()

结果如下:

enter image description here

enter image description here

所以,它们是截然不同的。即使内核会有所不同,我也不会期望会有这样的差异。我的脚本中遗漏了什么吗?

蟒蛇 opencv matplotlib scikit-image 拉普拉斯语

评论

0赞 Christoph Rackwitz 11/16/2023
matplotlib 问题。弄清楚你绘制的事物的数据类型和值范围。
0赞 user11634 11/16/2023
事实上,数据类型起着一定的作用。cv2 似乎在内部将 img 从 uint8 提升到 float32,而 skimage 没有,我必须手动完成,即使用 img = img.astype(float) for skimage,我得到的渐变大致相同的图片。奇怪的是,如果我将像素值转换为 cv2 的浮点数,cv2 会拒绝计算梯度和拉普拉斯。
0赞 Christoph Rackwitz 11/16/2023
之所以会发生所谓的“内部升级”,是因为您传递了结果类型参数。拉普拉斯函数和 Sobel 函数都应该接受单个浮点数。我不知道他们是否会接受双浮动。实际拒绝将导致断言失败和回溯。CV_32F

答:

0赞 user11634 11/17/2023 #1

我发布的代码有两个问题。

首先,skimage 的拉普拉斯滤镜仅适用于灰度图像,不适用于彩色图像。对于改编,我遵循了将灰度滤镜调整为 RGB 图像,因此我们应该有

from skimage.color.adapt_rgb import adapt_rgb, each_channel

@adapt_rgb(each_channel)
def skimage_filters_laplace(img, ksize):
    return skimage.filters.laplace(img, ksize)

然后

laplacian = skimage_filters_laplace(img,ksize=3)

二是存在规模问题;如果我正确地将 cv2 的输出重新调整为 [0,1],那就没问题了。我发现使用的例子,似乎使用 matplotlib 渲染用 cv2 分析的图像会带来麻烦。cv2.Sobel()cv2.imshow()