I have a series of small images, stored as 2d numpy arrays. After applying a threshold, I turn the input image into a masked array (mask out values below threshold). Based on this, as shown in the plot below I end up with a number of different objects (2 sometimes more). How can I identify the object that is nearest to center of this masked image, and return an array containing only that object?
img = masked_array(
data=[[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, 1.0, 1.0, --, --, --, --,
--, --, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, 1.0, 1.0, 1.0, --, --, --, --,
--, --, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, 1.0, 1.0, 1.0, --, --, --, --,
--, --, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, 1.0, 1.0, --, --, --, --,
--, --, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, 1.0, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, 1.0, 1.0, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, 1.0, 1.0, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, 1.0, 1.0, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --],
[--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,
--, --, --, --, --, --, --, --]],
mask=[[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, False, False,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, False, False, False,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, False, False, False,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, False, False,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, False, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, False, False, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, False, False, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, False, False, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True],
[ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True]],
fill_value=1e 20)
CodePudding user response:
First of all you can use a connected-component algorithm to label each object.
Then, you can find the centre of each object. You can do that for all object at once using np.where
and np.add.reduce
followed by a division (to compute the mean of all the pixel of each object). For more information, please read this post.
Then, for each object you can compute the distance between the centre of each object and the centre of the masked image in order to select the object with the minimal distance (np.argmin
may help to do that easily).
Finally, you can find the mask of the selected object using just a np.where
based on the label of the most centred object obtained previously.
CodePudding user response:
3 steps involved here:
- get indexes of the center and of non-masked points
- get the closest point to the center
- get the "object" in which the point closest to the center belongs. You can get this using opencv connected components (or findContour)
Step 1
Getting indexes of non masked point to get the one closest to the center
>>> center = [[img.shape[1] // 2, img.shape[0] // 2]]
>>> center
[[20, 20]]
>>> indexes = np.array(list(zip(*img.nonzero())))
>>> indexes
array([[18, 25],
[18, 26],
[19, 24],
[19, 25],
[19, 26],
[20, 24],
[20, 25],
[20, 26],
[21, 25],
[21, 26],
[22, 19],
[23, 19],
[23, 20],
[24, 19],
[24, 20],
[25, 19],
[25, 20]], dtype=int64)
Step 2
Compute the distance. I'll use scipy for this
>>> from scipy.spatial.distance import cdist
>>> distance = cdist(indexes, center)
>>> distance
array([[5.38516481],
[6.32455532],
[4.12310563],
[5.09901951],
[6.08276253],
[4. ],
[5. ],
[6. ],
[5.09901951],
[6.08276253],
[2.23606798],
[3.16227766],
[3. ],
[4.12310563],
[4. ],
[5.09901951],
[5. ]])
>>> np.argmin(distance)
10
>>> distance[10]
array([2.23606798])
>>> closest_point = indexes[10]
>>> closest_point
array([22, 19], dtype=int64)
Step 3
Find the "object" ( = the connected component) closest to the center I'll use OpenCV for this
>>> import cv2
>>> N_cc, cc = cv2.connectedComponents(img.data.astype(np.uint8))
>>> N_cc
3 # 3 object on your image: the 2 'black' and the white one
>>> obj = np.array(
list(zip(*np.where(cc == cc[closest_point[0], closest_point[1]])))
)
>>> obj
array([[22, 19],
[23, 19],
[23, 20],
[24, 19],
[24, 20],
[25, 19],
[25, 20]], dtype=int64)