Ejemplo n.º 1
0
        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)}");
            }
        }
Ejemplo n.º 2
0
        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);
                }
            }
        }