Ejemplo n.º 1
0
 public void Debug_Sobel()
 {
     using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(@"C:\Users\User\Downloads\Bikesgray.jpg"))
     {
         actual.Sobel().magnitude.Content.Save("debug.png");
     }
 }
Ejemplo n.º 2
0
 public void FastBitmap_ValidBitmap_ShouldSucceed()
 {
     using (SUT.FastBitmap expected =
                new SUT.FastBitmap(new Bitmap(Image.FromFile(FastBitmap.TestData1_KnownGood))))
     {
     }
 }
Ejemplo n.º 3
0
 public void RadonTransform_InvalidNumberOfAngles_ThrowsArgument(int numberOfAngles)
 {
     using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(FastBitmap.TestData1_KnownGood))
     {
         Assert.Throws <ArgumentException>(() => actual.RadonTransform(numberOfAngles));
     }
 }
Ejemplo n.º 4
0
 public void Max_ValidBitmap_ShouldSucceed()
 {
     using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(FastBitmap.TestData4_KnownGood))
     {
         Assert.Equal(146, actual.Max());
     }
 }
Ejemplo n.º 5
0
 public void Blur_ValidParams_ShouldSucceed(double sigma, int weight, string input, string expectedOutput)
 {
     using (Bitmap expected = (Bitmap)Image.FromFile(expectedOutput))
         using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(input))
         {
             TestUtil.AssertContentsEqual(expected, actual.Blur(sigma, weight).Content);
         }
 }
Ejemplo n.º 6
0
 public void ScaleBy_ValidFactor_ShouldSucceed(ushort factor, string input, string expectedOutput)
 {
     using (Bitmap expected = (Bitmap)Image.FromFile(expectedOutput))
         using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(input))
         {
             TestUtil.AssertContentsEqual(expected, actual.ScaleBy(factor).Content);
         }
 }
Ejemplo n.º 7
0
 public void Pow_ValidBitmap_ShouldSucceed()
 {
     using (Bitmap expected = new Bitmap(Image.FromFile(TestData1_Pow2_KnownGood)))
         using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(FastBitmap.TestData1_KnownGood))
         {
             TestUtil.AssertContentsEqual(expected, actual.Pow(2).Content);
         }
 }
Ejemplo n.º 8
0
 public void Grayscale_VaryingBitColorDepths_ShouldSucceed(string expectedFile, string actualFile)
 {
     using (Bitmap expected = new Bitmap(Image.FromFile(expectedFile)))
         using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(actualFile))
         {
             TestUtil.AssertContentsEqual(expected, actual.ToGrayscale().Content);
         }
 }
Ejemplo n.º 9
0
 public void EdgeDetect_ValidBitmap_ShouldSucceed()
 {
     using (SUT.FastBitmap expected = SUT.FastBitmap.FromFile(TestData1_EdgeDetect_KnownGood))
         using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(TestData1_KnownGood).EdgeDetect())
         {
             actual.Content.Save("output.png");
             TestUtil.AssertContentsEqual(expected.Content, actual.Content);
         }
 }
Ejemplo n.º 10
0
 public void Sobel_ValidBitmap_ShouldSucceed()
 {
     using (SUT.FastBitmap expected = SUT.FastBitmap.FromFile(FastBitmap.TestData1_Sobel_KnownGood))
         using (SUT.FastBitmap actual = SUT.FastBitmap.FromFile(FastBitmap.TestData1_KnownGood).Sobel().magnitude)
         {
             actual.Content.Save("sobel.png");
             TestUtil.AssertContentsEqual(expected.Content, actual.Content);
         }
 }
