This is a full working example of real time ObjectDetection (in this case, cars) using cascadeClassifiers, getting the input from a recorded video file, making use of Videocapture. The example was written by @moster67 who kindly gave me permission to publish it here. I have only tuned a couple of things ( ) , but the example is very good for learning as it makes use of several OpenCV classes.
This project can be used as a starting point for any other type of object detection: as in real-world applications, many things can be tuned: cascade classifier files, image conditioning, applying logic, ....
It is an excellent example to start experimenting. Also the code is both compact and commented.
A bit of explanation of cascade classifiers
http://docs.opencv.org/3.2.0/dc/d88/tutorial_traincascade.html
Link to the video of the original @moster67 post
The code
As the example needs the cascade classifier file and the video, its size is too big to be uploaded.
You can find it in this shared link:
https://drive.google.com/drive/folders/0B-eBY3pamAunMUJFSXFHMFZSbGM?usp=sharing
This project can be used as a starting point for any other type of object detection: as in real-world applications, many things can be tuned: cascade classifier files, image conditioning, applying logic, ....
It is an excellent example to start experimenting. Also the code is both compact and commented.
A bit of explanation of cascade classifiers
http://docs.opencv.org/3.2.0/dc/d88/tutorial_traincascade.html
Link to the video of the original @moster67 post
The code
B4X:
#Region Project Attributes
#ApplicationLabel: Car Detection
#VersionCode: 1
#VersionName:
'SupportedOrientations possible values: unspecified, landscape or portrait.
#SupportedOrientations: landscape
#CanInstallToExternalStorage: False
#End Region
#Region Activity Attributes
#FullScreen: true
#IncludeTitle: false
#End Region
'** SAMPLE CODE TO DETECT CARS FROM A VIDEO FILE USING OPENCV FOR B4A **
'** VIDEO MUST BE IN MJPEG AND WITHIN AN AVI CONTAINER (VIDEO INCLUDED) **
'** OPENCV WRAPPER BY @JordicCP, SAMPLE CODE BY @Moster67 **
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
Dim ocl As OCVOpenCVLoader
Dim mVideo As OCVVideoCapture
Dim mFrame As OCVMat
Dim mUtils As OCVUtils
Dim mVio As OCVVideoio
Dim mCasc As OCVCascadeClassifier
Dim mImgProc As OCVImgproc
Dim carsrect As OCVMatOfRect
Dim graycarframe As OCVMat
Dim mMinSize, mMaxSize As OCVSize
Dim mRect() As OCVRect
Dim mScalar As OCVScalar
End Sub
Sub Globals
'These global variables will be redeclared each time the activity is created.
'These variables can only be accessed from this module.
Private ImV As ImageView
Dim mBmap As Bitmap
End Sub
Sub Activity_Create(FirstTime As Boolean)
'Do not forget to load the layout file created with the visual designer. For example:
' Activity.LoadLayout("1")
'copying video file from Dir.Assets to Dir.Internal.
'Probably not needed....
If File.Exists(File.DirAssets, "cars3.avi") Then
File.Copy(File.DirAssets, "cars3.avi",File.DirInternal,"cars3.avi")
File.Copy(File.DirAssets, "cars.xml",File.DirInternal,"cars.xml")
Else
Log("Couldn't find a file. I am now exiting app")
Activity.Finish
End If
mCasc.Initialize(File.DirInternal & "/cars.xml") 'loading a cascade classification file specific for cars.
ImV.Initialize("ImV")
ImV.Gravity = Gravity.FILL
Activity.AddView(ImV,0,0,100%x,100%y)
mVideo.Initialize(File.DirInternal & "/cars3.avi",mVio.CAP_ANY)
Log(mVideo.isOpened)
mFrame.Initialize 'mframe is a MatObject
mBmap.InitializeMutable(520,520)
ImV.Bitmap = mBmap
Do While mVideo.isOpened 'looping through video to process each frame and display them
If mVideo.read(mFrame) Then
If mFrame.rows <> mBmap.Height Or mFrame.cols <> mBmap.Width Then
mBmap.InitializeMutable(mFrame.cols,mFrame.rows)
ImV.Bitmap = mBmap
'Also rescale ImV layout so that it keeps the same aspect ratio as its content
'We are working in ladscape. Will center horizontally in screen
Dim aspectRatio As Float = mFrame.cols/mFrame.rows
Dim delta As Int = (Activity.Width- 100%Y*aspectRatio)/2
ImV.SetLayout( delta,0,100%Y*aspectRatio,100%Y)
End If
'image processing
carsrect.Initialize
mImgProc.cvtColor1(mFrame,graycarframe,mImgProc.COLOR_BGR2GRAY) 'convert the frame in gray scale
mImgProc.equalizeHist(graycarframe,graycarframe) 'equalize the frame histogram to improve the result
'detecting the cars
mMinSize.Initialize2(Array As Double(0.0,0.0))
mCasc.detectMultiScale(graycarframe, carsrect, 1.1, 1, 2, mMinSize, mMaxSize)
'each rectangle in carsrect is a car: draw them
mRect = carsrect.toArray
mScalar.Initialize3(0,255,0)
For i = 0 To carsrect.toArray.Length -1
mImgProc.rectangle1(mFrame,mRect(i).tl,mRect(i).br, mScalar,1)
Next
'convert mat(=our frame) to bitmap and redraw imageview
mUtils.matToBitmap1(mFrame,mBmap)
ImV.Invalidate
Sleep(0) 'needed to update the GUI. For versions of B4A earlier than 7.00, you can use DoEvents instead
Else
mVideo.release 'very important
End If
Loop
Log("VIDEO ENDED")
End Sub
Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
As the example needs the cascade classifier file and the video, its size is too big to be uploaded.
You can find it in this shared link:
https://drive.google.com/drive/folders/0B-eBY3pamAunMUJFSXFHMFZSbGM?usp=sharing
Last edited: