我有一张电子显微镜图像,展示了生物系统中密集和稀疏层,如下所示。
这里涉及的层位于图像中间,从标签“re”附近开始,逐渐向左上方变细。我想要做到以下两点:1)统计黑暗/密集和明亮/稀疏层的总数
2)测量每层的宽度,给定右下角的黑色比例尺为1微米长
我一直在尝试用Python完成这个任务。如果我预先裁剪图像,只包含几个层的部分,例如这里显示的3个黑暗和3个明亮的层:
我可以使用以下代码计算层数:
import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage
from PIL import Image
tap = Image.open("VDtap.png").convert('L')
tap_a = np.array(tap)
tap_g = ndimage.gaussian_filter(tap_a, 1)
tap_norm = (tap_g - tap_g.min())/(float(tap_g.max()) - tap_g.min())
tap_norm[tap_norm < 0.5] = 0
tap_norm[tap_norm >= 0.5] = 1
result = 255 - (tap_norm * 255).astype(np.uint8)
tap_labeled, count = ndimage.label(result)
plt.imshow(tap_labeled)
plt.show()
然而,我不确定如何加入比例尺并测量我已经计算过的这些层的宽度。更糟糕的是,当分析整个图像以包括比例尺时,我甚至无法将这些层与图像中正在发生的其他事情区分开来。我非常感谢任何解决这个问题的见解。提前致谢。
编辑1:
到目前为止,我在这个问题上取得了一些进展。如果我事先裁剪图像,只包含一点点的层,我已经能够使用以下代码获取每个层的厚度。
import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage
from PIL import Image
from skimage.measure import regionprops
tap = Image.open("VDtap.png").convert('L')
tap_a = np.array(tap)
tap_g = ndimage.gaussian_filter(tap_a, 1)
tap_norm = (tap_g - tap_g.min())/(float(tap_g.max()) - tap_g.min())
tap_norm[tap_norm < 0.5] = 0
tap_norm[tap_norm >= 0.5] = 1
result = 255 - (tap_norm * 255).astype(np.uint8)
tap_labeled, count = ndimage.label(result)
props = regionprops(tap_labeled)
ds = np.array([])
for i in xrange(len(props)):
if i==0:
ds = np.append(ds, props[i].bbox[1] - 0)
else:
ds = np.append(ds, props[i].bbox[1] - props[i-1].bbox[3])
ds = np.append(ds, props[i].bbox[3] - props[i].bbox[1])
基本上,我发现了Python模块skimage,它可以取一个标记的图像数组并返回每个已标记对象的边界框的四个坐标。1 和 [3] 位置给出了边界框的 x 坐标,因此它们的差异确定了每个层在 x 方向上的范围。此外,for 循环的第一部分(if-else 条件语句)用于获取在每个黑暗/密集层之前的轻/稀层,因为只有黑暗层被 ndimage.label 标记。
不幸的是,这仍然不理想。首先,我希望不必预先裁剪图像,因为我打算对许多这样的图像重复此过程。我考虑到也许可以使用某种滤波器来突出层的(粗略的)周期性,但我不确定是否存在这样的滤波器?其次,上面的代码实际上只给出了每个层的相对宽度 - 我还没有找到一种方法来结合比例尺以获得实际宽度。