/**
         * Extract a palette by hill climbing on the given image
         * key - image name in the base directory (directory)
         * saliencyPattern - the label appended to the image name, to find the saliency map filename (i.e. "_Judd" for "[imagename]_Judd.[imagename extension]")
         * debug - if images should be resized smaller
         * paletteSize - the size of the palette to be extracted
         */
        public PaletteData HillClimbPalette(String key, String saliencyPattern, bool debug = false, int paletteSize=5)
        {
            //Now initialize a palette and start hill climbing
            int trials = 5;

            PaletteScoreCache cache = new PaletteScoreCache(1000000);

            PaletteData swatches = GetPaletteSwatches(key);

            List<CIELAB> shuffled = new List<CIELAB>();
            foreach (CIELAB c in swatches.lab)
                shuffled.Add(c);

            Random random = new Random();

            //weights
            Dictionary<Features, double> weights = new Dictionary<Features, double>();

            weights = LoadWeights(Path.Combine(weightsDir,"weights.csv"), Path.Combine(weightsDir,"featurenames.txt"));

            PaletteData best = new PaletteData();
            double bestScore = Double.NegativeInfinity;

            SortedSet<Features> included = new SortedSet<Features>(weights.Keys);

            Stopwatch watch = new Stopwatch();
            watch.Start();

            FeatureParams fparams = SetupFeatureParams(included, key, saliencyPattern, debug);

            Log(Path.Combine(dir, "out", "convergelog.txt"), "Setup feature params " + watch.ElapsedMilliseconds);

            //Generate all the random starts first
            List<PaletteData> starts = new List<PaletteData>();
            PaletteData[] allOptions = new PaletteData[trials];
            double[] allScores = new double[trials];

            for (int t = 0; t < trials; t++)
            {
                //setup
                PaletteData option = new PaletteData();

                //pick k random colors. First shuffle the colors and pick the top k
                for (int j = shuffled.Count() - 1; j >= 0; j--)
                {
                    int idx = random.Next(j + 1);
                    CIELAB temp = shuffled[j];
                    shuffled[j] = shuffled[idx];
                    shuffled[idx] = temp;
                }

                for (int i = 0; i < paletteSize; i++)
                {
                    option.lab.Add(shuffled[i]);
                    option.colors.Add(Util.LABtoRGB(shuffled[i]));
                }
                starts.Add(option);
                allOptions[t] = new PaletteData(option);
                double optionScore = ScorePalette(weights, CalculateFeatures(option, fparams));
                allScores[t] = optionScore;

                cache.SetScore(option.lab, optionScore);
            }

            watch.Restart();

            for (int t = 0; t < trials; t++)
            {
                //setup
                PaletteData option = new PaletteData(starts[t]);

                double optionScore = allScores[t];

                //Now hill climb, for each swatch, consider replacing it with a better swatch
                //Pick the best replacement, and continue until we reach the top of a hill
                int changes = 1;
                int iters = 0;
                int reuse = 0;

                watch.Restart();

                while (changes > 0)
                {
                    changes = 0;

                    for (int i = 0; i < option.lab.Count(); i++)
                    {
                        //find the best swatch replacement for this color
                        double bestTempScore = optionScore;
                        CIELAB bestRep = option.lab[i];
                        Color bestRGB = option.colors[i];

                        double[] scores = new double[swatches.lab.Count()];

                        for (int s = 0; s < swatches.lab.Count(); s++)
                        {
                            CIELAB r = swatches.lab[s];

                            PaletteData temp = new PaletteData(option);
                            if (!temp.lab.Contains(r))
                            {

                                temp.lab[i] = r;
                                temp.colors[i] = swatches.colors[s];

                                if (!cache.ContainsKey(temp.lab))
                                {
                                    double tempScore = ScorePalette(weights, CalculateFeatures(temp, fparams));
                                    scores[s] = tempScore;
                                    cache.SetScore(temp.lab, tempScore);
                                }
                                else
                                {
                                    scores[s] = cache.GetScore(temp.lab);
                                    reuse++;
                                }
                            }
                            else
                            {
                                scores[s] = Double.NegativeInfinity;
                            }
                        }

                        //aggregate results
                        for (int s = 0; s < scores.Count(); s++)
                        {
                            if (scores[s] > bestTempScore)
                            {
                                bestTempScore = scores[s];
                                bestRep = swatches.lab[s];
                                bestRGB = swatches.colors[s];
                            }
                        }

                        if (!option.lab[i].Equals(bestRep))
                        {
                            option.lab[i] = bestRep;
                            option.colors[i] = bestRGB;
                            optionScore = bestTempScore;
                            changes++;
                        }
                    }

                    iters++;
                }

                if (optionScore > allScores[t])
                {
                    allOptions[t] = option;
                    allScores[t] = optionScore;
                }
                Log(Path.Combine(dir, "out", "convergelog.txt"), "Trial " + t + " Key " + key + " BestScore: " + allScores[t] + " Steps: " + iters + " Time: " + watch.ElapsedMilliseconds);
                Log(Path.Combine(dir, "out", "convergelog.txt"), "Reused " + reuse);

            }

            //aggregate scores
            for (int i = 0; i < allScores.Count(); i++)
            {
                if (allScores[i] > bestScore)
                {
                    bestScore = allScores[i];
                    best = allOptions[i];
                }
            }

            //convert best lab to rgb
            best.colors = new List<Color>();
            foreach (CIELAB l in best.lab)
                best.colors.Add(Util.LABtoRGB(l));

            return best;
        }
