I'm currently working on one of the last parts of a project and I'm at a standstill. I am needing to remove pixels from an image that are smaller than a certain aspect. For example, if an image has a square or triangle that is smaller than 35,35 pixels, I would need to remove it by changing its color.

Feel free to ask any questions. The images will be in a picturebox.

Thank you in advance,

Resentful

Recommended Answers

All 6 Replies

Does anyone have a clue on this?

Member Avatar for Unhnd_Exception

I have a clue on it.

I should already have the code to do it. It might not make much sense to you and it won't be commented.

Do the shapes need to be less then 35x35 square pixels or need to be smaller than a 35x35 square box?

What do you mean by removing them by changing the color? What color?

commented: Great help. +1

The shapes would vary in size, but just XX by XX square pixels.

It would be turning the pixels to the color of white.

Member Avatar for Unhnd_Exception

It probably won't be until tomorrow.

And i guess there is no color to search for. Just search all colors on the image and change the colors that are made of less than 35x35 pixels to white. So if you passed in a size of 35x35, all shapes that are less than 1225 pixels will be turned to white. So even if the shape was a long narrow shape that didn't fit into a 35x35 box but was made up of less then 1225 pixels would be turned to white.

It probably won't be until tomorrow.

And i guess there is no color to search for. Just search all colors on the image and change the colors that are made of less than 35x35 pixels to white. So if you passed in a size of 35x35, all shapes that are less than 1225 pixels will be turned to white. So even if the shape was a long narrow shape that didn't fit into a 35x35 box but was made up of less then 1225 pixels would be turned to white.

That's exactly what I would need. Any time you could get it would be great.

Thanks in advance,

Resentful

Member Avatar for Unhnd_Exception

Done.

This is going to be no use to you. It does what you want but its confusing. I was going to comment it but would take an hour and still be confusing.

What your trying to do is based on a flood fill. This is a simple flood fill but is confusing because it doesn't deal with x,y coordinates but deals with indexes in the image bytes.

I would recommend searching Bob Powell flood fill. Its an easy flood fill that deals with get pixel and set pixel. If you get the basic flood fill working where it will fill a solid color you can pm me and i'll help you set it up so it searches all colors in the images. You should be able to do a copy and paste job to get it working.

This function's logic is identical to the get pixel and set pixel version from that site. Its where i based mine from a couple of years ago. Once the get pixel and set pixel version is complete you'll be able to compare the speed between the 2. You'll find this version is remarkably faster.

Happy to help.

Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        RemoveColors(PictureBox1.Image, New Size(35, 35))
        PictureBox1.Refresh()
    End Sub

    Public Sub RemoveColors(ByVal bmp As Bitmap, ByVal sqPixels As Size)
        If bmp Is Nothing Then Exit Sub

        Dim BitmapData As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat)
        Dim BitsPerPixel As Integer = BitmapData.Stride / bmp.Width
        Dim OverStride As Integer = BitmapData.Stride - bmp.Width * BitsPerPixel
        Dim BitmapPtr As IntPtr = BitmapData.Scan0

        Dim Stack As New Stack
        Dim CurrentShapeIndexes As New List(Of Integer)

        Dim FirstIndex, CurrentIndex, Index, CheckedIndex As Integer
        Dim IndexesChecked(bmp.Width * bmp.Height - 1) As Boolean
        Dim BitmapBytes(BitmapData.Stride * bmp.Height - 1) As Byte

        'Stores the color of the current color, a new color to fill it to, and 
        'the white color to change small shapes.
        Dim OriginalColor(2) As Byte
        Dim NewColor(2) As Byte
        Dim WhiteColor() As Byte = {255, 255, 255}
        Dim ColorToCopyBackTo(2) As Byte

        'Used to check around all neighboring pixels of the current pixel.
        Dim x() As Integer = {1, 0, -1, 0}
        Dim y() As Integer = {0, 1, 0, -1}

        Marshal.Copy(BitmapPtr, BitmapBytes, 0, BitmapBytes.Length)

        Do While True

            CurrentIndex = Array.IndexOf(IndexesChecked, False) * BitsPerPixel
            FirstIndex = CurrentIndex

            Stack.Push(CurrentIndex)
            CurrentShapeIndexes.Add(CurrentIndex)

            Array.Copy(BitmapBytes, CurrentIndex, OriginalColor, 0, 3)

            NewColor = GetNewColor(OriginalColor)

            Do While Stack.Count > 0

                CurrentIndex = Stack.Pop
                Array.Copy(NewColor, 0, BitmapBytes, CurrentIndex, 3)

                For i = 0 To 3

                    If ((CurrentIndex) Mod BitmapData.Stride = 0 And x(i) = -1) OrElse ((CurrentIndex + BitsPerPixel + OverStride) Mod BitmapData.Stride = 0 And x(i) = 1) Then Continue For

                    Index = CurrentIndex + (y(i) * (BitmapData.Stride) + x(i) * BitsPerPixel)

                    CheckedIndex = Index / BitsPerPixel

                    'check top and bottom bounds
                    If Index < 0 OrElse Index > BitmapBytes.Length - BitsPerPixel OrElse IndexesChecked(CheckedIndex) = True Then Continue For

                    If BitmapBytes(Index) = OriginalColor(0) AndAlso BitmapBytes(Index + 1) = OriginalColor(1) AndAlso BitmapBytes(Index + 2) = OriginalColor(2) Then
                        IndexesChecked(CheckedIndex) = True
                        Stack.Push(Index)
                        CurrentShapeIndexes.Add(Index)
                    End If
                Next

            Loop


            IndexesChecked(FirstIndex / BitsPerPixel) = True

            If CurrentShapeIndexes.Count < (sqPixels.Width * sqPixels.Height) Then
                ColorToCopyBackTo = WhiteColor
            Else
                ColorToCopyBackTo = OriginalColor
            End If

            For i = 0 To CurrentShapeIndexes.Count - 1
                Array.Copy(ColorToCopyBackTo, 0, BitmapBytes, CurrentShapeIndexes(i), 3)
            Next

            CurrentShapeIndexes.Clear()

            If Not IndexesChecked.Contains(False) Then Exit Do

        Loop


        Marshal.Copy(BitmapBytes, 0, BitmapPtr, BitmapBytes.Length)
        bmp.UnlockBits(BitmapData)

        BitmapPtr = IntPtr.Zero
        BitmapBytes = Nothing
        IndexesChecked = Nothing

    End Sub

    Private Function GetNewColor(ByVal OriginalColor As Byte()) As Byte()
        Dim newColor(2) As Byte
        Randomize()
        newColor(0) = 255 * Rnd()
        newColor(1) = 255 * Rnd()
        newColor(2) = 255 * Rnd()

        Return newColor

    End Function

End Class
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.