Answered by:
How to detect shape of bottle?

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
- Edited by Thorsten Gudera Monday, July 3, 2017 6:12 AM
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
Tuesday, July 4, 2017 5:38 AM -
Hi Bella67,
Please refer to the following document:
Contour Analysis for Image Recognition 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
- Edited by Thorsten Gudera Saturday, July 8, 2017 9:39 PM
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
- Edited by Thorsten Gudera Tuesday, July 11, 2017 1:26 AM
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
- Edited by Thorsten Gudera Tuesday, July 11, 2017 6:46 AM
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
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
- Edited by Thorsten Gudera Friday, July 14, 2017 2:54 AM
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
- Edited by Thorsten Gudera Monday, August 7, 2017 11:05 PM
- Proposed as answer by Sufyan Safwan Tuesday, August 8, 2017 3:34 PM
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 ClassTuesday, 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 ClassHi,
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 ClassHi,
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.
- Edited by Sufyan Safwan Wednesday, August 9, 2017 1:29 AM
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
- Edited by Thorsten Gudera Wednesday, August 9, 2017 2:52 AM
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.
- Edited by Sufyan Safwan Wednesday, August 9, 2017 4:13 AM
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 SafwanWednesday, August 9, 2017 10:04 AM -
Hi
Thank you. I will wait
Regards,
Sufyan SafwanHi,
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 IfRegards,
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
- Edited by Thorsten Gudera Thursday, August 10, 2017 2:56 AM
- Proposed as answer by Sufyan Safwan Thursday, August 10, 2017 5:00 AM
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 SafwanThursday, 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
- Edited by Thorsten Gudera Thursday, August 10, 2017 6:32 AM
Thursday, August 10, 2017 6:30 AM