Ejemplo n.º 11
0
 public void RadonTransform_ValidBitmap_ShouldSucceed()
 {
     using (SUT.FastBitmap input = SUT.FastBitmap.FromFile(FastBitmap.TestData1_KnownGood))
     {
         SUT.FastBitmap actual = input.ToGrayscale().Blur(1f, 5);
         actual = actual.ScaleBy(actual.Max()).Pow(2);
         actual.Content.Save("testing_before.png");
         actual.RadonTransform(actual.Content.Width).Transform.Content.Save("testing_after.png");
     }
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Returns the largest magnitude in the <see cref="FastBitmap"/>.
        /// </summary>
        /// <returns>
        /// The largest magnitude in the <see cref="FastBitmap"/>.
        /// </returns>
        public unsafe ushort Max()
        {
            object theLock     = new object();
            ushort returnValue = 0;

            using (FastBitmap asGrayscale = this.ToGrayscale())
            {
                int bpp = asGrayscale.bitsPerPixel;

                FastBitmap.Operation(asGrayscale.Content, (data, scan0) =>
                {
                    Parallel.For(0, data.Height, yPos =>
                    {
                        byte localMax = 0;

                        for (int xPos = 0; xPos < data.Width; xPos++)
                        {
                            byte current = *FastBitmap.PixelPointer(scan0, xPos, yPos, data.Stride, bpp);

                            if (current > localMax)
                            {
                                localMax = current;
                            }
                        }

                        lock (theLock)
                        {
                            if (localMax > returnValue)
                            {
                                returnValue = localMax;
                            }
                        }
                    });
                });
            }

            return(returnValue);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Performs Sobel edge detection on the <see cref="FastBitmap"/>.
        /// </summary>
        /// <param name="computeThetas">
        /// True if the thetas should be computed in addition to the resulting <see cref="FastBitmap"/>, and false otherwise. Defaults to false.
        /// </param>
        /// <returns>
        /// A named-field tuple containing the resulting Sobel-filtered <see cref="FastBitmap"/>, and the calculated thetas. If <paramref name="computeThetas"/> was false, then thetas will be null.
        /// </returns>
        public unsafe (FastBitmap magnitude, double[, ] thetas) Sobel(bool computeThetas = false)
        {
            FastBitmap horizontal = this.KernelOperation(Kernel.HorizontalSobel);
            FastBitmap vertical   = this.KernelOperation(Kernel.VerticalSobel);

            FastBitmap result = new FastBitmap(horizontal.Content.Width, horizontal.Content.Height);

            FastBitmap.Operation(result.Content, (resultData, resultScan0) =>
            {
                FastBitmap.Operation(horizontal.Content, (horizontalData, horizontalScan0) =>
                {
                    FastBitmap.Operation(vertical.Content, (verticalData, verticalScan0) =>
                    {
                        for (int yPos = 0; yPos < horizontal.Content.Height; yPos++)
                        {
                            for (int xPos = 0; xPos < horizontal.Content.Width; xPos++)
                            {
                                byte *horizontalR = FastBitmap.PixelPointer(
                                    horizontalScan0,
                                    xPos,
                                    yPos,
                                    horizontalData.Stride,
                                    horizontal.bitsPerPixel);
                                byte *horizontalG = horizontalR + 1;
                                byte *horizontalB = horizontalR + 2;

                                byte *verticalR = FastBitmap.PixelPointer(
                                    verticalScan0,
                                    xPos,
                                    yPos,
                                    verticalData.Stride,
                                    vertical.bitsPerPixel);
                                byte *verticalG = verticalR + 1;
                                byte *verticalB = verticalR + 2;

                                byte *resultR = FastBitmap.PixelPointer(
                                    resultScan0,
                                    xPos,
                                    yPos,
                                    resultData.Stride,
                                    result.bitsPerPixel);
                                byte *resultG = resultR + 1;
                                byte *resultB = resultR + 2;

                                *resultR       = (byte)(255 * Math.Sqrt(*horizontalR * *horizontalR + *verticalR * *verticalR) / 360);
                                *resultG       = (byte)(255 * Math.Sqrt(*horizontalG * *horizontalG + *verticalG * *verticalG) / 360);
                                *resultB       = (byte)(255 * Math.Sqrt(*horizontalB * *horizontalB + *verticalB * *verticalB) / 360);
                                *(resultR + 3) = 255;
                            }
                        }
                    });
                });
            }, ImageLockMode.WriteOnly);

            double[,] thetas = null;
            if (computeThetas)
            {
                FastBitmap.Operation(horizontal.Content, (horizontalData, horizontalScan0) =>
                {
                    FastBitmap.Operation(vertical.Content, (verticalData, verticalScan0) =>
                    {
                        for (int yPos = 0; yPos < horizontal.Content.Height; yPos++)
                        {
                            for (int xPos = 0; xPos < horizontal.Content.Width; xPos++)
                            {
                                thetas[xPos, yPos] = Math.Atan2(
                                    *FastBitmap.PixelPointer(
                                        verticalScan0,
                                        xPos,
                                        yPos,
                                        verticalData.Stride,
                                        vertical.bitsPerPixel),
                                    *FastBitmap.PixelPointer(
                                        horizontalScan0,
                                        xPos,
                                        yPos,
                                        horizontalData.Stride,
                                        horizontal.bitsPerPixel));
                            }
                        }
                    });
                });
            }

            return(result, thetas);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Performs a Radon transformation on the <see cref="FastBitmap"/>.
        /// </summary>
        /// <param name="numberOfAngles">
        /// The number of angles to consider. Should be a power of 2.
        /// </param>
        /// <returns>
        /// A <see cref="ProjectionResult"/> representing the produced transform.
        /// </returns>
        public unsafe ProjectionResult RadonTransform(int numberOfAngles)
        {
            if (numberOfAngles <= 0)
            {
                throw new ArgumentException(Resources.InvalidNumberOfAnglesSpecified, nameof(numberOfAngles));
            }

            if ((numberOfAngles & (numberOfAngles - 1)) != 0)
            {
                throw new ArgumentException(Resources.NumberOfAnglesShouldBePowerOfTwo, nameof(numberOfAngles));
            }

            FastBitmap buffer = new FastBitmap(new Bitmap(this.Content.Width, this.Content.Height));

            using (Graphics graphics = Graphics.FromImage(buffer.Content))
            {
                graphics.FillRectangle(Brushes.Black, 0, 0, buffer.Content.Width, buffer.Content.Height);
            }

            int[] pixelsPerLine = new int[numberOfAngles];

            int height = buffer.Content.Height;
            int width  = buffer.Content.Width;

            int diff = Math.Max(height, width);

            double xCenter = (double)width / 2f;
            double yCenter = (double)height / 2f;
            int    xOffset = (int)(xCenter + FastBitmap.RoundingFactor(xCenter));
            int    yOffset = (int)(yCenter + FastBitmap.RoundingFactor(yCenter));

            FastBitmap.Operation(this.Content, (data, scan0) =>
            {
                FastBitmap.Operation(buffer.Content, (subData, subScan0) =>
                {
                    for (int k = 0; k < (numberOfAngles / 4) + 1; k++)
                    {
                        double theta = k * Math.PI / numberOfAngles;
                        double alpha = Math.Tan(theta);

                        for (int x = 0; x < diff; x++)
                        {
                            double y = alpha * (x - xOffset);
                            int yd   = (int)(y + FastBitmap.RoundingFactor(y));
                            if ((yd + yOffset >= 0) &&
                                (yd + yOffset < height) &&
                                (x < width))
                            {
                                // Originally: *ptr_radon_map->data(k, x) = img(x, yd + yOffset);
                                *FastBitmap.PixelPointer(subScan0, k, x, subData.Stride, buffer.bitsPerPixel)
                                    = *FastBitmap.PixelPointer(scan0, x, yd + yOffset, data.Stride, this.bitsPerPixel);

                                pixelsPerLine[k]++;
                            }

                            if ((yd + xOffset >= 0) &&
                                (yd + xOffset < width) &&
                                (k != numberOfAngles / 4) &&
                                (x < height))
                            {
                                // Originally: *ptr_radon_map->data(numberOfAngles / 2 - k, x) = img(yd + xOffset, x);
                                *FastBitmap.PixelPointer(
                                    subScan0,
                                    (numberOfAngles / 2) - k,
                                    x,
                                    subData.Stride,
                                    buffer.bitsPerPixel)
                                    = *FastBitmap.PixelPointer(scan0, yd + xOffset, x, data.Stride, this.bitsPerPixel);

                                pixelsPerLine[(numberOfAngles / 2) - k]++;
                            }
                        }
                    }

                    int j = 0;
                    for (int k = 3 * numberOfAngles / 4; k < numberOfAngles; k++)
                    {
                        double theta = k * Math.PI / numberOfAngles;
                        double alpha = Math.Tan(theta);
                        for (int x = 0; x < diff; x++)
                        {
                            double y = alpha * (x - xOffset);
                            int yd   = (int)(y + FastBitmap.RoundingFactor(y));
                            if ((yd + yOffset >= 0) && (yd + yOffset < height) && (x < width))
                            {
                                // Originally: *ptr_radon_map->data(k, x) = img(x, yd + yOffset);
                                *FastBitmap.PixelPointer(subScan0, k, x, subData.Stride, buffer.bitsPerPixel) =
                                    *FastBitmap.PixelPointer(scan0, x, yd + yOffset, data.Stride, this.bitsPerPixel);

                                pixelsPerLine[k]++;
                            }

                            if ((yOffset - yd >= 0) &&
                                (yOffset - yd < width) &&
                                ((2 * yOffset) - x >= 0) &&
                                ((2 * yOffset) - x < height) &&
                                (k != (3 * numberOfAngles) / 4))
                            {
                                // Originally: *ptr_radon_map->data(k - j, x) = img(-yd + yOffset, -(x - yOffset) + yOffset);
                                *FastBitmap.PixelPointer(subScan0, k - j, x, subData.Stride, buffer.bitsPerPixel) =
                                    *FastBitmap.PixelPointer(
                                        scan0,
                                        -yd + yOffset,
                                        -(x - yOffset) + yOffset,
                                        data.Stride,
                                        this.bitsPerPixel);

                                pixelsPerLine[k - j]++;
                            }
                        }

                        j += 2;
                    }
                });
            });

            return(new ProjectionResult(buffer, pixelsPerLine));
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Performs a Canny Edge Detect on the <see cref="FastBitmap"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="FastBitmap"/> whose contents represent the edges of the current <see cref="FastBitmap"/>.
        /// </returns>
        public unsafe FastBitmap EdgeDetect()
        {
            (FastBitmap magnitude, double[,] thetas)edgeDetect = this.Sobel(computeThetas: true);
            FastBitmap buffer = edgeDetect.magnitude;

            double[,] angles = edgeDetect.thetas;

            FastBitmap output = new FastBitmap(new Bitmap(buffer.Content.Width - 2, buffer.Content.Height - 2));

            FastBitmap.Operation(output.Content, (outputData, outputScan0) =>
            {
                FastBitmap.Operation(buffer.Content, (bufferData, bufferScan0) =>
                {
                    int localWidth = output.Content.Width + 1;
                    int localBpp   = buffer.bitsPerPixel;

                    for (int yPos = 1; yPos < output.Content.Height + 1; yPos++)
                    {
                        for (int xPos = 1; xPos < localWidth; xPos++)
                        {
                            int prevX = 0;
                            int prevY = 0;
                            int nextX = 0;
                            int nextY = 0;
                            switch (angles[xPos - 1, yPos - 1])
                            {
                            case 0:
                                prevX = -1;
                                nextX = 1;
                                break;

                            case 1:
                                prevX = -1;
                                nextX = 1;
                                prevY = 1;
                                nextY = -1;
                                break;

                            case 2:
                                prevY = -1;
                                nextY = 1;
                                break;

                            case 3:
                                prevX = -1;
                                nextX = 1;
                                prevY = -1;
                                nextY = 1;
                                break;
                            }

                            byte *outputA = FastBitmap.PixelPointer(outputScan0, xPos - 1, yPos - 1, outputData.Stride, output.bitsPerPixel) + 3;
                            *outputA      = 255;

                            byte *currentR  = FastBitmap.PixelPointer(bufferScan0, xPos, yPos, bufferData.Stride, localBpp);
                            byte *previousR = FastBitmap.PixelPointer(bufferScan0, xPos + prevX, yPos + prevY, bufferData.Stride, buffer.bitsPerPixel);
                            byte *nextR     = FastBitmap.PixelPointer(bufferScan0, xPos + nextX, yPos + nextY, bufferData.Stride, buffer.bitsPerPixel);

                            if (*currentR > *previousR && *currentR > *nextR)
                            {
                                *(outputA - 3) = 255;
                                *(outputA - 2) = 255;
                                *(outputA - 1) = 255;
                            }
                            else
                            {
                                *currentR       = 0;
                                *(currentR + 1) = 0;
                                *(currentR + 2) = 0;
                            }
                        }
                    }
                });
            });

            return(output);
        }
Ejemplo n.º 16
0
 public void FromFile_ValidBitmap_ShouldSucceed()
 {
     using (SUT.FastBitmap expected = SUT.FastBitmap.FromFile(FastBitmap.TestData1_KnownGood))
     {
     }
 }