Beispiel #2
0
        private List<PaletteData> GenerateRandomPalettes(int count, List<PaletteData> palettes, PaletteData swatches)
        {
            PaletteScoreCache cache = new PaletteScoreCache(1000000);
            int k = 5;
            List<PaletteData> data = new List<PaletteData>();

            Random random = new Random();
            List<int> shuffled = new List<int>();
            for (int i = 0; i < swatches.lab.Count(); i++)
                shuffled.Add(i);

            //find the max scoring human palette
            double maxScore = Double.NegativeInfinity;

            foreach (PaletteData p in palettes)
            {
                double score = 1 - GetAvgDist(new List<PaletteData> { p }, palettes);
                maxScore = Math.Max(maxScore, score);
            }

            //generate random palettes to find the min score
            double minScore = Double.PositiveInfinity;
            for (int i = 0; i < 10000; i++)
            {

                PaletteData result = new PaletteData();
                result.id = -1;

                //pick k random colors. First shuffle the colors and pick the top k
                for (int j = shuffled.Count() - 1; j >= 0; j--)
                {
                    int idx = random.Next(j + 1);
                    int temp = shuffled[j];
                    shuffled[j] = shuffled[idx];
                    shuffled[idx] = temp;
                }

                for (int c = 0; c < k; c++)
                {
                    result.colors.Add(swatches.colors[shuffled[c]]);
                    result.lab.Add(swatches.lab[shuffled[c]]);
                }

                double score = 1 - GetAvgDist(new List<PaletteData>{result}, palettes);
                cache.SetScore(result.lab, score);

                minScore = Math.Min(minScore, score);
                maxScore = Math.Max(maxScore, score);
            }

            int numbins = 10;
            int[] counts = new int[numbins];
            int totalCount = 0;

            int thresh = count / numbins;
            int tries = 0;

            //generate random palettes, given swatches
            while (totalCount < count)
            {

                if (tries % 1000 == 0)
                {
                    String log = Path.Combine(trainOutDir, "randlog.txt");
                    Log(log, tries + "-" + totalCount + " binned ");
                    Log(log, " bins --- " + counts[0] + "," + counts[1] + "," + counts[2] + "," + counts[3] + "," + counts[4] + "," + counts[5] + "," + counts[6] + "," + counts[7] + "," + counts[8] + "," + counts[9]);

                    backgroundWorker.ReportProgress(-1,"bin counts " + String.Join(",",counts));
                }

                tries++;

                PaletteData result = new PaletteData();
                result.id = -1;

                //pick k random colors. First shuffle the colors and pick the top k
                for (int j = shuffled.Count() - 1; j >= 0; j--)
                {
                    int idx = random.Next(j + 1);
                    int temp = shuffled[j];
                    shuffled[j] = shuffled[idx];
                    shuffled[idx] = temp;
                }

                for (int c = 0; c < k; c++)
                {
                    result.colors.Add(swatches.colors[shuffled[c]]);
                    result.lab.Add(swatches.lab[shuffled[c]]);
                }

                double score = 0;
                if (cache.ContainsKey(result.lab))
                    score = cache.GetScore(result.lab);
                else
                {
                    score = 1 - GetAvgDist(new List<PaletteData> { result }, palettes);
                    cache.SetScore(result.lab, score);
                }

                score = (score - minScore) / (maxScore - minScore);

                int bin = (int)Math.Min(Math.Max(0, Math.Floor(score * numbins)), numbins - 1);

                if (counts[bin] >= thresh)
                    continue;
                totalCount++;
                counts[bin]++;

                data.Add(result);
            }
            return data;
        }