private static Convolution2D Convolute(Convolution2D conv, ToVectorInstructions instr) { Convolution2D retVal = conv; if (retVal.Width != retVal.Height) { int max = Math.Max(retVal.Width, retVal.Height); retVal = Convolutions.ExtendBorders(retVal, max, max); // make it square } if (instr.ShouldNormalize) { retVal = Convolutions.Normalize(retVal); } if (instr.Convolution != null) { retVal = Convolutions.Convolute(retVal, instr.Convolution); } retVal = Convolutions.MaxPool(retVal, instr.ToSize, instr.ToSize); retVal = Convolutions.Abs(retVal); return(retVal); }
private static SOMItem GetSOMItem_2D_Gray(VectorND item, ToVectorInstructions instr) { Convolution2D conv = new Convolution2D(item.VectorArray, instr.FromSizes[0], instr.FromSizes[1], false); conv = Convolute(conv, instr); return(new SOMItem(item, conv.Values.ToVectorND())); }
private static SOMItem GetSOMItem_2D_Color(VectorND item, ToVectorInstructions instr) { int width = instr.FromSizes[0]; int height = instr.FromSizes[1]; #region build arrays double[] r = new double[width * height]; double[] g = new double[width * height]; double[] b = new double[width * height]; //double scale = 1d / 255d; double scale = 1d; for (int y = 0; y < height; y++) { int yOffsetDest = y * width; // offset into the return array int yOffsetSource = y * width * 3; for (int x = 0; x < width; x++) { int xOffsetSource = x * 3; r[yOffsetDest + x] = item[yOffsetSource + xOffsetSource + 0] * scale; g[yOffsetDest + x] = item[yOffsetSource + xOffsetSource + 1] * scale; b[yOffsetDest + x] = item[yOffsetSource + xOffsetSource + 2] * scale; } } #endregion Convolution2D convR = Convolute(new Convolution2D(r, width, height, false), instr); Convolution2D convG = Convolute(new Convolution2D(g, width, height, false), instr); Convolution2D convB = Convolute(new Convolution2D(b, width, height, false), instr); #region merge arrays double[] merged = new double[convR.Values.Length * 3]; for (int cntr = 0; cntr < convR.Values.Length; cntr++) { int index = cntr * 3; merged[index + 0] = convR.Values[cntr]; merged[index + 1] = convG.Values[cntr]; merged[index + 2] = convB.Values[cntr]; } #endregion return(new SOMItem(item, merged.ToVectorND())); }
private static SOMItem GetSOMItem(VectorND item, ToVectorInstructions instr) { switch (instr.FromSizes.Length) { case 1: return(GetSOMItem_1D(item, instr)); case 2: if (instr.IsColor2D) { return(GetSOMItem_2D_Color(item, instr)); } else { return(GetSOMItem_2D_Gray(item, instr)); } default: throw new ApplicationException("TODO: handle arbitrary number of dimensions"); } }
private static SOMItem GetSOMItem_1D(VectorND item, ToVectorInstructions instr) { if (instr.FromSizes[0] == instr.ToSize) { return(new SOMItem(item, item)); } // Create a bezier through the points, then pull points off of that curve. Unless I read this wrong, this is what bicubic interpolation of images does (I'm just doing 1D instead of 2D) Point3D[] points = item. Select(o => new Point3D(o, 0, 0)). ToArray(); BezierSegment3D[] bezier = BezierUtil.GetBezierSegments(points); VectorND resized = BezierUtil.GetPath(instr.ToSize, bezier). Select(o => o.X). ToArray(). ToVectorND(); return(new SOMItem(item, resized)); }
private static Convolution2D Convolute(Convolution2D conv, ToVectorInstructions instr) { Convolution2D retVal = conv; if (retVal.Width != retVal.Height) { int max = Math.Max(retVal.Width, retVal.Height); retVal = Convolutions.ExtendBorders(retVal, max, max); // make it square } if (instr.ShouldNormalize) { retVal = Convolutions.Normalize(retVal); } if (instr.Convolution != null) { retVal = Convolutions.Convolute(retVal, instr.Convolution); } retVal = Convolutions.MaxPool(retVal, instr.ToSize, instr.ToSize); retVal = Convolutions.Abs(retVal); return retVal; }
/// <param name="itemDimensions"> /// The width, height, depth, etc of each item /// </param> /// <param name="convolution"> /// This gives a chance to run an edge detect, or some other convolution /// TODO: Support convolutions that can handle arbitrary dimensions /// </param> /// <param name="shouldNormalize"> /// Forces all inputs to go between 0 and 1. /// NOTE: Only do this if the inputs come from varied sources /// </param> /// <param name="dupeDistance"> /// If two items are closer together than this, they will be treated like they are the same. /// NOTE: If all the inputs are 0 to 1 (or even -1 to 1), then the default value should be fine. But if the /// inputs have larger values (like 0 to 255), you would want a larger min value /// </param> public SOMList(int[] itemDimensions, ConvolutionBase2D convolution = null, bool shouldNormalize = false, bool discardDupes = true, double dupeDistance = .001, bool isColor2D = false) { _instructions = new ToVectorInstructions(itemDimensions, GetResize(itemDimensions), convolution, shouldNormalize, isColor2D); _dupeDistSquared = dupeDistance * dupeDistance; }
private static SOMItem GetSOMItem_2D_Gray(double[] item, ToVectorInstructions instr) { Convolution2D conv = new Convolution2D(item, instr.FromSizes[0], instr.FromSizes[1], false); conv = Convolute(conv, instr); return new SOMItem(item, conv.Values); }
private static SOMItem GetSOMItem_2D_Color(double[] item, ToVectorInstructions instr) { int width = instr.FromSizes[0]; int height = instr.FromSizes[1]; #region build arrays double[] r = new double[width * height]; double[] g = new double[width * height]; double[] b = new double[width * height]; //double scale = 1d / 255d; double scale = 1d; for (int y = 0; y < height; y++) { int yOffsetDest = y * width; // offset into the return array int yOffsetSource = y * width * 3; for (int x = 0; x < width; x++) { int xOffsetSource = x * 3; r[yOffsetDest + x] = item[yOffsetSource + xOffsetSource + 0] * scale; g[yOffsetDest + x] = item[yOffsetSource + xOffsetSource + 1] * scale; b[yOffsetDest + x] = item[yOffsetSource + xOffsetSource + 2] * scale; } } #endregion Convolution2D convR = Convolute(new Convolution2D(r, width, height, false), instr); Convolution2D convG = Convolute(new Convolution2D(g, width, height, false), instr); Convolution2D convB = Convolute(new Convolution2D(b, width, height, false), instr); #region merge arrays double[] merged = new double[convR.Values.Length * 3]; for (int cntr = 0; cntr < convR.Values.Length; cntr++) { int index = cntr * 3; merged[index + 0] = convR.Values[cntr]; merged[index + 1] = convG.Values[cntr]; merged[index + 2] = convB.Values[cntr]; } #endregion return new SOMItem(item, merged); }
private static SOMItem GetSOMItem_1D(double[] item, ToVectorInstructions instr) { if (instr.FromSizes[0] == instr.ToSize) { return new SOMItem(item, item); } // Create a bezier through the points, then pull points off of that curve. Unless I read this wrong, this is what bicubic interpolation of images does (I'm just doing 1D instead of 2D) Point3D[] points = item. Select(o => new Point3D(o, 0, 0)). ToArray(); BezierSegment3D[] bezier = BezierUtil.GetBezierSegments(points); double[] resized = BezierUtil.GetPath(instr.ToSize, bezier). Select(o => o.X). ToArray(); return new SOMItem(item, resized); }
private static SOMItem GetSOMItem(double[] item, ToVectorInstructions instr) { switch (instr.FromSizes.Length) { case 1: return GetSOMItem_1D(item, instr); case 2: if (instr.IsColor2D) return GetSOMItem_2D_Color(item, instr); else return GetSOMItem_2D_Gray(item, instr); default: throw new ApplicationException("TODO: handle arbitrary number of dimensions"); } }