634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published
637 | by the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # train-yolov8-custom-dataset-step-by-step-guide
2 |
3 |
4 |
5 |
6 | Watch on YouTube: Train Yolo V8 object detector on your custom data | Step by step guide !
7 |
8 |
9 |
10 | ## dataset
11 |
12 | If you want to train yolov8 with the same dataset I use in the video, this is what you should do:
13 |
14 | 1. Download the [downloader.py](https://raw.githubusercontent.com/openimages/dataset/master/downloader.py) file.
15 | 2. Download the object detection dataset; [train](https://storage.googleapis.com/openimages/v6/oidv6-train-annotations-bbox.csv), [validation](https://storage.googleapis.com/openimages/v5/validation-annotations-bbox.csv) and [test](https://storage.googleapis.com/openimages/v5/test-annotations-bbox.csv).
16 | 2. Go to **prepare_data** directory.
17 | 4. Execute **create_image_list_file.py**.
18 | 5. Execute **downloader.py**.
19 |
20 | python downloader.py $IMAGE_LIST_FILE --download_folder=$DOWNLOAD_FOLDER
21 |
22 | 6. Execute **create_dataset_yolo_format.py**, changing **DATA_ALL_DIR** by **$DOWNLOAD_FOLDER**.
23 |
--------------------------------------------------------------------------------
/google_colab/TrainYolov8CustomDataset.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "provenance": []
7 | },
8 | "kernelspec": {
9 | "name": "python3",
10 | "display_name": "Python 3"
11 | },
12 | "language_info": {
13 | "name": "python"
14 | },
15 | "accelerator": "GPU",
16 | "gpuClass": "standard"
17 | },
18 | "cells": [
19 | {
20 | "cell_type": "code",
21 | "execution_count": null,
22 | "metadata": {
23 | "colab": {
24 | "base_uri": "https://localhost:8080/"
25 | },
26 | "id": "Dob4YRhec9Fm",
27 | "outputId": "a506784b-52e4-4f0f-a15e-ba591f7d5aff"
28 | },
29 | "outputs": [
30 | {
31 | "output_type": "stream",
32 | "name": "stdout",
33 | "text": [
34 | "Drive already mounted at /content/gdrive; to attempt to forcibly remount, call drive.mount(\"/content/gdrive\", force_remount=True).\n"
35 | ]
36 | }
37 | ],
38 | "source": [
39 | "from google.colab import drive\n",
40 | "\n",
41 | "drive.mount('/content/gdrive')"
42 | ]
43 | },
44 | {
45 | "cell_type": "code",
46 | "source": [
47 | "ROOT_DIR = '/content/gdrive/My Drive/ComputerVisionDeveloper/TrainYolov8CustomDataset'"
48 | ],
49 | "metadata": {
50 | "id": "xBHfolzSdnR5"
51 | },
52 | "execution_count": null,
53 | "outputs": []
54 | },
55 | {
56 | "cell_type": "code",
57 | "source": [
58 | "!pip install ultralytics"
59 | ],
60 | "metadata": {
61 | "id": "i8yghpa4eEjd"
62 | },
63 | "execution_count": null,
64 | "outputs": []
65 | },
66 | {
67 | "cell_type": "code",
68 | "source": [
69 | "import os\n",
70 | "\n",
71 | "from ultralytics import YOLO\n",
72 | "\n",
73 | "\n",
74 | "# Load a model\n",
75 | "model = YOLO(\"yolov8n.yaml\") # build a new model from scratch\n",
76 | "\n",
77 | "# Use the model\n",
78 | "results = model.train(data=os.path.join(ROOT_DIR, \"google_colab_config.yaml\"), epochs=1) # train the model\n"
79 | ],
80 | "metadata": {
81 | "id": "oyZJX6PVfE7J"
82 | },
83 | "execution_count": null,
84 | "outputs": []
85 | },
86 | {
87 | "cell_type": "code",
88 | "source": [
89 | "!scp -r /content/runs '/content/gdrive/My Drive/ComputerVisionDeveloper/TrainYolov8CustomDataset'"
90 | ],
91 | "metadata": {
92 | "id": "hbUDdF1Jk5rE"
93 | },
94 | "execution_count": null,
95 | "outputs": []
96 | }
97 | ]
98 | }
--------------------------------------------------------------------------------
/google_colab/google_colab_config.yaml:
--------------------------------------------------------------------------------
1 |
2 | path: '/content/gdrive/My Drive/ComputerVisionDeveloper/TrainYolov8CustomDataset/data' # dataset root dir
3 | train: images/train # train images (relative to 'path')
4 | val: images/train # val images (relative to 'path')
5 |
6 | # Classes
7 | names:
8 | 0: alpaca
9 |
--------------------------------------------------------------------------------
/local_env/config.yaml:
--------------------------------------------------------------------------------
1 |
2 | path: /home/phillip/Desktop/todays_tutorial/38_yolov8_train_custom_model/code/data # dataset root dir
3 | train: images/train # train images (relative to 'path')
4 | val: images/train # val images (relative to 'path')
5 |
6 | # Classes
7 | names:
8 | 0: alpaca
9 |
--------------------------------------------------------------------------------
/local_env/predict_video.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from ultralytics import YOLO
4 | import cv2
5 |
6 |
7 | VIDEOS_DIR = os.path.join('.', 'videos')
8 |
9 | video_path = os.path.join(VIDEOS_DIR, 'alpaca1.mp4')
10 | video_path_out = '{}_out.mp4'.format(video_path)
11 |
12 | cap = cv2.VideoCapture(video_path)
13 | ret, frame = cap.read()
14 | H, W, _ = frame.shape
15 | out = cv2.VideoWriter(video_path_out, cv2.VideoWriter_fourcc(*'MP4V'), int(cap.get(cv2.CAP_PROP_FPS)), (W, H))
16 |
17 | model_path = os.path.join('.', 'runs', 'detect', 'train', 'weights', 'last.pt')
18 |
19 | # Load a model
20 | model = YOLO(model_path) # load a custom model
21 |
22 | threshold = 0.5
23 |
24 | while ret:
25 |
26 | results = model(frame)[0]
27 |
28 | for result in results.boxes.data.tolist():
29 | x1, y1, x2, y2, score, class_id = result
30 |
31 | if score > threshold:
32 | cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 4)
33 | cv2.putText(frame, results.names[int(class_id)].upper(), (int(x1), int(y1 - 10)),
34 | cv2.FONT_HERSHEY_SIMPLEX, 1.3, (0, 255, 0), 3, cv2.LINE_AA)
35 |
36 | out.write(frame)
37 | ret, frame = cap.read()
38 |
39 | cap.release()
40 | out.release()
41 | cv2.destroyAllWindows()
42 |
--------------------------------------------------------------------------------
/local_env/requirements.txt:
--------------------------------------------------------------------------------
1 | ultralytics==8.0.23
2 |
--------------------------------------------------------------------------------
/local_env/train.py:
--------------------------------------------------------------------------------
1 | from ultralytics import YOLO
2 |
3 | # Load a model
4 | model = YOLO("yolov8n.yaml") # build a new model from scratch
5 |
6 | # Use the model
7 | results = model.train(data="config.yaml", epochs=1) # train the model
8 |
--------------------------------------------------------------------------------
/prepare_data/create_dataset_yolo_format.py:
--------------------------------------------------------------------------------
1 | import os
2 | import shutil
3 |
4 |
5 | DATA_ALL_DIR = os.path.join('.', 'data_all')
6 |
7 | DATA_OUT_DIR = os.path.join('.', 'data')
8 |
9 | for set_ in ['train', 'validation', 'test']:
10 | for dir_ in [os.path.join(DATA_OUT_DIR, set_),
11 | os.path.join(DATA_OUT_DIR, set_, 'imgs'),
12 | os.path.join(DATA_OUT_DIR, set_, 'anns')]:
13 | if os.path.exists(dir_):
14 | shutil.rmtree(dir_)
15 | os.mkdir(dir_)
16 |
17 | alpaca_id = '/m/0pcr'
18 |
19 | train_bboxes_filename = os.path.join('.', 'oidv6-train-annotations-bbox.csv')
20 | validation_bboxes_filename = os.path.join('.', 'validation-annotations-bbox.csv')
21 | test_bboxes_filename = os.path.join('.', 'test-annotations-bbox.csv')
22 |
23 |
24 | for j, filename in enumerate([train_bboxes_filename, validation_bboxes_filename, test_bboxes_filename]):
25 | set_ = ['train', 'validation', 'test'][j]
26 | print(filename)
27 | with open(filename, 'r') as f:
28 | line = f.readline()
29 | while len(line) != 0:
30 | id, _, class_name, _, x1, x2, y1, y2, _, _, _, _, _ = line.split(',')[:13]
31 | if class_name in [alpaca_id]:
32 | if not os.path.exists(os.path.join(DATA_OUT_DIR, set_, 'imgs', '{}.jpg'.format(id))):
33 | shutil.copy(os.path.join(DATA_ALL_DIR, '{}.jpg'.format(id)),
34 | os.path.join(DATA_OUT_DIR, set_, 'imgs', '{}.jpg'.format(id)))
35 | with open(os.path.join(DATA_OUT_DIR, set_, 'anns', '{}.txt'.format(id)), 'a') as f_ann:
36 | # class_id, xc, yx, w, h
37 | x1, x2, y1, y2 = [float(j) for j in [x1, x2, y1, y2]]
38 | xc = (x1 + x2) / 2
39 | yc = (y1 + y2) / 2
40 | w = x2 - x1
41 | h = y2 - y1
42 |
43 | f_ann.write('0 {} {} {} {}\n'.format(xc, yc, w, h))
44 | f_ann.close()
45 |
46 | line = f.readline()
47 |
--------------------------------------------------------------------------------
/prepare_data/create_image_list_file.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 |
4 | alpaca_id = '/m/0pcr'
5 |
6 | train_bboxes_filename = os.path.join('.', 'oidv6-train-annotations-bbox.csv')
7 | validation_bboxes_filename = os.path.join('.', 'validation-annotations-bbox.csv')
8 | test_bboxes_filename = os.path.join('.', 'test-annotations-bbox.csv')
9 |
10 | image_list_file_path = os.path.join('.', 'image_list_file')
11 |
12 | image_list_file_list = []
13 | for j, filename in enumerate([train_bboxes_filename, validation_bboxes_filename, test_bboxes_filename]):
14 | print(filename)
15 | with open(filename, 'r') as f:
16 | line = f.readline()
17 | while len(line) != 0:
18 | id, _, class_name, _, x1, x2, y1, y2, _, _, _, _, _ = line.split(',')[:13]
19 | if class_name in [alpaca_id] and id not in image_list_file_list:
20 | image_list_file_list.append(id)
21 | with open(image_list_file_path, 'a') as fw:
22 | fw.write('{}/{}\n'.format(['train', 'validation', 'test'][j], id))
23 | line = f.readline()
24 |
25 | f.close()
26 |
--------------------------------------------------------------------------------