locked
How to detect shape of bottle? RRS feed

  • Question

  • Hi,

    Do I want to ask how to detect a shape of a bottle using vb.net? If anyone has a link or any information about it, hope you can share with me. Thanks.

    Below is my image.

    • Moved by Stanly Fan Wednesday, July 26, 2017 3:01 AM from windows form general
    Monday, July 3, 2017 3:03 AM

Answers


  • Sure! I can wait for it. Thanks again.

    Regards,

    Bella

    Hi,

    I've setup a first version:

    https://1drv.ms/u/s!Aunk9dshveXVqxSA0GGDz2IGOSmx

    The SHA512 hash of the current zip-file (07/17/2017, 09:08 h MESZ) is

    AC-5A-BC-0C-7F-A9-BF-E6-32-B5-47-97-3F-04-B4-7D-20-1E-4B-7E-17-E0-35-73-86-82-D9-BC-86-05-7A-C6-30-CD-7E-9C-8D-04-91-AE-EB-79-3D-61-A9-11-95-9D-94-7F-B9-D4-16-B1-5E-9A-F7-15-6F-CF-29-A2-73-01


    Regards,

      Thorsten


    • Edited by Thorsten Gudera Monday, July 17, 2017 7:12 AM
    • Marked as answer by Bella67 Wednesday, July 26, 2017 9:10 AM
    Wednesday, July 12, 2017 10:02 PM

