コード例 #1
0
        //Saves the pixel states to the image
        private void SavePixels(PixelState[,] pixels, Color bgColor)
        {
            BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.ReadOnly, bmp.PixelFormat);

            byte r = bgColor.R;
            byte g = bgColor.G;
            byte b = bgColor.B;
            for (int x = 0; x < bmp.Width; x++)
            {
                for (int y = 0; y < bmp.Height; y++)
                {
                    PixelState state = pixels[x, y];
                    if (state != PixelState.PixelOff && state != PixelState.PixelOn)
                    {
                        NuGenImageProcessor.SetPixelAt(bmData, x, y, r, g, b);
                    }
                }
            }
            bmp.UnlockBits(bmData);
        }
コード例 #2
0
        private PixelState[,] InitializePixels()
        {
            PixelState[,] pixels = new PixelState[bmp.Width, bmp.Height];
            BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

            for (int x = 0; x < bmp.Width; x++)
            {
                for (int y = 0; y < bmp.Height; y++)
                {
                    int r, g, b;
                    NuGenImageProcessor.GetPixelAt(bmData, x, y, out r, out g, out b);

                    if ((Math.Round(((double)Math.Max(Math.Max(r, g), b)) * 255.0 / 100.0)) < 50)
                        pixels[x, y] = PixelState.PixelOn;
                    else
                        pixels[x, y] = PixelState.PixelOff;
                }
            }

            bmp.UnlockBits(bmData);
            return pixels;
        }
コード例 #3
0
 private void EraseThinPixels(PixelState[,] pixels, double thinThickness, PixelState pixelThreshold)
 {
     // loop through pixels, removing those on thin lines
     for (int x = 0; x < this.bmp.Width; x++)
     {
         for (int y = 0; y < this.bmp.Height; y++)
         {
             if (pixels[x, y] == PixelState.PixelOn)
             {
                 double dPlusX = DistanceToOffPixel(pixels, x, y, searchPatternPlusX,
                   pixelThreshold);
                 double dMinusX = DistanceToOffPixel(pixels, x, y, searchPatternMinusX,
                   pixelThreshold);
                 if (dMinusX + dPlusX <= thinThickness)
                 {
                     pixels[x, y] = pixelThreshold;
                     continue;
                 }
                 else
                 {
                     double dPlusY = DistanceToOffPixel(pixels, x, y, searchPatternPlusY,
                       pixelThreshold);
                     double dMinusY = DistanceToOffPixel(pixels, x, y, searchPatternMinusY,
                       pixelThreshold);
                     if (dMinusY + dPlusY <= thinThickness)
                     {
                         pixels[x, y] = pixelThreshold;
                         continue;
                     }
                 }
             }
         }
     }
 }
コード例 #4
0
        private double DistanceToOffPixel(PixelState[,] pixels, int x, int y, List<SearchPoint> searchPattern, PixelState pixelThreshold)
        {
            // pixels having values of pixelThreshold and higher are considered "on"
            foreach (SearchPoint p in searchPattern)
            {
                int i = x + p.X;
                if (0 <= i && i < this.bmp.Width)
                {
                    int j = y + p.Y;
                    if (0 <= j && j < this.bmp.Height)
                    {
                        if ((int)pixels[i, j] < (int)pixelThreshold)
                        {
                            // reduce by one half since the distance is from the center of the on pixel
                            // to the boundary of the off pixel
                            return p.Distance - 0.5;
                        }
                    }
                }
            }

            // return really big number
            return (double)this.bmp.Width;
        }
コード例 #5
0
        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;
                    }
                }
            }
        }
コード例 #6
0
        //Removes thin lines which are parallel to the user defined axes
        private void RemoveThinLines(PixelState[,] pixels, CoordSettings coordSettings, NuGenScreenTranslate transform,
                                     double thinThickness, PixelState pixelStateRemovedPass1, PixelState pixelStateRemovedPass2)
        {
            if (transform.ValidAxes)
            {
                InitializeThin(coordSettings, transform, thinThickness);

                // first pass erases the gridMeshSettings lines, except for the junctions
                EraseThinPixels(pixels, thinThickness, pixelStateRemovedPass1);

                // second pass erases the gridMeshSettings line junctions, which are little islands of on-pixels
                EraseThinPixels(pixels, thinThickness, pixelStateRemovedPass2);
            }
        }
