Exemplo n.º 1
0
        protected void RemoveVisualChildren(ICollection coll)
        {
            foreach (object obj in coll)
            {
                Darwin.Point point = obj as Darwin.Point;

                if (point != null)
                {
                    RemoveVisualChild(point);
                }
            }
        }
Exemplo n.º 2
0
        protected void CreateVisualChild(Darwin.Point point)
        {
            DrawingVisualPlus drawingVisual = new DrawingVisualPlus();

            drawingVisual.DataPoint = point;
            DrawingContext dc = drawingVisual.RenderOpen();

            switch (point.Type)
            {
            case PointType.Chopping:
                dc.DrawEllipse(Brushes[1], null, new System.Windows.Point(point.X / ContourScale + XOffset, point.Y / ContourScale + YOffset), PointSize, PointSize);
                break;

            case PointType.Feature:
                dc.DrawEllipse(Brushes[2], null, new System.Windows.Point(point.X / ContourScale + XOffset, point.Y / ContourScale + YOffset), FeaturePointSize, FeaturePointSize);
                break;

            case PointType.FeatureMoving:
                dc.DrawEllipse(Brushes[1], null, new System.Windows.Point(point.X / ContourScale + XOffset, point.Y / ContourScale + YOffset), FeaturePointSize, FeaturePointSize);
                break;

            case PointType.Normal:
            default:
                dc.DrawEllipse(Brushes[0], null, new System.Windows.Point(point.X / ContourScale + XOffset, point.Y / ContourScale + YOffset), PointSize, PointSize);
                break;
            }

            if (point.Type == PointType.Moving && Pens != null)
            {
                DrawMovingLines(point, dc);
            }

            //drawingVisual.Transform = new TranslateTransform(RenderSize.Width * dataPoint.X,
            //                                                 RenderSize.Height * dataPoint.Y);

            dc.Close();

            // If it's a feature point, add it, otherwise insert so the Feature points have
            // the highest ZIndex
            if (point.Type == PointType.Feature || point.Type == PointType.FeatureMoving)
            {
                visualChildren.Add(drawingVisual);
            }
            else
            {
                visualChildren.Insert(0, drawingVisual);
            }
        }
Exemplo n.º 3
0
        protected void RemoveVisualChild(Darwin.Point point)
        {
            List <DrawingVisualPlus> removeList = new List <DrawingVisualPlus>();

            foreach (Visual child in visualChildren)
            {
                DrawingVisualPlus drawingVisual = child as DrawingVisualPlus;
                if (drawingVisual.DataPoint == point)
                {
                    removeList.Add(drawingVisual);
                    break;
                }
            }
            foreach (DrawingVisualPlus drawingVisual in removeList)
            {
                visualChildren.Remove(drawingVisual);
            }
        }
Exemplo n.º 4
0
        private void DrawMovingLines(Darwin.Point dataPoint, DrawingContext dc)
        {
            var pointIndex = ItemsSource.IndexOf(dataPoint);

            if (pointIndex >= 0)
            {
                if (pointIndex >= 1)
                {
                    dc.DrawLine(Pens[0],
                                new System.Windows.Point(ItemsSource[pointIndex - 1].X / ContourScale + XOffset, ItemsSource[pointIndex - 1].Y / ContourScale + YOffset),
                                new System.Windows.Point(dataPoint.X / ContourScale + XOffset, dataPoint.Y / ContourScale));
                }

                if (pointIndex < ItemsSource.Count - 1)
                {
                    dc.DrawLine(Pens[0],
                                new System.Windows.Point(ItemsSource[pointIndex + 1].X / ContourScale + XOffset, ItemsSource[pointIndex + 1].Y / ContourScale + YOffset),
                                new System.Windows.Point(dataPoint.X / ContourScale + XOffset, dataPoint.Y / ContourScale + YOffset));
                }
            }
        }
