The code below:
reads in a number of png images, where the background is dark and objects of interest (here 3) are bright dots
determines in each image the coordinates and other information about the objects
tracks the objects by using
Nearest
Single image (reduced size, cropped) with 3 tiny bright objects (at upper corners and lower center):
Pixels of a single object:
The code below can only be used if the number of objects in each image is the same.
As output the objects' coordinates are printed before and after tracking.
9 test images (zipped) are located here: http://bit.ly/28J56Pd
The notebook file which contains the code can be downloaded here: http://goo.gl/WhS7eP
My question is: Where can the code be improved?
Especially: How can I combine all
ComponentMeasurement
calls and assign the results to the set of used arrays (now in single command lines)?
ChoiceDialog[{FileNameSetter[Dynamic[imageDir], "Directory"], Dynamic[imageDir]}];
SetDirectory[imageDir];
dirBase = FileNameTake[imageDir];
(*read in file names and determine number of files*)
fNames = FileNames["*.png"];
numFiles = Length[fNames];
(*find number of objects in first image*)
i = 1;
image = Import[fNames[[i]]];
t = FindThreshold[image, Method -> "Entropy"];
binImage = DeleteSmallComponents[Binarize[image, t], 8];
newImage = ImageMultiply[image, binImage];
numObjects = Length@ComponentMeasurements[newImage, "IntensityCentroid"][[All, 2]];
(*define arrays*)
coordinates = Array[0 &, {numFiles, numObjects, 2}];
threshold = Array[0 &, {numFiles, numObjects}];
equivalentDiskRadius = Array[0 &, {numFiles, numObjects}];
totalIntensity = Array[0 &, {numFiles, numObjects}];
meanIntensity = Array[0 &, {numFiles, numObjects}];
standardDeviationIntensity = Array[0 &, {numFiles, numObjects}];
boundingBoxArea = Array[0 &, {numFiles, numObjects}];
numPixels = Array[0 &, {numFiles, numObjects}];
(*find coordinates and other relevant data of each object in first frame*)
i = 1;
coordinates[[i, All]] =
ComponentMeasurements[newImage, "IntensityCentroid"][[All, 2]];
threshold[[i, All]] = t;
equivalentDiskRadius[[i, All]] =
ComponentMeasurements[newImage, "EquivalentDiskRadius"][[All, 2]];
totalIntensity[[i, All]] =
ComponentMeasurements[newImage, "TotalIntensity"][[All, 2]];
meanIntensity[[i, All]] =
ComponentMeasurements[newImage, "MeanIntensity"][[All, 2]];
standardDeviationIntensity[[i]] =
ComponentMeasurements[newImage, "StandardDeviationIntensity"][[All,
2]];
boundingBoxArea[[i, All]] =
ComponentMeasurements[newImage, "BoundingBoxArea"][[All, 2]];
numPixels[[i, All]] =
ComponentMeasurements[newImage, "Count"][[All, 2]];
Print[i, " ", coordinates[[i, All]], "\n"];
(*loop over all images*)
Do[
image = Import[fNames[[i]]];
t = FindThreshold[image, Method -> "Entropy"];
binImage =
DeleteSmallComponents[Binarize[image, t],
8];(*8 has to be manually set*);
newImage = ImageMultiply[image, binImage];
coordinates[[i, All]] =
ComponentMeasurements[newImage, "IntensityCentroid"][[All, 2]];
threshold[[i, All]] = t;
equivalentDiskRadius[[i, All]] =
ComponentMeasurements[newImage, "EquivalentDiskRadius"][[All, 2]];
totalIntensity[[i, All]] =
ComponentMeasurements[newImage, "TotalIntensity"][[All, 2]];
meanIntensity[[i, All]] =
ComponentMeasurements[newImage, "MeanIntensity"][[All, 2]];
standardDeviationIntensity[[i]] =
ComponentMeasurements[newImage, "StandardDeviationIntensity"][[All,
2]];
boundingBoxArea[[i, All]] =
ComponentMeasurements[newImage, "BoundingBoxArea"][[All, 2]];
numPixels[[i, All]] =
ComponentMeasurements[newImage, "Count"][[All, 2]];
Print[i, " ", coordinates[[i, All]]];
(*sort coordinate order according to nearest neighbors, so that objects are tracked*)
(* This is wrong: order = Flatten@Nearest[coordinates[[i - 1, All]] -> Automatic][coordinates[[i, All]]];*)
order = Flatten@Nearest[coordinates[[i, All]] -> Automatic][coordinates[[i - 1, All]]];
coordinates[[i, All]] = coordinates[[i, #]] & /@ order;
threshold[[i, All]] = threshold[[i, #]] & /@ order;
equivalentDiskRadius[[i, All]] =
equivalentDiskRadius[[i, #]] & /@ order;
totalIntensity[[i, All]] = totalIntensity[[i, #]] & /@ order;
meanIntensity[[i, All]] = meanIntensity[[i, #]] & /@ order;
standardDeviationIntensity[[i]] =
standardDeviationIntensity[[i, #]] & /@ order;
boundingBoxArea[[i, All]] = boundingBoxArea[[i, #]] & /@ order;
numPixels[[i, All]] = numPixels[[i, #]] & /@ order;
Print[i, " ", coordinates[[i, All]], "\n"],
{i, 2, numFiles}
];
1 {{600.924,1321.05},{1282.57,1319.71},{927.97,726.014}}
2 {{601.472,1320.6},{1282.83,1320.66},{928.494,726.171}}
2 {{601.472,1320.6},{1282.83,1320.66},{928.494,726.171}}
3 {{601.599,1320.62},{1283.29,1321.66},{928.725,726.025}}
3 {{601.599,1320.62},{1283.29,1321.66},{928.725,726.025}}
4 {{1284.07,1322.6},{601.375,1320.79},{929.205,724.945}}
4 {{601.375,1320.79},{1284.07,1322.6},{929.205,724.945}}
5 {{1284.84,1323.69},{600.729,1321.26},{929.304,723.538}}
5 {{600.729,1321.26},{1284.84,1323.69},{929.304,723.538}}
6 {{1285.88,1324.76},{599.797,1321.9},{929.635,721.943}}
6 {{599.797,1321.9},{1285.88,1324.76},{929.635,721.943}}
7 {{1287.23,1325.46},{598.597,1322.92},{930.251,720.146}}
7 {{598.597,1322.92},{1287.23,1325.46},{930.251,720.146}}
8 {{1288.29,1325.99},{596.995,1324.19},{930.652,718.686}}
8 {{596.995,1324.19},{1288.29,1325.99},{930.652,718.686}}
9 {{595.348,1325.49},{1289.63,1326.32},{931.156,717.095}}
9 {{595.348,1325.49},{1289.63,1326.32},{931.156,717.095}}
Plot of the tracks:
ListPlot[# & /@ Transpose[coordinates],
AspectRatio -> Automatic, PlotRange -> Automatic,
PlotStyle -> AbsolutePointSize[10], Frame -> True,
AspectRatio -> 1, FrameLabel -> {{"y (m)", ""}, {"x (m)", ""}},
BaseStyle -> {FontWeight -> "Bold", FontSize -> 20,
FontFamily -> "Calibri"}, ImageSize -> 600]