问题描述
目标:我的图像带有需要查找其区域的粒子。 ((array([],dtype=int32),array([],dtype=int64)),<class 'numpy.ndarray'> (512,512,3) <class 'tuple'>
)每个粒子还有四个到五个子区域,我需要知道它们的面积。想一想图片中一堆脱光的衬衫。我需要找到每件衬衫的面积,对于某件衬衫,我需要知道每条条纹的面积。问题是我需要知道条纹穿的是哪件衬衫。我需要知道较小区域对应的粒子。这样一来,我可以获得一个区域中每个子区域的面积百分比。
我只有一个大颗粒的灰度图像,所有覆盖子区域的图像以及每个子区域的图像。我创建了图像的简化模型。 [SubRegion1] [1] [SubRegion2] [2] [TotalAreaRegion] [3]
我尝试过的方法: 使用openCV进行分割,然后从scikit-image.org进行regionprops,我可以获得主要的粒径,长宽比等。 我无法做的是获取这些子区域的面积,并知道它们要去到哪个父粒子。如果需要,我会生成两个单独的标签列表。
代码:
#markers are the marked regions in the total image. red_markers are the marked sub-regions in the second image.
markers = cv2.watershed(crop_img,markers)
red_markers = cv2.watershed(red_crop_img,red_markers)
#if marker = 1,bg,then color
crop_img[markers == 1] = [0,255,255]
red_crop_img[red_markers == 1] = [0,255]
img2 = color.label2rgb(markers,bg_label=0)
red_img2 = color.label2rgb(red_markers,bg_label=0)
mask = red_markers == 255
masked_img = markers[mask] = 255
img3 = np.unique(masked_img,return_counts=True)
print(img3)
output: array[0]array[255]
'''
[1]: https://i.stack.imgur.com/wVef6.png
[2]: https://i.stack.imgur.com/AhqDZ.png
[3]: https://i.stack.imgur.com/cZWJC.png
解决方法
我对这个问题尚不完全清楚,但如果我正确理解以下内容,则应该起作用:
- 标记大颗粒灰度图像(
skimage.morphology.label
)中的颗粒 - 使用子区域蒙版之一屏蔽图像(您可以为此使用numpy索引,例如
label_image[mask]
) - 查看剩下的标签,这些标签标识与蒙版(
np.unique(label_image[mask])
)重叠的粒子 - 重复其余子区域
您可以测量np.unique(label_image,return_counts=True)
之类的区域。这将返回标签数组和具有该标签的像素数数组。同样,对于仅由mask定义的给定子区域中的像素,您可以测量np.unique(label_image[mask],return_counts=True)
之类的区域。
这里是MWE演示了这种方法
import numpy as np
import skimage.morphology
### Create example images
full_image = np.array(
[[ 255,255,0],[ 255,[ 0,255],255]],dtype='uint8')
subregion_image = np.array(
[[255,[255,[ 0,0]],dtype='uint8')
# Make format match that format (i.e. RGB) and datatype of OP
full_image = np.repeat(full_image[:,:,np.newaxis],3,axis=2).astype(dtype='int32')
subregion_image = np.repeat(subregion_image[:,axis=2).astype(dtype='int64')
### Simplify images
# If we know all three channels are the same it's easier (and equivalent) to have a single channel
full_image = full_image[:,0]
subregion_image = subregion_image[:,0]
# If we know values are all in the range 0 to 255 we may as well use uint8,miage not matter but it's
# generally helps avoid confusion when dealing with images to have intensity range and datatype match
full_image = full_image.astype('uint8')
subregion_image = subregion_image.astype('uint8')
### Solve the problem
# Label the particles in the large particle image
label_image = skimage.morphology.label(full_image)
# Create a mask for the sub-region
mask = subregion_image == 255
# See which labels remain,these labels identify the particles that overlap with the mask
print(np.unique(label_image[mask]))
# To measure the area we'll set pixels outside the subregion to 0 for background
label_image[~mask] = 0
# Count pixels belonging to each particle
particle_label,pixel_count = np.unique(label_image,return_counts=True)
print(particle_label)
print(pixel_count)
如果您有PIL图片或类似图片,则可能需要转换为numpy数组,例如your_image = np.array(your_image)
。
由于您将遍历子区域,因此如果您有数百万个子区域,则此方法可能不会很快。