static void Main(string[] args) { const string basePath = "..\\..\\..\\..\\images"; ZsImage srcImage = GetArgbImage(basePath, "t009.jpg"); ZsImage destImage = srcImage.Clone(); var srcMarkup = GetArea2D(basePath, "m009.png"); var destMarkup = srcMarkup.Translate(-300, -30); destImage.CopyFromImage(destMarkup, destImage, srcMarkup); destImage.FromArgbToBitmap() .SaveTo("..\\..\\..\\target.png", ImageFormat.Png); // Prepage setting for the PM algorithm const byte patchSize = 5; var settings = new PatchMatchSettings { PatchSize = patchSize }; // Init an nnf var nnf = new Nnf(destImage.Width, destImage.Height, srcImage.Width, srcImage.Height, patchSize); srcImage.FromArgbToRgb(new[] { 1.0, 1.0, 1.0 }) .FromRgbToLab(); destImage.FromArgbToRgb(new[] { 1.0, 1.0, 1.0 }) .FromRgbToLab(); destImage .Clone() .FromLabToRgb() .FromRgbToBitmap() .SaveTo($"..\\..\\..\\dest.png", ImageFormat.Png); var patchMatchNnfBuilder = new PatchMatchNnfBuilder(); patchMatchNnfBuilder.RunRandomNnfInitIteration(nnf, destImage, srcImage, settings); for (int j = 0; j < 3; j++) { patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings); Console.WriteLine($"\tIteration {j * 2}"); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Backward, settings); Console.WriteLine($"\tIteration {j * 2 + 1}"); } nnf.ToRgbImage() .FromRgbToBitmap() .SaveTo($"..\\..\\..\\nnf.png", ImageFormat.Png); nnf.RestoreImage(srcImage, 3, patchSize) .FromLabToRgb() .FromRgbToBitmap() .SaveTo($"..\\..\\..\\restored.png", ImageFormat.Png); }
static void Main(string[] args) { const string basePath = "..\\..\\..\\images"; var destImageName = "pm2small.png"; var srcImageName = "pm1small.png"; var emptyAreaImageName = "pm2small_ignore.png"; // This is our input data. var destImage = GetLabImage(basePath, destImageName); var srcImage = GetLabImage(basePath, srcImageName); var destArea = Area2D.Create(0, 0, destImage.Width, destImage.Height); var srcArea = Area2D.Create(0, 0, srcImage.Width, srcImage.Height); var emptyArea = GetArea2D(basePath, emptyAreaImageName); var destPixelsArea = destArea.Substract(emptyArea); var map = new Area2DMapBuilder() .InitNewMap(destArea, srcArea) .Build(); const byte patchSize = 5; var settings = new PatchMatchSettings { PatchSize = patchSize }; var nnf = new Nnf(destImage.Width, destImage.Height, srcImage.Width, srcImage.Height, patchSize); var calculator = ImagePatchDistance.Cie76; var patchMatchNnfBuilder = new PatchMatchNnfBuilder(); // Create the nnf the images // with a couple of iterations. patchMatchNnfBuilder.RunRandomNnfInitIteration(nnf, destImage, srcImage, settings, calculator, map, destPixelsArea); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map, destPixelsArea); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map, destPixelsArea); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map, destPixelsArea); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map, destPixelsArea); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map, destPixelsArea); // Restore dest image from the NNF and source image. nnf .RestoreImage(srcImage, 3, settings.PatchSize) .FromLabToRgb() .FromRgbToBitmap() .SaveTo(@"..\..\restored.png", ImageFormat.Png); // Convert the NNF to an image, save and show it nnf .ToRgbImage() .FromRgbToBitmap() .SaveTo(@"..\..\nnf.png", ImageFormat.Png) .ShowFile(); Console.WriteLine($"PatchMatchPipeline processing is finished."); }
public static async Task NnfBuildIteration([ActivityTrigger] NnfInputData input) { var container = BlobHelper.OpenBlobContainer(input.Container); var imageBlob = container.GetBlockBlobReference(input.Image); var imageArgb = await BlobHelper.ConvertBlobToArgbImage(imageBlob); var image = imageArgb .FromArgbToRgb(new[] { 0.0, 0.0, 0.0 }) .FromRgbToLab(); var imageArea = Area2D.Create(0, 0, image.Width, image.Height); var pixelsArea = imageArea; var nnfSettings = input.Settings.PatchMatch; var calculator = input.IsCie79Calc ? ImagePatchDistance.Cie76 : ImagePatchDistance.Cie2000; var nnfState = BlobHelper.ReadFromBlob <NnfState>(input.NnfName, container); var nnf = new Nnf(nnfState); var mappingState = BlobHelper.ReadFromBlob <Area2DMapState>(input.Mapping, container); var mapping = new Area2DMap(mappingState); if (input.ExcludeInpaintArea) { var inpaintAreaState = BlobHelper.ReadFromBlob <Area2DState>(input.InpaintAreaName, container); var inpaintArea = Area2D.RestoreFrom(inpaintAreaState); pixelsArea = imageArea.Substract(inpaintArea); } var nnfBuilder = new PatchMatchNnfBuilder(); var direction = input.IsForward ? NeighboursCheckDirection.Forward : NeighboursCheckDirection.Backward; nnfBuilder.RunBuildNnfIteration(nnf, image, image, direction, nnfSettings, calculator, mapping, pixelsArea); var nnfData = JsonConvert.SerializeObject(nnf.GetState()); BlobHelper.SaveJsonToBlob(nnfData, container, input.NnfName); }
static void Main(string[] args) { const string basePath = "..\\..\\..\\..\\images"; const int patchSize = 5; var srcImageName = "t009.jpg"; // Prepare images var srcImage = GetLabImage(basePath, srcImageName); var destImage = GetLabImage(basePath, srcImageName); var ignoreArea = GetArea2D(basePath, "m009.png"); var destArea = ignoreArea.Dilation(patchSize * 2 + 1); // Init an nnf var nnf = new Nnf(destImage.Width, destImage.Height, srcImage.Width, srcImage.Height, patchSize); // Create a mapping of the areas on the dest and source areas. var imageArea = Area2D.Create(0, 0, srcImage.Width, srcImage.Height); var map = new Area2DMapBuilder() .InitNewMap(imageArea, imageArea) .SetIgnoredSourcedArea(ignoreArea) .Build(); // Prepage setting for the PM algorithm var settings = new PatchMatchSettings { PatchSize = patchSize }; var calculator = ImagePatchDistance.Cie76; var patchMatchNnfBuilder = new PatchMatchNnfBuilder(); // Create the nnf for the image(while ignoring some area) // with a couple of iterations. patchMatchNnfBuilder.RunRandomNnfInitIteration(nnf, destImage, srcImage, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map); // Create a mapping for the area that is a bit bigger // then ignored area. map = new Area2DMapBuilder() .InitNewMap(imageArea, imageArea) .ReduceDestArea(destArea) .SetIgnoredSourcedArea(ignoreArea) .Build(); patchMatchNnfBuilder.RunRandomNnfInitIteration(nnf, destImage, srcImage, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map); string fileName1 = @"..\..\..\nnf1_pure.png"; nnf .ToRgbImage() .FromRgbToBitmap() .SaveTo(fileName1, ImageFormat.Png); // Normalize the NNF in the ignored area. nnf.Normalize(ignoreArea); // Prepare results, save and show them string fileName2 = @"..\..\..\nnf2_normalized.png"; nnf .ToRgbImage() .FromRgbToBitmap() .SaveTo(fileName2, ImageFormat.Png) .ShowFile(); Console.WriteLine($"Nnf normalization is finished."); }
static void Main(string[] args) { const string basePath = "..\\..\\..\\images"; const string srcImageName = "pm1.png"; const string destImageName = "pm2.png"; const int patchSize = 5; // Prepare 2 source images - one small and another 2x bigger var srcBitmap = new Bitmap(Path.Combine(basePath, srcImageName)); var srcImage = srcBitmap .ToRgbImage() .FromRgbToLab(); var srcSmallBitmap = srcBitmap.CloneWithScaleTo(srcBitmap.Width / 2, srcBitmap.Height / 2); var srcSmallImage = srcSmallBitmap .ToRgbImage() .FromRgbToLab(); srcSmallBitmap.Dispose(); srcBitmap.Dispose(); var destBitmap = new Bitmap(Path.Combine(basePath, destImageName)); var destImage = destBitmap .ToRgbImage() .FromRgbToLab(); var destSmallBitmap = destBitmap.CloneWithScaleTo(destBitmap.Width / 2, destBitmap.Height / 2); var destSmallImage = destSmallBitmap .ToRgbImage() .FromRgbToLab(); destBitmap.Dispose(); destSmallBitmap.Dispose(); // Init an nnf var nnf = new Nnf(destSmallImage.Width, destSmallImage.Height, srcSmallImage.Width, srcSmallImage.Height, patchSize); // Prepage setting for the PM algorithm var settings = new PatchMatchSettings { PatchSize = patchSize }; var patchMatchNnfBuilder = new PatchMatchNnfBuilder(); // Create the nnf for the small variant of the images // with a couple of iterations. patchMatchNnfBuilder.RunRandomNnfInitIteration(nnf, destSmallImage, srcSmallImage, settings); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destSmallImage, srcSmallImage, NeighboursCheckDirection.Backward, settings); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destSmallImage, srcSmallImage, NeighboursCheckDirection.Forward, settings); // The scaling of the NNF from the small images to the bigger ones. var scaledNnf = nnf.CloneAndScale2XWithUpdate(destImage, srcImage, settings); // Prepare results, save and show them scaledNnf .RestoreImage(srcImage, 3, patchSize) .FromLabToRgb() .FromRgbToBitmap() .SaveTo(@"..\..\l2r.png", ImageFormat.Png); scaledNnf .ToRgbImage() .FromRgbToBitmap() .SaveTo(@"..\..\l2n.png", ImageFormat.Png) .ShowFile(); Console.WriteLine($"NnfScaleUp processing is finished."); }
private ZsImage InternalInpaint(Pyramid pyramid, InpaintSettings settings) { #region cache settings var patchSize = settings.PatchSize; var calculator = settings.PatchDistanceCalculator; var nnfSettings = settings.PatchMatch; var changedPixelsPercentTreshold = settings.ChangedPixelsPercentTreshold; var maxInpaintIterationsAmount = settings.MaxInpaintIterations; var kStep = settings.MeanShift.KDecreaseStep; var minK = settings.MeanShift.MinK; #endregion ZsImage image = null; // go thru all the pyramid levels starting from the top one Nnf nnf = null; for (byte levelIndex = 0; levelIndex < pyramid.LevelsAmount; levelIndex++) { image = pyramid.GetImage(levelIndex); var mapping = pyramid.GetMapping(levelIndex); var inpaintArea = pyramid.GetInpaintArea(levelIndex); var imageArea = Area2D.Create(0, 0, image.Width, image.Height); // if there is a NNF built on the prev level // scale it up nnf = nnf == null ? new Nnf(image.Width, image.Height, image.Width, image.Height, patchSize) : nnf.CloneAndScale2XWithUpdate(image, image, nnfSettings, mapping, calculator); // start inpaint iterations var k = settings.MeanShift.K; for (var inpaintIterationIndex = 0; inpaintIterationIndex < maxInpaintIterationsAmount; inpaintIterationIndex++) { // Obtain pixels area. // Pixels area defines which pixels are allowed to be used // for the patches distance calculation. We must avoid pixels // that we want to inpaint. That is why before the area is not // inpainted - we should exclude this area. var pixelsArea = imageArea; if (levelIndex == 0 && inpaintIterationIndex == 0 && settings.IgnoreInpaintedPixelsOnFirstIteration) { pixelsArea = imageArea.Substract(inpaintArea); } // skip building NNF for the first iteration in the level // unless it is top level (for the top one we haven't built NNF yet) if (levelIndex == 0 || inpaintIterationIndex > 0) { // in order to find best matches for the inpainted area, // we build NNF for this image as a dest and a source // but excluding the inpainted area from the source area // (our mapping already takes care of it) _nnfBuilder.RunRandomNnfInitIteration(nnf, image, image, nnfSettings, calculator, mapping, pixelsArea); _nnfBuilder.RunBuildNnfIteration(nnf, image, image, NeighboursCheckDirection.Forward, nnfSettings, calculator, mapping, pixelsArea); _nnfBuilder.RunBuildNnfIteration(nnf, image, image, NeighboursCheckDirection.Backward, nnfSettings, calculator, mapping, pixelsArea); _nnfBuilder.RunBuildNnfIteration(nnf, image, image, NeighboursCheckDirection.Forward, nnfSettings, calculator, mapping, pixelsArea); _nnfBuilder.RunBuildNnfIteration(nnf, image, image, NeighboursCheckDirection.Backward, nnfSettings, calculator, mapping, pixelsArea); _nnfBuilder.RunBuildNnfIteration(nnf, image, image, NeighboursCheckDirection.Forward, nnfSettings, calculator, mapping, pixelsArea); } var nnfNormalized = nnf.Clone(); nnfNormalized.Normalize(); // after we have the NNF - we calculate the values of the pixels in the inpainted area var inpaintResult = Inpaint(image, inpaintArea, nnfNormalized, k, settings); k = k > minK ? k - kStep : k; if (IterationFinished != null) { var eventArgs = new InpaintIterationFinishedEventArgs { InpaintedLabImage = image.Clone(), InpaintResult = inpaintResult, LevelIndex = levelIndex, InpaintIteration = inpaintIterationIndex }; IterationFinished(this, eventArgs); } // if the change is smaller then a treshold, we quit if (inpaintResult.ChangedPixelsPercent < changedPixelsPercentTreshold) { break; } //if (levelIndex == pyramid.LevelsAmount - 1) break; } } return(image); }
static void Main(string[] args) { const string basePath = "..\\..\\..\\..\\images"; var destImageName = "pm1.png"; var srcImageName = "pm2.png"; var destArea1ImageName = "pm1_target1.png"; var destArea2ImageName = "pm1_target2.png"; // this is our input data. var destImage = GetLabImage(basePath, destImageName); var srcImage = GetLabImage(basePath, srcImageName); var destArea1 = GetArea2D(basePath, destArea1ImageName); var destArea2 = GetArea2D(basePath, destArea2ImageName); var srcArea = Area2D.Create(0, 0, srcImage.Width, srcImage.Height); var map1 = new Area2DMapBuilder() .InitNewMap(destArea1, srcArea) .Build(); var map2 = new Area2DMapBuilder() .InitNewMap(destArea2, srcArea) .Build(); var settings = new PatchMatchSettings { PatchSize = 5 }; var patchMatchNnfBuilder = new PatchMatchNnfBuilder(); var calculator = ImagePatchDistance.Cie76; // Create nnf for the images // with a couple of iterations. var nnf1 = new Nnf(destImage.Width, destImage.Height, srcImage.Width, srcImage.Height, settings.PatchSize); patchMatchNnfBuilder.RunRandomNnfInitIteration(nnf1, destImage, srcImage, settings, calculator, map1); patchMatchNnfBuilder.RunBuildNnfIteration(nnf1, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map1); patchMatchNnfBuilder.RunBuildNnfIteration(nnf1, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map1); patchMatchNnfBuilder.RunBuildNnfIteration(nnf1, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map1); patchMatchNnfBuilder.RunBuildNnfIteration(nnf1, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map1); patchMatchNnfBuilder.RunBuildNnfIteration(nnf1, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map1); // Create the nnf for the images // with a couple of iterations. var nnf2 = new Nnf(destImage.Width, destImage.Height, srcImage.Width, srcImage.Height, settings.PatchSize); patchMatchNnfBuilder.RunRandomNnfInitIteration(nnf2, destImage, srcImage, settings, calculator, map2); patchMatchNnfBuilder.RunBuildNnfIteration(nnf2, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map2); patchMatchNnfBuilder.RunBuildNnfIteration(nnf2, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map2); patchMatchNnfBuilder.RunBuildNnfIteration(nnf2, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map2); patchMatchNnfBuilder.RunBuildNnfIteration(nnf2, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map2); patchMatchNnfBuilder.RunBuildNnfIteration(nnf2, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map2); // Show the built NNFs and restored images nnf2 .RestoreImage(srcImage, 3, settings.PatchSize) .FromLabToRgb() .FromRgbToBitmap() .SaveTo(@"..\..\..\restored1.png", ImageFormat.Png); nnf1 .RestoreImage(srcImage, 3, settings.PatchSize) .FromLabToRgb() .FromRgbToBitmap() .SaveTo(@"..\..\..\restored2.png", ImageFormat.Png); nnf1 .ToRgbImage() .FromRgbToBitmap() .SaveTo(@"..\..\..\nnf1.png", ImageFormat.Png); nnf2 .ToRgbImage() .FromRgbToBitmap() .SaveTo(@"..\..\..\nnf2.png", ImageFormat.Png); // Let's now merge the built NNFs and try to restore an image nnf2.Merge(nnf1, map2, map1); nnf2 .RestoreImage(srcImage, 3, settings.PatchSize) .FromLabToRgb() .FromRgbToBitmap() .SaveTo(@"..\..\..\restored_whole.png", ImageFormat.Png); nnf2 .ToRgbImage() .FromRgbToBitmap() .SaveTo(@"..\..\..\merged_nnf.png", ImageFormat.Png) .ShowFile(); Console.WriteLine($"PatchMatchPipeline processing is finished."); }
static void Main(string[] args) { var sw = new Stopwatch(); sw.Start(); const string basePath = "..\\..\\..\\..\\images"; var destImageName = "pm1.png"; var srcImageName = "pm2.png"; var destTargetImageName = "dd1.png"; // this is our input data. var destImage = GetLabImage(basePath, destImageName); var srcImage = GetLabImage(basePath, srcImageName); var destTargetArea1 = GetArea2D(basePath, destTargetImageName); var srcArea1 = GetArea2D(basePath, "sd1.png"); var destArea2 = GetArea2D(basePath, "dd2.png"); var srcArea2 = GetArea2D(basePath, "sd2.png"); var destArea = Area2D.Create(0, 0, destImage.Width, destImage.Height); var srcArea = Area2D.Create(0, 0, srcImage.Width, srcImage.Height); var map = new Area2DMapBuilder() .InitNewMap(destArea, srcArea) .AddAssociatedAreas(destTargetArea1, srcArea1) .AddAssociatedAreas(destArea2, srcArea2) .Build(); const byte patchSize = 5; var nnf = new Nnf(destImage.Width, destImage.Height, srcImage.Width, srcImage.Height, patchSize); // Prepage setting for the PM algorithm var settings = new PatchMatchSettings { PatchSize = patchSize }; var calculator = ImagePatchDistance.Cie76; var patchMatchNnfBuilder = new PatchMatchNnfBuilder(); // Create the nnf for the small variant of the images // with a couple of iterations. patchMatchNnfBuilder.RunRandomNnfInitIteration(nnf, destImage, srcImage, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Backward, settings, calculator, map); patchMatchNnfBuilder.RunBuildNnfIteration(nnf, destImage, srcImage, NeighboursCheckDirection.Forward, settings, calculator, map); // Restore dest image from the NNF and source image. nnf .RestoreImage(srcImage, 3, patchSize) .FromLabToRgb() .FromRgbToBitmap() .SaveTo(@"..\..\..\restored.png", ImageFormat.Png); // Convert the NNF to an image, save and show it nnf .ToRgbImage() .FromRgbToBitmap() .SaveTo(@"..\..\..\nnf.png", ImageFormat.Png) .ShowFile(); sw.Stop(); Console.WriteLine($"Elapsed time: {sw.Elapsed}"); Console.WriteLine($"PatchMatchPipeline processing is finished."); }