protected TaskSearchSketch(PhotoSketchCBIR cbr, string sketchPath, Gender gender, int rankSize)
        {
            Func <Tuple <PhotoMetadata, double>, string> formatLabel = t =>
                                                                       string.Format("Id: {0}, Gender: {1}, Score: {2}", t.Item1.Id, t.Item1.Gender, t.Item2);

            DoWork += (s, e) =>
            {
                // background work compute a search
                var rank   = cbr.Search(sketchPath, gender, rankSize);
                var images = rank.Select(r => r.Item1.AbsolutePath).ToArray();
                var labels = rank.Select(formatLabel).ToArray();
                e.Result = Tuple.Create(images, labels);
            };

            RunWorkerCompleted += (s, e) => OnSearchCompleted.Invoke(this, e.Result as Tuple <string[], string[]>);
        }
        private static double[] CreateRecognitionCMC(PhotoSketchCBIR cbr, List <PhotoMetadata> sketches, bool filterGender = true)
        {
            var maxRank = RANKS.Max();

            var accuracies = new double[RANKS.Length];

            sketches.ForEach(sketch =>
            {
                try
                {
                    var ranks = cbr.Search(sketch.AbsolutePath, filterGender ? sketch.Gender : Gender.UNKNOWN, maxRank);
                    for (int i = 0; i < RANKS.Length; i++)
                    {
                        accuracies[i] += ranks.Take(RANKS[i]).Any(t => t.Item1.Id == sketch.Id) ? 1 : 0;
                    }
                }
                catch (Exception) { }
            });

            return(accuracies.Select(v => v / sketches.Count * 100d).ToArray());
        }