Celltracker possibilities?

Hi im a student and was wondering if this would be a good language to make a program that tracks cells in a video rather than python or MATLAB. If so I was wondering where I should start.
Thanks!

1 Like

Welcome! You might consider using VideoIO.jl to load the video (depending on its format), and the JuliaImages suite should provide you with a lot of tools. In particular there is ImageTracking, which might get you much of the way there…and if not, might be a good place to submit improvements.

5 Likes

I have something, pester me to not to forget it: We track cells by doing watershed algorithm with https://juliaimages.org/v0.20/imagesegmentation/ on a transformation of the 3d array of image frames and got something working

3 Likes

We have 3d image data for `cell`s and 3d image data for `nucleus`.
Think of the cells creating worms in the space-time picture (the third axis is the time).

After some preprocessing (e.g. `imfilter!` with `Kernel.gaussian((2,2,0))`),
we start finding cells in the first frame by doing a feature transform on their nuclei:

``````using Images, ImageSegmentation, ImageFiltering
seeds1_ = distance_transform(feature_transform((nucleus[:,:,1]) .< t1))) .> t2
seeds1 = (label_components(seeds1_))
``````

I typically use a Makie script to find good thresholds:

``````
println("Sliders to tune thresholds")
t1slider, t1_ = textslider(0.01:0.01:1.0, "t1", start = t1);
t2slider, t2_ = textslider(0.01:0.01:1.0, "t2", start = t2);
seed_img = lift(t1_, t2_) do t1, t2
nlz(distance_transform(feature_transform(testimage) .< t1))) .> t2
end
p3 = hbox(image(seed_img), t1slider, t2slider)
``````

The next step puts the recognised nuclei into the picture and fixes some background pixels

``````seeds = zeros(UInt16, m, n, T)
seeds[:,:,1] = seeds1
seeds[end,1,1] = seeds[1,end,1] = seeds[end,end,1] = seeds[1,1,1] = maximum(seeds1) + 1
``````

Then I am segmenting the cells on a picture with cell boundaries being the “walls” separating cell-interiors and background through watershed

``````nlz(x, (a,b) = (minimum(x), maximum(x)), (c,d) = (zero(eltype(x)), one(eltype(x)))) = clamp.(c .+ (x .- a) .* ((d-c)/(b-a)), c, d)
cell2 = N0f16.(1 .-nlz(abs.(cell  .- t))) # normalize
segments = watershed(cell2, seeds)
``````

Basically I am flooding the worms and the outside.

Later I will explain the post processing giving me the cell trajectories.

1 Like

Tracking cells should be similar like tracking bugs, so I’ll @yakir12 too.

3 Likes

That goes for all of Julia - when you start out it can be frustrating to get ll the packages installed which you need. Please do not give up in despair - come back here and ask. We are a friendly group of people and an expert will guide you.

2 Likes

Tons of great stuff already. To address the OP’s specific question, yes, the future is definitely in Julia rather than Matlab and Python. That is my very opinionated opinion. Having said that, you might find more complete solutions elsewhere, but if you’re into some image analysis then please do give it a try. Images.jl is very complete and faaaaaast. And @mschauer showed how to get far with just a few LOC. And I need to check out https://github.com/JuliaImages/ImageTracking.jl !!!
Things are happening very quickly here and I’d say that Julia is the best bet in the long run for a student to get into.

4 Likes

Thanks everyone for all the recommendations seems like I have some stuff to look into. Definitely looks like a great community here time to start using Julia!

1 Like

Hi thanks for the info would there be a way to plot the path of the cells on a graph that you are aware of ?

Yeah, so I check which cells are in the first and the last frame and did not leave the image and create

``````background = argmax(segments.segment_pixel_count)
labels_ = unique(seeds1)
surv = intersect(segments.image_indexmap[:,:,end], setdiff(labels_, background))
surv = sort(surv)
K = length(surv)
survkey = [searchsorted(surv, i) for i in segments.segment_labels]
``````

and then I aggregate for example average location at each frame for each cell. I do that with something like below… careful, I deleted some lines so I hope those lines which are left make a meaningful program

``````function fillseries(segments, survkey, cells)
m, n, T = size(cells)
K = sum(.!isempty.(survkey))
cell_indsum = [(0,0) for k in 1:K, t in 1:T]
cell_count = zeros(Int, K, T)
for t in 1:T
for i in 1:m, j in 1:n
k = survkey[segments.image_indexmap[i,j,t]]
isempty(k) && continue
cell_indsum[k[], t] = cell_indsum[k[], t] .+ (i, j)
cell_count[k[], t] += 1
end
end
cell_center = map((nc, np) -> nc./np, cell_indsum, cell_count)

cell_center
end

``````

Hi sorry for the late response. So I tried to do a background subtraction of sorts but I have dead cells which are much darker than the light cells. I was wondering if there was documentation or how you would go about doing the analysis by size of the object. I attached an image below for reference. Thanks so much for your help!

Have you had a look at this?

1 Like