private static void Main() { // Let's imagine you need to assign N people to N jobs. Additionally, each person will make // your company a certain amount of money at each job, but each person has different skills // so they are better at some jobs and worse at others. You would like to find the best way // to assign people to these jobs. In particular, you would like to maximize the amount of // money the group makes as a whole. This is an example of an assignment problem and is // what is solved by the max_cost_assignment() routine. // // So in this example, let's imagine we have 3 people and 3 jobs. We represent the amount of // money each person will produce at each job with a cost matrix. Each row corresponds to a // person and each column corresponds to a job. So for example, below we are saying that // person 0 will make $1 at job 0, $2 at job 1, and $6 at job 2. using (var cost = new Matrix <int>(3, 3)) { cost.Assign(new[] { 1, 2, 6, 5, 3, 6, 4, 5, 0 }); // To find out the best assignment of people to jobs we just need to call this function. var assignment = Dlib.MaxCostAssignment(cost).ToArray(); // This prints optimal assignments: [2, 0, 1] which indicates that we should assign // the person from the first row of the cost matrix to job 2, the middle row person to // job 0, and the bottom row person to job 1. for (var i = 0; i < assignment.Count(); i++) { Console.WriteLine(assignment[i]); } // This prints optimal cost: 16.0 // which is correct since our optimal assignment is 6+5+5. Console.WriteLine($"optimal cost: {Dlib.AssignmentCost(cost, assignment)}"); } }
private static IList <long> AlignPoints(IList <DPoint> from, IList <DPoint> to, double minAngle = -90 *Math.PI / 180.0, double maxAngle = 90 *Math.PI / 180.0, long numAngles = 181) { /*! * ensures * - Figures out how to align the points in from with the points in to. Returns an * assignment array A that indicates that from[i] matches with to[A[i]]. * * We use the Hungarian algorithm with a search over reasonable angles. This method * works because we just need to account for a translation and a mild rotation and * nothing else. If there is any other more complex mapping then you probably don't * have landmarks that make sense to flip. * !*/ if (from.Count != to.Count) { throw new ArgumentException(); } long[] bestAssignment = null; var bestAssignmentCost = double.PositiveInfinity; using (var dists = new Matrix <double>(from.Count, to.Count)) { foreach (var angle in Dlib.Linspace(minAngle, maxAngle, (int)numAngles)) { using (var rot = Dlib.RotationMatrix(angle)) for (int r = 0, rows = dists.Rows; r < rows; ++r) { using (var tmp = rot * from[r]) for (int c = 0, columns = dists.Columns; c < columns; ++c) { using (var tmp2 = tmp - to[c]) dists[r, c] = Dlib.LengthSquared(tmp2); } } using (var tmp = dists / Dlib.Max(dists)) using (var tmp2 = long.MaxValue * tmp) using (var tmp3 = Dlib.Round(tmp2)) using (var idists = Dlib.MatrixCast <long>(-tmp3)) { var assignment = Dlib.MaxCostAssignment(idists).ToArray(); var cost = Dlib.AssignmentCost(dists, assignment); if (cost < bestAssignmentCost) { bestAssignmentCost = cost; bestAssignment = assignment.ToArray(); } } } // Now compute the alignment error in terms of average distance moved by each part. We // do this so we can give the user a warning if it's impossible to make a good // alignment. using (var rs = new RunningStats <double>()) { var tmp = new List <DPoint>(Enumerable.Range(0, to.Count).Select(i => new DPoint())); for (var i = 0; i < to.Count; ++i) { tmp[(int)bestAssignment[i]] = to[i]; } using (var tform = Dlib.FindSimilarityTransform(from, tmp)) for (var i = 0; i < from.Count; ++i) { var p = tform.Operator(from[i]) - tmp[i]; rs.Add(Dlib.Length(p)); } if (rs.Mean > 0.05) { Console.WriteLine("WARNING, your dataset has object part annotations and you asked imglab to "); Console.WriteLine("flip the data. Imglab tried to adjust the part labels so that the average"); Console.WriteLine("part layout in the flipped dataset is the same as the source dataset. "); Console.WriteLine("However, the part annotation scheme doesn't seem to be left-right symmetric."); Console.WriteLine("You should manually review the output to make sure the part annotations are "); Console.WriteLine("labeled as you expect."); } return(bestAssignment); } } }