コード例 #7
0
        //Connects neurons which are seperated by synapses
        private void ConnectNeuronsAcrossGaps(PixelState[,] pixels, double gapSeperation)
        {
            int[,] pixel2Neuron = InitializePixel2Neuron(pixels);

            //neuronDict.Clear();            

            for (int i = 0; i < neuronDict.Count; i++)
            {
                neuronDict[i].ConnectNeuronAcrossGaps(pixels, pixel2Neuron, neuronDict, this.bmp.Width, this.bmp.Height, gapSeperation);
            }
        }
コード例 #8
0
        private void RemoveGridlineVertical(PixelState[,] pixels, int xStart, int yStart, int xStop, int yStop, GridRemovalSettings gridSettings, PixelState pixelStateRemove)
        {
            // theta is the angle between the horizontal row and the gridline. since we
            // divide by sinTheta, this function should NOT be used for horizontal gridlines
            // since divide-by-zero error would occur
            if (yStart > yStop)
            {
                int temp = yStart;
                yStart = yStop;
                yStop = temp;
                temp = xStart;
                xStart = xStop;
                xStop = temp;
            }

            double sinTheta;
            double atan;

            try
            {
                atan = Math.Atan2(yStop - yStart, xStop - xStart);
            }
            catch (Exception e)
            {
                atan = 0;
            }

            sinTheta = Math.Sin(atan);

            for (int y = (int)(yStart - gridSettings.gridDistance + 0.5);
              y < (int)(yStop + gridSettings.gridDistance + 0.5); y++)
            {
                // interest this pixel row (y=yc) with the gridline (x-x0)/(x1-x0)=(y-y0)/(y1-y0)
                // to get (xp,yp)
                double sLine1, sLine2;
                try
                {
                    double[] results = IntersectTwoLines(0.0, y, this.bmp.Width, y, xStart, yStart, xStop, yStop);
                    sLine1 = results[0];
                    sLine2 = results[1];
                }
                catch (Exception e)
                {
                    //The lines did not intersect, so continue
                    continue;
                }
                double xp = (1.0 - sLine2) * xStart + sLine2 * xStop;
                int xLow = (int)(-gridSettings.gridDistance / sinTheta + xp + 0.5);
                int xHigh = (int)(gridSettings.gridDistance / sinTheta + xp + 0.5);
                for (int x = xLow; x <= xHigh; x++)
                {
                    bool include = true;
                    if (sLine2 < 0.0)
                    {
                        // at start end, the pixels have to be on the same side of (xStart,yStart) as
                        // (xStop,yStop), so use dot product to see if this pixel is on the same side
                        double dotProduct = (x - xStart) * (xStop - xStart) + (y - yStart) * (yStop - yStart);
                        include = (dotProduct >= 0.0);
                    }
                    else if (sLine2 > 1.0)
                    {
                        // at stop end, the pixels have to be on the same side of (xStop,yStop) as
                        // (xStart,yStart), so use dot product to see if this pixel is on the same side
                        double dotProduct = (x - xStop) * (xStart - xStop) + (y - yStop) * (yStart - yStop);
                        include = (dotProduct >= 0.0);
                    }

                    if (include && (0 <= x) && (x < this.bmp.Width) && (0 <= y) && (y < this.bmp.Height))
                    {
                        // overwrite this pixel with background color
                        pixels[x, y] = pixelStateRemove;
                    }
                }
            }
        }
