如何从 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产生了两条不受欢迎的线。