Model : YOLOv8 Nano Version
Video input : https://drive.google.com/file/d/1sWPt_fqvK82YPGzzOqg-BkOyBNMsog1h/view?usp=sharing
Video output : https://drive.google.com/file/d/1SXSWvfkxsb4-xOuETEB4CNhJJ0gpr9aR/view?usp=sharing
Dataset for training : https://drive.google.com/drive/folders/1S083U2eWm-EKZyTFqF3EcCqRNYWtxQ2F?usp=sharing
Before running my code, don't forget to install ultralytics library with this syntax: pip install ultralytics
notes for code :
- run.ipynb = the code to detect the winner between 1vs1 beyblade.
- train.ipynb = the code to train yolov8.
- extract_pict.py = the code to extract images from video.
notes for output :
- winner.jpg : The image of the winner Beyblade.
- losser.jpg : The image of the losser Beyblade.
- kondisi terakhir.jpg = The last frame processed before the battle ended.
- battle_result.csv : CSV file that contains battle time (on seconds), location of the winner and loser on the battle, and the reason for the winner (is because the opponent is out of the arena (musuh keluar arena), stopped spinning (musuh berhenti berputar) or the owner the the beyblade (musuh diambil).
- best.pt : The yolov8 nano weight after training the model with our data.
I downloaded a YouTube video and extracted the image from the video from my code called extract_picture.py, In my code I defined a variable called frame_total to get 150 images, you can change it with another integer value.
After we get images from the video, we label them with labelImg repo that you can access via this link : https://github.com/HumanSignal/labelImg. from labeling we get the txt file that contains object classes and the position of the object we want to detect before we run the repo, don't forget to prepare classes.txt that contains the name of the object you want to detect.
After label the image, we need to split the dataset into 3 folders, train, val and test, every folder have another 2 folder too to save images and labels, so the structure will like this :
-- Train
---- Images
-------- img_1.jpg
---- Labels
-------- img_1.txt
-- Test
..........................
Before we train the model, we need to create the yaml file, the structure looks like this :
with :
- names : name of the object you want to detect (just copy and paste from classes.txt on step 2)
- nc : number of classes that you want to detect
- train, test, and val is the location of the folder train, test, and val from step 3.
For the code to train the model, you can see that at Train.ipynb, in this case, I train the model with 40 epochs, and here is the result for validation data :
we got a 0.6033 class loss which means is good.
To detect who the winner is between 1vs1 in Beyblade, you can see the code on run.ipynb
is to check if there are already have 2 beyblades in the arena of battle, if yes we can get the starting of the battle.
Is to define the area of the battle arena. we will use the coordinate to check on the is_out function, to call it you need to press D on your keyboard, click on 4 end points of the arena and then press F for save your arena coordinate.
To know if any Beyblade gets out from the battle arena or not, we detect it with the cv2.pointpolygontest function, so if the Xcenter and Ycenter of all Beyblade on the polygon (in this case is the arena we draw in create_region function) all beyblade will get winner status, but if one of them get out from polygon so the status will change into lose.
Is like checking "The RPM" of the Beyblade, so if the Beyblade stops spinning, the value on the movement variable will be below 1, so that's why I define min_movement = 1.
After I give a short explanation of each function in my code, so now I will explain the main code.
In the above code, we call the is_out function to get the status of 2 Beyblades, if the 2 Beyblades are still in the fight, we will get 2 winners in the kondisi dictionary, but if one of them is out we will get the 1 winner and 1 loser in kondisi dictionary, then we capture the winner and losses. the kondisi dictionary will be reset after checking because we will check the spin of Beyblade.
The logic of this code is the same as the is_out condition.