コード例 #9
0
        private void RemoveGridlineVertical(PixelState[,] pixels, int xStart, int yStart, int xStop, int yStop, GridRemovalSettings gridSettings, PixelState pixelStateRemove)
        {
            // theta is the angle between the horizontal row and the gridline. since we
            // divide by sinTheta, this function should NOT be used for horizontal gridlines
            // since divide-by-zero error would occur
            if (yStart > yStop)
            {
                int temp = yStart;
                yStart = yStop;
                yStop  = temp;
                temp   = xStart;
                xStart = xStop;
                xStop  = temp;
            }

            double sinTheta;
            double atan;

            try
            {
                atan = Math.Atan2(yStop - yStart, xStop - xStart);
            }
            catch (Exception e)
            {
                atan = 0;
            }

            sinTheta = Math.Sin(atan);

            for (int y = (int)(yStart - gridSettings.gridDistance + 0.5);
                 y < (int)(yStop + gridSettings.gridDistance + 0.5); y++)
            {
                // interest this pixel row (y=yc) with the gridline (x-x0)/(x1-x0)=(y-y0)/(y1-y0)
                // to get (xp,yp)
                double sLine1, sLine2;
                try
                {
                    double[] results = IntersectTwoLines(0.0, y, this.bmp.Width, y, xStart, yStart, xStop, yStop);
                    sLine1 = results[0];
                    sLine2 = results[1];
                }
                catch (Exception e)
                {
                    //The lines did not intersect, so continue
                    continue;
                }
                double xp    = (1.0 - sLine2) * xStart + sLine2 * xStop;
                int    xLow  = (int)(-gridSettings.gridDistance / sinTheta + xp + 0.5);
                int    xHigh = (int)(gridSettings.gridDistance / sinTheta + xp + 0.5);
                for (int x = xLow; x <= xHigh; x++)
                {
                    bool include = true;
                    if (sLine2 < 0.0)
                    {
                        // at start end, the pixels have to be on the same side of (xStart,yStart) as
                        // (xStop,yStop), so use dot product to see if this pixel is on the same side
                        double dotProduct = (x - xStart) * (xStop - xStart) + (y - yStart) * (yStop - yStart);
                        include = (dotProduct >= 0.0);
                    }
                    else if (sLine2 > 1.0)
                    {
                        // at stop end, the pixels have to be on the same side of (xStop,yStop) as
                        // (xStart,yStart), so use dot product to see if this pixel is on the same side
                        double dotProduct = (x - xStop) * (xStart - xStop) + (y - yStop) * (yStart - yStop);
                        include = (dotProduct >= 0.0);
                    }

                    if (include && (0 <= x) && (x < this.bmp.Width) && (0 <= y) && (y < this.bmp.Height))
                    {
                        // overwrite this pixel with background color
                        pixels[x, y] = pixelStateRemove;
                    }
                }
            }
        }
コード例 #10
0
ファイル: Renderer.cs プロジェクト: mathijshenquet/mandelbrot
 protected bool checkBits(PixelState s, PixelState bits)
 {
     return (s & bits) == bits;
 }
コード例 #11
0
        //Removes pixels around user defined gridlines
        private void RemoveGridlines(PixelState[,] pixels, NuGenScreenTranslate transform,
                                     CoordSettings coordSettings, GridRemovalSettings gridRemovalSettings, PixelState pxState)
        {
            if (transform.ValidAxes)
            {
                List <GridlineScreen> gridlines;
                gridlines = NuGenGridMesh.MakeGridLines(transform, coordSettings, gridRemovalSettings.gridMesh);

                foreach (GridlineScreen gridline in gridlines)
                {
                    int xStart = gridline.Start.X;
                    int yStart = gridline.Start.Y;
                    int xStop  = gridline.Stop.X;
                    int yStop  = gridline.Stop.Y;

                    if (Math.Abs(xStop - xStart) < Math.Abs(yStop - yStart))
                    {
                        //Vertical lines
                        RemoveGridlineVertical(pixels, xStart, yStart, xStop, yStop, gridRemovalSettings, pxState);
                    }
                    else
                    {
                        //Horizontal lines
                        RemoveGridlineHorizontal(pixels, xStart, yStart, xStop, yStop, gridRemovalSettings, pxState);
                    }
                }
            }
        }
コード例 #12
0
        //Removes pixels of a certain color
        private void RemoveColor(PixelState[,] pixels, GridRemovalSettings gridSettings, PixelState pxState)
        {
            for (int x = 0; x < bmp.Width; x++)
            {
                for (int y = 0; y < bmp.Height; y++)
                {
                    int value = discretize.DiscretizeValueForeground(x, y, gridSettings.color);

                    if (!discretize.PixelIsOn(value, gridSettings))
                    {
                        pixels[x, y] = pxState;
                    }
                }
            }
        }
コード例 #13
0
        private double DistanceToOffPixel(PixelState[,] pixels, int x, int y, List <SearchPoint> searchPattern, PixelState pixelThreshold)
        {
            // pixels having values of pixelThreshold and higher are considered "on"
            foreach (SearchPoint p in searchPattern)
            {
                int i = x + p.X;
                if (0 <= i && i < this.bmp.Width)
                {
                    int j = y + p.Y;
                    if (0 <= j && j < this.bmp.Height)
                    {
                        if ((int)pixels[i, j] < (int)pixelThreshold)
                        {
                            // reduce by one half since the distance is from the center of the on pixel
                            // to the boundary of the off pixel
                            return(p.Distance - 0.5);
                        }
                    }
                }
            }

            // return really big number
            return((double)this.bmp.Width);
        }
