Hi Pieter,
The example you mentioned in the given link can be fine-tuned to better suit your video. There are 2 distinct phases of object tracking:
- Object detection and track creation (a track is a detected object and its position)
- Track creation (involves updating the position of the tracked object and deleting the track if the object disappears for a certain threshold of frames)
I could help you out with the object detection part as I don’t have your video it would be difficult for me to create one. However, I could create a single frame containing dots:
I = zeros(100,150, 'uint8');
I2 = imnoise(I, "salt & pepper", 0.01);
I3 = imdilate(I2, strel("square", 3));
There is a function named detectObjects in the example link you have shared, which does a poor job of preprocessing this image with morphological operations. Here is just the pre-processing part:
function mask = morph_ops1(mask)
mask = imopen(mask, strel('rectangle', [3,3]));
mask = imclose(mask, strel('rectangle', [15, 15]));
mask = imfill(mask, 'holes');
title('Original Morphological Operations')
The following is a template function for blob analysis you can use:
function plotBlobs(img, originalImage, border)
blobAnalyzer = vision.BlobAnalysis('BoundingBoxOutputPort', true, ...
'AreaOutputPort', false, ...
'CentroidOutputPort', true, ...
'MinimumBlobArea', 1, ...
[centroids, boxes] = step(blobAnalyzer, img);
rectangle('Position', boxes(i, :), 'EdgeColor', 'r');
plot(centroids(i,1), centroids(i,2), 'b.');
Let’s run blob analysis on the obtained image from the example’s preprocessing:
As you can see most of the nearby dots have been merged, and hence the blob analysis did a bad job. To tackle this, you can modify the code to apply a series of 2 gentle erode operation as follows:
I5 = imerode(I5, strel("square", 2));
I5 = imerode(I5, strel("square", 2));
Let us know find blobs:
We can also plot the blob centroids on top of the original image to see if it aligns with the dots:
plotBlobs(I5, I3, false);
After solving the object detection part, you can configure the Kalman filter of each dot by specifying different arguments:
- You could set the MotionModel argument based on the whether the dots move with a constant velocity or constant acceleration.
- The InitialLocation argument can be set to the centroid of the blob.
- Since the centroid locations doesn’t exactly match the dots’ location the InitialEstimateError argument can also be specified for the tracker to accommodate the error.
Details on other arguments of configureKalmanFilter can be seen here:
Based on how often dots eclipse or go out of the frame, you can also adjust the invisibleForTooLong and ageThreshold variables given in the example.
Regards.