使用EmguCV和Vb.net进行车辆计数和分类

时间:2017-12-08 01:18:27

标签: vb.net opencv

我是Stackoverflow的新手 我正在做第四阶段大学的项目,即基于EmguCV和Vb.net的车辆计数和分类,现在我已完成编码车计数,但我在分类方面存在问题,我不知道如何编码一个分类,如多少重型汽车和轻型汽车。

这是我的代码:

    'MultipleObjectTrackingVB.sln
'frmMain.vb
'
'form components
'
'tableLayoutPanel
'btnOpenFile
'lblChosenFile
'imageBox
'txtInfo
'openFileDialog
'
'Emgu CV 3.1.0

Option Explicit On      'require explicit declaration of variables, this is NOT Python !!
Option Strict On        'restrict implicit data type conversions to only widening conversions

Imports Emgu.CV                 '
Imports Emgu.CV.CvEnum          'usual Emgu Cv imports
Imports Emgu.CV.Structure       '
Imports Emgu.CV.UI              '
Imports Emgu.CV.Util

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''




Public Class Form1

    ' member variables ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Dim SCALAR_BLACK As New MCvScalar(0.0, 0.0, 0.0)
    Dim SCALAR_WHITE As New MCvScalar(255.0, 255.0, 255.0)
    Dim SCALAR_BLUE As New MCvScalar(255.0, 0.0, 0.0)
    Dim SCALAR_GREEN As New MCvScalar(0.0, 200.0, 0.0)
    Dim SCALAR_RED As New MCvScalar(0.0, 0.0, 255.0)

    Dim capVideo As Capture

    Dim blnFormClosing As Boolean = False

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        blnFormClosing = True
        CvInvoke.DestroyAllWindows()
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Private Sub btnOpenFile_Click(sender As Object, e As EventArgs) Handles btnOpenFile.Click
        Dim drChosenFile As DialogResult

        drChosenFile = openFileDialog.ShowDialog()                 'open file dialog

        If (drChosenFile <> DialogResult.OK Or openFileDialog.FileName = "") Then    'if user chose Cancel or filename is blank . . .
            lblChosenFile.Text = "file not chosen"              'show error message on label
            Return                                              'and exit function
        End If

        Try
            capVideo = New Capture(openFileDialog.FileName)        'attempt to open chosen video file
        Catch ex As Exception                                   'catch error if unsuccessful
            'show error via message box
            MessageBox.Show("unable to read video file, error: " + ex.Message)
            Return
        End Try

        lblChosenFile.Text = openFileDialog.FileName

        If (capVideo Is Nothing) Then
            txtInfo.AppendText("unable to read video file")
        End If

        If (capVideo.GetCaptureProperty(CapProp.FrameCount) < 2) Then               'check and make sure the video has at least 2 frames
            txtInfo.AppendText("error: video file must have at least two frames")
        End If

        trackBlobsAndUpdateGUI()
        End Sub
    Sub trackBlobsAndUpdateGUI()

        Dim imgFrame1 As Mat
        Dim imgFrame2 As Mat

        Dim blobs As New List(Of Blob)

        Dim crossingLine(2) As Point

        Dim carCount As Integer = 0

        imgFrame1 = capVideo.QueryFrame()
        imgFrame2 = capVideo.QueryFrame()

        Dim horizontalLinePosition As Integer = CInt(Math.Round(CDbl(imgFrame1.Rows()) * 0.3))

        crossingLine(0).X = 0
        crossingLine(0).Y = horizontalLinePosition

        crossingLine(1).X = imgFrame1.Cols() - 1
        crossingLine(1).Y = horizontalLinePosition

        Dim blnFirstFrame As Boolean = True

        While (blnFormClosing = False)

            Dim currentFrameBlobs As New List(Of Blob)

            Dim imgFrame1Copy As Mat = imgFrame1.Clone()
            Dim imgFrame2Copy As Mat = imgFrame2.Clone()

            Dim imgDifference As New Mat(imgFrame1.Size, DepthType.Cv8U, 1)
            Dim imgThresh As New Mat(imgFrame1.Size, DepthType.Cv8U, 1)

            CvInvoke.CvtColor(imgFrame1Copy, imgFrame1Copy, ColorConversion.Bgr2Gray)
            CvInvoke.CvtColor(imgFrame2Copy, imgFrame2Copy, ColorConversion.Bgr2Gray)

            CvInvoke.GaussianBlur(imgFrame1Copy, imgFrame1Copy, New Size(5, 5), 0)
            CvInvoke.GaussianBlur(imgFrame2Copy, imgFrame2Copy, New Size(5, 5), 0)

            CvInvoke.AbsDiff(imgFrame1Copy, imgFrame2Copy, imgDifference)

            CvInvoke.Threshold(imgDifference, imgThresh, 30, 255.0, ThresholdType.Binary)

            CvInvoke.Imshow("imgThresh", imgThresh)


            Dim structuringElement3x3 As Mat = CvInvoke.GetStructuringElement(ElementShape.Rectangle, New Size(3, 3), New Point(-1, -1))



                Dim structuringElement5x5 As Mat = CvInvoke.GetStructuringElement(ElementShape.Rectangle, New Size(5, 5), New Point(-1, -1))
            Dim structuringElement7x7 As Mat = CvInvoke.GetStructuringElement(ElementShape.Rectangle, New Size(7, 7), New Point(-1, -1))
            Dim structuringElement9x9 As Mat = CvInvoke.GetStructuringElement(ElementShape.Rectangle, New Size(9, 9), New Point(-1, -1))

            For i As Integer = 0 To 1
                CvInvoke.Dilate(imgThresh, imgThresh, structuringElement5x5, New Point(-1, -1), 1, BorderType.Default, New MCvScalar(0, 0, 0))
                CvInvoke.Dilate(imgThresh, imgThresh, structuringElement5x5, New Point(-1, -1), 1, BorderType.Default, New MCvScalar(0, 0, 0))
                CvInvoke.Erode(imgThresh, imgThresh, structuringElement5x5, New Point(-1, -1), 1, BorderType.Default, New MCvScalar(0, 0, 0))
            Next

            Dim imgThreshCopy As Mat = imgThresh.Clone()

            Dim contours As New VectorOfVectorOfPoint()

            CvInvoke.FindContours(imgThreshCopy, contours, Nothing, RetrType.External, ChainApproxMethod.ChainApproxSimple)

            'drawAndShowContours(imgThresh.Size(), contours, "imgContours")

            Dim convexHulls As New VectorOfVectorOfPoint(contours.Size())

            For i As Integer = 0 To contours.Size() - 1
                CvInvoke.ConvexHull(contours(i), convexHulls(i))
            Next

            'drawAndShowContours(imgThresh.Size(), convexHulls, "imgConvexHulls")

            For i As Integer = 0 To contours.Size() - 1

                Dim possibleBlob As New Blob(convexHulls(i))

                If (possibleBlob.intCurrentRectArea > 400 And
                    possibleBlob.dblCurrentAspectRatio > 0.2 And
                    possibleBlob.dblCurrentAspectRatio < 4.0 And
                    possibleBlob.currentBoundingRect.Width > 30 And
                    possibleBlob.currentBoundingRect.Height > 30 And
                    possibleBlob.dblCurrentDiagonalSize > 60.0 And
                    (CvInvoke.ContourArea(possibleBlob.currentContour) / possibleBlob.intCurrentRectArea) > 0.5) Then
                    currentFrameBlobs.Add(possibleBlob)
                End If

            Next

            'drawAndShowContours(imgThresh.Size(), currentFrameBlobs, "imgCurrentFrameBlobs")

            If (blnFirstFrame = True) Then
                For Each currentFrameBlob As Blob In currentFrameBlobs
                    blobs.Add(currentFrameBlob)
                Next
            Else
                matchCurrentFrameBlobsToExistingBlobs(blobs, currentFrameBlobs)
            End If

            'drawAndShowContours(imgThresh.Size(), blobs, "imgBlobs")

            imgFrame2Copy = imgFrame2.Clone()

            drawBlobInfoOnImage(blobs, imgFrame2Copy)

            Dim atLeastOneBlobCrossedTheLine = checkIfBlobsCrossedTheLine(blobs, horizontalLinePosition, carCount)

            If (atLeastOneBlobCrossedTheLine) Then
                CvInvoke.Line(imgFrame2Copy, crossingLine(0), crossingLine(1), SCALAR_GREEN, 2)
            Else
                CvInvoke.Line(imgFrame2Copy, crossingLine(0), crossingLine(1), SCALAR_RED, 2)
            End If

            drawCarCountOnImage(carCount, imgFrame2Copy)

            imageBox.Image = imgFrame2Copy

            'now we prepare for the next iteration

            currentFrameBlobs.Clear()

            imgFrame1 = imgFrame2.Clone()                   'move frame 1 up to where frame 2 is

            If (capVideo.GetCaptureProperty(CapProp.PosFrames) + 1 < capVideo.GetCaptureProperty(CapProp.FrameCount)) Then      'if there is at least one more frame
                imgFrame2 = capVideo.QueryFrame()               'get the next frame
            Else                                                'else if there is not at least one more frame
                txtInfo.AppendText("end of video")              'show end of video message
                Exit While                                      'and jump out of while loop
            End If

            blnFirstFrame = False

            Application.DoEvents()

        End While

    End Sub

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub matchCurrentFrameBlobsToExistingBlobs(ByRef existingBlobs As List(Of Blob), ByRef currentFrameBlobs As List(Of Blob))

        For Each existingBlob As Blob In existingBlobs
            existingBlob.blnCurrentMatchFoundOrNewBlob = False
            existingBlob.predictNextPosition()
        Next

        For Each currentFrameBlob As Blob In currentFrameBlobs

            Dim intIndexOfLeastDistance As Integer = 0
            Dim dblLeastDistance As Double = 1000000.0

            For i As Integer = 0 To existingBlobs.Count() - 1

                If (existingBlobs(i).blnStillBeingTracked = True) Then

                    Dim dblDistance As Double = distanceBetweenPoints(currentFrameBlob.centerPositions.Last(), existingBlobs(i).predictedNextPosition)

                    If (dblDistance < dblLeastDistance) Then
                        dblLeastDistance = dblDistance
                        intIndexOfLeastDistance = i
                    End If

                End If

            Next

            If (dblLeastDistance < currentFrameBlob.dblCurrentDiagonalSize * 0.5) Then
                addBlobToExistingBlobs(currentFrameBlob, existingBlobs, intIndexOfLeastDistance)
            Else
                addNewBlob(currentFrameBlob, existingBlobs)
            End If

        Next

        For Each existingBlob As Blob In existingBlobs

            If (existingBlob.blnCurrentMatchFoundOrNewBlob = False) Then
                existingBlob.intNumOfConsecutiveFramesWithoutAMatch = existingBlob.intNumOfConsecutiveFramesWithoutAMatch + 1
            End If

            If (existingBlob.intNumOfConsecutiveFramesWithoutAMatch >= 5) Then
                existingBlob.blnStillBeingTracked = False
            End If

        Next

    End Sub

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub addBlobToExistingBlobs(ByRef currentFrameBlob As Blob, ByRef existingBlobs As List(Of Blob), ByRef intIndex As Integer)

        existingBlobs(intIndex).currentContour = currentFrameBlob.currentContour
        existingBlobs(intIndex).currentBoundingRect = currentFrameBlob.currentBoundingRect

        existingBlobs(intIndex).centerPositions.Add(currentFrameBlob.centerPositions.Last())

        existingBlobs(intIndex).dblCurrentDiagonalSize = currentFrameBlob.dblCurrentDiagonalSize
        existingBlobs(intIndex).dblCurrentAspectRatio = currentFrameBlob.dblCurrentAspectRatio

        existingBlobs(intIndex).blnStillBeingTracked = True
        existingBlobs(intIndex).blnCurrentMatchFoundOrNewBlob = True

    End Sub

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub addNewBlob(ByRef currentFrameBlob As Blob, ByRef existingBlobs As List(Of Blob))

        currentFrameBlob.blnCurrentMatchFoundOrNewBlob = True

        existingBlobs.Add(currentFrameBlob)

    End Sub

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function distanceBetweenPoints(point1 As Point, point2 As Point) As Double

        Dim intX As Integer = Math.Abs(point1.X - point2.X)
        Dim intY As Integer = Math.Abs(point1.Y - point2.Y)

        Return Math.Sqrt((intX ^ 2) + (intY ^ 2))

    End Function

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub drawAndShowContours(imageSize As Size, contours As VectorOfVectorOfPoint, strImageName As String)

        Dim image As New Mat(imageSize, DepthType.Cv8U, 3)

        CvInvoke.DrawContours(image, contours, -1, SCALAR_WHITE, -1)

        CvInvoke.Imshow(strImageName, image)

    End Sub

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub drawAndShowContours(imageSize As Size, blobs As List(Of Blob), strImageName As String)

        Dim image As New Mat(imageSize, DepthType.Cv8U, 3)

        Dim contours As New VectorOfVectorOfPoint()

        For Each blob As Blob In blobs
            If (blob.blnStillBeingTracked = True) Then
                contours.Push(blob.currentContour)
            End If
        Next

        CvInvoke.DrawContours(image, contours, -1, SCALAR_WHITE, -1)

        CvInvoke.Imshow(strImageName, image)

    End Sub

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function checkIfBlobsCrossedTheLine(ByRef blobs As List(Of Blob), ByRef horizontalLinePosition As Integer, ByRef carCount As Integer) As Boolean

        Dim atLeastOneBlobCrossedTheLine As Boolean = False             'this will be the return value

        For Each blob As Blob In blobs

            If (blob.blnStillBeingTracked = True And blob.centerPositions.Count() >= 2) Then

                Dim prevFrameIndex As Integer = blob.centerPositions.Count() - 2
                Dim currFrameIndex As Integer = blob.centerPositions.Count() - 1

                If (blob.centerPositions(prevFrameIndex).Y > horizontalLinePosition And blob.centerPositions(currFrameIndex).Y <= horizontalLinePosition) Then
                    carCount = carCount + 1
                    atLeastOneBlobCrossedTheLine = True
                End If

            End If

        Next

        Return (atLeastOneBlobCrossedTheLine)

    End Function

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub drawBlobInfoOnImage(ByRef blobs As List(Of Blob), ByRef imgFrame2Copy As Mat)

        For i As Integer = 0 To blobs.Count - 1

            If (blobs(i).blnStillBeingTracked = True) Then

                CvInvoke.Rectangle(imgFrame2Copy, blobs(i).currentBoundingRect, SCALAR_RED, 2)

                Dim fontFace As FontFace = FontFace.HersheySimplex
                Dim dblFontScale As Double = blobs(i).dblCurrentDiagonalSize / 60.0
                Dim intFontThickness As Integer = CInt(Math.Round(dblFontScale * 1.0))

                CvInvoke.PutText(imgFrame2Copy, i.ToString(), blobs(i).centerPositions.Last(), fontFace, dblFontScale, SCALAR_GREEN, intFontThickness)

            End If

        Next

    End Sub

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub drawCarCountOnImage(ByRef carCount As Integer, ByRef imgFrame2Copy As Mat)

        Dim fontFace As FontFace = FontFace.HersheySimplex
        Dim dblFontScale As Double = CDbl(imgFrame2Copy.Rows() * imgFrame2Copy.Cols()) / 300000.0
        Dim intFontThickness As Integer = CInt(Math.Round(dblFontScale * 1.5))

        Dim textSize As Size = getTextSize(carCount.ToString(), fontFace, dblFontScale, intFontThickness)

        Dim bottomLeftTextPosition As New Point()

        bottomLeftTextPosition.X = imgFrame2Copy.Cols - 1 - CInt(CDbl(textSize.Width) * 1.3)
        bottomLeftTextPosition.Y = CInt(CDbl(textSize.Height) * 1.3)

        CvInvoke.PutText(imgFrame2Copy, carCount.ToString(), bottomLeftTextPosition, fontFace, dblFontScale, SCALAR_GREEN, intFontThickness)
    End Sub

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function getTextSize(strText As String, intFontFace As Integer, dblFontScale As Double, intFontThickness As Integer) As Size

        Dim textSize As New Size()              'this will be the return value

        Dim intNumChars As Integer = strText.Count()

        textSize.Width = 55 * intNumChars
        textSize.Height = 65

        Return (textSize)

    End Function

    Private Sub imageBox_Click(sender As Object, e As EventArgs) Handles imageBox.Click

    End Sub
End Class

0 个答案:

没有答案