Shape Detection
' translated in VB:NET from c#
' by Giuseppe Di Santo - Studio IT
Imports Emgu.CV.UI
Imports Emgu.CV
Imports Emgu.CV.Structure
Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Collections.Generic
Public Class ShapeDetection
Private Sub loadImageButton_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles loadImageButton.Click
Select Case Me.openFileDialog1.ShowDialog
Case DialogResult.OK, DialogResult.Yes
Me.fileNameTextBox.Text = Me.openFileDialog1.FileName
Exit Select
End Select
End Sub
Public Sub PerformShapeDetection()
If (Me.fileNameTextBox.Text <> String.Empty) Then
' Load the image from file and resize it for display
Dim img As Emgu.CV.Image(Of Emgu.CV.Structure.Bgr, Byte) = New Emgu.CV.Image(Of Emgu.CV.Structure.Bgr, Byte)(fileNameTextBox.Text).Resize(400, 400, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR, True)
' Convert the image to grayscale and filter out the noise
Dim gray As Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) = img.Convert(Of Gray, Byte).PyrDown.PyrUp()
Dim cannyThreshold As New Gray(180)
Dim cannyThresholdLinking As New Gray(120)
Dim circleAccumulatorThreshold As New Gray(500)
Dim circles As CircleF() = gray.HoughCircles(cannyThreshold, circleAccumulatorThreshold, 4.0, 15.0, 5, 0)(0) 'Get the circles from the first channel
Dim cannyEdges As Image(Of Gray, Byte) = gray.Canny(cannyThreshold, cannyThresholdLinking)
Dim lines As LineSegment2D() = cannyEdges.HoughLinesBinary(1, Math.PI / 45.0, 20, 30, 10)(0)
Dim triangleList As New List(Of Triangle2DF)()
Dim boxList As New List(Of MCvBox2D)() 'a box is a rotated rectangle
Using storage As New MemStorage()
'allocate storage for contour approximation
Dim contours As Contour(Of Point) = cannyEdges.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage)
While contours IsNot Nothing
Dim currentContour As Contour(Of Point) = contours.ApproxPoly(contours.Perimeter * 0.05, storage)
If currentContour.Area > 250 Then
'only consider contours with area greater than 250
If currentContour.Total = 3 Then
'The contour has 3 vertices, it is a triangle
Dim pts As Point() = currentContour.ToArray()
triangleList.Add(New Triangle2DF(pts(0), pts(1), pts(2)))
ElseIf currentContour.Total = 4 Then
'The contour has 4 vertices.
' "determine if all the angles in the contour are within [80, 100] degree"
Dim isRectangle As Boolean = True
Dim pts As Point() = currentContour.ToArray()
Dim edges As LineSegment2D() = PointCollection.PolyLine(pts, True)
For i As Integer = 0 To edges.Length - 1
Dim angle As Double = Math.Abs(edges((i + 1) Mod edges.Length).GetExteriorAngleDegree(edges(i)))
If angle < 80 OrElse angle > 100 Then
isRectangle = False
Exit For
End If
Next
If isRectangle Then
boxList.Add(currentContour.GetMinAreaRect())
End If
End If
End If
contours = contours.HNext
End While
End Using
originalImageBox.Image = img
Dim triangleRectangleImage As Image(Of Bgr, Byte) = img.CopyBlank
Dim triangle As Triangle2DF
For Each triangle In triangleList
triangleRectangleImage.Draw(triangle, New Bgr(Color.DarkBlue), 2)
Next
Dim box As MCvBox2D
For Each box In boxList
triangleRectangleImage.Draw(box, New Bgr(Color.DarkOrange), 2)
Next
triangleRectangleImageBox.Image = triangleRectangleImage
Dim circleImage As Image(Of Bgr, Byte) = img.CopyBlank
Dim circle As CircleF
For Each circle In circles
circleImage.Draw(circle, New Bgr(Color.Brown), 2)
Next
circleImageBox.Image = circleImage
Dim lineImage As Image(Of Bgr, Byte) = img.CopyBlank
Dim line As LineSegment2D
For Each line In lines
lineImage.Draw(line, New Bgr(Color.Green), 2)
Next
lineImageBox.Image = lineImage
End If
End Sub
Private Sub fileNameTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles fileNameTextBox.TextChanged
Me.PerformShapeDetection()
End Sub
End Class
<< back to index
|