0

TIF showing monocytes in 3D gel

my previous attempts

Long story short: I have a video of monocytes migrating in a 3D gel that is subdivided into 241 TIF files (each represents a specific moment in time). As you can see in the image, the monocytes (little circles) look very similar to the background. How can I process each TIF file using python to make the monocytes stand out from the background? Please be specific and explain all the necessary steps. My ultimate goal is to track the movement of those cells with something like OpenCV and sketch out their trajectories over time.

Previously I tried using skimage and holoviews, but I was unable to make the monocytes appear distinct from the background.

  • 1
    You may try `cv2.adaptiveThreshold` as in the [following answer](https://stackoverflow.com/a/72692465/4926757) (but with different parameters). Post some code that shows that it's not working, add OpenCV tag and hope that someone comes out with a solution... – Rotem Jun 22 '22 at 18:53
  • 2
    You mention a 3D gel and a movie and 241 TIFFs. Does each TIFF represent a different time? Or a different layer in 3D? Or a different part of a larger image? – Mark Setchell Jun 22 '22 at 19:00
  • 1
    you should try various "background subtraction/segmentation" algorithms. -- depending on how variable those critters' appearance is, you might also have success by detecting them, and then assembling detections into tracks. -- oh... and welcome, please take the [tour] and review [ask]. you seem to have some demands while not having shown that you did any research (googling) – Christoph Rackwitz Jun 22 '22 at 19:18
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Jun 22 '22 at 23:08

2 Answers2

1

I don't actually have a complete answer for you, but nobody said answers have to be complete and what I am suggesting may stimulate discussion and an exchange of ideas that gets you nearer a solution...

Firstly, I would look at your histogram:

enter image description here

You clearly have a low-contrast image with all brightnesses in the range around 64-88, i.e. 25% to 33% of the 0..255 range. So my first instinct is to stretch the contrast so that 64 becomes zero and 88 becomes 255. I am doing it with ImageMagick here because it is conceptual and you/we can do it with OpenCV later if necessary.

magick RPU7I.png -level 25,33% 1.jpg

enter image description here


We could then copy that image, blur it and subtract to remove the low-frequency background features. Firstly with a small blur:

magick 1.jpg \( +clone -blur 0x10 \) -compose difference -composite -auto-level 2.jpg

enter image description here


Then with a larger blur:

magick 1.jpg \( +clone -blur 0x80 \) -compose difference -composite -auto-level 3.jpg

enter image description here


Or, we could go back to our original contrast-stretched image 1.jpg and try CLAHE on that:

magick 1.jpg -clahe 20x20%+128+20 result.jpg 

enter image description here


Any image-processing wizards welcome to copy, steal, disagree, improve, extend, edit any concepts here...

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
1

Here is another approach using division normalization followed by some dynamic range stretching in Python/OpenCV.

  • Read the input
  • Convert to grayscale
  • Blur with relatively large sigma
  • Divide the blurred image by the input
  • Stretch the dynamic range
  • Save the result

Input:

enter image description here

import cv2
import numpy as np
import skimage.exposure

# load image
img = cv2.imread("monocytes.png")

# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# blur
blur = cv2.GaussianBlur(gray, (0,0), sigmaX=39, sigmaY=39)

# divide
divide = cv2.divide(blur, gray, scale=255)
divide = 255 - divide

# stretch
maxval = np.amax(divide)/4
stretch = skimage.exposure.rescale_intensity(divide, in_range=(0,maxval), out_range=(0,255)).astype(np.uint8)

# write result to disk
cv2.imwrite("monocytes_division.png", divide)
cv2.imwrite("monocytes_stretch.jpg", stretch)

# display it
cv2.imshow("gray", gray)
cv2.imshow("divide", divide)
cv2.imshow("stretch", stretch)
cv2.waitKey(0)
cv2.destroyAllWindows()

Stretched Result:

enter image description here

fmw42
  • 46,825
  • 10
  • 62
  • 80