private static ZsImage CreateImage(int w, int h, double vals = 1.0) { var pixels = Enumerable.Repeat(vals, w * h * 4).ToArray(); var image = new ZsImage(pixels, w, h, 4); return(image); }
public PmData(ZsImage destImage, ZsImage srcImage, Nnf nnf, Area2DMap map) { if (destImage == null) { throw new ArgumentNullException(nameof(destImage)); } if (srcImage == null) { throw new ArgumentNullException(nameof(srcImage)); } if (map == null) { throw new ArgumentNullException(nameof(map)); } if (nnf == null) { throw new ArgumentNullException(nameof(nnf)); } Map = map; Nnf = nnf; DestImage = destImage; SrcImage = srcImage; DestImagePixelsArea = Area2D.Create(0, 0, destImage.Width, destImage.Height); Settings = new PatchMatchSettings(); }
/// <summary> /// Runs the NNF build iteration using the whole areas of the dest and the source images. Uses CIE76 to calculate patch similarity. /// </summary> /// <param name="nnf">The NNF.</param> /// <param name="destImage">The dest image. For each patch at this image we will look for a similar one at the source image.</param> /// <param name="srcImage">The source image. Source of the patches for the dest image.</param> /// <param name="direction">The direction to look for a patches.</param> /// <param name="settings">The settings that control parameters of the algorithm.</param> public void RunBuildNnfIteration(Nnf nnf, ZsImage destImage, ZsImage srcImage, NeighboursCheckDirection direction, PatchMatchSettings settings) { var patchDistanceCalculator = ImagePatchDistance.Cie76; RunBuildNnfIteration(nnf, destImage, srcImage, direction, settings, patchDistanceCalculator); }
private static ZsImage Create3pixBiggerMarkupNotEmptyOutsideOfTheImage(int imageWidth, int imageHeight) { int mw = imageWidth + 3; int mh = imageHeight + 3; var pixels = Enumerable.Repeat <double>(0.0, mw * mh * 4).ToArray(); var x1 = imageWidth + 0; var y1 = imageHeight + 0; var x2 = imageWidth + 1; var y2 = imageHeight + 1; var x3 = imageWidth + 2; var y3 = imageHeight + 2; pixels[(y1 * mw + x1) * 4 + 0] = 1.0; pixels[(y1 * mw + x1) * 4 + 1] = 1.0; pixels[(y1 * mw + x1) * 4 + 2] = 1.0; pixels[(y2 * mw + x2) * 4 + 0] = 1.0; pixels[(y2 * mw + x2) * 4 + 1] = 1.0; pixels[(y2 * mw + x2) * 4 + 2] = 1.0; pixels[(y3 * mw + x3) * 4 + 0] = 1.0; pixels[(y3 * mw + x3) * 4 + 1] = 1.0; pixels[(y3 * mw + x3) * 4 + 2] = 1.0; var markup = new ZsImage(pixels, mw, mh, 4); return(markup); }
public void Init(ZsImage imageArgb, ZsImage inpaintMarkupArgb) { if (imageArgb == null) { throw new ArgumentNullException(nameof(imageArgb)); } if (inpaintMarkupArgb == null) { throw new ArgumentNullException(nameof(inpaintMarkupArgb)); } if (imageArgb.NumberOfComponents != 4) { throw new WrongImageFormatException(); } if (inpaintMarkupArgb.NumberOfComponents != 4) { throw new WrongImageFormatException(); } _imageArgb = imageArgb; _inpaintMarkup = inpaintMarkupArgb; _donors.Clear(); }
public void AddDonorMarkup(ZsImage donorArgb) { if (donorArgb != null) { _donors.Add(donorArgb); } }
protected static ZsImage CreateImage(int w, int h) { var pixels = Enumerable.Repeat(0.0, w * h * 4).ToArray(); var image = new ZsImage(pixels, w, h, 4); return(image); }
public PmData(ZsImage destImage, ZsImage srcImage) { if (destImage == null) { throw new ArgumentNullException(nameof(destImage)); } if (srcImage == null) { throw new ArgumentNullException(nameof(srcImage)); } DestImage = destImage; SrcImage = srcImage; Nnf = new Nnf(destImage.Width, destImage.Height, srcImage.Width, srcImage.Height); Settings = new PatchMatchSettings(); var destImageArea = Area2D.Create(0, 0, destImage.Width, destImage.Height); DestImagePixelsArea = destImageArea; var mapBuilder = new Area2DMapBuilder(); mapBuilder.InitNewMap( destImageArea, Area2D.Create(0, 0, srcImage.Width, srcImage.Height)); Map = mapBuilder.Build(); }
public void Should_Increase_Stride(double[] pixels, int width, int height, byte componentsAmount, double[] components, byte position, int result) { var image = new ZsImage(pixels, width, height, componentsAmount); image.InsertComponents(components, position); image.Stride.ShouldBe(result); }
private static ZsImage CopyImageArea(ZsImage imageArgb, Area2D imageSrcArea) { var pixels = Enumerable.Repeat(0.0, imageSrcArea.Bound.Width * imageSrcArea.Bound.Height * 4).ToArray(); var resultImage = new ZsImage(pixels, imageSrcArea.Bound.Width, imageSrcArea.Bound.Height, 4); var imageArgbArea = Area2D.Create(0, 0, imageSrcArea.Bound.Width, imageSrcArea.Bound.Height); resultImage.CopyFromImage(imageArgbArea, imageArgb, imageSrcArea); return(resultImage); }
public static unsafe void MergeImage(this ZsImage grayImage1, ZsImage grayImage2) { if (grayImage1 == null) { throw new ArgumentNullException(); } if (grayImage2 == null) { throw new ArgumentNullException(); } const int NotDividableMinAmountElements = 80; double[] pixelsData1 = grayImage1.PixelsData; double[] pixelsData2 = grayImage2.PixelsData; int pointsAmount = grayImage1.Width * grayImage1.Height; // Decide on how many partitions we should divade the processing // of the elements. var partsCount = pointsAmount > NotDividableMinAmountElements ? Environment.ProcessorCount : 1; var partSize = (int)(pointsAmount / partsCount); Parallel.For(0, partsCount, partIndex => { var firstPointIndex = partIndex * partSize; var lastPointIndex = firstPointIndex + partSize - 1; if (partIndex == partsCount - 1) { lastPointIndex = pointsAmount - 1; } if (lastPointIndex > pointsAmount) { lastPointIndex = pointsAmount - 1; } fixed(double *pixelsDataP1 = pixelsData1) fixed(double *pixelsDataP2 = pixelsData2) { for (int pointIndex = lastPointIndex; pointIndex >= firstPointIndex; pointIndex--) { int i = pointIndex * 1; // components should be in the range [0.0 , 1.0] double g1 = *(pixelsDataP1 + i + 0); double g2 = *(pixelsDataP2 + i + 0); *(pixelsDataP1 + i + 0) = Math.Sqrt(g1 * g1 + g2 * g2); } } }); }
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); }
private static ZsImage AlignImage(ZsImage wrongSizedImageArgb, ZsImage correctSizedImageArgb) { var correctArea = Area2D.Create(0, 0, correctSizedImageArgb.Width, correctSizedImageArgb.Height); var wrongArea = Area2D.Create(0, 0, wrongSizedImageArgb.Width, wrongSizedImageArgb.Height); var srcArea = wrongArea.Intersect(correctArea); var pixels = Enumerable.Repeat(0.0, correctSizedImageArgb.Width * correctSizedImageArgb.Height * 4).ToArray(); var correctedImage = new ZsImage(pixels, correctSizedImageArgb.Width, correctSizedImageArgb.Height, 4); return(correctedImage.CopyFromImage(correctArea, wrongSizedImageArgb, srcArea)); }
public WhenRemoveComponents() { _pixelsData = new[] { 0.00, 1.00, 2.00, 3.00, 0.50, 1.50, 2.50, 3.50, 0.25, 1.25, 2.25, 3.25, 0.125, 1.125, 2.125, 3.125 }; _image = new ZsImage(_pixelsData, 2, 2, 4); }
private Area2D GetImageAreaToProcess(ZsImage imageArgb, ZsImage markupArgb, byte levelsAmount) { var size = Calculate(imageArgb.Width, imageArgb.Height, levelsAmount); var markupArgbArea = markupArgb.FromArgbToArea2D(); var offset = CalculateOffset(size.Item1, size.Item2, markupArgbArea); var imageSrcArea = Area2D.Create((int)offset.X, (int)offset.Y, size.Item1, size.Item2); return(imageSrcArea); }
public void Should_Throw_ArgumentOutOfRangeException_When_PatchSize_Less_Than_2(byte patchSize) { // Arrange var detector = new PyramidLevelsDetector(); ZsImage image = CreateImage(100, 100); ZsImage markup = CreateImage(50, 100); Action act = () => detector.CalculateLevelsAmount(image, markup, patchSize); // Act & Assert act.ShouldThrow <ArgumentOutOfRangeException>(); }
/// <summary> /// Runs the random NNF initialization iteration for the associated areas of the dest and the source images. /// </summary> /// <param name="nnf">The NNF.</param> /// <param name="destImage">The dest image. For each patch at this image we will look for a similar one at the source image.</param> /// <param name="srcImage">The source image. Source of the patches for the dest image.</param> /// <param name="settings">The settings that control parameters of the algorithm.</param> /// <param name="patchDistanceCalculator">The calculator that calculates similarity of two patches. By deafult the Cie76 is used.</param> /// <param name="areasMapping">The areas mapping. By default whole area of the dest image is associated with the whole area of the source image.</param> /// <exception cref="ArgumentNullException">destImage</exception> public void RunRandomNnfInitIteration(Nnf nnf, ZsImage destImage, ZsImage srcImage, PatchMatchSettings settings, ImagePatchDistanceCalculator patchDistanceCalculator, Area2DMap areasMapping) { if (destImage == null) { throw new ArgumentNullException(nameof(destImage)); } var destPixelsArea = Area2D.Create(0, 0, destImage.Width, destImage.Height); RunRandomNnfInitIteration(nnf, destImage, srcImage, settings, patchDistanceCalculator, areasMapping, destPixelsArea); }
public static unsafe void NormalizeWeights(this ZsImage grayImage, double w1, double w2, Area2D imageArea) { if (grayImage == null) { throw new ArgumentNullException(); } const int NotDividableMinAmountElements = 80; const byte componentsAmount = 1; double[] pixelsData1 = grayImage.PixelsData; int pointsAmount = imageArea.ElementsCount; var pointIndecies = new int[pointsAmount]; imageArea.FillMappedPointsIndexes(pointIndecies, grayImage.Width); // Decide on how many partitions we should divade the processing // of the elements. var partsCount = pointsAmount > NotDividableMinAmountElements ? Environment.ProcessorCount : 1; var partSize = (int)(pointsAmount / partsCount); Parallel.For(0, partsCount, partIndex => { var firstPointIndex = partIndex * partSize; var lastPointIndex = firstPointIndex + partSize - 1; if (partIndex == partsCount - 1) { lastPointIndex = pointsAmount - 1; } if (lastPointIndex > pointsAmount) { lastPointIndex = pointsAmount - 1; } fixed(double *pixelsDataP1 = pixelsData1) { for (int j = lastPointIndex; j >= firstPointIndex; j--) { int absIndex = pointIndecies[j] * componentsAmount; // components should be in the range [0.0 , 1.0] double g = *(pixelsDataP1 + absIndex + 0); g = g > 1.0 ? 1.0 : g < 0.0 ? 0.0 : g; *(pixelsDataP1 + absIndex + 0) = (g + w1) / w2; } } }); }
public WhenSetComponentsValues() { _pixelsData = new[] { 1.00, 1.00, 1.00, 0.50, 0.50, 0.50, 0.25, 0.25, 0.25, 0.125, 0.125, 0.125 }; _image = new ZsImage(_pixelsData, 2, 2, 3); _area = Area2D.Create(0, 0, 2, 2); }
private Pyramid BuildPyramid(ZsImage imageArgb, ZsImage markupArgb, IEnumerable <ZsImage> donorsArgb, byte levelsAmount, byte patchSize) { _pyramidBuilder.Init(imageArgb, markupArgb); foreach (var donorArgb in donorsArgb) { _pyramidBuilder.AddDonorMarkup(donorArgb); } var pyramid = _pyramidBuilder.Build(levelsAmount, patchSize); return(pyramid); }
private static unsafe void FillMinSequence(int[] minSequence, ZsImage energyMap, Area2D imageArea) { if (energyMap == null) { throw new ArgumentNullException(); } if (!IsRectangle(imageArea)) { throw new ArgumentException("imageArea that has not rectangular shape is not allowed"); } if (energyMap.Height != imageArea.Bound.Height) { throw new ArgumentException("imageArea should occupay the whole height of the energyMap"); } double[] pixelsData = energyMap.PixelsData; int width = energyMap.Width; int height = energyMap.Height; byte cmpsAmount = energyMap.NumberOfComponents; int x = FindMinEnergySequenceStart(energyMap, imageArea); minSequence[height - 1] = x; var isValudIndex = CreateIndexValidator(imageArea, width); fixed(double *pixelsDataP = pixelsData) { for (int y = height - 2; y >= 0; y--) { int tlIndex = y * width + (x - 1); int trIndex = y * width + (x + 1); double tl = x > 1 && isValudIndex(tlIndex) ? *(pixelsDataP + tlIndex * cmpsAmount + 0) : double.MaxValue; double tc = *(pixelsDataP + (y * width + (x + 0)) * cmpsAmount + 0); double tr = x < (width - 1) && isValudIndex(trIndex) ? *(pixelsDataP + trIndex * cmpsAmount + 0) : double.MaxValue; if (tl < tc && tl < tr) { x = x - 1; } else if (tr < tl && tr < tc) { x = x + 1; } minSequence[y] = x; } } }
public void Should_Throw_ArgumentNullException_When_RemoveMarkup_IsNull() { // Arrange var detector = new PyramidLevelsDetector(); ZsImage image = CreateImage(100, 100); ZsImage markup = null; byte patchSize = 7; Action act = () => detector.CalculateLevelsAmount(image, markup, patchSize); // Act & Assert act.ShouldThrow <ArgumentNullException>(); }
public void Should_Throw_AreaRemovedException_When_Markup_Covers_Image(int iw, int ih, int mw, int mh) { // Arrange var detector = new PyramidLevelsDetector(); ZsImage image = CreateImage(iw, ih); ZsImage markup = CreateImage(mw, mh); byte patchSize = 7; Action act = () => detector.CalculateLevelsAmount(image, markup, patchSize); // Act & Assert act.ShouldThrow <AreaRemovedException>(); }
public void Should_Return_1_When_Markup_IsEmpty_Inside_Image_Area() { // Arrange var detector = new PyramidLevelsDetector(); ZsImage image = CreateImage(100, 100); ZsImage markup = Create3pixBiggerMarkupNotEmptyOutsideOfTheImage(100, 100); byte patchSize = 7; // Act var levelsAmount = detector.CalculateLevelsAmount(image, markup, patchSize); // Assert levelsAmount.ShouldBe((byte)1); }
public void Should_Return_1_When_Markup_IsEmpty() { // Arrange var detector = new PyramidLevelsDetector(); ZsImage image = CreateImage(100, 100); ZsImage markup = CreateImage(100, 100, 0.0); byte patchSize = 7; // Act var levelsAmount = detector.CalculateLevelsAmount(image, markup, patchSize); // Assert levelsAmount.ShouldBe((byte)1); }
public void Should_Throw_ArgumentOutOfRangeException_Index_Greater_Than_Components_Amount(double[] pixels, int width, int height, byte componentsAmount, double[] components, byte index, Type expectedType) { var image = new ZsImage(pixels, width, height, componentsAmount); var result = typeof(object); try { image.InsertComponents(components, index); } catch (Exception ex) { result = ex.GetType(); } result.ShouldBe(expectedType); }
private static unsafe int FindMinEnergySequenceStart(ZsImage energyMap, Area2D imageArea) { if (energyMap == null) { throw new ArgumentNullException(); } if (!IsRectangle(imageArea)) { throw new ArgumentException("imageArea that has not rectangular shape is not allowed"); } if (energyMap.Height != imageArea.Bound.Height) { throw new ArgumentException("imageArea should occupay the whole height of the energyMap"); } double[] pixelsData = energyMap.PixelsData; int width = energyMap.Width; byte cmpsAmount = energyMap.NumberOfComponents; int startX = imageArea.Bound.X; int endX = imageArea.Bound.Width + startX; int minEnergyIndex = startX; int y = energyMap.Height - 1; double currentEnergy; double minEnergy = double.MaxValue; fixed(double *pixelsDataP = pixelsData) { for (int x = startX; x < endX; x++) { currentEnergy = *(pixelsDataP + (y * width + x) * cmpsAmount + 0); if (currentEnergy < minEnergy) { minEnergy = currentEnergy; minEnergyIndex = x; } } } return(minEnergyIndex); }
public void Should_Insert_Provided_Values(double[] pixels, int width, int height, byte componentsAmount, double[] components, byte index, double[] result, bool expected) { var image = new ZsImage(pixels, width, height, componentsAmount); image.InsertComponents(components, index); var pixels2 = image.PixelsData; var equal = result.Length == pixels2.Length; for (int i = 0; i < result.Length && equal; i++) { if (result[i] != pixels2[i]) { equal = false; } } equal.ShouldBe(expected); }
public static async Task SaveImageLabToBlob(ZsImage imageLab, CloudBlobContainer container, string fileName) { var argbImage = imageLab .Clone() .FromLabToRgb() .FromRgbToArgb(Area2D.Create(0, 0, imageLab.Width, imageLab.Height)); using (var bitmap = argbImage.FromArgbToBitmap()) using (var outputStream = new MemoryStream()) { // modify image bitmap.Save(outputStream, ImageFormat.Png); // save the result back outputStream.Position = 0; var resultImageBlob = container.GetBlockBlobReference(fileName); await resultImageBlob.UploadFromStreamAsync(outputStream); } }
/// <summary> /// Runs the random NNF initialization iteration using the whole areas of the dest and the source images. /// </summary> /// <param name="nnf">The NNF.</param> /// <param name="destImage">The dest image. For each patch at this image we will look for a similar one at the source image.</param> /// <param name="srcImage">The source image. Source of the patches for the dest image.</param> /// <param name="settings">The settings that control parameters of the algorithm.</param> /// <param name="patchDistanceCalculator">The calculator that calculates similarity of two patches. By deafult the Cie76 is used.</param> /// <exception cref="ArgumentNullException"> /// destImage /// or /// srcImage /// </exception> public void RunRandomNnfInitIteration(Nnf nnf, ZsImage destImage, ZsImage srcImage, PatchMatchSettings settings, ImagePatchDistanceCalculator patchDistanceCalculator) { if (destImage == null) { throw new ArgumentNullException(nameof(destImage)); } if (srcImage == null) { throw new ArgumentNullException(nameof(srcImage)); } 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) .Build(); RunRandomNnfInitIteration(nnf, destImage, srcImage, settings, patchDistanceCalculator, map); }