コード例 #14
0
        //Removes pixels of a certain color
        private void RemoveColor(PixelState[,] pixels, GridRemovalSettings gridSettings, PixelState pxState)
        {
            for (int x = 0; x < bmp.Width; x++)
            {
                for (int y = 0; y < bmp.Height; y++)
                {
                    int value = discretize.DiscretizeValueForeground(x, y, gridSettings.color);

                    if (!discretize.PixelIsOn(value, gridSettings))
                        pixels[x, y] = pxState;
                }
            }
        }
コード例 #15
0
        //Initializes the pixel array to create neurons
        private int[,] InitializePixel2Neuron(PixelState[,] pixels)
        {
            int width = bmp.Width;
            int height = bmp.Height;

            // each pixel gets assigned to a neuron. each neuron has its own index
            int[,] pixel2Neuron = new int[width, height];

            int x, y;
            for (x = 0; x < width; x++)
                for (y = 0; y < height; y++)
                    pixel2Neuron[x, y] = -1;

            for (x = 0; x < width; x++)
                for (y = 0; y < height; y++)
                    RecursivelySetPixel2Neuron(pixels, pixel2Neuron, x, y, width, height, null, null, 0);

            return pixel2Neuron;
        }
コード例 #16
0
        //Removes pixels around user defined gridlines
        private void RemoveGridlines(PixelState[,] pixels, NuGenScreenTranslate transform,
            CoordSettings coordSettings, GridRemovalSettings gridRemovalSettings, PixelState pxState)
        {
            if (transform.ValidAxes)
            {
                List<GridlineScreen> gridlines;
                gridlines = NuGenGridMesh.MakeGridLines(transform, coordSettings, gridRemovalSettings.gridMesh);

                foreach (GridlineScreen gridline in gridlines)
                {
                    int xStart = gridline.Start.X;
                    int yStart = gridline.Start.Y;
                    int xStop = gridline.Stop.X;
                    int yStop = gridline.Stop.Y;

                    if (Math.Abs(xStop - xStart) < Math.Abs(yStop - yStart))
                    {
                        //Vertical lines
                        RemoveGridlineVertical(pixels, xStart, yStart, xStop, yStop, gridRemovalSettings, pxState);
                    }
                    else
                    {
                        //Horizontal lines
                        RemoveGridlineHorizontal(pixels, xStart, yStart, xStop, yStop, gridRemovalSettings, pxState);
                    }
                }
            }
        }
コード例 #17
0
        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);
                            }
                        }
            }
        }
コード例 #18
0
        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);
                    }
                }
            }
        }
コード例 #19
0
        //Removes thin lines which are parallel to the user defined axes
        private void RemoveThinLines(PixelState[,] pixels, CoordSettings coordSettings, NuGenScreenTranslate transform,
                double thinThickness, PixelState pixelStateRemovedPass1, PixelState pixelStateRemovedPass2)
        {
            if (transform.ValidAxes)
            {
                InitializeThin(coordSettings, transform, thinThickness);

                // first pass erases the gridMeshSettings lines, except for the junctions
                EraseThinPixels(pixels, thinThickness, pixelStateRemovedPass1);

                // second pass erases the gridMeshSettings line junctions, which are little islands of on-pixels
                EraseThinPixels(pixels, thinThickness, pixelStateRemovedPass2);
            }
        }
コード例 #20
0
        public void ConnectSynapseToSynapsesSource(PixelState[,] pixels, int[,] pixel2Neuron,
                        Dictionary<int, Neuron> neuronDict, int width, int height,
                        double gapSeparation, int x, int y,
                        int xLook, int yLook, List<int> neuronsProcessed)
        {
            // this function tries to connect this synapse with center-of-mass at (x,y),
            // to the synapses of another neuron. the other neuron actually does the
            // work of making the connections

            if ((0 <= xLook) && (xLook < width) && (0 <= yLook) && (yLook < height))
            {
                // see if pixel belongs to a neuron, that is not this neuron,
                // and this synapse has not already been connected to that neuron
                int n = pixel2Neuron[xLook, yLook];
                if ((n != 0) &&
                  (n != index) &&
                  (neuronsProcessed.Contains(n)))
                {
                    // let the other neuron do the actual connections, since there may be
                    // zero, one or more and it alone knows where its synapses are
                    neuronDict[n].ConnectSynapseToSynapsesDestination(pixels, height, gapSeparation,
                      x, y);

                    // update list of process neurons
                    neuronsProcessed.Add(n);
                }
            }
        }
コード例 #21
0
 public void ChangeStateTo(PixelState state)
 {
     this.State = state;
 }