Unfortunately, I couldn't find anything towards this topic so here goes:
I have an image as a numpy array containing masks for different nuclei of cells as integer numbers that looks like this:
https://i.stack.imgur.com/nn8hG.png
The individual masks have different values and the background is 0. Now for every mask in that image I would like to get the identity of other touching masks (if there are any). What I have so far is code that gets the pixel positions of every masks value (via the argwhere function) and checks whether any pixel in the 8 surrounding pixels is not 0 or its own value.
for i in range(1, np.max(mask_image+1)):
coordinates = np.argwhere(mask_image==i)
touching_masks = []
for pixel in coordinates:
if mask_image[pixel[0] + 1, pixel[1]] != 0 and mask_image[pixel[0] + 1, pixel[1]] != i:
touching_masks.append(mask_image[pixel[0] + 1, pixel[1]]) #bottom neighbour
elif mask_image[pixel[0] -1, pixel[1]] != 0 and mask_image[pixel[0] -1, pixel[1]] != i:
touching_masks.append(mask_image[pixel[0] -1, pixel[1]]) #top neighbour
elif mask_image[pixel[0], pixel[1]-1] != 0 and mask_image[pixel[0], pixel[1]-1] != i:
touching_masks.append(mask_image[pixel[0], pixel[1]-1]) #left neighbour
elif mask_image[pixel[0], pixel[1] + 1] != 0 and mask_image[pixel[0], pixel[1] + 1] != i:
touching_masks.append(mask_image[pixel[0], pixel[1] + 1]) #right neighbour
elif mask_image[pixel[0] + 1, pixel[1] + 1] != 0 and mask_image[pixel[0] + 1, pixel[1] + 1] != i:
touching_masks.append(mask_image[pixel[0] + 1, pixel[1] + 1]) #bottom-right neighbour
elif mask_image[pixel[0] - 1, pixel[1] - 1] != 0 and mask_image[pixel[0] - 1, pixel[1] - 1] != i:
touching_masks.append(mask_image[pixel[0] - 1, pixel[1] - 1]) #top-left neighbour
elif mask_image[pixel[0] + 1, pixel[1] - 1] != 0 and mask_image[pixel[0] + 1, pixel[1] - 1] != i:
touching_masks.append(mask_image[pixel[0] + 1, pixel[1] - 1]) #bottom-left neighbour
elif mask_image[pixel[0] - 1, pixel[1] + 1] != 0 and mask_image[pixel[0] - 1, pixel[1] + 1] != i:
touching_masks.append(mask_image[pixel[0] - 1, pixel[1] + 1]) #top-right neighbour
Since I have about 500 masks per image and a time series of about 200 images this is very slow and I would like to improve it. I tried a bit with regionprops, and skimage.segmentation and scipy but didn't find a proper function for that.
I would like to know whether
- there already is a pre-existing function that could do that (and which I blindly overlooked)
- one can retain only the positions of the argwhere function that are border-pixels of the mask and thereby reduce the number of input pixels for the checks of the surrounding 8 pixels. The condition being that these border-pixels always retain their original value as a form of identifier.
Any kind of advice is much appreciated!
A bit more background information about why I am trying to do this:
I am currently acquiring timelapses of multiple cells over the course of various hours. Sometimes after cell division the two daughter nuclei stick to another and can be missegmented as one nucleus or proeprly as two nuclei. This happens rarely, but I would like to filter out time-tracks of such cells that alternate between one or two masks. I also calculate the area of such cells, but filtering for unreasonable changes in mask area runs into two problems:
- Cells that wander into (or out of) the image can also display such size changes and
- misfocusing of the microscope can also result in smaller masks (and larger ones when the proper focus is achieved again). Unfortunately, this also happens with our microscope from time to time during tha timelapse. My idea was to get the identity of touching masks throughout the timelapse to have one more criteria to take into account while filtering out such cells.