problems.mot.re_id

This module implements a re-id feature for tracking in ultralytics 8.

class tno.quantum.problems.mot.re_id.FlowReID[source]

Bases: object

Class to initialize the flow re-identification object.

__init__()[source]

Initialize FlowReID object.

pick_sequences(det_sequence, min_len=50, max_len=80)[source]

Picks frame sequences to run re-id on.

Sequences containing new id’s are selected for the re-id module. The sequences are checked for compatibility with the re-id module.

Parameters:
  • det_sequence (DetectionSequence) – detection sequence

  • min_len (int) – minimum length of picked sequences

  • max_len (int) – maximum length of picked sequences

Return type:

list[tuple[int, int]]

Returns:

List with start and end frames for the selected sequences.

run_classic(det_sequence)[source]

Runs re-id using a classic MILP solver from SciPy.

The classic approach solves the following network flow model:

  • Capacity constraint: At most one unit of flow per edge.

  • Flow conservation: Incoming flow equals outgoing flow for intermediate nodes.

  • Boundary condition: One unit of flow originates from each initial node.

This approach uses SciPy’s MILP solver milp().

The decision variables are:

1. \(x_{ijt} \in \{0, 1\}\) representing whether detection \(i\) in frame \(t\) is associated with detection \(j\) in frame \(t+1\).

  • \(x_{ijt} = 1\) Detection \(i\) at time \(t\) and detection \(j\) at time \(t+1\) belong to the same object.

  • \(x_{ijt} = 0\) No association.

2. \(y_{ij} \in \{0, 1\}\) representing additional edges introduced when the number of detections in intermediate frames drops below the initial frame count.

  • \(y_{ij} = 1\) Detection \(i\) in frame \(f_1\) is linked to detection \(j\) in frame \(f_2\) to maintain feasibility.

  • \(y_{ij} = 0\) No link between these detections.

When the number of detections drops below the initial layer, additional edges are introduced between frames \(f_1\) and \(f_2\) to maintain feasibility:

\[\begin{split}\begin{split} & \sum_{j=1}^{nd_{f_1+1}} x_{ijf_1} + \sum_{j=1}^{nd_{f_2}} y_{ij} \leq 1, \quad i = 1, \dots, nd_{f_1} \\ & \sum_{j=1}^{nd_{f_1-1}} x_{jif_1-1} = \sum_{j=1}^{nd_{f_1+1}} x_{ijf_1} + \sum_{j=1}^{nd_{f_2}} y_{ij}, \quad i = 1, \dots, nd_{f_1} \\ & \sum_{j=1}^{nd_{f_2-1}} x_{jif_2-1} + \sum_{j=1}^{nd_{f_1}} y_{ji} = \sum_{j=1}^{nd_{f_2+1}} x_{ijf_2}, \quad i = 1, \dots, nd_{f_2}. \end{split}\end{split}\]
Parameters:

det_sequence (DetectionSequence) – detection sequence to re-id.

Return type:

DetectionSequence

Returns:

The detection sequence after re-id.

run_continuous_reid(det_sequence)[source]

Runs re-id continuously.

Parameters:

det_sequence (DetectionSequence) – detection sequence

Return type:

DetectionSequence

Returns:

The detection sequence after re-id on several frame sequences.

run_qubo(det_sequence, solver_config=None)[source]

Runs re-id using a qubo model.

Instead of handling constraints explicitly, we add penalty terms to the objective function:

\[\begin{split}\\\mathbf{c}^T \mathbf{x} + \lambda H(\mathbf{x})\end{split}\]
  • \(\mathbf{c}^T \mathbf{x}\): Original cost function.

  • \(H(\mathbf{x})\): Penalty function encoding constraints.

  • \(\lambda\): Penalty weight ensuring feasibility.

By tuning \(\lambda\), minimizing this unconstrained quadratic objective yields feasible solutions.

For a constraint of the form \(\mathbf{a}^T \mathbf{x} = b\):

\[\begin{split}\\H_1(\mathbf{x}) = (\mathbf{a}^T \mathbf{x} - b)^2\end{split}\]

This penalty is zero when the constraint is satisfied and positive otherwise.

For a constraint of the form \(\sum{x_i} \leq 1\):

\[\begin{split}\\H_2( \mathbf{x} ) = \sum_{i<j}{x_i x_j}\end{split}\]

This ensures that at most one variable in the set can take the value 1.

Parameters:
  • det_sequence (DetectionSequence) – detection sequence to re-id.

  • solver_config (SolverConfig | Mapping[str, Any] | None) – Configuration for the qubo solver to use. Must be a SolverConfig or a mapping with "name" and "options" keys. If None (default) is provided, the SimulatedAnnealingSolver will be used, i.e. {"name": "simulated_annealing_solver", "options": {}}.

Return type:

DetectionSequence

Returns:

The detection sequence after re-id. If the solver did not converge to a feasible solution, returns the input detection sequence.