public IONodeConvolutionParallel(Point2D inputDim, IONode filter, Point2D stepSize) : base(inputDim, new Point2D(filter.output.Width * inputDim.X / stepSize.X, filter.output.Height * inputDim.Y / stepSize.Y)) { this.filter = filter; this.stepSize = stepSize; //if (this.filter.input.Width % 2 == 0||this.filter.input.Height % 2 == 0) //{ // throw new ArgumentException("Filter input cannot be even."); //} }
public void pushLayer(IONode n) { if (layers.Count != 0 && layers.Last().output.Size != n.input.Size) { throw new Exception("The input size of the layer you are trying to push is not consistent with the output of the previous layer."); } layers.Add(n); if (layers.Count == 1) { Resize(n.input.Size, n.output.Size); //resize both input and output } else { Resize(input.Size, n.output.Size); //resize only the output } }
/// <summary> /// Move a sliding window and apply the filter by using its BottomUp() method. /// </summary> protected override void bottomUp() { System.Collections.Concurrent.ConcurrentStack <IONode> filterClones = new ConcurrentStack <IONode>(); int stepsWidth = (int)(input.Width / stepSize.X); int stepsHeight = (int)(input.Height / stepSize.Y); int totalIterations = stepsWidth * stepsHeight; for (int i = 0; i < totalIterations; i++) { IONode clone = ObjectCopier.Clone(filter); filterClones.Push(clone); } System.Collections.Concurrent.ConcurrentStack <IONode> filterClonesUsed = new ConcurrentStack <IONode>(); //We pass all components of the input signal Parallel.For(0, stepsWidth, stepX => { int xI = stepX * (int)stepSize.X; Parallel.For(0, stepsHeight, stepY => { int yI = stepY * (int)stepSize.Y; //Clone the filter IONode clone; while (!filterClones.TryPop(out clone)) { ; } //We construct the filter input based on its dimensions for (int xF = 0; xF < clone.input.Width; xF++) { for (int yF = 0; yF < clone.input.Height; yF++) { int x = xI - clone.input.Width / 2 + xF; int y = yI - clone.input.Height / 2 + yF; x = Math.Min(input.Width - 1, Math.Max(x, 0)); y = Math.Min(input.Height - 1, Math.Max(y, 0)); clone.input.reality[xF, yF] = input.reality[x, y]; } } //We apply the clone clone.BottomUp(); //We copy the result of the clone to the output for (int xF = 0; xF < clone.output.Width; xF++) { for (int yF = 0; yF < clone.output.Height; yF++) { output.prediction[(int)(xI / stepSize.X) * clone.output.Width + xF, (int)(yI / stepSize.Y) * clone.output.Height + yF] = clone.output.prediction[xF, yF]; } } filterClonesUsed.Push(clone); }); }); if (filter is IONodeAdaptive) { IEnumerable <IONodeAdaptive> casted = filterClonesUsed.Cast <IONodeAdaptive>(); (filter as IONodeAdaptive).fuse(casted); } }