示例#1
0
        /// <summary>
        ///   Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            // get width and height
            int         width          = sourceData.Width;
            int         height         = sourceData.Height;
            PixelFormat srcPixelFormat = sourceData.PixelFormat;

            if (
                (srcPixelFormat == PixelFormat.Format24bppRgb) ||
                (srcPixelFormat == PixelFormat.Format32bppRgb) ||
                (srcPixelFormat == PixelFormat.Format32bppArgb))
            {
                int pixelSize = (srcPixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
                int srcOffset = sourceData.Stride - width * pixelSize;
                int dstOffset = destinationData.Stride - width;

                int rc = (int)(0x10000 * RedCoefficient);
                int gc = (int)(0x10000 * GreenCoefficient);
                int bc = (int)(0x10000 * BlueCoefficient);

                // make sure sum of coefficients equals to 0x10000
                while (rc + gc + bc < 0x10000)
                {
                    bc++;
                }

                // do the job
                byte *src = (byte *)sourceData.ImageData.ToPointer();
                byte *dst = (byte *)destinationData.ImageData.ToPointer();

                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, src += pixelSize, dst++)
                    {
                        destinationData.CheckBounds(dst);

                        *dst = (byte)((rc * src[RGB.R] + gc * src[RGB.G] + bc * src[RGB.B]) >> 16);
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
            else
            {
                int   pixelSize = (srcPixelFormat == PixelFormat.Format48bppRgb) ? 3 : 4;
                byte *srcBase   = (byte *)sourceData.ImageData.ToPointer();
                byte *dstBase   = (byte *)destinationData.ImageData.ToPointer();
                int   srcStride = sourceData.Stride;
                int   dstStride = destinationData.Stride;

                // for each line
                for (int y = 0; y < height; y++)
                {
                    ushort *src = (ushort *)(srcBase + y * srcStride);
                    ushort *dst = (ushort *)(dstBase + y * dstStride);

                    // for each pixel
                    for (int x = 0; x < width; x++, src += pixelSize, dst++)
                    {
                        *dst = (ushort)(RedCoefficient * src[RGB.R] + GreenCoefficient * src[RGB.G] + BlueCoefficient * src[RGB.B]);
                    }
                }
            }
        }
示例#2
0
            public List <IntPoint> FindContour(UnmanagedImage image)
            {
                CheckPixelFormat(image.PixelFormat);

                int width  = image.Width;
                int height = image.Height;
                int stride = image.Stride;

                List <IntPoint> contour = new List <IntPoint>();

                unsafe
                {
                    byte src = (byte)image.ImageData.ToPointer();

                    int start = 0;

                    IntPoint prevPosition = new IntPoint();

                    // 1. Find the lowest point in the image

                    // The lowest point is searched first by lowest X, then lowest Y, to use
                    // the same ordering of AForge.NET's GrahamConvexHull. Unfortunately, this
                    // means we have to search our image by inspecting columns rather than rows.

                    bool found = false;

                    int col = (int)src;
                    for (int x = 0; x < width && !found; x++, col++)
                    {
                        int row = col;
                        for (int y = 0; y < height && !found; y++, row += stride)
                        {
                            image.CheckBounds(row);

                            if (row > Threshold)
                            {
                                start        = row;
                                prevPosition = new IntPoint(x, y);
                                contour.Add(prevPosition);
                                found = true; // 현재 시작점 후보가 threshold 이상이면 컨투어 시작점으로 고른다.
                            }
                        }
                    }

                    if (contour.Count == 0)
                    {
                        // Empty image
                        return(contour);
                    }


                    // 2. Beginning on the first point, starting from left
                    //    neighbor and going into counter-clockwise direction,
                    //    find a neighbor pixel which is black.

                    int[] windowOffset =
                    {
                        +1,          // 0: Right
                        -stride + 1, // 1: Top-Right
                        -stride,     // 2: Top
                        -stride - 1, // 3: Top-Left
                        -1,          // 4: Left
                        +stride - 1, // 5: Bottom-Left
                        +stride,     // 6: Bottom
                        +stride + 1, // 7: Bottom-Right
                    };

                    int direction = 4; // 4: Left
                    int current   = start;
                    int previous  = 0;

                    #region find
                    do // Search until we find a dead end (or the starting pixel)
                    {
                        found = false;

                        // Search in the neighborhood window
                        for (int i = 0; i < windowOffset.Length; i++)
                        {
                            // Find the next candidate neighbor point
                            IntPoint next = prevPosition + positionOffset[direction];

                            // Check if it is inside the blob area
                            if (next.X < 0 || next.X >= width ||
                                next.Y < 0 || next.Y >= height)
                            {
                                // It isn't. Change direction and continue.
                                direction = (direction + 1) % windowOffset.Length;
                                continue;
                            }

                            // It is inside. Then find the next candidate neighbor pixel
                            int neighbor = unchecked (current + windowOffset[direction]);

                            CheckBounds(image, neighbor);   // Make sure we are in the image

                            // Check if it is a colored pixel
                            if (neighbor <= Threshold)
                            {
                                // It isn't. Change direction and continue.
                                direction = (direction + 1) % windowOffset.Length;
                                continue;
                            }

                            // Check if it is a previously found pixel
                            if (neighbor == previous || neighbor == start)
                            {
                                // We found a dead end.
                                found = false; break;
                            }

                            // If we reached until here, we have
                            //  found a neighboring black pixel.
                            found = true; break;
                        }

                        if (found)
                        {
                            // Navigate to neighbor pixel
                            previous = current;
                            current  = unchecked (current + windowOffset[direction]);

                            // Add to the contour
                            prevPosition += positionOffset[direction];
                            contour.Add(prevPosition);

                            // Continue counter-clockwise search
                            //  from the most promising direction
                            direction = nextDirection[direction];
                        }
                    } while (found);

                    #endregion
                }


                return(contour);
            }