All replies

  • Hi,

    didnt we have something like this about a year ago? Do you want to detect the complete bottle, or just the green filling?

    Regards,

      Thorsten

    Monday, July 3, 2017 5:44 AM

  • Do I want to ask how to detect a shape of a bottle using vb.net? If anyone has a link or any information about it, hope you can share with me. Thanks.


    Hi,

    consider using one or more of the following:

    - Thresholding

    - Edge Detection

    - Clustering

    I think, you can get good results with each of the mentioned, where Thresholding and a ChainCode for edge detection seem to be the most performant with ChainCode edge detection as fastest...

    Regards,

      Thorsten


    Monday, July 3, 2017 6:11 AM
  • yes. but now i want to detect the shape of bottle only.

    thanks

    Tuesday, July 4, 2017 5:36 AM

  • Do I want to ask how to detect a shape of a bottle using vb.net? If anyone has a link or any information about it, hope you can share with me. Thanks.


    Hi,

    consider using one or more of the following:

    - Thresholding

    - Edge Detection

    - Clustering

    I think, you can get good results with each of the mentioned, where Thresholding and a ChainCode for edge detection seem to be the most performant with ChainCode edge detection as fastest...

    Regards,

      Thorsten


    Do u have any link or anything that i can refer?
    Tuesday, July 4, 2017 5:38 AM
  • Hi Bella67,

    Please refer to the following document:

    Contour Analysis for Image Recognition in C#

    Image Processing Lab in C#

    Best Regards,

    Stanly


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, July 4, 2017 9:51 AM
  • yes. but now i want to detect the shape of bottle only.

    thanks

    Hi,

    could you show us, how the result shall look like? Do you need the complete bottle? Ort just the parts that have big contrast to the background? do you need the outline as a list of coordinates?...

    Is this enough?

    or do you need the missing parts too?

    [Note that this is done by taking 2 thresholds and cropping]

    Regards,

      Thorsten

    Thursday, July 6, 2017 1:21 PM
  • Hi,

    Thanks for helping. Here, the result that I want.

    - Original Image

    - Segment image

    - from segment image, we can see the defect of the bottle.

    - Binary image

    - I want like binary image


    • Edited by Bella67 Friday, July 7, 2017 5:49 AM error
    Friday, July 7, 2017 5:48 AM
  • Hi,

    Thanks for helping. Here, the result that I want.

    - Original Image

    - Segment image

    - from segment image, we can see the defect of the bottle.

    - Binary image

    - I want like binary image


    Ok, you seem to have found a way to detect what you want, dont you?

    Do you perhaps need some hints to implement the processing steps? If so, here are some algorithms to compute the variance:

    https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

    Maybe I find some time in the next days to help you with that by showing some code.

    (I often use the simple way, E[X²] - E[X]² (mean of the squares - square of the mean))

    [Also I use a different formula that results in a strong edge detection: (x - Mean)² ]

    Regards,

      Thorsten

    Friday, July 7, 2017 2:39 PM
  • Hi,

    Thanks for helping. Here, the result that I want.

    - Original Image

    - Segment image

    - from segment image, we can see the defect of the bottle.

    - Binary image

    - I want like binary image


    Ok, you seem to have found a way to detect what you want, dont you?

    Do you perhaps need some hints to implement the processing steps? If so, here are some algorithms to compute the variance:

    https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

    Maybe I find some time in the next days to help you with that by showing some code.

    (I often use the simple way, E[X²] - E[X]² (mean of the squares - square of the mean))

    [Also I use a different formula that results in a strong edge detection: (x - Mean)² ]

    Regards,

      Thorsten

    Yes, I need to detect the defect from the bottle. For the previous detection, I used standard deviation to get the segmentation image. Yes, I need some info about the steps and thanks for the link. 

    Regards,

    Bella

    Monday, July 10, 2017 4:34 AM

  • Yes, I need to detect the defect from the bottle. For the previous detection, I used standard deviation to get the segmentation image. Yes, I need some info about the steps and thanks for the link. 

    Regards,

    Bella

    Ok,
    what I need to know is, which result of the following is closest to your needs:

    the easy way is to apply a threshold to the image. It usually will detect the top part and the main bottle, but not the part in between (see picture below). If this is alright for you choose this way since it is easy to implement and quite fast in processing.

    The second approach is somewhat better in results but will take more processing steps including some convolution which may slow down the processing too much:
    -first apply a median to remove noise
    -get the edges with a strong statistical edge-finding algorithm like the (x-mean)² one (kind of a statistical derivative) - or use the common x - mean algorithm to find the edges

    -remove - or set to white - the outer background, so that only the shape of the bottle now is black

    -invert that image and

    -optionally, binarize it

    alternatively, maybe faster, is to get the edges like above, but with a larger kernel and
    -get the outline of the bottle by applying a chaincode:

    -now binarize this based on the alpha values (which will give you a white foreground)

    Please tell me, which way to go...

    Regards,

      Thorsten


    Monday, July 10, 2017 6:15 PM

  • Yes, I need to detect the defect from the bottle. For the previous detection, I used standard deviation to get the segmentation image. Yes, I need some info about the steps and thanks for the link. 

    Regards,

    Bella

    Ok,
    what I need to know is, which result of the following is closest to your needs:

    the easy way is to apply a threshold to the image. It usually will detect the top part and the main bottle, but not the part in between (see picture below). If this is alright for you choose this way since it is easy to implement and quite fast in processing.

    The second approach is somewhat better in results but will take more processing steps including some convolution which may slow down the processing too much:
    -first apply a median to remove noise
    -get the edges with a strong statistical edge-finding algorithm like the (x-mean)² one (kind of a statistical derivative)

    -remove - or set to white - the outer background, so that only the shape of the bottle now is black

    -invert that image and

    -optionally, binarize it

    alternatively, maybe faster, is to get the edges like above, but with a larger kernel and
    -get the outline of the bottle by applying a chaincode:

    -now binarize this based on the alpha values (which will give you a white foreground)

    Please tell me, which way to go...

    Regards,

      Thorsten

    Great! The second and third method is better. But, the third method shows blur image. I will choose the third method because you've said that second method takes longer processing time. So, I need shorter time for computational complexity. Below I give defect image. Can you process this image with the third method?

    Tuesday, July 11, 2017 1:41 AM

  • Great! The second and third method is better. But, the third method shows blur image. I will choose the third method because you've said that second method takes longer processing time. So, I need shorter time for computational complexity. Below I give defect image. Can you process this image with the third method?


    Ok, here the results, using the third method (Note: I resampled that pic to 1024 px in height)

    [Note that I didnt clean the path nor approximated lines for it, so the image has aliased edges, there's no problem to change that]

    here is the pic with all colors with an alpha value > 0 set to white (the background is a style of the paragraph)

    Regards,

      Thorsten


    Tuesday, July 11, 2017 6:43 AM
  • ... if you want, I will setup a sample application to do these steps, but this may take some days...

    Regards,

      Thorsten

    Tuesday, July 11, 2017 6:51 AM

  • Great! The second and third method is better. But, the third method shows blur image. I will choose the third method because you've said that second method takes longer processing time. So, I need shorter time for computational complexity. Below I give defect image. Can you process this image with the third method?


    Ok, here the results, using the third method (Note: I resampled that pic to 1024 px in height)

    [Note that I didnt clean the path nor approximated lines for it, so the image has aliased edges, there's no problem to change that]

    here is the pic with all colors with an alpha value > 0 set to white (the background is a style of the paragraph)

    Regards,

      Thorsten


    Excellent! the binary image is exactly what I want. Thanks for helping me!
    Wednesday, July 12, 2017 6:10 AM
  • ... if you want, I will setup a sample application to do these steps, but this may take some days...

    Regards,

      Thorsten

    Sure! I can wait for it. Thanks again.

    Regards,

    Bella

    Wednesday, July 12, 2017 6:11 AM

  • Sure! I can wait for it. Thanks again.

    Regards,

    Bella

    Hi,

    I've setup a first version:

    https://1drv.ms/u/s!Aunk9dshveXVqxSA0GGDz2IGOSmx

    The SHA512 hash of the current zip-file (07/17/2017, 09:08 h MESZ) is

    AC-5A-BC-0C-7F-A9-BF-E6-32-B5-47-97-3F-04-B4-7D-20-1E-4B-7E-17-E0-35-73-86-82-D9-BC-86-05-7A-C6-30-CD-7E-9C-8D-04-91-AE-EB-79-3D-61-A9-11-95-9D-94-7F-B9-D4-16-B1-5E-9A-F7-15-6F-CF-29-A2-73-01


    Regards,

      Thorsten


    • Edited by Thorsten Gudera Monday, July 17, 2017 7:12 AM
    • Marked as answer by Bella67 Wednesday, July 26, 2017 9:10 AM
    Wednesday, July 12, 2017 10:02 PM
  • Hi,

    I added a third edge-finding modus. (Magnitude of a Sobel processed image)

    The download address stays the same.

    Regards,

      Thorsten

    Thursday, July 13, 2017 10:53 PM
  • Hi,

    I added a third edge-finding modus. (Magnitude of a Sobel processed image)

    The download address stays the same.

    Regards,

      Thorsten

    Hi,

    Thanks for helping me. what version did you use? I can't open the file. My visual studio is not compatible with your version.

    Regards,

    Bella

    Friday, July 14, 2017 1:35 AM

  • Hi,

    Thanks for helping me. what version did you use? I can't open the file. My visual studio is not compatible with your version.

    Regards,

    Bella

    Hi,

    VS 2015 Community, fw 4.6.1. Which Version do you need? I think, I could go back up to fw 4.0, but not sure. Edit: fw 4.0 is ok for the code.

    Regards,

      Thorsten

    Friday, July 14, 2017 2:36 AM

  • Hi,

    Thanks for helping me. what version did you use? I can't open the file. My visual studio is not compatible with your version.

    Regards,

    Bella

    Hi,

    VS 2015 Community, fw 4.6.1. Which Version do you need? I think, I could go back up to fw 4.0, but not sure. Edit: fw 4.0 is ok for the code.

    Regards,

      Thorsten

    Hi,

    I have used VS 2010. Never mind, I can install VS 2015 community. Thanks.

    Regards,

    Bella 

    Monday, July 17, 2017 4:58 AM
  • Excellent work using Sobel edge and set the content to white. It seem u apply median filter to eliminate the noise. What if i want to apply in PictureBox for button click with just Original bottle image > grayscale > Sobel edge > content to white. Is there any simplest way.
    Monday, August 7, 2017 6:37 PM
  • Hi,

    I wrote the program so, that you could select the steps with custom parameters to find the correct settings that will detect the bottle shape reliably. Once you have found the correct settings, as it seems to be, you could take the code for these parts and rewrite them so, that a minimum amount of locking and copying pixels is needed.

    If you have problems in writing the code, I can help you. The only thing I need is the steps to do (that you already gave me in your last post) and the parameters for the methods.

    So, you want to greyscale the image and dont use a median?

    Then use the Sobel edge detector with what settings of threshold? Maybe just the default 0.

    Then the chain code, with what settings? [Threshold, ApproxLines etc]

    Then do you want to remove the outline pixels?

    And set content to white you said you want to do.

    Regards,

      Thorsten

    Monday, August 7, 2017 9:35 PM
  • Excellent work using Sobel edge and set the content to white. It seem u apply median filter to eliminate the noise. What if i want to apply in PictureBox for button click with just Original bottle image > grayscale > Sobel edge > content to white. Is there any simplest way.


    Hi,

    I didnt notice your not the OP...

    So you want to add a grayscale method right before the Sobel edge detection.

    First add a Property to the ProcessingArguments class and in the DoWork method for the Backgroundworker check if this property is set, and if, add the code to grayscale the bitmap (variable "bmp").

    If you need assistance, just tell me.

    Regards,

      Thorsten

    Tuesday, August 8, 2017 12:27 AM
  • Excellent work using Sobel edge and set the content to white. It seem u apply median filter to eliminate the noise. What if i want to apply in PictureBox for button click with just Original bottle image > grayscale > Sobel edge > content to white. Is there any simplest way.


    Hi,

    I didnt notice your not the OP...

    So you want to add a grayscale method right before the Sobel edge detection.

    First add a Property to the ProcessingArguments class and in the DoWork method for the Backgroundworker check if this property is set, and if, add the code to grayscale the bitmap (variable "bmp").

    If you need assistance, just tell me.

    Regards,

      Thorsten

    Did you mean like this.

     -Yes the Sobel edge detector threshold settings is just the default 0.

     -For the chain code. I just the the threshold that you given which is 30 and its works fine.

     -Then the outline should be in black while the content in white. I unchecked [Exclude, Cleaned, ApproxLines]. I works for me now although the    picture not too smooth

    I try to extract the code from your example but got confused with the class. Hope that you can assist me with this.

    Thank you

    Public Class Form1

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
                PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
            End If
        End Sub
       
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim img As New Bitmap(PictureBox1.Image)

            'Pre-processing 
            img = New Bitmap(img, 1024, 768)

            'Grayscale
            Dim X As Integer
            Dim Y As Integer
            Dim clr As Integer

            For X = 0 To img.Width - 1
                For Y = 0 To img.Height - 1
                    clr = (CInt(img.GetPixel(X, Y).R) + _
                           img.GetPixel(X, Y).G + _
                           img.GetPixel(X, Y).B) \ 3
                    img.SetPixel(X, Y, Color.FromArgb(clr, clr, clr))
                Next Y
            Next X


            'Try to do Sobel
            SobelEdge(img)

            Me.PictureBox2.Image = img

        End Sub
        
        Public Shared Sub SobelEdge(ByRef bmp As Bitmap)


        End Sub

    End Class

    Tuesday, August 8, 2017 2:30 AM

  • I try to extract the code from your example but got confused with the class. Hope that you can assist me with this.

    Thank you

    Public Class Form1

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
                PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
            End If
        End Sub
       
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim img As New Bitmap(PictureBox1.Image)

            'Pre-processing 
            img = New Bitmap(img, 1024, 768)

            'Grayscale
            Dim X As Integer
            Dim Y As Integer
            Dim clr As Integer

            For X = 0 To img.Width - 1
                For Y = 0 To img.Height - 1
                    clr = (CInt(img.GetPixel(X, Y).R) + _
                           img.GetPixel(X, Y).G + _
                           img.GetPixel(X, Y).B) \ 3
                    img.SetPixel(X, Y, Color.FromArgb(clr, clr, clr))
                Next Y
            Next X


            'Try to do Sobel
            SobelEdge(img)

            Me.PictureBox2.Image = img

        End Sub
        
        Public Shared Sub SobelEdge(ByRef bmp As Bitmap)


        End Sub

    End Class

    Hi,

    to do the Sobel magnitude (as the gradient of the image), you need two temp bitmaps representing the partial derivatives (one i x dir, one in y dir) and then merge these two with the norm operator (sqrt of squaresum).

    I'm very tired right now, so I'll write the sobelEdge function later for you. The general steps are just (using the code from the program):

                                bmpRes = CType(bmp.Clone(), Bitmap)
                                Dim threshold As Integer = 0
                                Dim conv As New Convolution
                                conv.CancelLoops = False
                                AddHandler conv.ProgressPlus, AddressOf ReportProgress 'comment out, if not needed
                                bmp2 = DirectCast(bmp.Clone(), Bitmap)
                                fipbmp.EdgeDetection_Sobel_Horz(bmp2, 1, False, 127, conv, Me.BackgroundWorker1) 'dx
                                bmp4 = DirectCast(bmp.Clone(), Bitmap)
                                fipbmp.EdgeDetection_Sobel_Vert(bmp4, 1, False, 127, conv, Me.BackgroundWorker1) 'dy
                                fipbmp.MergeBitmaps(bmpRes, bmp2, bmp4, CByte(threshold), 127) 'gradient
                                fipbmp.replaceColors(bmpRes, 255, 0, 0, 0, 2,
                                    255, CByte(threshold), CByte(threshold), CByte(threshold))
                                RemoveHandler conv.ProgressPlus, AddressOf ReportProgress ' comment out, if not needed
                                conv = Nothing

    If you dont use a Backgroundworker, simply pass "Nothing" to the methods as 6th parameter like:

     fipbmp.EdgeDetection_Sobel_Horz(bmp2, 1, False, 127, conv, Nothing) 'dx

    The bitmaps must be declared and should be correctly disposed after use (without the resulting pic of course).

    Regards,

      Thorsten



    • Proposed as answer by Sufyan Safwan Tuesday, August 8, 2017 5:22 AM
    Tuesday, August 8, 2017 3:25 AM
  • Hi

    Thank for your guidance. Then should declare for both dx (Sobel Horz) and dy (Sobel Vert). I will wait for your function for more understanding.

    Regards,

      Sufyan Safwan


    Tuesday, August 8, 2017 5:39 AM

  • I try to extract the code from your example but got confused with the class. Hope that you can assist me with this.

    Thank you

    Public Class Form1

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
                PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
            End If
        End Sub
       
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim img As New Bitmap(PictureBox1.Image)

            'Pre-processing 
            img = New Bitmap(img, 1024, 768)

            'Grayscale
            Dim X As Integer
            Dim Y As Integer
            Dim clr As Integer

            For X = 0 To img.Width - 1
                For Y = 0 To img.Height - 1
                    clr = (CInt(img.GetPixel(X, Y).R) + _
                           img.GetPixel(X, Y).G + _
                           img.GetPixel(X, Y).B) \ 3
                    img.SetPixel(X, Y, Color.FromArgb(clr, clr, clr))
                Next Y
            Next X


            'Try to do Sobel
            SobelEdge(img)

            Me.PictureBox2.Image = img

        End Sub
        
        Public Shared Sub SobelEdge(ByRef bmp As Bitmap)


        End Sub

    End Class

    Hi,

    to do the Sobel magnitude (as the gradient of the image), you need two temp bitmaps representing the partial derivatives (one i x dir, one in y dir) and then merge these two with the norm operator (sqrt of squaresum).

    I'm very tired right now, so I'll write the sobelEdge function later for you. The general steps are just (using the code from the program):

                                bmpRes = CType(bmp.Clone(), Bitmap)
                                Dim threshold As Integer = 0
                                Dim conv As New Convolution
                                conv.CancelLoops = False
                                AddHandler conv.ProgressPlus, AddressOf ReportProgress 'comment out, if not needed
                                bmp2 = DirectCast(bmp.Clone(), Bitmap)
                                fipbmp.EdgeDetection_Sobel_Horz(bmp2, 1, False, 127, conv, Me.BackgroundWorker1) 'dx
                                bmp4 = DirectCast(bmp.Clone(), Bitmap)
                                fipbmp.EdgeDetection_Sobel_Vert(bmp4, 1, False, 127, conv, Me.BackgroundWorker1) 'dy
                                fipbmp.MergeBitmaps(bmpRes, bmp2, bmp4, CByte(threshold), 127) 'gradient
                                fipbmp.replaceColors(bmpRes, 255, 0, 0, 0, 2,
                                    255, CByte(threshold), CByte(threshold), CByte(threshold))
                                RemoveHandler conv.ProgressPlus, AddressOf ReportProgress ' comment out, if not needed
                                conv = Nothing

    If you dont use a Backgroundworker, simply pass "Nothing" to the methods as 6th parameter like:

     fipbmp.EdgeDetection_Sobel_Horz(bmp2, 1, False, 127, conv, Nothing) 'dx

    The bitmaps must be declared and should be correctly disposed after use (without the resulting pic of course).

    Regards,

      Thorsten



    It really helpfull. I already done it in VS2010. I just facing problem to invert the content in white. From that i can count the black and white pixels of the image. Sry i can't upload the GUI picture yet because i am new and waiting for Microsoft to verify my acc. I think you can imagine where i load picture in PictureBox1 and by pressing the Button2, the black image with sobel edge detection appears at PictureBox2. Hope you can assist in invert the content in white.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
                PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
            End If

            Dim bmp As Bitmap = New Bitmap(PictureBox1.Image)
          
        End Sub

        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim img As New Bitmap(PictureBox1.Image)
            PictureBox2.Image = sobelEdge(img)
       

        End Sub

        Public Function sobelEdge(ByVal bmpRes As Bitmap) As Bitmap
            Dim bmp As Bitmap = New Bitmap(PictureBox1.Image)
            Dim bmp2 As Bitmap
            Dim bmp4 As Bitmap
            bmpRes = CType(bmp.Clone(), Bitmap)
            Dim threshold As Integer = 0
            Dim conv As New Convolution
            conv.CancelLoops = False

            bmp2 = DirectCast(bmp.Clone(), Bitmap)
            fipbmp.EdgeDetection_Sobel_Horz(bmp2, 1, False, 127, conv, Nothing) 'dx
            bmp4 = DirectCast(bmp.Clone(), Bitmap)
            fipbmp.EdgeDetection_Sobel_Vert(bmp4, 1, False, 127, conv, Nothing) 'dy
            fipbmp.MergeBitmaps(bmpRes, bmp2, bmp4, CByte(threshold), 127) 'gradient
            fipbmp.replaceColors(bmpRes, 255, 0, 0, 0, 2,
                255, CByte(threshold), CByte(threshold), CByte(threshold))

            conv = Nothing

            Return bmpRes
        End Function


    Regards,

      Sufyan Safwan


    Tuesday, August 8, 2017 6:25 AM
  • Sry i can't upload the GUI picture yet because i am new and waiting for Microsoft to verify my acc. I think you can imagine where i load picture in PictureBox1 and by pressing the Button2, the black image with sobel edge detection appears at PictureBox2. Hope you can assist in invert the content in white.

    Hi, you mean you get an image like this?

    And what should be colored white now? Only the bottle? If so, this is not esy from this picture because it is too noisy... (To make the bottle white, we first need to detect the shape of the bottle...)

    (For your code: Please dont forget to dispose bmp, bmp2 and bmp4 ...)

    Regards,

      Thorsten

    Tuesday, August 8, 2017 9:08 PM
  • Sry i can't upload the GUI picture yet because i am new and waiting for Microsoft to verify my acc. I think you can imagine where i load picture in PictureBox1 and by pressing the Button2, the black image with sobel edge detection appears at PictureBox2. Hope you can assist in invert the content in white.

    Hi, you mean you get an image like this?

    And what should be colored white now? Only the bottle? If so, this is not esy from this picture because it is too noisy... (To make the bottle white, we first need to detect the shape of the bottle...)

    (For your code: Please dont forget to dispose bmp, bmp2 and bmp4 ...)

    Regards,

      Thorsten

    True..same image that you got.

    Yeah, only the bottle should be colored in white. 

    I try to change the content to white but it didn't happen. So, how you propose for the shape detection? I try to follow all the step based on you attachment above. But there are some step like change the content to white that i didn't understand (binarize this based on the alpha values (which will give you a white foreground).

    Wednesday, August 9, 2017 1:08 AM
  • And if i just simply apply that. The image will be in white include the background. Maybe first i should remove the background like you did at the bottle outline (i quite not understand this part in coding and how to apply that). Then the bottle can simply change to white and after that i add back the background from nothing to black.  

    Wednesday, August 9, 2017 1:25 AM

  • I try to change the content to white but it didn't happen. So, how you propose for the shape detection? I try to follow all the step based on you attachment above. But there are some step like change the content to white that i didn't understand (binarize this based on the alpha values (which will give you a white foreground).

    Hi,

    for the detection of the shape I use the ChainCode. This searches for a start-pixel which meets the criteria and then moves around the found shape again by checking the criteria (here: the grey-value). This prcedure detects a chain of coordinates from which we build a GraphjcsPath (variable "fPath").

    The next step is to fill the path in white color. This is simply done by re-drawing the picture: a) create a new blank picture (if you need a black bg then clear the new image with color black); b) fill the path (of the bottle of the chaincode results) into that picture.

    This last step is done by the following code - lines that I'll explain:

                                'replaceColors
                                bmpTmp = bmpRes
                                bmpRes = New Bitmap(_bmp.Width, _bmp.Height)
    
                                Using g As Graphics = Graphics.FromImage(bmpRes)
                                    If p.ChainCodePathApproxLines Then
                                        g.SmoothingMode = SmoothingMode.AntiAlias
                                    End If
                                    If p.SetContentToWhite Then
                                        g.FillPath(Brushes.White, fPath)
                                    Else
                                        Using tb As New TextureBrush(_bmp)
                                            g.FillPath(tb, fPath)
                                        End Using
                                    End If
                                End Using

    first I assign the current state (current picture after Sobel and Greyscale) to a temp bitmap to dispose later. Then I assign the new Bitmap of the correct size to the output bitmap variable (bmpRes). So now we have the old image in a stage that it can be disposed correctly and the new picture in the correct variable.

    Now I get a Graphics-object from the new bitmap and decide, if to fill the path in white color, or fill the path with the part of the orig image that represents the inner of the path. (Before I set, or set not, a property of the Graphics object to draw smooth outlines (or not) (If we approximate lines from the chaincode data - as a vectorization - we draw smooth, else we use the pixel-coordinates from the ChainCode which will produce an aliased outline))

    So, if you always want to set the bottle to white, you could compress the above code to:

                                bmpTmp = bmpRes
                                bmpRes = New Bitmap(_bmp.Width, _bmp.Height)
    
                                Using g As Graphics = Graphics.FromImage(bmpRes)
                                    g.SmoothingMode = SmoothingMode.AntiAlias 'remove this line, if you need the exact integer coords of the path
    
          				g.Clear(Color.Black) 'black bg
                                    g.FillPath(Brushes.White, fPath) 'white fg
                                End Using

    Regards,

      Thorsten

    Wednesday, August 9, 2017 2:50 AM
  • Hi Thorsten

    Good explanation but i can't get the idea how to integrate it in my example coding (my coding attachment above). I try to merge it same like what i'm doing for sobel with your guidance. I understand the theory that you explain but how to implement it become my greatest problem. 


    Wednesday, August 9, 2017 3:45 AM
  • Hi Thorsten

    Good explanation but i can't get the idea how to integrate it in my example coding (my coding attachment above). I try to merge it same like what i'm doing for sobel with your guidance. I understand the theory that you explain but how to implement it become my greatest problem.

    Hi,

    ok I've to do other things now, so I'll post something here this evening to do the smoothing, chaincode and set_content_to_white with the lines that are needed (for the default settings).

    Regards,

      Thorsten

    • Proposed as answer by Sufyan Safwan Wednesday, August 9, 2017 4:25 AM
    Wednesday, August 9, 2017 4:18 AM
  • Hi

    Thank you. I will wait

    Regards,

      Sufyan Safwan

    Wednesday, August 9, 2017 10:04 AM
  • Hi

    Thank you. I will wait

    Regards,

      Sufyan Safwan

    Hi,

    ok, sorry for the delay, I slept 7 hrs too long !!!

    I will begin now and then post something, but htere is one problem, we have to think about:

    When you do not use a noise reduction before using the ChainCode, the CahinCode will return you a *lot* of outlines of objects it has found. Even when sorting the results so, that the longest chain (= longest perimeter of found objects) will be the top chain in the results, we will have some difficulties to find the correct shape (= the bottle). Its rather suuposable, that it will find the comlete, rectangluar outline of the entire image. Nevertheless, I'll post the relevant code and then we could think, if we find a way to detect the correct shape or if we must do a smoothening.

    Regards,

      Thorsten

    Thursday, August 10, 2017 1:18 AM
  • Hi, here's the minimal code needed to do the chaincode and the coloring (bmpTmp needs to be declared, Function GetPath is in the Form1 of the project and we now need to modify it so, that it finds the correct chain (= outline of the bottle) if possible):

    Dim fbmp As New ChainFinder() fbmp.GrayScaleImage(bmpRes) Dim fList As List(Of ChainCode) = fbmp.GetOutline(bmpRes, 30, True, 0, False, 0, False) 'find all chains

                        'Dim fList As List(Of ChainCode) = fbmp.GetOutline(bmpRes, 30, True,
                        '                                                    0, True, 0, False) 'find only outer chains fList = fList.OrderByDescending(Function(a) a.Coord.Count).ToList() If fList.Count > 0 Then Using fPath As GraphicsPath = GetPath(fList, True, True, Math.Sqrt(2.0)) 'replaceColors bmpTmp = bmpRes bmpRes = New Bitmap(_bmp.Width, _bmp.Height) Using g As Graphics = Graphics.FromImage(bmpRes) g.SmoothingMode = SmoothingMode.AntiAlias g.FillPath(Brushes.White, fPath) End Using End Using End If

    Regards,

      Thorsten


    • Proposed as answer by Sufyan Safwan Thursday, August 10, 2017 5:00 AM
    Thursday, August 10, 2017 1:28 AM
  • Hi,

    to illustrate:

    This is the picture I get when collecting all paths by a modification of the GetPath method like:

    [Note that drawing all chains/paths could take a long time...]

        Private Function GetPath(chainList As List(Of ChainCode), cleaned As Boolean, approxLines As Boolean, epsilon As Double) As GraphicsPath
            Dim fPath As New GraphicsPath()
            Dim fBmp As New ChainFinder()
    
            For i As Integer = 0 To chainList.Count - 1
                Using gPath As New GraphicsPath()
                    Dim c As ChainCode = chainList(i)
    
                    Dim fList As List(Of Point) = c.Coord
    
                    If cleaned Then
                        fList = fBmp.RemoveColinearity(fList, True)
                    End If
    
                    If approxLines Then
                        fList = fBmp.ApproximateLines(fList, epsilon)
                    End If
    
                    gPath.StartFigure()
                    gPath.AddLines(fList.ToArray())
    
                    If CheckBox4.Checked Then
                        gPath.CloseFigure()
                    End If
    
                    If gPath IsNot Nothing Then
                        Try
                            If gPath.PathPoints.Length > 1 Then
                                fPath.AddPath(gPath, False)
                            Else
                                Dim p As PointF = gPath.PathPoints(0)
                                fPath.AddRectangle(New RectangleF(p.X, p.Y, 1.0F, 1.0F))
                            End If
    
                        Catch
                        End Try
                    End If
                End Using
            Next
    
            Return fPath
        End Function

    As you see we now get all outlines.


    Regards,

      Thorsten


    Thursday, August 10, 2017 1:39 AM
  • Hi

    Very helpful suggestions. I totally get the results for the green and purple color bottle. I get the binary image from what bella67 expected.

    But when it come to bright color (yellow, orange and sometime red), the results is quite not ok.

    I already post to Microsoft to allow me post the image. Hope that they will reply ASAP because i would like to show you the results. 

    Maybe because i neglect the smoothing process as well as filtering the noise cause the shape of the image undetected.

    Regards,

      Sufyan Safwan

    Thursday, August 10, 2017 5:00 AM
  • Hi

    Now i know without setting (kernal 7), the line for certain bottle color become blur. The line is appear but too blur for the chainFinder to recognize. Maybe i should add some smoothing process before go through Sobel and then my task is complete. If you could show some simple coding for this, that will be helpful. Thank a lot for your contribution. 

    Regards,

      Sufyan Safwan



    Thursday, August 10, 2017 5:47 AM
  • Hi

    Now i know without setting (kernal 7), the line for certain bottle color become blur. The line is appear but too blur for the chainFinder to recognize. Maybe i should add some smoothing process before go through Sobel and then my task is complete. If you could show some simple coding for this, that will be helpful. Thank a lot for your contribution. 

    Regards,

      Sufyan Safwan



    Hi,

    to reduce the noise without blurring edges too much, a median filter is quite good. "Normal" blurring the image with a gaussian kernel will blur the outline of the bottle too, there are some options though (eg. you could use a bilateral filter).

    So, I think a Median will work vest, maybe we can apply it with a smaller kernel (5, or maybe even 3 pixels wide).

    To apply the median with the code of the above project, just call it like:

    Dim pe As New ProgressEventArgs(bmp.Height, 0, 500)
    fip.MedianFilter(bmp, 5, False, 25, Me.BackgroundWorker1, pe)

    Regards,

      Thorsten

    • Proposed as answer by Sufyan Safwan Thursday, August 10, 2017 6:33 AM
    Thursday, August 10, 2017 6:28 AM
  • ... using a median with a 3px kernel does work, when you set the threshold of the ChainCode finder to 45 (instead of 30).

    like:

         Dim fList As List(Of ChainCode) = fbmp.GetOutline(bmpRes, 45, True,
                             0, True, 0, False) 'find only outer chain

    Regards,

      Thorsten


    Thursday, August 10, 2017 6:30 AM