private async void GenerateMosaic(object sender, RoutedEventArgs e) { var availableSources = sources.ToList(); var sourcePixels = sampledBitmap.Pixels.Select(p => ColorSpaces.CieLab.ConvertFromStandardRgb(p)).ToArray(); ColorClusteredBitmap[] targetPixelImages = new ColorClusteredBitmap[sourcePixels.Length]; int progressIndex = 0; var timer = InitializeProgress(targetPixelImages.Length * 2, () => progressIndex); await Task.Run(() => { for (; progressIndex < sampledBitmap.Pixels.Length; progressIndex++) { targetPixelImages[progressIndex] = FindBestMatchAndRemove(sourcePixels[progressIndex], ColorSpaces.CieLab, availableSources); } }); FinishProgress(timer); const double maxSize = 23000; double scaleXFit = Math.Min(1, maxSize / (sampledBitmap.Width * averageWidth)); double scaleYFit = Math.Min(1, maxSize / (sampledBitmap.Height * averageHeight)); double scaleFit = Math.Min(scaleXFit, scaleYFit); int cellWidth = (int)(averageWidth * scaleFit); int cellHeight = (int)(averageHeight * scaleFit); var output = await CreateOutputBitmap(targetPixelImages, sampledBitmap.Width, sampledBitmap.Height, (int)(averageWidth *scaleFit), (int)(averageHeight *scaleFit)); SimplifiedBitmap.Source = output; SimplifiedBitmap.Width = output.PixelWidth; SimplifiedBitmap.Height = output.PixelHeight; }
private float DistanceTo(ColorClusteredBitmap other, IReadOnlyList <int> indexLookup) { float distance = 0; for (int i = 0; i < this.Histogram.Colors.Count; i++) { float thisWeight = (float)this.Histogram.Colors[i].PixelCount / this.Histogram.PixelCount; float otherWeight = (float)other.Histogram.Colors[indexLookup[i]].PixelCount / other.Histogram.PixelCount; float distanceSquared = Vector3.DistanceSquared((Vector3)this.Histogram.Colors[i].Color.ToCieLab(), (Vector3)other.Histogram.Colors[indexLookup[i]].Color.ToCieLab()); distance += distanceSquared * (thisWeight + otherWeight) / 2; } return(distance); }
private async void PopulateImagesAsync(string originalImages, string computedImages) { string[] originalFilePaths = Directory.GetFiles(originalImages, "*.png").Concat(Directory.GetFiles(originalImages, "*.jpg")).ToArray(); string[] computedFilesPaths = Directory.GetFiles(computedImages, "*.png"); Tuple <string, string>[] joinedPaths = originalFilePaths.Join(computedFilesPaths, o => Path.GetFileNameWithoutExtension(o), i => GetPrefix(i), (o, i) => Tuple.Create(o, i)).ToArray(); ColorClusteredBitmap[] bitmaps = new ColorClusteredBitmap[originalFilePaths.Length]; int progress = 0; var timer = InitializeProgress(joinedPaths.Length, () => progress); long totalWidths = 0; long totalHeights = 0; await Task.Run(() => { Parallel.For(0, joinedPaths.Length, i => { string histogramFile = Path.Combine(Path.GetDirectoryName(joinedPaths[i].Item2), "colorHistograms", $"{Path.GetFileNameWithoutExtension(joinedPaths[i].Item2)}.json"); if (File.Exists(histogramFile)) { WeightedColorSet set = JsonConvert.DeserializeObject <WeightedColorSet>(File.ReadAllText(histogramFile)); bitmaps[i] = new ColorClusteredBitmap(joinedPaths[i].Item1, joinedPaths[i].Item2, set); Interlocked.Add(ref totalWidths, bitmaps[i].Histogram.PixelWidth); Interlocked.Add(ref totalHeights, bitmaps[i].Histogram.PixelHeight); } Interlocked.Increment(ref progress); }); }); FinishProgress(timer); foreach (ColorClusteredBitmap result in bitmaps.Where(b => b != null)) { sources.Add(result); } averageWidth = (int)(totalWidths / sources.Count); averageHeight = (int)(totalHeights / sources.Count); averageAspectRatio = (float)totalWidths / totalHeights; }
public float DistanceTo(ColorClusteredBitmap other, bool usePermutations) { float distance = float.MaxValue; if (usePermutations) { foreach (var permutation in Permutation.GetPermutations(this.Histogram.Colors.Count)) { float newDistance = DistanceTo(other, permutation); if (newDistance < distance) { distance = newDistance; } } } else { distance = DistanceTo(other, Permutation.GetPermutations(this.Histogram.Colors.Count).First()); } return(distance); }