public void ConnectNeuronAcrossGaps(PixelState[,] pixels, int[,] pixel2Neuron, Dictionary <int, Neuron> neuronDict, int width, int height, double gapSeparation) { int searchHalfWidth = (int)(gapSeparation + 0.5); for (int i = 0; i < synapseDict.Count; i++) { Synapse s = synapseDict[i]; int x = s.XCenterOfMass; int y = s.YCenterOfMass; // look at all pixels within a square centered around this synapse center-of-mass, // but only halfway around, starting straight up and going clockwise) around the // current pixel for other neurons. do not look in a full circle since then // we would end up with two connections for each pair of synapses (one in // either direction) List <int> neuronsProcessed = new List <int>();; int xDelta, yDelta; for (xDelta = 0; xDelta <= searchHalfWidth; xDelta++) { for (yDelta = -searchHalfWidth; yDelta <= searchHalfWidth; yDelta++) { if ((0 < xDelta) || (yDelta < 0)) { ConnectSynapseToSynapsesSource(pixels, pixel2Neuron, neuronDict, width, height, gapSeparation, x, y, x + xDelta, y + yDelta, neuronsProcessed); } } } } }
public void ConnectSynapseToSynapsesDestination(PixelState[,] pixels, int height, double gapSeperation, int xSource, int ySource) { for (int i = 0; i < synapseDict.Count; i++) { Synapse s = synapseDict[i]; int xDestination = s.XCenterOfMass; int yDestination = s.YCenterOfMass; double seperation = Math.Sqrt((xDestination - xSource) * (xDestination - xSource) + (yDestination - ySource) * (yDestination - ySource)); if (seperation <= gapSeperation) { // draw a line from the source to the destination. we sacrifice efficiency for // simplicity, and do not use the Bresenham line-drawing algorithm (this is // a one-time cost and at most there should be less than a few hundred // pixels drawn in total) int nSteps = 1 + (int)(seperation / 0.5); double xDelta = (double)(xDestination - xSource) / (double)nSteps; double yDelta = (double)(yDestination - ySource) / (double)nSteps; double x = xSource + xDelta, y = ySource + yDelta; for (int j = 0; j < nSteps; j++) { // any pixel within a half pixel of (x,y) will be turned on int xLine = (int)x; int yLine = (int)y; if (Math.Sqrt((x - xLine) * (x - xLine) + (y - yLine) * (y - yLine)) < 0.5) { pixels[xLine, yLine] = PixelState.PixelOn; } xLine += 1; if (Math.Sqrt((x - xLine) * (x - xLine) + (y - yLine) * (y - yLine)) < 0.5) { pixels[xLine, yLine] = PixelState.PixelOn; } yLine += 1; if (Math.Sqrt((x - xLine) * (x - xLine) + (y - yLine) * (y - yLine)) < 0.5) { pixels[xLine, yLine] = PixelState.PixelOn; } xLine -= 1; if (Math.Sqrt((x - xLine) * (x - xLine) + (y - yLine) * (y - yLine)) < 0.5) { pixels[xLine, yLine] = PixelState.PixelOn; } x += xDelta; y += yDelta; } } } }
public Synapse AddSynapse() { Synapse synapse = new Synapse(synapseDict); return synapse; }
private void RecursivelySetPixel2Neuron(PixelState[,] pixels, int[,] pixel2Neuron, int x, int y, int width, int height, Neuron activeNeuron, Synapse activeSynapse, int level) { // if this pixel should belong to a neuron, then assign it to the active neuron. // if there is no active neuron (activeNeuron is null), then create one int xDelta, yDelta; // do not set this pixel if it is not on, or if it has already been assigned // to a neuron if ((pixels[x, y] != PixelState.PixelOn) || (pixel2Neuron[x, y] != -1)) return; // this pixel needs to be assigned to a neuron if (activeNeuron == null) { activeNeuron = new Neuron(neuronDict); } pixel2Neuron[x, y] = activeNeuron.Index; // does this pixel need to be assigned to a synapse? look at eight // nearest neighbors bool needSynapse = false; for (xDelta = -1; !needSynapse && (xDelta <= 1); xDelta++) for (yDelta = -1; !needSynapse && (yDelta <= 1); yDelta++) if ((xDelta != 0) || (yDelta != 0)) { int xNeighbor = x + xDelta; int yNeighbor = y + yDelta; if ((0 <= xNeighbor) && (xNeighbor < width) && (0 <= yNeighbor) && (yNeighbor < height)) { if ((pixels[xNeighbor, yNeighbor] != PixelState.PixelOff) && (pixels[xNeighbor, yNeighbor] != PixelState.PixelOn)) { needSynapse = true; } } } // assign to synapse, creating a new one if necessary if (needSynapse) { if (activeSynapse == null) { activeSynapse = activeNeuron.AddSynapse(); } activeSynapse.addPixel(x, y); } else activeSynapse = null; // limit the levels of recursion since Microsoft Windows will run out of stack // space. specifically, the default stack size of one megabyte only handles // 5700 levels of recursion here, and a stack size of two megabytes only // handles 11000 levels of recursion. extreme amounts of recursion happen in // images with extreme numbers of lines if (level < removalMaxRecursion) { // also set the eight nearest neighbors for (xDelta = -1; xDelta <= 1; xDelta++) for (yDelta = -1; yDelta <= 1; yDelta++) if ((xDelta != 0) || (yDelta != 0)) { int xNeighbor = x + xDelta; int yNeighbor = y + yDelta; if ((0 <= xNeighbor) && (xNeighbor < width) && (0 <= yNeighbor) && (yNeighbor < height)) { RecursivelySetPixel2Neuron(pixels, pixel2Neuron, xNeighbor, yNeighbor, width, height, activeNeuron, activeSynapse, level + 1); } } } }
public Synapse AddSynapse() { Synapse synapse = new Synapse(synapseDict); return(synapse); }
private void RecursivelySetPixel2Neuron(PixelState[,] pixels, int[,] pixel2Neuron, int x, int y, int width, int height, Neuron activeNeuron, Synapse activeSynapse, int level) { // if this pixel should belong to a neuron, then assign it to the active neuron. // if there is no active neuron (activeNeuron is null), then create one int xDelta, yDelta; // do not set this pixel if it is not on, or if it has already been assigned // to a neuron if ((pixels[x, y] != PixelState.PixelOn) || (pixel2Neuron[x, y] != -1)) { return; } // this pixel needs to be assigned to a neuron if (activeNeuron == null) { activeNeuron = new Neuron(neuronDict); } pixel2Neuron[x, y] = activeNeuron.Index; // does this pixel need to be assigned to a synapse? look at eight // nearest neighbors bool needSynapse = false; for (xDelta = -1; !needSynapse && (xDelta <= 1); xDelta++) { for (yDelta = -1; !needSynapse && (yDelta <= 1); yDelta++) { if ((xDelta != 0) || (yDelta != 0)) { int xNeighbor = x + xDelta; int yNeighbor = y + yDelta; if ((0 <= xNeighbor) && (xNeighbor < width) && (0 <= yNeighbor) && (yNeighbor < height)) { if ((pixels[xNeighbor, yNeighbor] != PixelState.PixelOff) && (pixels[xNeighbor, yNeighbor] != PixelState.PixelOn)) { needSynapse = true; } } } } } // assign to synapse, creating a new one if necessary if (needSynapse) { if (activeSynapse == null) { activeSynapse = activeNeuron.AddSynapse(); } activeSynapse.addPixel(x, y); } else { activeSynapse = null; } // limit the levels of recursion since Microsoft Windows will run out of stack // space. specifically, the default stack size of one megabyte only handles // 5700 levels of recursion here, and a stack size of two megabytes only // handles 11000 levels of recursion. extreme amounts of recursion happen in // images with extreme numbers of lines if (level < removalMaxRecursion) { // also set the eight nearest neighbors for (xDelta = -1; xDelta <= 1; xDelta++) { for (yDelta = -1; yDelta <= 1; yDelta++) { if ((xDelta != 0) || (yDelta != 0)) { int xNeighbor = x + xDelta; int yNeighbor = y + yDelta; if ((0 <= xNeighbor) && (xNeighbor < width) && (0 <= yNeighbor) && (yNeighbor < height)) { RecursivelySetPixel2Neuron(pixels, pixel2Neuron, xNeighbor, yNeighbor, width, height, activeNeuron, activeSynapse, level + 1); } } } } } }