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:
objectClass to initialize the flow re-identification 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.
- 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:
- 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:
- 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 aSolverConfigor a mapping with"name"and"options"keys. IfNone(default) is provided, theSimulatedAnnealingSolverwill be used, i.e.{"name": "simulated_annealing_solver", "options": {}}.
- Return type:
- Returns:
The detection sequence after re-id. If the solver did not converge to a feasible solution, returns the input detection sequence.