Exemplo n.º 5
0
        protected void OnItemPropertyChanged(object sender, ItemPropertyChangedEventArgs args)
        {
            Darwin.Point point = args.Item as Darwin.Point;

            RemoveVisualChild(point);
            CreateVisualChild(point);
            //foreach (Visual child in visualChildren)
            //{
            //    DrawingVisualPlus drawingVisual = child as DrawingVisualPlus;

            //    if (dataPoint == drawingVisual.DataPoint)
            //    {
            //        if (dataPoint.Type == PointType.Moving)
            //        {
            //            dc.DrawEllipse(Brushes[0], null, new System.Windows.Point(dataPoint.X, dataPoint.Y), 3, 3);

            //            if (dataPoint.Type == PointType.Moving && Pens != null)
            //            {
            //                DrawMovingLines(dataPoint, dc);
            //            }
            //        }

            //        // Assume only VariableX or VariableY are changing
            //        TranslateTransform xform = drawingVisual.Transform as TranslateTransform;

            //        if (xform != null)
            //        {
            //            if (args.PropertyName == "X")
            //                xform.X = RenderSize.Width * dataPoint.X;

            //            else if (args.PropertyName == "Y")
            //                xform.Y = RenderSize.Height * dataPoint.Y;
            //        }
            //    }
            //}
        }
Exemplo n.º 6
0
 public static System.Drawing.Point ToDrawingPoint(this Darwin.Point point)
 {
     return(new System.Drawing.Point(point.X, point.Y));
 }
Exemplo n.º 7
0
        public static bool MoveContour(
            ref Contour contour,    // The contour we'd like to move

            DirectBitmap edgeImage, // Edge strength image used for energy calculations

            int neighborhoodSize,   // Neighborhood window size
                                    // neighborhoodSize x neighborhoodSize

            float[] energyWeights
            )
        {
            if (contour == null)
            {
                throw new ArgumentNullException(nameof(contour));
            }

            if (edgeImage == null)
            {
                throw new ArgumentNullException(nameof(edgeImage));
            }

            if (neighborhoodSize <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(neighborhoodSize));
            }


            int
                minPosition = 0,    // keeps track of the value of k (the current node)
                                    // corresponding to the minimum energy found so far
                                    // in the search using k over all neighbors of the
                                    // current node
                                    // It's initialized to zero because there's a (very)
                                    // slight chance that it could be used unitialized
                                    // otherwise

                numNeighbors;

            float
                minEnergy,  // keeps track of the minimum energy found so far
                            // in the search using k over all neighbors of the
                            // current node.

                energy;     // is used in the search over the neighbors of the

            // current node as a temporary storage of the energy computed

            System.Drawing.Point
                nextNode = new System.Drawing.Point(),   // contains the coordinates, for the neighbor of the
            // next node indexed by j. These coordinates are used
            // only to compute the energy associated with the
            // associated choice of snaxel positions

                currNode = new System.Drawing.Point();   // contains the coordinates, for the neighbor of the
            // current node indexed by k. These coordinates are
            // used only to compute the energy associated with the
            // associated choice of snaxel positions

            numNeighbors = neighborhoodSize * neighborhoodSize;

            int numPoints = contour.NumPoints;

            if (numPoints <= 2)
            {
                return(false);
            }

            float[,] energyMtx = new float[numPoints - 1, numNeighbors];
            int[,] posMtx      = new int[numPoints - 1, numNeighbors];

            System.Drawing.Point[] neighbor = new System.Drawing.Point[numNeighbors];

            for (int a = 0; a < numNeighbors; a++)
            {
                neighbor[a].X = (a % neighborhoodSize) - (neighborhoodSize - 1) / 2;
                neighbor[a].Y = (a / neighborhoodSize) - (neighborhoodSize - 1) / 2;
            }

            // initialize first column of energy matrix
            // This block of code simply sets the first column of the energy
            // matrix to zero, since there is no energy associated solely
            // with the first snaxel; energy is based on distance, and there
            // is no distance associated with a single snaxel. It is only when
            // we get to the second snaxel, that we have some measure of distance
            for (int l = 0; l < numNeighbors; l++)
            {
                energyMtx[0, l] = 0.0f;
                posMtx[0, l]    = 0;
            }

            // Find the average distance between points
            float distSum = 0.0f;

            for (int d = 1; d < numPoints; d++)
            {
                distSum += (float)MathHelper.GetDistance(contour[d].X, contour[d].Y, contour[d - 1].X, contour[d - 1].Y);
            }

            float averageDistance = distSum / numPoints;

            for (int i = 1; i < numPoints - 1; i++)
            {
                for (int j = 0; j < numNeighbors; j++)
                { // for all neighbors of next node
                    minEnergy = BigFloat;

                    nextNode.X = contour[i + 1].X + neighbor[j].X;
                    nextNode.Y = contour[i + 1].Y + neighbor[j].Y;

                    for (int k = 0; k < numNeighbors; k++)
                    { // for all neighors of curr node
                        currNode.X = contour[i].X + neighbor[k].X;
                        currNode.Y = contour[i].Y + neighbor[k].Y;

                        energy = energyMtx[i - 1, k] +
                                 EnergyCalc(
                            edgeImage,
                            energyWeights,
                            contour[i - 1].X + neighbor[posMtx[i - 1, k]].X,
                            contour[i - 1].Y + neighbor[posMtx[i - 1, k]].Y,
                            currNode.X, currNode.Y,
                            nextNode.X, nextNode.Y,
                            averageDistance
                            );
                        if (energy < minEnergy)
                        {
                            minEnergy   = energy;
                            minPosition = k;
                        }
                    }

                    // Store minimum energy into table matrix
                    energyMtx[i, j] = minEnergy;
                    posMtx[i, j]    = minPosition;
                }
            }

            int pos = posMtx[numPoints - 2, 4];

            // search backwards through table to find optimum positions
            for (int k = numPoints - 2; k > 0; k--)
            {
                contour[k] = new Darwin.Point(contour[k].X + neighbor[pos].X, contour[k].Y + neighbor[pos].Y);

                pos = posMtx[k - 1, pos];
            }

            return(true);
        }
