如何从 skimage.measure 中消除 compare_ssim 的 SSIM 图像输出中差异周围的边缘

Posted

技术标签:

【中文标题】如何从 skimage.measure 中消除 compare_ssim 的 SSIM 图像输出中差异周围的边缘【英文标题】:How to eliminate the edges surrounding the differences in the SSIM image output of compare_ssim from skimage.measure 【发布时间】:2020-10-30 10:45:01 【问题描述】:

我正在尝试编写一个代码来计算显微镜图像上轨道所占据的区域,如下所示:

由于轨道不均匀(我的意思是,它们没有独特的灰度,因为它们在边缘较暗,在中心较亮),我不能仅通过比较它们的灰度来做到这一点背景的灰度,因为在轨道的某些部分它是相同的。

因此,我尝试将图像与背景图像进行比较:

我这样做是为了提取这两个图像之间的差异(对应于轨道本身)。为了做到这一点,我使用了 skimage 的 compare_ssim 函数。我使用的代码如下:

from skimage.measure import compare_ssim 
import imutils
import cv2
import numpy as np

# load the two input images
imageA = cv2.imread("./b.jpg")
imageB = cv2.imread("./a.jpg")
# convert the images to grayscale
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
    
# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
# show the diff image
cv2.imshow("Diff", diff)

我得到的差异图如下:

这个挺好的,因为现在轨道中的灰度和背景的灰度有很好的区分,我可以计算出轨道占据的面积(轨道中有些点比较亮,但他们很少,这对我来说没问题)。

然而,问题在于,在 diff 图像中,不仅轨迹显示为黑色,而且轨迹周围还有一个粗边框:

这条边使我的面积估计不正确。 所以我想知道我怎样才能消除这个边缘,或者至少让它变薄。

如果这是不可能的,如果你能告诉我另一个 Python 函数,它可以实现我计算轨道占用面积的目的,那将是非常有帮助的。

【问题讨论】:

【参考方案1】:

总是有更好的方法来做同样的事情,但我在这里使用了一种简单的方法,您可以根据自己的需要进行改进或调整:


算法:

    首先,适当的阈值将只保留边缘 其次,形态学(膨胀或腐蚀,取决于您的阈值方法)会使边缘变薄。 最后,要清除所有内容,除了您的足迹,您可以使用 Flood_Fill 算法,然后计算白色像素以获得您的区域(以像素为单位)。

结果:

在最终结果中: The count of the white of pixels is: 52219


代码:

#========================
# Import Libraries
#========================
import numpy as np
import matplotlib.pyplot as plt
import cv2
from skimage.morphology import flood_fill

#========================
# Read images
#========================
img = cv2.imread('1.png',0)
bck = cv2.imread('2.png',0)

#========================
# Gaussian Blur
#========================
gauss = cv2.GaussianBlur(img, (5,5), 1)
bck_gauss = cv2.GaussianBlur(bck, (5,5), 1)
#========================
# Thresholding
#========================
_,thresh1 = cv2.threshold(gauss,127,255,cv2.THRESH_BINARY)
_,bck_th = cv2.threshold(bck_gauss,127,255,cv2.THRESH_BINARY_INV)

# Get rid of black borders
thresh1 = thresh1 + bck_th

#========================
# Morphology
#========================
kernel = np.zeros((7,7),np.uint8)
kernel[2,:] = 1
kernel[:,2] = 1
dilation = cv2.dilate(thresh1,kernel,iterations = 1)

#========================
# Flood Fill 
#========================

res = flood_fill(dilation,(1,1), 0)
print("The count of the white of pixels is: ", int(np.sum(res)/np.max(res)))
#========================
# Visualize Results
#========================
plt.figure(num='Blobs')

plt.subplot(221)
plt.imshow(img, cmap='gray')
plt.title('Original')
plt.axis('off')

plt.subplot(222)
plt.imshow(thresh1, cmap='gray')
plt.title('Thresholded')
plt.axis('off')

plt.subplot(223)
plt.imshow(dilation, cmap='gray')
plt.title('Morphology')
plt.axis('off')

plt.subplot(224)
plt.imshow(res, cmap='gray')
plt.title('Final Result')
plt.axis('off')

plt.show()

【讨论】:

以上是关于如何从 skimage.measure 中消除 compare_ssim 的 SSIM 图像输出中差异周围的边缘的主要内容,如果未能解决你的问题,请参考以下文章

Skimage.draw.ellipse产生了两条不受欢迎的线。

边缘与轮廓

如何从GCC /铿锵声组件输出中消除“噪音”?

如何使用C ++消除记事本.txt文件中的BOM? [重复]

概率图模型(推理:变量消除)

概率图模型(推理:变量消除)