Exemplo n.º 1
0
        public static SCalcRegionTask calcRegions(CancellationToken cToken, SCalcRegionTask data)
        {
            Rectangle roiRect = data.roiRect;

            // Flatten RGA to 1 byte pixel buffer with 1 indicating segment
//			if(!FlattenImage(cToken, roiRect, data.pixelData)) {
//				return data;
//			}

            // ********************************************************
            // DETECT REGIONS
            // ********************************************************


            // Allocate stuff
            List <Point>       points  = new List <Point>(128 * 128);
            SCalcRegionBuffers buffers = new SCalcRegionBuffers();

            buffers.Prepare(256 * 256);
            bool isEDM = true;


            // Get regions at tags
            bool propertiesSet = false;
            int  test          = 0;

            foreach (Tag tag in data.tags)
            {
                Point posROI = new Point((int)tag.Pos.X - roiRect.Location.X, (int)tag.Pos.Y - roiRect.Location.Y);
                int   index  = posROI.Y * roiRect.Size.Width + posROI.X;
                uint  val    = data.pixelData[index];
                if (val == 0x00FFFFFF)
                {
                    points.Clear();
                    QuickFill <uint> .FloodFill(posROI, data.pixelData, roiRect.Size, val, 0, points);

                    if (!propertiesSet)
                    {
                        propertiesSet = true;

                        // Get bounds
                        Rectangle regionBounds;
                        Region.Transform(points, Point.Empty, out regionBounds);

                        if (cToken.IsCancellationRequested)
                        {
                            return(data);
                        }

                        // Prepare buffers
                        int regionsize = regionBounds.Width * regionBounds.Height;
                        buffers.Prepare(regionsize);

                        // Load binary map
                        Region.loadBinaryMap(points, new Point(-regionBounds.X, -regionBounds.Y), buffers.EDMMap, regionBounds.Width);

                        if (cToken.IsCancellationRequested)
                        {
                            return(data);
                        }

                        // Create EDM
                        EDM.createEDM(buffers.EDMMap, regionBounds.Width, regionBounds.Height);

                        int[] globalMinMax;
                        Segmentation.FindGlobalMinMax(buffers.EDMMap, regionBounds.Width, regionBounds.Height, out globalMinMax);

                        test = globalMinMax[1];
                    }
                }

                if (cToken.IsCancellationRequested)
                {
                    return(data);
                }
            }



            // Create regions from segmentation map
            int   height   = roiRect.Size.Height;
            int   width    = roiRect.Size.Width;
            int   count    = height * width;
            float invWidth = 1.0f / (float)width;

            for (int index = 0; index < count; index++)
            {
                uint val = data.pixelData[index];
                if (val == 0x00FFFFFF)
                {
                    int   x2  = index % width - 1;
                    int   y2  = (int)((float)(index - x2) * invWidth);
                    Point pos = new Point(x2, y2);

                    points.Clear();
//					QuickFill<uint>.FloodFill(pos, data.pixelData, roiRect.Size, val, 0, points);
                    QuickFillUint.FloodFill(pos, data.pixelData, roiRect.Size, val, 0, points);

                    if (cToken.IsCancellationRequested)
                    {
                        return(data);
                    }

                    // Transform region points to image space
                    Rectangle regionBounds;
                    Region.Transform(points, roiRect.Location, out regionBounds);

                    // Prepare buffers
                    int regionsize = regionBounds.Width * regionBounds.Height;
                    buffers.Prepare(regionsize);

                    // Load binary map
                    Region.loadBinaryMap(points, new Point(-regionBounds.X, -regionBounds.Y), buffers.EDMMap, regionBounds.Width);

                    if (cToken.IsCancellationRequested)
                    {
                        return(data);
                    }

                    // Create EDM
                    EDM.createEDM(buffers.EDMMap, regionBounds.Width, regionBounds.Height);

                    if (cToken.IsCancellationRequested)
                    {
                        return(data);
                    }

                    // Debug render EDM
                    if (data.bDebugDrawEDM)
                    {
                        DebugDragEDM(regionBounds, buffers, data);
                    }

                    if (cToken.IsCancellationRequested)
                    {
                        return(data);
                    }

                    // Find maxima
                    int    minSize   = Math.Min(regionBounds.Width, regionBounds.Height);
                    double tolerance = 20;

//					double findMaxThreshold = 4*EDM.ONE;
                    double findMaxThreshold = (float)test * 0.5f;

                    Segmentation.MaxPoint[] maxPoints;
                    int[] globalMinMax;
                    Segmentation.FindGlobalMinMax(buffers.EDMMap, regionBounds.Width, regionBounds.Height, out globalMinMax);
                    Segmentation.findMaxima(buffers.EDMMap, regionBounds.Width, regionBounds.Height, tolerance,
                                            findMaxThreshold, buffers.maxMap, isEDM, globalMinMax, out maxPoints);

                    // Count max points
                    int iMaxPointCount = 0;
                    foreach (Segmentation.MaxPoint maxPoint in maxPoints)
                    {
                        int ri   = maxPoint.y * regionBounds.Width + maxPoint.x;
                        int iVal = buffers.maxMap[ri];
                        if ((iVal & Segmentation.MAX_POINT) > 0)
                        {
                            iMaxPointCount++;
                        }
                    }


                    // Skip all regions with no max
                    if (iMaxPointCount == 0)
                    {
                        continue;
                    }

                    // Debug Render maxima
                    if (data.bDebugDrawEDM)
                    {
                        DebugDragMaxima(regionBounds, buffers, data, maxPoints, iMaxPointCount);
                    }


                    if (cToken.IsCancellationRequested)
                    {
                        return(data);
                    }

                    if (iMaxPointCount == 1)
                    {
                        Region region = new Region(points, regionBounds);
                        data.regions.Add(region);
                        data.SendRegionAdded(region);
                    }
                    else
                    {
                        // TODO: could watershed write region map in different colors (so we dont have to quickfill)
                        double watershedThreshold = 1;
                        Segmentation.performWatershed(buffers.EDMMap, regionBounds.Width, regionBounds.Height, watershedThreshold,
                                                      buffers.maxMap, isEDM, buffers.regionMap, maxPoints, globalMinMax);

                        // Debug render region map
                        if (data.bDebugDrawRegions)
                        {
                            int offsetX = regionBounds.X - roiRect.X;
                            int offsetY = regionBounds.Y - roiRect.Y;
                            int ri      = 0;
                            for (int ry = 0; ry < regionBounds.Height; ry++)
                            {
                                for (int rx = 0; rx < regionBounds.Width; rx++)
                                {
                                    int iVal = buffers.regionMap[ri];
                                    data.debugTexture.SetPixel(rx + offsetX, ry + offsetY, iVal, 0, 0, 1);
                                    ri++;
                                }
                            }
                        }

                        if (cToken.IsCancellationRequested)
                        {
                            return(data);
                        }

                        for (int ry = 0; ry < regionBounds.Height; ry++)
                        {
                            for (int rx = 0; rx < regionBounds.Width; rx++)
                            {
                                int  ri   = (regionBounds.Width * ry) + rx;
                                uint iVal = (uint)(buffers.regionMap[ri] & 0xFF);

                                if (iVal == 255)
                                {
                                    points.Clear();
//									QuickFill<byte>.FloodFill(new Point(rx, ry), buffers.regionMap, regionBounds.Size, (byte)iVal, 0, points);
                                    QuickFillByte.FloodFill(new Point(rx, ry), buffers.regionMap, regionBounds.Size, (byte)iVal, 0, points);

                                    if (cToken.IsCancellationRequested)
                                    {
                                        return(data);
                                    }

                                    Rectangle bounds;
                                    Region.Transform(points, regionBounds.Location, out bounds);

                                    Region region = new Region(points, bounds);
                                    data.regions.Add(region);
                                    data.SendRegionAdded(region);
                                }
                            }
                        }
                    }

                    if (cToken.IsCancellationRequested)
                    {
                        return(data);
                    }
                }
            }
            return(data);
        }