Page 1 of 1

Calculate Speed/Velocity Of Tracked Object

PostPosted: Thu May 15, 2025 11:14 pm
by haikelareff
So I've been wondering, if we can track any moving object in the frame, is it possible we can also calculate how fast its moving? And can we visualise the movement of the object in the video to a 2D plane?


Example: To analyse a football team by tracking players movement

Re: Calculate Speed/Velocity Of Tracked Object

PostPosted: Sat May 17, 2025 1:33 am
by philipbowser
It depends on the footage, but it can technically be done in Fusion for simple scenarios. However if there is significant camera motion or the subject's motion path is very complex, then you may require some more advanced 3D reconstruction techniques which can be a bit outside of Fusion's capabilities.

I believe that in order to calculate the velocity of a subject, you'd need to either know the camera's angle of view and the distance from the camera to the subject, or you'd have to know the real world distance between two points on screen that are on the same plane that the subject travelled. This assumes the camera doesn't move (or is stabilized) and the subject's movement is fairly restricted to a single plane that is more or less perpendicular to the camera's view.

Here's an example that uses both of those methods in expressions on Text+ nodes. Also I think my math on this is correct, but you may want to double check.
Code: Select all
{
   Tools = ordered() {
      Ellipse1 = EllipseMask {
         Inputs = {
            Filter = Input { Value = FuID { "Fast Gaussian" }, },
            MaskWidth = Input { Value = 3840, },
            MaskHeight = Input { Value = 2160, },
            PixelAspect = Input { Value = { 1, 1 }, },
            ClippingMode = Input { Value = FuID { "None" }, },
            Center = Input {
               SourceOp = "XYPath1",
               Source = "Value",
            },
            Width = Input { Value = 0.02, },
            Height = Input { Value = 0.02, }
         },
         ViewInfo = OperatorInfo { Pos = { 275, 148.5 } },
      },
      XYPath1 = XYPath {
         ShowKeyPoints = false,
         DrawMode = "ModifyOnly",
         CtrlWZoom = false,
         Inputs = {
            X = Input {
               SourceOp = "Ellipse1CenterXYPath1X",
               Source = "Value",
            },
            Y = Input {
               SourceOp = "Ellipse1CenterXYPath1Y",
               Source = "Value",
            }
         },
      },
      Ellipse1CenterXYPath1X = BezierSpline {
         SplineColor = { Red = 255, Green = 0, Blue = 0 },
         NameSet = true,
         KeyFrames = {
            [0] = { 0.134831460674157, RH = { 8, 0.134831460674157 }, Flags = { Linear = true } },
            [24] = { 0.533911692017631, LH = { 16, 0.533911692017631 }, RH = { 31.6666666666667, 0.533911692017631 } },
            [47] = { 0.777599429284823, LH = { 39.3333333333333, 0.777599429284823 } }
         }
      },
      Ellipse1CenterXYPath1Y = BezierSpline {
         SplineColor = { Red = 0, Green = 255, Blue = 0 },
         NameSet = true,
         KeyFrames = {
            [0] = { 0.278887303851641, RH = { 8, 0.278887303851641 }, Flags = { Linear = true } },
            [24] = { 0.790236298425912, LH = { 16, 0.790236298425912 }, RH = { 31.6666666666667, 0.790236298425912 } },
            [47] = { 0.549212530536721, LH = { 39.3333333333333, 0.549212530536721 } }
         }
      },
      Background1 = Background {
         Inputs = {
            EffectMask = Input {
               SourceOp = "Ellipse1",
               Source = "Mask",
            },
            Width = Input { Value = 3840, },
            Height = Input { Value = 2160, },
            ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
            TopLeftRed = Input { Value = 1, },
            TopLeftGreen = Input { Value = 1, },
            TopLeftBlue = Input { Value = 1, }
         },
         ViewInfo = OperatorInfo { Pos = { 275, 181.5 } },
      },
      Tracker1 = Tracker {
         Trackers = {
            {
               ID = 1,
               PatternTime = 0,
               PatternX = 0.134675543834933,
               PatternY = 0.279254007559605
            }
         },
         Inputs = {
            Input = Input {
               SourceOp = "Background1",
               Source = "Output",
            },
            Name2 = Input { Value = "Point 2", },
            PatternCenter2 = Input { Value = { 0.777438808808892, 0.549580975152198 }, },
            PatternWidth2 = Input { Value = 0.0230400774542027, },
            PatternHeight2 = Input { Value = 0.0408865358394174, },
            SearchWidth2 = Input { Value = 0.121829862767674, },
            SearchHeight2 = Input { Value = 0.205892448620436, },
            TrackedCenter2 = Input {
               SourceOp = "Tracker1Point2XYPath",
               Source = "Value",
            }
         },
         ViewInfo = OperatorInfo { Pos = { 275, 214.5 } },
      },
      Tracker1Point2XYPath = XYPath {
         ShowKeyPoints = false,
         DrawMode = "InsertAndModify",
         CtrlWZoom = false,
         NameSet = true,
         Inputs = {
            X = Input {
               SourceOp = "Tracker1Point2XYPathX",
               Source = "Value",
            },
            Y = Input {
               SourceOp = "Tracker1Point2XYPathY",
               Source = "Value",
            }
         },
      },
      Tracker1Point2XYPathX = BezierSpline {
         SplineColor = { Red = 255, Green = 0, Blue = 0 },
         NameSet = true,
         KeyFrames = {
            [0] = { 0.134675543834933, RH = { 0.333333333333333, 0.135348965058891 }, Flags = { Linear = true } },
            [1] = { 0.136695807506808, LH = { 0.666666666666667, 0.13602238628285 }, RH = { 1.33333333333333, 0.138638081812364 }, Flags = { Linear = true } },
            [2] = { 0.142522630423475, LH = { 1.66666666666667, 0.140580356117919 }, RH = { 2.33333333333333, 0.145622538192572 }, Flags = { Linear = true } },
            [3] = { 0.151822353730767, LH = { 2.66666666666667, 0.14872244596167 }, RH = { 3.33333333333333, 0.155959180987711 }, Flags = { Linear = true } },
            [4] = { 0.1642328355016, LH = { 3.66666666666667, 0.160096008244656 }, RH = { 4.33333333333333, 0.169295362628336 }, Flags = { Linear = true } },
            [5] = { 0.179420416881808, LH = { 4.66666666666667, 0.174357889755072 }, RH = { 5.33333333333333, 0.185289286239447 }, Flags = { Linear = true } },
            [6] = { 0.197027024954725, LH = { 5.66666666666667, 0.191158155597086 }, RH = { 6.33333333333333, 0.203591695093614 }, Flags = { Linear = true } },
            [7] = { 0.216721035371392, LH = { 6.66666666666667, 0.210156365232503 }, RH = { 7.33333333333333, 0.223859435979031 }, Flags = { Linear = true } },
            [8] = { 0.238136237194308, LH = { 7.66666666666667, 0.230997836586669 }, RH = { 8.33333333333333, 0.245739861326253 }, Flags = { Linear = true } },
            [9] = { 0.260947109590142, LH = { 8.66666666666667, 0.253343485458197 }, RH = { 9.33333333333333, 0.268893886933892 }, Flags = { Linear = true } },
            [10] = { 0.284787441621392, LH = { 9.66666666666667, 0.276840664277642 }, RH = { 10.3333333333333, 0.292967508895697 }, Flags = { Linear = true } },
            [11] = { 0.309327643444308, LH = { 10.6666666666667, 0.301147576170003 }, RH = { 11.3333333333333, 0.31762164301028 }, Flags = { Linear = true } },
            [12] = { 0.334209642142225, LH = { 11.6666666666667, 0.325915642576253 }, RH = { 12.3333333333333, 0.342505676213406 }, Flags = { Linear = true } },
            [13] = { 0.359097744355767, LH = { 12.6666666666667, 0.350801710284586 }, RH = { 13.3333333333333, 0.367278489798475 }, Flags = { Linear = true } },
            [14] = { 0.383639980683892, LH = { 13.6666666666667, 0.375459235241184 }, RH = { 14.3333333333333, 0.391586758027642 }, Flags = { Linear = true } },
            [15] = { 0.407480312715142, LH = { 14.6666666666667, 0.399533535371392 }, RH = { 15.3333333333333, 0.415082580510281 }, Flags = { Linear = true } },
            [16] = { 0.430287116100558, LH = { 15.6666666666667, 0.422684848305419 }, RH = { 16.3333333333333, 0.437426873045003 }, Flags = { Linear = true } },
            [17] = { 0.451706386933892, LH = { 16.6666666666667, 0.444566629989447 }, RH = { 17.3333333333333, 0.458271057072781 }, Flags = { Linear = true } },
            [18] = { 0.471400397350558, LH = { 17.6666666666667, 0.464835727211669 }, RH = { 18.3333333333333, 0.477269266708197 }, Flags = { Linear = true } },
            [19] = { 0.489007005423475, LH = { 18.6666666666667, 0.483138136065836 }, RH = { 19.3333333333333, 0.494069532550211 }, Flags = { Linear = true } },
            [20] = { 0.504194586803683, LH = { 19.6666666666667, 0.499132059676947 }, RH = { 20.3333333333333, 0.508330735892225 }, Flags = { Linear = true } },
            [21] = { 0.516603034069308, LH = { 20.6666666666667, 0.512466884980766 }, RH = { 21.3333333333333, 0.5197015855016 }, Flags = { Linear = true } },
            [22] = { 0.525898688366183, LH = { 21.6666666666667, 0.522800136933891 }, RH = { 22.3333333333333, 0.527842997176947 }, Flags = { Linear = true } },
            [23] = { 0.531731614798475, LH = { 22.6666666666667, 0.529787305987711 }, RH = { 23.3333333333333, 0.532405036022433 }, Flags = { Linear = true } },
            [24] = { 0.53375187847035, LH = { 23.6666666666667, 0.533078457246392 }, RH = { 24.3333333333333, 0.534199469616183 }, Flags = { Linear = true } },
            [25] = { 0.53509465190785, LH = { 24.6666666666667, 0.534647060762017 }, RH = { 25.3333333333333, 0.536382493704725 }, Flags = { Linear = true } },
            [26] = { 0.538958177298475, LH = { 25.6666666666667, 0.5376703355016 }, RH = { 26.3333333333333, 0.541008958548475 }, Flags = { Linear = true } },
            [27] = { 0.545110521048475, LH = { 26.6666666666667, 0.543059739798475 }, RH = { 27.3333333333333, 0.547840148869656 }, Flags = { Linear = true } },
            [28] = { 0.553299404512017, LH = { 27.6666666666667, 0.550569776690836 }, RH = { 28.3333333333333, 0.55663260221167 }, Flags = { Linear = true } },
            [29] = { 0.563298997610975, LH = { 28.6666666666667, 0.559965799911322 }, RH = { 29.3333333333333, 0.567148959633544 }, Flags = { Linear = true } },
            [30] = { 0.574848883678683, LH = { 29.6666666666667, 0.570998921656114 }, RH = { 30.3333333333333, 0.579142367836669 }, Flags = { Linear = true } },
            [31] = { 0.587729336152642, LH = { 30.6666666666667, 0.583435851994656 }, RH = { 31.3333333333333, 0.5923822495641 }, Flags = { Linear = true } },
            [32] = { 0.601688076387017, LH = { 31.6666666666667, 0.597035162975559 }, RH = { 32.3333333333333, 0.606621751517225 }, Flags = { Linear = true } },
            [33] = { 0.616489101777642, LH = { 32.6666666666667, 0.611555426647434 }, RH = { 33.3333333333333, 0.62162283658667 }, Flags = { Linear = true } },
            [34] = { 0.631890306204725, LH = { 33.6666666666667, 0.626756571395697 }, RH = { 34.3333333333333, 0.63714543315785 }, Flags = { Linear = true } },
            [35] = { 0.6476556870641, LH = { 34.6666666666667, 0.642400560110975 }, RH = { 35.3333333333333, 0.652950147784586 }, Flags = { Linear = true } },
            [36] = { 0.663539069225558, LH = { 35.6666666666667, 0.658244608505072 }, RH = { 36.3333333333333, 0.668792161673475 }, Flags = { Linear = true } },
            [37] = { 0.679298346569308, LH = { 36.6666666666667, 0.674045254121391 }, RH = { 37.3333333333333, 0.684432759546739 }, Flags = { Linear = true } },
            [38] = { 0.6947015855016, LH = { 37.6666666666667, 0.689567172524169 }, RH = { 38.3333333333333, 0.699635260631808 }, Flags = { Linear = true } },
            [39] = { 0.709502610892225, LH = { 38.6666666666667, 0.704568935762017 }, RH = { 39.3333333333333, 0.714156880640489 }, Flags = { Linear = true } },
            [40] = { 0.723465420137017, LH = { 39.6666666666667, 0.718811150388753 }, RH = { 40.3333333333333, 0.727756869789795 }, Flags = { Linear = true } },
            [41] = { 0.73633976909535, LH = { 40.6666666666667, 0.732048319442572 }, RH = { 41.3333333333333, 0.740192443791531 }, Flags = { Linear = true } },
            [42] = { 0.747897793183892, LH = { 41.6666666666667, 0.744045118487711 }, RH = { 42.3333333333333, 0.751228956378336 }, Flags = { Linear = true } },
            [43] = { 0.757891282767225, LH = { 42.6666666666667, 0.754560119572781 }, RH = { 43.3333333333333, 0.760622266925211 }, Flags = { Linear = true } },
            [44] = { 0.766084235241183, LH = { 43.6666666666667, 0.763353251083197 }, RH = { 44.3333333333333, 0.768133660154378 }, Flags = { Linear = true } },
            [45] = { 0.772232509980767, LH = { 44.6666666666667, 0.770183085067572 }, RH = { 45.3333333333333, 0.773521708114447 }, Flags = { Linear = true } },
            [46] = { 0.776100104381808, LH = { 45.6666666666667, 0.774810906248128 }, RH = { 46.3333333333333, 0.776546339190836 }, Flags = { Linear = true } },
            [47] = { 0.777438808808892, LH = { 46.6666666666667, 0.776992573999864 }, RH = { 47.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [48] = { 0.777438808808892, LH = { 47.6666666666667, 0.777438808808892 }, RH = { 48.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [49] = { 0.777438808808892, LH = { 48.6666666666667, 0.777438808808892 }, RH = { 49.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [50] = { 0.777438808808892, LH = { 49.6666666666667, 0.777438808808892 }, RH = { 50.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [51] = { 0.777438808808892, LH = { 50.6666666666667, 0.777438808808892 }, RH = { 51.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [52] = { 0.777438808808892, LH = { 51.6666666666667, 0.777438808808892 }, RH = { 52.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [53] = { 0.777438808808892, LH = { 52.6666666666667, 0.777438808808892 }, RH = { 53.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [54] = { 0.777438808808892, LH = { 53.6666666666667, 0.777438808808892 }, RH = { 54.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [55] = { 0.777438808808892, LH = { 54.6666666666667, 0.777438808808892 }, RH = { 55.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [56] = { 0.777438808808892, LH = { 55.6666666666667, 0.777438808808892 }, RH = { 56.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [57] = { 0.777438808808892, LH = { 56.6666666666667, 0.777438808808892 }, RH = { 57.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [58] = { 0.777438808808892, LH = { 57.6666666666667, 0.777438808808892 }, RH = { 58.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [59] = { 0.777438808808892, LH = { 58.6666666666667, 0.777438808808892 }, RH = { 59.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [60] = { 0.777438808808892, LH = { 59.6666666666667, 0.777438808808892 }, RH = { 60.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [61] = { 0.777438808808892, LH = { 60.6666666666667, 0.777438808808892 }, RH = { 61.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [62] = { 0.777438808808892, LH = { 61.6666666666667, 0.777438808808892 }, RH = { 62.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [63] = { 0.777438808808892, LH = { 62.6666666666667, 0.777438808808892 }, RH = { 63.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [64] = { 0.777438808808892, LH = { 63.6666666666667, 0.777438808808892 }, RH = { 64.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [65] = { 0.777438808808892, LH = { 64.6666666666667, 0.777438808808892 }, RH = { 65.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [66] = { 0.777438808808892, LH = { 65.6666666666667, 0.777438808808892 }, RH = { 66.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [67] = { 0.777438808808892, LH = { 66.6666666666667, 0.777438808808892 }, RH = { 67.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [68] = { 0.777438808808892, LH = { 67.6666666666667, 0.777438808808892 }, RH = { 68.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [69] = { 0.777438808808892, LH = { 68.6666666666667, 0.777438808808892 }, RH = { 69.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [70] = { 0.777438808808892, LH = { 69.6666666666667, 0.777438808808892 }, RH = { 70.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [71] = { 0.777438808808892, LH = { 70.6666666666667, 0.777438808808892 }, RH = { 71.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [72] = { 0.777438808808892, LH = { 71.6666666666667, 0.777438808808892 }, RH = { 72.3333333333333, 0.777438808808892 }, Flags = { Linear = true } },
            [73] = { 0.777438808808892, LH = { 72.6666666666667, 0.777438808808892 }, Flags = { Linear = true } }
         }
      },
      Tracker1Point2XYPathY = BezierSpline {
         SplineColor = { Red = 0, Green = 255, Blue = 0 },
         NameSet = true,
         KeyFrames = {
            [0] = { 0.279254007559605, RH = { 0.333333333333333, 0.280118446217012 }, Flags = { Linear = true } },
            [1] = { 0.281847323531827, LH = { 0.666666666666667, 0.28098288487442 }, RH = { 1.33333333333333, 0.284336955090469 }, Flags = { Linear = true } },
            [2] = { 0.289316218207753, LH = { 1.66666666666667, 0.286826586649111 }, RH = { 2.33333333333333, 0.29328757237442 }, Flags = { Linear = true } },
            [3] = { 0.301230280707753, LH = { 2.66666666666667, 0.297258926541086 }, RH = { 3.33333333333333, 0.306531447760222 }, Flags = { Linear = true } },
            [4] = { 0.317133781865161, LH = { 3.66666666666667, 0.311832614812692 }, RH = { 4.33333333333333, 0.323618880244791 }, Flags = { Linear = true } },
            [5] = { 0.33658907700405, LH = { 4.66666666666667, 0.33010397862442 }, RH = { 5.33333333333333, 0.344111019519482 }, Flags = { Linear = true } },
            [6] = { 0.359154904550346, LH = { 5.66666666666667, 0.351632962034914 }, RH = { 6.33333333333333, 0.36756419274479 }, Flags = { Linear = true } },
            [7] = { 0.384382769133679, LH = { 6.66666666666667, 0.375973480939235 }, RH = { 7.33333333333333, 0.393532315815778 }, Flags = { Linear = true } },
            [8] = { 0.411831409179976, LH = { 7.66666666666667, 0.402681862497877 }, RH = { 8.33333333333333, 0.421571715892939 }, Flags = { Linear = true } },
            [9] = { 0.441052329318864, LH = { 8.66666666666667, 0.431312022605901 }, RH = { 9.33333333333333, 0.451236308871333 }, Flags = { Linear = true } },
            [10] = { 0.471604267976272, LH = { 9.66666666666667, 0.461420288423803 }, RH = { 10.3333333333333, 0.482086038809605 }, Flags = { Linear = true } },
            [11] = { 0.503049580476272, LH = { 10.6666666666667, 0.492567809642939 }, RH = { 11.3333333333333, 0.513677232868247 }, Flags = { Linear = true } },
            [12] = { 0.534932537652198, LH = { 11.6666666666667, 0.524304885260223 }, RH = { 12.3333333333333, 0.545560190044173 }, Flags = { Linear = true } },
            [13] = { 0.566815494828124, LH = { 12.6666666666667, 0.556187842436149 }, RH = { 13.3333333333333, 0.577296060028741 }, Flags = { Linear = true } },
            [14] = { 0.598257190429975, LH = { 13.6666666666667, 0.587776625229358 }, RH = { 14.3333333333333, 0.608441169982444 }, Flags = { Linear = true } },
            [15] = { 0.628809129087383, LH = { 14.6666666666667, 0.618625149534914 }, RH = { 15.3333333333333, 0.638550641433062 }, Flags = { Linear = true } },
            [16] = { 0.65803366612442, LH = { 15.6666666666667, 0.648292153778741 }, RH = { 16.3333333333333, 0.667183212806519 }, Flags = { Linear = true } },
            [17] = { 0.685482306170716, LH = { 16.6666666666667, 0.676332759488617 }, RH = { 17.3333333333333, 0.693889183099728 }, Flags = { Linear = true } },
            [18] = { 0.710702936957753, LH = { 17.6666666666667, 0.702296060028741 }, RH = { 18.3333333333333, 0.718226085105901 }, Flags = { Linear = true } },
            [19] = { 0.733272381402198, LH = { 18.6666666666667, 0.72574923325405 }, RH = { 19.3333333333333, 0.739757479781828 }, Flags = { Linear = true } },
            [20] = { 0.752727676541087, LH = { 19.6666666666667, 0.746242578161457 }, RH = { 20.3333333333333, 0.758028843593556 }, Flags = { Linear = true } },
            [21] = { 0.768631177698494, LH = { 20.6666666666667, 0.763330010646025 }, RH = { 21.3333333333333, 0.772602531865161 }, Flags = { Linear = true } },
            [22] = { 0.780545240198494, LH = { 21.6666666666667, 0.776573886031827 }, RH = { 22.3333333333333, 0.783034871757136 }, Flags = { Linear = true } },
            [23] = { 0.78801413487442, LH = { 22.6666666666667, 0.785524503315778 }, RH = { 23.3333333333333, 0.788878573531827 }, Flags = { Linear = true } },
            [24] = { 0.790607450846642, LH = { 23.6666666666667, 0.789743012189235 }, RH = { 24.3333333333333, 0.790164983639852 }, Flags = { Linear = true } },
            [25] = { 0.789280049226272, LH = { 24.6666666666667, 0.789722516433062 }, RH = { 25.3333333333333, 0.788005695445408 }, Flags = { Linear = true } },
            [26] = { 0.785456987883679, LH = { 25.6666666666667, 0.786731341664543 }, RH = { 26.3333333333333, 0.783430319288 }, Flags = { Linear = true } },
            [27] = { 0.779376982096642, LH = { 26.6666666666667, 0.781403650692321 }, RH = { 27.3333333333333, 0.776675159179975 }, Flags = { Linear = true } },
            [28] = { 0.771271513346642, LH = { 27.6666666666667, 0.773973336263309 }, RH = { 28.3333333333333, 0.767977724766395 }, Flags = { Linear = true } },
            [29] = { 0.761390147605901, LH = { 28.6666666666667, 0.764683936186148 }, RH = { 29.3333333333333, 0.757579142590469 }, Flags = { Linear = true } },
            [30] = { 0.749957132559605, LH = { 29.6666666666667, 0.753768137575037 }, RH = { 30.3333333333333, 0.745710894133679 }, Flags = { Linear = true } },
            [31] = { 0.737218417281827, LH = { 30.6666666666667, 0.741464655707753 }, RH = { 31.3333333333333, 0.732616517204667 }, Flags = { Linear = true } },
            [32] = { 0.723412717050346, LH = { 31.6666666666667, 0.728014617127506 }, RH = { 32.3333333333333, 0.718532315815778 }, Flags = { Linear = true } },
            [33] = { 0.708771513346642, LH = { 32.6666666666667, 0.71365191458121 }, RH = { 33.3333333333333, 0.703693388346642 }, Flags = { Linear = true } },
            [34] = { 0.693537138346642, LH = { 33.6666666666667, 0.698615263346642 }, RH = { 34.3333333333333, 0.688340861340469 }, Flags = { Linear = true } },
            [35] = { 0.677948307328124, LH = { 34.6666666666667, 0.683144584334297 }, RH = { 35.3333333333333, 0.672712244442321 }, Flags = { Linear = true } },
            [36] = { 0.662240118670716, LH = { 35.6666666666667, 0.667476181556519 }, RH = { 36.3333333333333, 0.657043841664543 }, Flags = { Linear = true } },
            [37] = { 0.646651287652198, LH = { 36.6666666666667, 0.651847564658371 }, RH = { 37.3333333333333, 0.641573162652198 }, Flags = { Linear = true } },
            [38] = { 0.631416912652198, LH = { 37.6666666666667, 0.636495037652198 }, RH = { 38.3333333333333, 0.626535305784914 }, Flags = { Linear = true } },
            [39] = { 0.616772092050346, LH = { 38.6666666666667, 0.62165369891763 }, RH = { 39.3333333333333, 0.612171397605902 }, Flags = { Linear = true } },
            [40] = { 0.602970008717013, LH = { 39.6666666666667, 0.607570703161457 }, RH = { 40.3333333333333, 0.598723770291087 }, Flags = { Linear = true } },
            [41] = { 0.590231293439235, LH = { 40.6666666666667, 0.594477531865161 }, RH = { 41.3333333333333, 0.586421494056519 }, Flags = { Linear = true } },
            [42] = { 0.578801895291087, LH = { 41.6666666666667, 0.582611694673803 }, RH = { 42.3333333333333, 0.575506901078124 }, Flags = { Linear = true } },
            [43] = { 0.568916912652198, LH = { 42.6666666666667, 0.572211906865161 }, RH = { 43.3333333333333, 0.566216295368247 }, Flags = { Linear = true } },
            [44] = { 0.560815060800346, LH = { 43.6666666666667, 0.563515678084297 }, RH = { 44.3333333333333, 0.558785980939235 }, Flags = { Linear = true } },
            [45] = { 0.554727821217013, LH = { 44.6666666666667, 0.556756901078124 }, RH = { 45.3333333333333, 0.553454673068865 }, Flags = { Linear = true } },
            [46] = { 0.550908376772568, LH = { 45.6666666666667, 0.552181524920716 }, RH = { 46.3333333333333, 0.550465909565778 }, Flags = { Linear = true } },
            [47] = { 0.549580975152198, LH = { 46.6666666666667, 0.550023442358988 }, RH = { 47.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [48] = { 0.549580975152198, LH = { 47.6666666666667, 0.549580975152198 }, RH = { 48.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [49] = { 0.549580975152198, LH = { 48.6666666666667, 0.549580975152198 }, RH = { 49.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [50] = { 0.549580975152198, LH = { 49.6666666666667, 0.549580975152198 }, RH = { 50.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [51] = { 0.549580975152198, LH = { 50.6666666666667, 0.549580975152198 }, RH = { 51.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [52] = { 0.549580975152198, LH = { 51.6666666666667, 0.549580975152198 }, RH = { 52.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [53] = { 0.549580975152198, LH = { 52.6666666666667, 0.549580975152198 }, RH = { 53.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [54] = { 0.549580975152198, LH = { 53.6666666666667, 0.549580975152198 }, RH = { 54.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [55] = { 0.549580975152198, LH = { 54.6666666666667, 0.549580975152198 }, RH = { 55.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [56] = { 0.549580975152198, LH = { 55.6666666666667, 0.549580975152198 }, RH = { 56.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [57] = { 0.549580975152198, LH = { 56.6666666666667, 0.549580975152198 }, RH = { 57.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [58] = { 0.549580975152198, LH = { 57.6666666666667, 0.549580975152198 }, RH = { 58.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [59] = { 0.549580975152198, LH = { 58.6666666666667, 0.549580975152198 }, RH = { 59.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [60] = { 0.549580975152198, LH = { 59.6666666666667, 0.549580975152198 }, RH = { 60.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [61] = { 0.549580975152198, LH = { 60.6666666666667, 0.549580975152198 }, RH = { 61.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [62] = { 0.549580975152198, LH = { 61.6666666666667, 0.549580975152198 }, RH = { 62.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [63] = { 0.549580975152198, LH = { 62.6666666666667, 0.549580975152198 }, RH = { 63.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [64] = { 0.549580975152198, LH = { 63.6666666666667, 0.549580975152198 }, RH = { 64.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [65] = { 0.549580975152198, LH = { 64.6666666666667, 0.549580975152198 }, RH = { 65.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [66] = { 0.549580975152198, LH = { 65.6666666666667, 0.549580975152198 }, RH = { 66.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [67] = { 0.549580975152198, LH = { 66.6666666666667, 0.549580975152198 }, RH = { 67.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [68] = { 0.549580975152198, LH = { 67.6666666666667, 0.549580975152198 }, RH = { 68.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [69] = { 0.549580975152198, LH = { 68.6666666666667, 0.549580975152198 }, RH = { 69.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [70] = { 0.549580975152198, LH = { 69.6666666666667, 0.549580975152198 }, RH = { 70.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [71] = { 0.549580975152198, LH = { 70.6666666666667, 0.549580975152198 }, RH = { 71.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [72] = { 0.549580975152198, LH = { 71.6666666666667, 0.549580975152198 }, RH = { 72.3333333333333, 0.549580975152198 }, Flags = { Linear = true } },
            [73] = { 0.549580975152198, LH = { 72.6666666666667, 0.549580975152198 }, Flags = { Linear = true } }
         }
      },
      DistanceBased = TextPlus {
         CtrlWZoom = false,
         NameSet = true,
         Inputs = {
            Wrap = Input { Value = 1, },
            Width = Input { Value = 3840, },
            Height = Input { Value = 2160, },
            ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
            Center = Input { Value = { 0.0361155698234, 0.1068548387097 }, },
            LayoutRotation = Input { Value = 1, },
            TransformRotation = Input { Value = 1, },
            Softness1 = Input { Value = 1, },
            StyledText = Input { Expression = ":RealDistance = self.Distance;\nScreenDistance = sqrt((PointB.X - PointA.X)^2 + (PointB.Y - PointA.Y)^2);\nScaledDistance = RealDistance / ScreenDistance;\nX = Tracker1.TrackedCenter2.X - Tracker1:GetValue(\"TrackedCenter2\", time -1).X;\nY = Tracker1.TrackedCenter2.Y - Tracker1:GetValue(\"TrackedCenter2\", time -1).Y;\nDisplacement = sqrt(X*X + Y*Y);\nFPS = 1 / comp:GetPrefs().Comp.FrameFormat.Rate;\nVelocity = Displacement * ScaledDistance / FPS;\nreturn \"Speed = \"..floor(Velocity);", },
            Font = Input { Value = "Open Sans", },
            Style = Input { Value = "Bold", },
            VerticalJustificationNew = Input { Value = 3, },
            HorizontalLeftCenterRight = Input { Value = -1, },
            HorizontalJustificationNew = Input { Value = 3, },
            Distance = Input { Value = 10, },
            PointA = Input { Value = { 0.134426303854875, 0.274193548387097 }, },
            PointB = Input { Value = { 0.534367346938776, 0.786290322580645 }, }
         },
         ViewInfo = OperatorInfo { Pos = { 385, 280.5 } },
         UserControls = ordered() {
            Distance = {
               INP_MaxAllowed = 1000000,
               INP_Integer = false,
               INPID_InputControl = "ScrewControl",
               INP_MaxScale = 1,
               INP_MinScale = 0,
               INP_MinAllowed = -1000000,
               LINKID_DataType = "Number",
               ICS_ControlPage = "Text",
               INP_SplineType = "Default",
               LINKS_Name = "Real World Distance"
            },
            PointA = {
               INPID_PreviewControl = "CrosshairControl",
               LINKID_DataType = "Point",
               ICS_ControlPage = "Text",
               INPID_InputControl = "OffsetControl",
               CHC_Style = "NormalCross",
               LINKS_Name = "Point A",
            },
            PointB = {
               INPID_PreviewControl = "CrosshairControl",
               LINKID_DataType = "Point",
               ICS_ControlPage = "Text",
               INPID_InputControl = "OffsetControl",
               CHC_Style = "NormalCross",
               LINKS_Name = "Point B",
            }
         }
      },
      AoVBased = TextPlus {
         NameSet = true,
         Inputs = {
            Wrap = Input { Value = 1, },
            Width = Input { Value = 3840, },
            Height = Input { Value = 2160, },
            ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
            Center = Input { Value = { 0.036115569823435, 0.106854838709677 }, },
            LayoutRotation = Input { Value = 1, },
            TransformRotation = Input { Value = 1, },
            Softness1 = Input { Value = 1, },
            StyledText = Input { Expression = ":Aspect = Background1.Output.Width / Background1.Output.Height;\nFPS = 1 / comp:GetPrefs().Comp.FrameFormat.Rate;\nX = Tracker1.TrackedCenter2.X - Tracker1:GetValue(\"TrackedCenter2\", time -1).X;\nY = Tracker1.TrackedCenter2.Y - Tracker1:GetValue(\"TrackedCenter2\", time -1).Y;\nDisplacement = sqrt(X*X + Y*Y);\nDiagonalAoV = deg(2 * atan(tan(rad(self.AoV/2)) * sqrt(1 + 1/(Aspect * Aspect))));\nAngularMotion = rad(Displacement * DiagonalAoV);\nVelocity = self.Distance * AngularMotion / FPS;\nreturn \"Speed = \"..floor(Velocity);", },
            Font = Input { Value = "Open Sans", },
            Style = Input { Value = "Bold", },
            VerticalJustificationNew = Input { Value = 3, },
            HorizontalLeftCenterRight = Input { Value = -1, },
            HorizontalJustificationNew = Input { Value = 3, },
            AoV = Input { Value = 45, },
            Distance = Input { Value = 20, }
         },
         ViewInfo = OperatorInfo { Pos = { 165, 280.5 } },
         UserControls = ordered() {
            AoV = {
               INP_MaxAllowed = 1000000,
               INP_Integer = false,
               INPID_InputControl = "ScrewControl",
               INP_MaxScale = 1,
               INP_MinScale = 0,
               INP_MinAllowed = -1000000,
               LINKID_DataType = "Number",
               ICS_ControlPage = "Text",
               INP_SplineType = "Default",
               LINKS_Name = "Horizontal AoV"
            },
            Distance = {
               INP_MaxAllowed = 1000000,
               INP_Integer = false,
               INPID_InputControl = "ScrewControl",
               INP_MaxScale = 1,
               INP_MinScale = 0,
               INP_MinAllowed = -1000000,
               LINKID_DataType = "Number",
               ICS_ControlPage = "Text",
               INP_SplineType = "Default",
               LINKS_Name = "Distance to Subject"
            }
         }
      },
      Merge1 = Merge {
         Inputs = {
            Background = Input {
               SourceOp = "Tracker1",
               Source = "Output",
            },
            Foreground = Input {
               SourceOp = "AoVBased",
               Source = "Output",
            },
            PerformDepthMerge = Input { Value = 0, }
         },
         ViewInfo = OperatorInfo { Pos = { 165, 313.5 } },
      },
      Merge2 = Merge {
         Inputs = {
            Background = Input {
               SourceOp = "Tracker1",
               Source = "Output",
            },
            Foreground = Input {
               SourceOp = "DistanceBased",
               Source = "Output",
            },
            PerformDepthMerge = Input { Value = 0, }
         },
         ViewInfo = OperatorInfo { Pos = { 385, 313.5 } },
      }
   }
}


The first method is the AoVBased Text+ node which has a "Horizontal AoV" and a "Distance to Subject" slider. And the second method is the DistanceBased Text+ node which has a "Real World Distance" slider to establish the real-world distance between the "Point A" and "Point B" controls.

The units are whatever you want them to be, it could be meters, feet, yards etc. So if you decide the distance slider is in meters, then the speed is meters per second.

You'll have to modify the expression for whatever tracker or point you're trying to calculate, but hopefully this provides the core concepts.

Re: Calculate Speed/Velocity Of Tracked Object

PostPosted: Sat May 17, 2025 11:08 am
by haikelareff
Screenshot 2025-05-16 135531.png
heatmap
Screenshot 2025-05-16 135531.png (971.25 KiB) Viewed 855 times
At the moment my camera is recorded using tripod. Its just that the wide angle lens causing the field distorted.

1. I can assume the field is 120m (L) x 90m (w)
2. I can use player height as to get relative measurement to real world?
3. And from there, how do I use the tracking data and projecting into a 2D flat view for heat map and other purpose?

Screenshot 2025-05-16 135531.png
heatmap
Screenshot 2025-05-16 135531.png (971.25 KiB) Viewed 855 times

Re: Calculate Speed/Velocity Of Tracked Object

PostPosted: Wed May 21, 2025 6:36 pm
by philipbowser
If you're looking to do this for gameplay analysis or with any kind of accuracy, then Fusion isn't the tool. To do data visualizations for gameplay analysis you'd typically need wearable tracking devices on the players or an array of cameras around the field to be fed into specialized software.

You can achieve the "look" of the heat map in Fusion, but it will be a purely creative representation for entertainment purposes.

Re: Calculate Speed/Velocity Of Tracked Object

PostPosted: Fri May 23, 2025 12:51 am
by Andrew Hazelden
If you used a Python based computer vision library like "Ultralytics YOLO" you would likely get a lot closer to your goals.

The output from a computer vision library could then be imported into Resolve/Fusion using a data exchange format like JSON, and a scripting language like Lua/Python or a Fuse plugin used to drive the visuals and overlays.

Re: Calculate Speed/Velocity Of Tracked Object

PostPosted: Sun May 25, 2025 6:03 pm
by Sam Steti
Hey

Just as a basic input, I know an app called fSpy - don't know if it exists for windows - which calculates several parameters in an image (see attachment).
It exports camera parametrs as JSON files...