Exemplo n.º 8
0
        /* TODO: References spots in old code
         * The main algorithm to extract a fin outline from an image.
         * This method is called from all of this class's constructors, which are called in
         * TraceWindow.cxx (on_traceButtonImageOK_clicked).
         *
         * There are 9 stages:
         *
         * 1) Construct, analyize histogram
         * 2) Threshold GrayImage to create BinaryImage
         * 3) Clean up / get a cleanner edge through morphological processes
         *      a) open (erode, dialate)
         *      b) erosion with high coefficient to clean up noise, but leave the fin intact
         *      c) AND with the orginal BinaryImage (#3) to restore the fin shape
         * 4) Feature recognition to select the largest Feature / blob
         * 5) Get a one pixel outline through one erosion and XORing with #4
         * 6) Feature recognition to slect the largest outline (feature /blob) (same code as #4)
         * 7) Find the start point
         *      A valid start point (p1) must be in math quadrant III
         *      and be followed by two points (p2,p3)
         *      such that p1.row>p2.row>p3.row && p1.col<p2.col<p3.col
         * 8) Walk the outline from the starting point, recording a pixel in the contour every 3 pixels
         * 9) Walk ends when no more black pixels may be found. The outline is recouresed backwards until
         *      a valid end point (p1) is found. A valid end point must be in math quadrant IV
         *      and be prefaced by two points (p2,p3) such that p1.row>p2.row>p3.row && p1.col>p2.col>p3.col
         *
         * The Contour represented by this object has a length of 0 if at anytime the algorithm
         *      cannot continue. This often occurs for images of poor contrast.
         *
         * The Contour represented by this object is adjusted with the snake code in TraceWindow.cxx
         *      if its length is greater than 0.
         *
         */
        public Contour GetPointsFromBitmap(ref DirectBitmap bmp, Contour ctour, int left, int top, int right, int bottom)
        {
            // Resample the image to lower resolution
            int width = right - left;

            int factor = 1;

            while (width / (float)factor > 1024)
            { //***1.96 - changed magic num JHS
                factor *= 2;
            }

            DirectBitmap workingBmp;

            if (factor > 1)
            {
                workingBmp = DirectBitmapHelper.ResizePercentageNearestNeighbor(bmp, 100.0f / factor);
            }
            else
            {
                workingBmp = new DirectBitmap(bmp.Bitmap);
            }

            int xoffset;
            int yoffset;

            workingBmp = DirectBitmapHelper.ApplyBounds(workingBmp, left, top, right, bottom, factor,
                                                        out xoffset, out yoffset);

            IntensityHistogram histogram = new IntensityHistogram(workingBmp);

            Range lowestRange = histogram.FindNextValley(0);

            Range nextRange = histogram.FindNextValley(lowestRange.End);

            int totalPixels = workingBmp.Width * workingBmp.Height;

            // TODO: Magic numbers?
            if (nextRange.Tip - lowestRange.End < 25 && nextRange.HighestValue > totalPixels / 256)
            {
                lowestRange.End = nextRange.End;
                //TODO: update other values in strut as needed
            }

            // TODO: Magic numbers?
            // low contrast check
            if (lowestRange.PixelCount > totalPixels * .7 || lowestRange.End > 150 ||
                lowestRange.PixelCount < totalPixels * .2)
            {
                //exceeds 90% of images
                //cout << "Low Contrast Warning..." << endl;
                //TODO: Do something
            }

            // use the range to threshold
            DirectBitmapHelper.ThresholdRange(ref workingBmp, lowestRange);

            DirectBitmap saveBinaryBmp = new DirectBitmap(workingBmp.Bitmap);

            /* ----------------------------------------------------
             * Open the image (erode and dilate)
             * ----------------------------------------------------
             */

            int iterations = 4; // Default number of iterations
            int ecount     = 0;
            int itcount    = 0;
            int i;

            for (i = 0; i < iterations; i++)
            {
                ecount = MorphologicalOperators.Erode(ref workingBmp, i % 2);
            }

            // Shrink all other regions with less than 5 neighbor black pixles
            while (ecount != 0)
            {
                ecount = MorphologicalOperators.Erode(ref workingBmp, 5);
                itcount++;
            }

            for (i = 0; i < iterations; i++)
            {
                MorphologicalOperators.Dilate(ref workingBmp, i % 2);
            }
            ;

            // AND opended image with orginal
            MorphologicalOperators.And(ref workingBmp, saveBinaryBmp);

            //Trace.WriteLine("Starting feature recognition...");

            var largestFeature = FeatureIdentification.FindLargestFeature(workingBmp);

            Trace.WriteLine("Feature recognition complete.");

            // now binImg can be reset to the mask of the NEW largestFeature
            DirectBitmap binaryBmp = largestFeature.Mask;

            DirectBitmap outline = new DirectBitmap(binaryBmp.Bitmap);

            for (i = 0; i < 1; i++)
            {
                MorphologicalOperators.Erode(ref outline, 0);
            }

            MorphologicalOperators.Xor(ref binaryBmp, outline);

            //***1.0LK - a bit of a mess - JHS
            // at this point binImg points to the largestFeature->mask (eroded and XORed).
            // We want to use this binImg to find a new largestFeature, but we cannot
            // delete the current largestFeature until after the call to binImg->getLargestFeature()
            // because binImg will be wiped out by the deletion of the current largestFeature
            // We must delete the current largestFeature at some point OTHEWISE we have a
            // memory leak.

            //get rid of outlines of inner features (e.g. glare spots) by selecting largest outline

            //cout << "Looking for 2nd Fin Candidate: ";

            //Feature oldLargest = largestFeature; //***1.0LK

            var finalLargestFeature = FeatureIdentification.FindLargestFeature(binaryBmp);

            if (finalLargestFeature == null)
            {
                // TODO
                Trace.WriteLine("largestFeature NULL, aborting. No fin outline determined");
                return(null);
            }

            // now binImg can be reset to the mask of the NEW largestFeature
            DirectBitmap finalWorkingBmp = finalLargestFeature.Mask;

            int  row = 0, col = 0;
            int  rows = finalWorkingBmp.Height, cols = finalWorkingBmp.Width;
            bool done = false;

            width = 15;

            //cout << "Finding first point..." << endl;

            Darwin.Point pt = ctour[0];
            //Contour::addPoint(pt.x,pt.y);//Add User start
            int stx = pt.X / factor - xoffset;
            int sty = pt.Y / factor - yoffset;

            pt = ctour[1];
            int endy = pt.Y / factor - yoffset;
            int endx = pt.X / factor - xoffset;

            //find starting point (midx,midy)
            int midx;
            int midy = 0;

            int maxy = (sty > endy) ? sty : endy; // Math.max(sty,endy);

            midx = Convert.ToInt32((endx + stx) * .5);

            //find black pixel closest to bottom in column midx
            row = maxy;
            while (!done && row >= 0)
            {
                if (finalWorkingBmp.GetPixel(midx, row).GetIntensity() == 0)
                {
                    midy = row;
                    done = true;
                }
                else
                {
                    row--;
                }
            }

            if (!done)
            {
                Trace.WriteLine("no starting point found.");

                Trace.WriteLine("\nNo outline intersected the bisector of the secant line formed by user supplied start and end points!\n");

                // TODO
                return(null);
            }

            Trace.WriteLine(string.Format("Have starting point ({0}, {1})", midx, midy));
            Trace.WriteLine(string.Format("FYI ending point ({0}, {1})", endy, endx));

            row = midy;
            col = midx;

            int st2y = row;
            int st2x = col;

            // Walk from point (row,col)
            finalWorkingBmp.SetPixel(col, row, Color1);

            /* Prioritize direction of movement
             *
             *      4 | 3 | 2
             *      -- --  --
             *      5 | * | 1
             *      -- --  --
             *      4 | 3 | 2
             */

            i = 0;
            bool foundPoint = true;
            bool prepend    = false;

            done = false;
            while (!done)
            {
                /* Prioritize direction of movement
                 *
                 *      4 | 3 | 2
                 *      -- --  --
                 *      5 | * | 1
                 *      -- --  --
                 *      4 | 3 | 2
                 */
                if (col + 1 < cols && finalWorkingBmp.GetPixel(col + 1, row).GetIntensity() == 0)
                {//E
                    foundPoint = true;
                    col        = col + 1;
                }
                else if (row - 1 >= 0 && finalWorkingBmp.GetPixel(col, row - 1).GetIntensity() == 0)
                {//N
                    foundPoint = true;
                    row        = row - 1;
                }
                else if (row + 1 < rows && finalWorkingBmp.GetPixel(col, row + 1).GetIntensity() == 0)
                {//S
                    foundPoint = true;
                    row        = row + 1;
                }
                else if (col - 1 >= 0 && finalWorkingBmp.GetPixel(col - 1, row).GetIntensity() == 0)
                {//W
                    foundPoint = true;
                    col        = col - 1;
                }
                else
                {
                    if (prepend)
                    {
                        done = true;
                        break;
                    }
                    else
                    {
                        prepend = true;
                        row     = midy;
                        col     = midx;
                        continue;
                    }
                }

                if (foundPoint /*&& i%3==0*/)
                {
                    if (prepend)
                    {
                        AddPoint(factor * (col + xoffset), factor * (row + yoffset), 0);//prepend
                    }
                    else
                    {
                        AddPoint(factor * (col + xoffset), factor * (row + yoffset));
                    }
                    finalWorkingBmp.SetPixel(col, row, Color128);
                    if (row == maxy)
                    {
                        //done with this direction
                        if (prepend)
                        {
                            done = true;
                            break;
                        }
                        else
                        {
                            prepend = true;
                            row     = midy;
                            col     = midx;
                            continue;
                        }
                    }
                }
                i++;
            } // end loop until done

            TrimAndReorder(ctour[0], ctour[1]);

            Trace.WriteLine("IntensityContour::GetPointsFromBitmap COMPLETE");

            return(null);
        }