commit 0c1da5fe87f791543525402acf8476b0458ebc2a Author: AntonMu Date: Wed Jul 17 14:48:35 2019 -0700 Initial commit diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..c1a1dd1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,45 @@ +--- +name: Bug Report or Feature Request +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- +Before filing a report consider the following two questions: + +### Have you followed the instructions exactly (word by word)? + +### Have you checked the [troubleshooting](https://github.com/AntonMu/TrainYourOwnYOLO#troubleshooting) section? + +Once you are familiar with the code, you're welcome to modify it. Please only continue to file a bug report if you encounter an issue with the provided code and after having followed the instructions. + +If you have followed the instructions exactly, couldn't solve your problem with the provided troubleshooting tips and would still like to file a bug or make a feature requests please follow the steps below. + +1. It must be a bug, a feature request, or a significant problem with the documentation (for small docs fixes please send a PR instead). +2. **Every section** of the form below must be filled out. + +------------------------ + +### Readme + +- I have followed all Readme instructions carefully word by word: **Answer** + +### System information +- **What is the top-level directory of the model you are using**: +- **Have I written custom code (as opposed to using a stock example script provided in the repo)**: +- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: +- **TensorFlow version (use command below)**: +- **CUDA/cuDNN version**: +- **GPU model and memory**: +- **Exact command to reproduce**: + +You can obtain the TensorFlow version with + +`python -c "import tensorflow as tf; print(tf.GIT_VERSION, tf.VERSION)"` + +### Describe the problem +Describe the problem clearly here. Be sure to convey here why it's a bug or a feature request. + +### Source code / logs +Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached. Try to provide a reproducible test case that is the bare minimum necessary to generate the problem. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4176656 --- /dev/null +++ b/.gitignore @@ -0,0 +1,135 @@ +# Keras model files +*.h5 +*.weights + +# tf event files +events.out.tfevents.* + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# All hidden files and + +.vscode/ +.vscode + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/1_Image_Annotation/Convert_to_YOLO_format.py b/1_Image_Annotation/Convert_to_YOLO_format.py new file mode 100644 index 0000000..36ea155 --- /dev/null +++ b/1_Image_Annotation/Convert_to_YOLO_format.py @@ -0,0 +1,80 @@ +from PIL import Image +from os import path, makedirs +import os +import re +import pandas as pd +import sys +import argparse + + +def get_parent_dir(n=1): + """ returns the n-th parent dicrectory of the current + working directory """ + current_path = os.path.dirname(os.path.abspath(__file__)) + for k in range(n): + current_path = os.path.dirname(current_path) + return current_path + + +sys.path.append(os.path.join(get_parent_dir(1), "Utils")) +from Convert_Format import convert_vott_csv_to_yolo + +Data_Folder = os.path.join(get_parent_dir(1), "Data") +VoTT_Folder = os.path.join( + Data_Folder, "Source_Images", "Training_Images", "vott-csv-export" +) +VoTT_csv = os.path.join(VoTT_Folder, "Annotations-export.csv") +YOLO_filename = os.path.join(VoTT_Folder, "data_train.txt") + +model_folder = os.path.join(Data_Folder, "Model_Weights") +classes_filename = os.path.join(model_folder, "data_classes.txt") + +if __name__ == "__main__": + # surpress any inhereted default values + parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS) + """ + Command line options + """ + parser.add_argument( + "--VoTT_Folder", + type=str, + default=VoTT_Folder, + help="Absolute path to the exported files from the image tagging step with VoTT. Default is " + + VoTT_Folder, + ) + + parser.add_argument( + "--VoTT_csv", + type=str, + default=VoTT_csv, + help="Absolute path to the *.csv file exported from VoTT. Default is " + + VoTT_csv, + ) + parser.add_argument( + "--YOLO_filename", + type=str, + default=YOLO_filename, + help="Absolute path to the file where the annotations in YOLO format should be saved. Default is " + + YOLO_filename, + ) + + FLAGS = parser.parse_args() + + # Prepare the dataset for YOLO + multi_df = pd.read_csv(FLAGS.VoTT_csv) + labels = multi_df["label"].unique() + labeldict = dict(zip(labels, range(len(labels)))) + multi_df.drop_duplicates(subset=None, keep="first", inplace=True) + train_path = FLAGS.VoTT_Folder + convert_vott_csv_to_yolo( + multi_df, labeldict, path=train_path, target_name=FLAGS.YOLO_filename + ) + + # Make classes file + file = open(classes_filename, "w") + + # Sort Dict by Values + SortedLabelDict = sorted(labeldict.items(), key=lambda x: x[1]) + for elem in SortedLabelDict: + file.write(elem[0] + "\n") + file.close() diff --git a/1_Image_Annotation/README.md b/1_Image_Annotation/README.md new file mode 100644 index 0000000..bc7bfa0 --- /dev/null +++ b/1_Image_Annotation/README.md @@ -0,0 +1,51 @@ +# TrainYourOwnYOLO: Image Annotation + +## Dataset +To train the YOLO object detector on your own dataset, copy your training images to [`TrainYourOwnYOLO/Data/Source_Images/Training_Images`](/Data/Source_Images/Training_Images/). By default, this directory is pre-populated with 101 cat images. Feel free to delete all existing cat images to make your project cleaner. + +### Creating a Dataset from Scratch +If you do not already have an image dataset, consider using a Chrome extension such as [Fatkun Batch Downloader](https://chrome.google.com/webstore/detail/fatkun-batch-download-ima/nnjjahlikiabnchcpehcpkdeckfgnohf?hl=en) which lets you search and download images from Google Images. For instance, you can build a fidget spinner detector by searching for images with fidget spinners. + +## Annotation +To make our detector learn, we first need to feed it some good training examples. We use Microsoft's Visual Object Tagging Tool (VoTT) to manually label images in our training folder [`TrainYourOwnYOLO/Data/Source_Images/Training_Images`](/Data/Source_Images/Training_Images/). To achieve decent results annotate at least 100 images. For good results label at least 300 images and for great results label 1000+ images. + +### Download VoTT +Head to VoTT [releases](https://github.com/Microsoft/VoTT/releases) and download and install the version for your operating system. Under `Assets` select the package for your operating system: +- `vott-2.x.x-darwin.dmg` for Mac users, +- `vott-2.x.x-win32.exe` for Windows users and +- `vott-2.x.x-linux.snap` for Linux users. + +Installing `*.snap` files requires the snapd package manager which is available at [snapcraft.io](https://snapcraft.io/docs/installing-snapd). + +### Create a New Project + +Create a **New Project** and call it `Annotations`. It is highly recommended to use `Annotations` as your project name. If you like to use a different name for your project, you will have to modify the command line arguments of subsequent scripts accordingly. + +Under **Source Connection** choose **Add Connection** and put `Images` as **Display Name**. Under **Provider** choose **Local File System** and select [`TrainYourOwnYOLO/Data/Source Images/Training_Images`](/Data/Source_Images/Training_Images) and then **Save Connection**. For **Target Connection** choose the same folder as for **Source Connection**. Hit **Save Project** to finish project creation. + +![New Project](/1_Image_Annotation/Screen_Recordings/New_Project.gif) + +### Export Settings +Navigate to **Export Settings** in the sidebar and then change the **Provider** to `Comma Separated Values (CSV)`, then hit **Save Export Settings**. + +![New Project](/1_Image_Annotation/Screen_Recordings/Export_Settings.gif) + + +### Labeling +First create a new tag on the right and give it a relevant tag name. In our example, we choose `Cat_Face`. Then draw bounding boxes around your objects. You can use the number key **1** to quickly assign the first tag to the current bounding box. + +![New Project](/1_Image_Annotation/Screen_Recordings/Labeling.gif) + +### Export Results +Once you have labeled enough images press **CRTL+E** to export the project. You should now see a folder called [`vott-csv-export`](/Data/Source_Images/Training_Images/vott-csv-export) in the [`Training_Images`](/Data/Source_Images/Training_Images) directory. Within that folder, you should see a `*.csv` file called [`Annotations-export.csv`](/Data/Source_Images/Training_Images/vott-csv-export/Annotations-export.csv) which contains file names and bounding box coordinates. + +## Convert to YOLO Format +As a final step, convert the VoTT csv format to the YOLOv3 format. To do so, run the conversion script from within the [`TrainYourOwnYOLO/1_Image_Annotation`](/1_Image_Annotation/) folder: + +``` +python Convert_to_YOLO_format.py +``` +The script generates two output files: [`data_train.txt`](/Data/Source_Images/Training_Images/vott-csv-export/data_train.txt) located in the [`TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export`](/Data/Source_Images/Training_Images/vott-csv-export) folder and [`data_classes.txt`](/Data/Model_Weights/data_classes.txt) located in the [`TrainYourOwnYOLO/Data/Model_Weights`](/Data/Model_Weights/) folder. To list available command line options run `python Convert_to_YOLO_format.py -h`. + +### That's all for annotation! +Next, go to [`TrainYourOwnYOLO/2_Training`](/2_Training) to train your YOLOv3 detector. \ No newline at end of file diff --git a/1_Image_Annotation/Screen_Recordings/ColabUpload.png b/1_Image_Annotation/Screen_Recordings/ColabUpload.png new file mode 100644 index 0000000..2da3648 Binary files /dev/null and b/1_Image_Annotation/Screen_Recordings/ColabUpload.png differ diff --git a/1_Image_Annotation/Screen_Recordings/Export_Settings.gif b/1_Image_Annotation/Screen_Recordings/Export_Settings.gif new file mode 100644 index 0000000..ec79fd3 Binary files /dev/null and b/1_Image_Annotation/Screen_Recordings/Export_Settings.gif differ diff --git a/1_Image_Annotation/Screen_Recordings/Labeling.gif b/1_Image_Annotation/Screen_Recordings/Labeling.gif new file mode 100644 index 0000000..4706c46 Binary files /dev/null and b/1_Image_Annotation/Screen_Recordings/Labeling.gif differ diff --git a/1_Image_Annotation/Screen_Recordings/Medium.gif b/1_Image_Annotation/Screen_Recordings/Medium.gif new file mode 100644 index 0000000..613115a Binary files /dev/null and b/1_Image_Annotation/Screen_Recordings/Medium.gif differ diff --git a/1_Image_Annotation/Screen_Recordings/New_Project.gif b/1_Image_Annotation/Screen_Recordings/New_Project.gif new file mode 100644 index 0000000..9915a14 Binary files /dev/null and b/1_Image_Annotation/Screen_Recordings/New_Project.gif differ diff --git a/2_Training/AWS/README.md b/2_Training/AWS/README.md new file mode 100644 index 0000000..9b50fc2 --- /dev/null +++ b/2_Training/AWS/README.md @@ -0,0 +1,15 @@ +# TrainYourOwnYOLO: Training on AWS + +If your local machine does not have a GPU, training could take a very long time. To speed things up use an [AWS](https://aws.amazon.com/) GPU instance. + +## Spinning up a GPU Instance +To spin up a GPU instance, go to **EC2** and select **Launch Instance**. Then go to **Deep Learning AMI (Ubuntu) Version xx.x** and hit **Select**. Under instance type, select **p2.xlarge** as the Instance Type. Click through to Step 4 `Add Storage` and add at least 10 GB more than the default value. Proceed by hitting **Review and Launch**. + +![Deep_Learning_AMI](/2_Training/AWS/Screen_Recordings/AWS_Deep_Learning_AMI.gif) + +## Starting the Training +Connect to your instance and follow the same steps as on your local machine. Make sure that all your Source Images are in [`TrainYourOwnYOLO/Data/Source_Images`](/Data/Source_Images) and that both + - [`TrainYourOwnYOLO/Data/Source_Images/vott-csv-export/data_train.txt`](/Data/Source_Images/vott-csv-export/data_train.txt) and + - [`TrainYourOwnYOLO/Model_Weights/data_classes.txt`](/Data/Model_Weights/data_classes.txt) + +are up-to-date. \ No newline at end of file diff --git a/2_Training/AWS/Screen_Recordings/AWS_Deep_Learning_AMI.gif b/2_Training/AWS/Screen_Recordings/AWS_Deep_Learning_AMI.gif new file mode 100644 index 0000000..43aaf00 Binary files /dev/null and b/2_Training/AWS/Screen_Recordings/AWS_Deep_Learning_AMI.gif differ diff --git a/2_Training/Download_and_Convert_YOLO_weights.py b/2_Training/Download_and_Convert_YOLO_weights.py new file mode 100644 index 0000000..fbf7d64 --- /dev/null +++ b/2_Training/Download_and_Convert_YOLO_weights.py @@ -0,0 +1,46 @@ +import os +import subprocess +import time +import sys +import argparse +import requests +import progressbar + +FLAGS = None + +root_folder = os.path.dirname(os.path.abspath(__file__)) +download_folder = os.path.join(root_folder, "src", "keras_yolo3") + +if __name__ == "__main__": + # Delete all default flags + parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS) + """ + Command line options + """ + parser.add_argument( + "--download_folder", + type=str, + default=download_folder, + help="Folder to download weights to. Default is " + download_folder, + ) + + FLAGS = parser.parse_args() + + url = "https://pjreddie.com/media/files/yolov3.weights" + r = requests.get(url, stream=True) + + f = open(os.path.join(download_folder, "yolov3.weights"), "wb") + file_size = int(r.headers.get("content-length")) + chunk = 100 + num_bars = file_size // chunk + bar = progressbar.ProgressBar(maxval=num_bars).start() + i = 0 + for chunk in r.iter_content(chunk): + f.write(chunk) + bar.update(i) + i += 1 + f.close() + + call_string = "python convert.py yolov3.cfg yolov3.weights yolo.h5" + + subprocess.call(call_string, shell=True, cwd=download_folder) diff --git a/2_Training/README.md b/2_Training/README.md new file mode 100644 index 0000000..e7b5e89 --- /dev/null +++ b/2_Training/README.md @@ -0,0 +1,26 @@ +# TrainYourOwnYOLO: Training + +## Training +Using the training images located in [`TrainYourOwnYOLO/Data/Source_Images/Training_Images`](/Data/Source_Images/Training_Images) and the annotation file [`data_train.txt`](/Data/Source_Images/Training_Images/vott-csv-export) which we have created in the [previous step](/1_Image_Annotation/) we are now ready to train our YOLOv3 detector. + +## Download and Convert Pre-Trained Weights +Before getting started download the pre-trained YOLOv3 weights and convert them to the keras format. To run both steps run the download and conversion script from within the [`TrainYourOwnYOLO/2_Training`](/2_Training/) directory: + +``` +python Download_and_Convert_YOLO_weights.py +``` +To list available command line options run `python Download_and_Convert_YOLO_weights.py -h`. + +The weights are pre-trained on the [ImageNet 1000 dataset](http://image-net.org/challenges/LSVRC/2015/index) and thus work well for object detection tasks that are very similar to the types of images and objects in the ImageNet 1000 dataset. + +## Train YOLOv3 Detector +To start the training, run the training script from within the [`TrainYourOwnYOLO/2_Training`](/2_Training/) directory: +``` +python Train_YOLO.py +``` +Depending on your set-up, this process can take a few minutes to a few hours. The final weights are saved in [`TrainYourOwnYOLO/Data/Model_weights`](/Data/Model_weights). To list available command line options run `python Train_YOLO.py -h`. + +If training is too slow on your local machine, consider using cloud computing services such as AWS to speed things up. To learn more about training on AWS navigate to [`TrainYourOwnYOLO/2_Training/AWS`](/2_Training/AWS). + +### That's all for training! +Next, go to [`TrainYourOwnYOLO/3_Inference`](/3_Inference) to test your YOLO detector on new images! diff --git a/2_Training/Train_YOLO.py b/2_Training/Train_YOLO.py new file mode 100644 index 0000000..0bafc53 --- /dev/null +++ b/2_Training/Train_YOLO.py @@ -0,0 +1,283 @@ +""" +MODIFIED FROM keras-yolo3 PACKAGE, https://github.com/qqwweee/keras-yolo3 +Retrain the YOLO model for your own dataset. +""" + +import os +import sys +import argparse + + +def get_parent_dir(n=1): + """ returns the n-th parent dicrectory of the current + working directory """ + current_path = os.path.dirname(os.path.abspath(__file__)) + for k in range(n): + current_path = os.path.dirname(current_path) + return current_path + + +src_path = os.path.join(get_parent_dir(0), "src") +sys.path.append(src_path) + +utils_path = os.path.join(get_parent_dir(1), "Utils") +sys.path.append(utils_path) + +import numpy as np +import keras.backend as K +from keras.layers import Input, Lambda +from keras.models import Model +from keras.optimizers import Adam +from keras.callbacks import ( + TensorBoard, + ModelCheckpoint, + ReduceLROnPlateau, + EarlyStopping, +) +from keras_yolo3.yolo3.model import ( + preprocess_true_boxes, + yolo_body, + tiny_yolo_body, + yolo_loss, +) +from keras_yolo3.yolo3.utils import get_random_data +from PIL import Image +from time import time +import pickle + +from Train_Utils import ( + get_classes, + get_anchors, + create_model, + create_tiny_model, + data_generator, + data_generator_wrapper, + ChangeToOtherMachine, +) + + +keras_path = os.path.join(src_path, "keras_yolo3") +Data_Folder = os.path.join(get_parent_dir(1), "Data") +Image_Folder = os.path.join(Data_Folder, "Source_Images", "Training_Images") +VoTT_Folder = os.path.join(Image_Folder, "vott-csv-export") +YOLO_filename = os.path.join(VoTT_Folder, "data_train.txt") + +Model_Folder = os.path.join(Data_Folder, "Model_Weights") +YOLO_classname = os.path.join(Model_Folder, "data_classes.txt") + +log_dir = Model_Folder +anchors_path = os.path.join(keras_path, "model_data", "yolo_anchors.txt") +weights_path = os.path.join(keras_path, "yolo.h5") + +FLAGS = None + +if __name__ == "__main__": + # Delete all default flags + parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS) + """ + Command line options + """ + + parser.add_argument( + "--annotation_file", + type=str, + default=YOLO_filename, + help="Path to annotation file for Yolo. Default is " + YOLO_filename, + ) + parser.add_argument( + "--classes_file", + type=str, + default=YOLO_classname, + help="Path to YOLO classnames. Default is " + YOLO_classname, + ) + + parser.add_argument( + "--log_dir", + type=str, + default=log_dir, + help="Folder to save training logs and trained weights to. Default is " + + log_dir, + ) + + parser.add_argument( + "--anchors_path", + type=str, + default=anchors_path, + help="Path to YOLO anchors. Default is " + anchors_path, + ) + + parser.add_argument( + "--weights_path", + type=str, + default=weights_path, + help="Path to pre-trained YOLO weights. Default is " + weights_path, + ) + parser.add_argument( + "--val_split", + type=float, + default=0.1, + help="Percentage of training set to be used for validation. Default is 10%.", + ) + parser.add_argument( + "--is_tiny", + default=False, + action="store_true", + help="Use the tiny Yolo version for better performance and less accuracy. Default is False.", + ) + parser.add_argument( + "--random_seed", + type=float, + default=None, + help="Random seed value to make script deterministic. Default is 'None', i.e. non-deterministic.", + ) + parser.add_argument( + "--epochs", + type=float, + default=51, + help="Number of epochs for training last layers and number of epochs for fine-tuning layers. Default is 51.", + ) + + FLAGS = parser.parse_args() + + np.random.seed(FLAGS.random_seed) + + log_dir = FLAGS.log_dir + + class_names = get_classes(FLAGS.classes_file) + num_classes = len(class_names) + anchors = get_anchors(FLAGS.anchors_path) + weights_path = FLAGS.weights_path + + input_shape = (416, 416) # multiple of 32, height, width + epoch1, epoch2 = FLAGS.epochs, FLAGS.epochs + + is_tiny_version = len(anchors) == 6 # default setting + if FLAGS.is_tiny: + model = create_tiny_model( + input_shape, anchors, num_classes, freeze_body=2, weights_path=weights_path + ) + else: + model = create_model( + input_shape, anchors, num_classes, freeze_body=2, weights_path=weights_path + ) # make sure you know what you freeze + + log_dir_time = os.path.join(log_dir, "{}".format(int(time()))) + logging = TensorBoard(log_dir=log_dir_time) + checkpoint = ModelCheckpoint( + os.path.join(log_dir, "checkpoint.h5"), + monitor="val_loss", + save_weights_only=True, + save_best_only=True, + period=5, + ) + reduce_lr = ReduceLROnPlateau(monitor="val_loss", factor=0.1, patience=3, verbose=1) + early_stopping = EarlyStopping( + monitor="val_loss", min_delta=0, patience=10, verbose=1 + ) + + val_split = FLAGS.val_split + with open(FLAGS.annotation_file) as f: + lines = f.readlines() + + # This step makes sure that the path names correspond to the local machine + # This is important if annotation and training are done on different machines (e.g. training on AWS) + lines = ChangeToOtherMachine(lines, remote_machine="") + np.random.shuffle(lines) + num_val = int(len(lines) * val_split) + num_train = len(lines) - num_val + + # Train with frozen layers first, to get a stable loss. + # Adjust num epochs to your dataset. This step is enough to obtain a decent model. + if True: + model.compile( + optimizer=Adam(lr=1e-3), + loss={ + # use custom yolo_loss Lambda layer. + "yolo_loss": lambda y_true, y_pred: y_pred + }, + ) + + batch_size = 32 + print( + "Train on {} samples, val on {} samples, with batch size {}.".format( + num_train, num_val, batch_size + ) + ) + history = model.fit_generator( + data_generator_wrapper( + lines[:num_train], batch_size, input_shape, anchors, num_classes + ), + steps_per_epoch=max(1, num_train // batch_size), + validation_data=data_generator_wrapper( + lines[num_train:], batch_size, input_shape, anchors, num_classes + ), + validation_steps=max(1, num_val // batch_size), + epochs=epoch1, + initial_epoch=0, + callbacks=[logging, checkpoint], + ) + model.save_weights(os.path.join(log_dir, "trained_weights_stage_1.h5")) + + step1_train_loss = history.history["loss"] + + file = open(os.path.join(log_dir_time, "step1_loss.npy"), "w") + with open(os.path.join(log_dir_time, "step1_loss.npy"), "w") as f: + for item in step1_train_loss: + f.write("%s\n" % item) + file.close() + + step1_val_loss = np.array(history.history["val_loss"]) + + file = open(os.path.join(log_dir_time, "step1_val_loss.npy"), "w") + with open(os.path.join(log_dir_time, "step1_val_loss.npy"), "w") as f: + for item in step1_val_loss: + f.write("%s\n" % item) + file.close() + + # Unfreeze and continue training, to fine-tune. + # Train longer if the result is unsatisfactory. + if True: + for i in range(len(model.layers)): + model.layers[i].trainable = True + model.compile( + optimizer=Adam(lr=1e-4), loss={"yolo_loss": lambda y_true, y_pred: y_pred} + ) # recompile to apply the change + print("Unfreeze all layers.") + + batch_size = ( + 4 # note that more GPU memory is required after unfreezing the body + ) + print( + "Train on {} samples, val on {} samples, with batch size {}.".format( + num_train, num_val, batch_size + ) + ) + history = model.fit_generator( + data_generator_wrapper( + lines[:num_train], batch_size, input_shape, anchors, num_classes + ), + steps_per_epoch=max(1, num_train // batch_size), + validation_data=data_generator_wrapper( + lines[num_train:], batch_size, input_shape, anchors, num_classes + ), + validation_steps=max(1, num_val // batch_size), + epochs=epoch1 + epoch2, + initial_epoch=epoch1, + callbacks=[logging, checkpoint, reduce_lr, early_stopping], + ) + model.save_weights(os.path.join(log_dir, "trained_weights_final.h5")) + step2_train_loss = history.history["loss"] + + file = open(os.path.join(log_dir_time, "step2_loss.npy"), "w") + with open(os.path.join(log_dir_time, "step2_loss.npy"), "w") as f: + for item in step2_train_loss: + f.write("%s\n" % item) + file.close() + + step2_val_loss = np.array(history.history["val_loss"]) + + file = open(os.path.join(log_dir_time, "step2_val_loss.npy"), "w") + with open(os.path.join(log_dir_time, "step2_val_loss.npy"), "w") as f: + for item in step2_val_loss: + f.write("%s\n" % item) + file.close() diff --git a/2_Training/src/README.md b/2_Training/src/README.md new file mode 100644 index 0000000..fb44a4b --- /dev/null +++ b/2_Training/src/README.md @@ -0,0 +1,3 @@ +# Keras YOLOv3 + +This part of the repo is a fork of [**qqwweee/keras-yolo3**](https://github.com/qqwweee/keras-yolo3): **A Keras implementation of YOLOv3 (Tensorflow backend)**. diff --git a/2_Training/src/keras_yolo3/LICENSE b/2_Training/src/keras_yolo3/LICENSE new file mode 100644 index 0000000..767465b --- /dev/null +++ b/2_Training/src/keras_yolo3/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 qqwweee + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/2_Training/src/keras_yolo3/README.md b/2_Training/src/keras_yolo3/README.md new file mode 100644 index 0000000..46f1238 --- /dev/null +++ b/2_Training/src/keras_yolo3/README.md @@ -0,0 +1,99 @@ +# keras-yolo3 + +[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) + +## Introduction + +A Keras implementation of YOLOv3 (Tensorflow backend) inspired by [allanzelener/YAD2K](https://github.com/allanzelener/YAD2K). + + +--- + +## Quick Start + +1. Download YOLOv3 weights from [YOLO website](http://pjreddie.com/darknet/yolo/). +2. Convert the Darknet YOLO model to a Keras model. +3. Run YOLO detection. + +``` +wget https://pjreddie.com/media/files/yolov3.weights +python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5 +python yolo_video.py [OPTIONS...] --image, for image detection mode, OR +python yolo_video.py [video_path] [output_path (optional)] +``` + +For Tiny YOLOv3, just do in a similar way, just specify model path and anchor path with `--model model_file` and `--anchors anchor_file`. + +### Usage +Use --help to see usage of yolo_video.py: +``` +usage: yolo_video.py [-h] [--model MODEL] [--anchors ANCHORS] + [--classes CLASSES] [--gpu_num GPU_NUM] [--image] + [--input] [--output] + +positional arguments: + --input Video input path + --output Video output path + +optional arguments: + -h, --help show this help message and exit + --model MODEL path to model weight file, default model_data/yolo.h5 + --anchors ANCHORS path to anchor definitions, default + model_data/yolo_anchors.txt + --classes CLASSES path to class definitions, default + model_data/coco_classes.txt + --gpu_num GPU_NUM Number of GPU to use, default 1 + --image Image detection mode, will ignore all positional arguments +``` +--- + +4. MultiGPU usage: use `--gpu_num N` to use N GPUs. It is passed to the [Keras multi_gpu_model()](https://keras.io/utils/#multi_gpu_model). + +## Training + +1. Generate your own annotation file and class names file. + One row for one image; + Row format: `image_file_path box1 box2 ... boxN`; + Box format: `x_min,y_min,x_max,y_max,class_id` (no space). + For VOC dataset, try `python voc_annotation.py` + Here is an example: + ``` + path/to/img1.jpg 50,100,150,200,0 30,50,200,120,3 + path/to/img2.jpg 120,300,250,600,2 + ... + ``` + +2. Make sure you have run `python convert.py -w yolov3.cfg yolov3.weights model_data/yolo_weights.h5` + The file model_data/yolo_weights.h5 is used to load pretrained weights. + +3. Modify train.py and start training. + `python train.py` + Use your trained weights or checkpoint weights with command line option `--model model_file` when using yolo_video.py + Remember to modify class path or anchor path, with `--classes class_file` and `--anchors anchor_file`. + +If you want to use original pretrained weights for YOLOv3: + 1. `wget https://pjreddie.com/media/files/darknet53.conv.74` + 2. rename it as darknet53.weights + 3. `python convert.py -w darknet53.cfg darknet53.weights model_data/darknet53_weights.h5` + 4. use model_data/darknet53_weights.h5 in train.py + +--- + +## Some issues to know + +1. The test environment is + - Python 3.5.2 + - Keras 2.1.5 + - tensorflow 1.6.0 + +2. Default anchors are used. If you use your own anchors, probably some changes are needed. + +3. The inference result is not totally the same as Darknet but the difference is small. + +4. The speed is slower than Darknet. Replacing PIL with opencv may help a little. + +5. Always load pretrained weights and freeze layers in the first stage of training. Or try Darknet training. It's OK if there is a mismatch warning. + +6. The training strategy is for reference only. Adjust it according to your dataset and your goal. And add further strategy if needed. + +7. For speeding up the training process with frozen layers train_bottleneck.py can be used. It will compute the bottleneck features of the frozen model first and then only trains the last layers. This makes training on CPU possible in a reasonable time. See [this](https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html) for more information on bottleneck features. diff --git a/2_Training/src/keras_yolo3/coco_annotation.py b/2_Training/src/keras_yolo3/coco_annotation.py new file mode 100644 index 0000000..fc2eb14 --- /dev/null +++ b/2_Training/src/keras_yolo3/coco_annotation.py @@ -0,0 +1,49 @@ +import json +from collections import defaultdict + +name_box_id = defaultdict(list) +id_name = dict() +f = open("mscoco2017/annotations/instances_train2017.json", encoding="utf-8") +data = json.load(f) + +annotations = data["annotations"] +for ant in annotations: + id = ant["image_id"] + name = "mscoco2017/train2017/%012d.jpg" % id + cat = ant["category_id"] + + if cat >= 1 and cat <= 11: + cat = cat - 1 + elif cat >= 13 and cat <= 25: + cat = cat - 2 + elif cat >= 27 and cat <= 28: + cat = cat - 3 + elif cat >= 31 and cat <= 44: + cat = cat - 5 + elif cat >= 46 and cat <= 65: + cat = cat - 6 + elif cat == 67: + cat = cat - 7 + elif cat == 70: + cat = cat - 9 + elif cat >= 72 and cat <= 82: + cat = cat - 10 + elif cat >= 84 and cat <= 90: + cat = cat - 11 + + name_box_id[name].append([ant["bbox"], cat]) + +f = open("train.txt", "w") +for key in name_box_id.keys(): + f.write(key) + box_infos = name_box_id[key] + for info in box_infos: + x_min = int(info[0][0]) + y_min = int(info[0][1]) + x_max = x_min + int(info[0][2]) + y_max = y_min + int(info[0][3]) + + box_info = " %d,%d,%d,%d,%d" % (x_min, y_min, x_max, y_max, int(info[1])) + f.write(box_info) + f.write("\n") +f.close() diff --git a/2_Training/src/keras_yolo3/convert.py b/2_Training/src/keras_yolo3/convert.py new file mode 100644 index 0000000..3ea693c --- /dev/null +++ b/2_Training/src/keras_yolo3/convert.py @@ -0,0 +1,286 @@ +#! /usr/bin/env python +""" +Reads Darknet config and weights and creates Keras model with TF backend. + +""" + +import argparse +import configparser +import io +import os +from collections import defaultdict + +import numpy as np +from keras import backend as K +from keras.layers import ( + Conv2D, + Input, + ZeroPadding2D, + Add, + UpSampling2D, + MaxPooling2D, + Concatenate, +) +from keras.layers.advanced_activations import LeakyReLU +from keras.layers.normalization import BatchNormalization +from keras.models import Model +from keras.regularizers import l2 +from keras.utils.vis_utils import plot_model as plot + + +parser = argparse.ArgumentParser(description="Darknet To Keras Converter.") +parser.add_argument("config_path", help="Path to Darknet cfg file.") +parser.add_argument("weights_path", help="Path to Darknet weights file.") +parser.add_argument("output_path", help="Path to output Keras model file.") +parser.add_argument( + "-p", + "--plot_model", + help="Plot generated Keras model and save as image.", + action="store_true", +) +parser.add_argument( + "-w", + "--weights_only", + help="Save as Keras weights file instead of model file.", + action="store_true", +) + + +def unique_config_sections(config_file): + """Convert all config sections to have unique names. + + Adds unique suffixes to config sections for compability with configparser. + """ + section_counters = defaultdict(int) + output_stream = io.StringIO() + with open(config_file) as fin: + for line in fin: + if line.startswith("["): + section = line.strip().strip("[]") + _section = section + "_" + str(section_counters[section]) + section_counters[section] += 1 + line = line.replace(section, _section) + output_stream.write(line) + output_stream.seek(0) + return output_stream + + +# %% +def _main(args): + config_path = os.path.expanduser(args.config_path) + weights_path = os.path.expanduser(args.weights_path) + assert config_path.endswith(".cfg"), "{} is not a .cfg file".format(config_path) + assert weights_path.endswith(".weights"), "{} is not a .weights file".format( + weights_path + ) + + output_path = os.path.expanduser(args.output_path) + assert output_path.endswith(".h5"), "output path {} is not a .h5 file".format( + output_path + ) + output_root = os.path.splitext(output_path)[0] + + # Load weights and config. + print("Loading weights.") + weights_file = open(weights_path, "rb") + major, minor, revision = np.ndarray( + shape=(3,), dtype="int32", buffer=weights_file.read(12) + ) + if (major * 10 + minor) >= 2 and major < 1000 and minor < 1000: + seen = np.ndarray(shape=(1,), dtype="int64", buffer=weights_file.read(8)) + else: + seen = np.ndarray(shape=(1,), dtype="int32", buffer=weights_file.read(4)) + print("Weights Header: ", major, minor, revision, seen) + + print("Parsing Darknet config.") + unique_config_file = unique_config_sections(config_path) + cfg_parser = configparser.ConfigParser() + cfg_parser.read_file(unique_config_file) + + print("Creating Keras model.") + input_layer = Input(shape=(None, None, 3)) + prev_layer = input_layer + all_layers = [] + + weight_decay = ( + float(cfg_parser["net_0"]["decay"]) + if "net_0" in cfg_parser.sections() + else 5e-4 + ) + count = 0 + out_index = [] + for section in cfg_parser.sections(): + print("Parsing section {}".format(section)) + if section.startswith("convolutional"): + filters = int(cfg_parser[section]["filters"]) + size = int(cfg_parser[section]["size"]) + stride = int(cfg_parser[section]["stride"]) + pad = int(cfg_parser[section]["pad"]) + activation = cfg_parser[section]["activation"] + batch_normalize = "batch_normalize" in cfg_parser[section] + + padding = "same" if pad == 1 and stride == 1 else "valid" + + # Setting weights. + # Darknet serializes convolutional weights as: + # [bias/beta, [gamma, mean, variance], conv_weights] + prev_layer_shape = K.int_shape(prev_layer) + + weights_shape = (size, size, prev_layer_shape[-1], filters) + darknet_w_shape = (filters, weights_shape[2], size, size) + weights_size = np.product(weights_shape) + + print( + "conv2d", "bn" if batch_normalize else " ", activation, weights_shape + ) + + conv_bias = np.ndarray( + shape=(filters,), dtype="float32", buffer=weights_file.read(filters * 4) + ) + count += filters + + if batch_normalize: + bn_weights = np.ndarray( + shape=(3, filters), + dtype="float32", + buffer=weights_file.read(filters * 12), + ) + count += 3 * filters + + bn_weight_list = [ + bn_weights[0], # scale gamma + conv_bias, # shift beta + bn_weights[1], # running mean + bn_weights[2], # running var + ] + + conv_weights = np.ndarray( + shape=darknet_w_shape, + dtype="float32", + buffer=weights_file.read(weights_size * 4), + ) + count += weights_size + + # DarkNet conv_weights are serialized Caffe-style: + # (out_dim, in_dim, height, width) + # We would like to set these to Tensorflow order: + # (height, width, in_dim, out_dim) + conv_weights = np.transpose(conv_weights, [2, 3, 1, 0]) + conv_weights = ( + [conv_weights] if batch_normalize else [conv_weights, conv_bias] + ) + + # Handle activation. + act_fn = None + if activation == "leaky": + pass # Add advanced activation later. + elif activation != "linear": + raise ValueError( + "Unknown activation function `{}` in section {}".format( + activation, section + ) + ) + + # Create Conv2D layer + if stride > 1: + # Darknet uses left and top padding instead of 'same' mode + prev_layer = ZeroPadding2D(((1, 0), (1, 0)))(prev_layer) + conv_layer = ( + Conv2D( + filters, + (size, size), + strides=(stride, stride), + kernel_regularizer=l2(weight_decay), + use_bias=not batch_normalize, + weights=conv_weights, + activation=act_fn, + padding=padding, + ) + )(prev_layer) + + if batch_normalize: + conv_layer = (BatchNormalization(weights=bn_weight_list))(conv_layer) + prev_layer = conv_layer + + if activation == "linear": + all_layers.append(prev_layer) + elif activation == "leaky": + act_layer = LeakyReLU(alpha=0.1)(prev_layer) + prev_layer = act_layer + all_layers.append(act_layer) + + elif section.startswith("route"): + ids = [int(i) for i in cfg_parser[section]["layers"].split(",")] + layers = [all_layers[i] for i in ids] + if len(layers) > 1: + print("Concatenating route layers:", layers) + concatenate_layer = Concatenate()(layers) + all_layers.append(concatenate_layer) + prev_layer = concatenate_layer + else: + skip_layer = layers[0] # only one layer to route + all_layers.append(skip_layer) + prev_layer = skip_layer + + elif section.startswith("maxpool"): + size = int(cfg_parser[section]["size"]) + stride = int(cfg_parser[section]["stride"]) + all_layers.append( + MaxPooling2D( + pool_size=(size, size), strides=(stride, stride), padding="same" + )(prev_layer) + ) + prev_layer = all_layers[-1] + + elif section.startswith("shortcut"): + index = int(cfg_parser[section]["from"]) + activation = cfg_parser[section]["activation"] + assert activation == "linear", "Only linear activation supported." + all_layers.append(Add()([all_layers[index], prev_layer])) + prev_layer = all_layers[-1] + + elif section.startswith("upsample"): + stride = int(cfg_parser[section]["stride"]) + assert stride == 2, "Only stride=2 supported." + all_layers.append(UpSampling2D(stride)(prev_layer)) + prev_layer = all_layers[-1] + + elif section.startswith("yolo"): + out_index.append(len(all_layers) - 1) + all_layers.append(None) + prev_layer = all_layers[-1] + + elif section.startswith("net"): + pass + + else: + raise ValueError("Unsupported section header type: {}".format(section)) + + # Create and save model. + if len(out_index) == 0: + out_index.append(len(all_layers) - 1) + model = Model(inputs=input_layer, outputs=[all_layers[i] for i in out_index]) + print(model.summary()) + if args.weights_only: + model.save_weights("{}".format(output_path)) + print("Saved Keras weights to {}".format(output_path)) + else: + model.save("{}".format(output_path)) + print("Saved Keras model to {}".format(output_path)) + + # Check to see if all weights have been read. + remaining_weights = len(weights_file.read()) / 4 + weights_file.close() + print( + "Read {} of {} from Darknet weights.".format(count, count + remaining_weights) + ) + if remaining_weights > 0: + print("Warning: {} unused weights".format(remaining_weights)) + + if args.plot_model: + plot(model, to_file="{}.png".format(output_root), show_shapes=True) + print("Saved model plot to {}.png".format(output_root)) + + +if __name__ == "__main__": + _main(parser.parse_args()) diff --git a/2_Training/src/keras_yolo3/darknet53.cfg b/2_Training/src/keras_yolo3/darknet53.cfg new file mode 100644 index 0000000..bdf3ef3 --- /dev/null +++ b/2_Training/src/keras_yolo3/darknet53.cfg @@ -0,0 +1,548 @@ +[net] +# Testing +batch=1 +subdivisions=1 +# Training +# batch=64 +# subdivisions=16 +width=640 +height=640 +channels=3 +momentum=0.9 +decay=0.0005 +angle=0 +saturation = 1.5 +exposure = 1.5 +hue=.1 + +learning_rate=0.001 +burn_in=1000 +max_batches = 500200 +policy=steps +steps=400000,450000 +scales=.1,.1 + +[convolutional] +batch_normalize=1 +filters=32 +size=3 +stride=1 +pad=1 +activation=leaky + +# Downsample + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=32 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=64 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=64 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + diff --git a/2_Training/src/keras_yolo3/font/FiraMono-Medium.otf b/2_Training/src/keras_yolo3/font/FiraMono-Medium.otf new file mode 100644 index 0000000..4f208e9 Binary files /dev/null and b/2_Training/src/keras_yolo3/font/FiraMono-Medium.otf differ diff --git a/2_Training/src/keras_yolo3/font/SIL Open Font License.txt b/2_Training/src/keras_yolo3/font/SIL Open Font License.txt new file mode 100644 index 0000000..285151a --- /dev/null +++ b/2_Training/src/keras_yolo3/font/SIL Open Font License.txt @@ -0,0 +1,45 @@ +Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ with Reserved Font Name Fira Mono. + +Copyright (c) 2014, Telefonica S.A. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. + +5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/2_Training/src/keras_yolo3/kmeans.py b/2_Training/src/keras_yolo3/kmeans.py new file mode 100644 index 0000000..6eb218b --- /dev/null +++ b/2_Training/src/keras_yolo3/kmeans.py @@ -0,0 +1,99 @@ +import numpy as np + + +class YOLO_Kmeans: + def __init__(self, cluster_number, filename): + self.cluster_number = cluster_number + self.filename = "2012_train.txt" + + def iou(self, boxes, clusters): # 1 box -> k clusters + n = boxes.shape[0] + k = self.cluster_number + + box_area = boxes[:, 0] * boxes[:, 1] + box_area = box_area.repeat(k) + box_area = np.reshape(box_area, (n, k)) + + cluster_area = clusters[:, 0] * clusters[:, 1] + cluster_area = np.tile(cluster_area, [1, n]) + cluster_area = np.reshape(cluster_area, (n, k)) + + box_w_matrix = np.reshape(boxes[:, 0].repeat(k), (n, k)) + cluster_w_matrix = np.reshape(np.tile(clusters[:, 0], (1, n)), (n, k)) + min_w_matrix = np.minimum(cluster_w_matrix, box_w_matrix) + + box_h_matrix = np.reshape(boxes[:, 1].repeat(k), (n, k)) + cluster_h_matrix = np.reshape(np.tile(clusters[:, 1], (1, n)), (n, k)) + min_h_matrix = np.minimum(cluster_h_matrix, box_h_matrix) + inter_area = np.multiply(min_w_matrix, min_h_matrix) + + result = inter_area / (box_area + cluster_area - inter_area) + return result + + def avg_iou(self, boxes, clusters): + accuracy = np.mean([np.max(self.iou(boxes, clusters), axis=1)]) + return accuracy + + def kmeans(self, boxes, k, dist=np.median): + box_number = boxes.shape[0] + distances = np.empty((box_number, k)) + last_nearest = np.zeros((box_number,)) + np.random.seed() + clusters = boxes[ + np.random.choice(box_number, k, replace=False) + ] # init k clusters + while True: + + distances = 1 - self.iou(boxes, clusters) + + current_nearest = np.argmin(distances, axis=1) + if (last_nearest == current_nearest).all(): + break # clusters won't change + for cluster in range(k): + clusters[cluster] = dist( # update clusters + boxes[current_nearest == cluster], axis=0 + ) + + last_nearest = current_nearest + + return clusters + + def result2txt(self, data): + f = open("yolo_anchors.txt", "w") + row = np.shape(data)[0] + for i in range(row): + if i == 0: + x_y = "%d,%d" % (data[i][0], data[i][1]) + else: + x_y = ", %d,%d" % (data[i][0], data[i][1]) + f.write(x_y) + f.close() + + def txt2boxes(self): + f = open(self.filename, "r") + dataSet = [] + for line in f: + infos = line.split(" ") + length = len(infos) + for i in range(1, length): + width = int(infos[i].split(",")[2]) - int(infos[i].split(",")[0]) + height = int(infos[i].split(",")[3]) - int(infos[i].split(",")[1]) + dataSet.append([width, height]) + result = np.array(dataSet) + f.close() + return result + + def txt2clusters(self): + all_boxes = self.txt2boxes() + result = self.kmeans(all_boxes, k=self.cluster_number) + result = result[np.lexsort(result.T[0, None])] + self.result2txt(result) + print("K anchors:\n {}".format(result)) + print("Accuracy: {:.2f}%".format(self.avg_iou(all_boxes, result) * 100)) + + +if __name__ == "__main__": + cluster_number = 9 + filename = "2012_train.txt" + kmeans = YOLO_Kmeans(cluster_number, filename) + kmeans.txt2clusters() diff --git a/2_Training/src/keras_yolo3/model_data/coco_classes.txt b/2_Training/src/keras_yolo3/model_data/coco_classes.txt new file mode 100644 index 0000000..ca76c80 --- /dev/null +++ b/2_Training/src/keras_yolo3/model_data/coco_classes.txt @@ -0,0 +1,80 @@ +person +bicycle +car +motorbike +aeroplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +sofa +pottedplant +bed +diningtable +toilet +tvmonitor +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush diff --git a/2_Training/src/keras_yolo3/model_data/voc_classes.txt b/2_Training/src/keras_yolo3/model_data/voc_classes.txt new file mode 100644 index 0000000..8420ab3 --- /dev/null +++ b/2_Training/src/keras_yolo3/model_data/voc_classes.txt @@ -0,0 +1,20 @@ +aeroplane +bicycle +bird +boat +bottle +bus +car +cat +chair +cow +diningtable +dog +horse +motorbike +person +pottedplant +sheep +sofa +train +tvmonitor diff --git a/2_Training/src/keras_yolo3/model_data/yolo-tiny_anchors.txt b/2_Training/src/keras_yolo3/model_data/yolo-tiny_anchors.txt new file mode 100644 index 0000000..0125ee4 --- /dev/null +++ b/2_Training/src/keras_yolo3/model_data/yolo-tiny_anchors.txt @@ -0,0 +1 @@ +10,14, 23,27, 37,58, 81,82, 135,169, 344,319 diff --git a/2_Training/src/keras_yolo3/model_data/yolo_anchors.txt b/2_Training/src/keras_yolo3/model_data/yolo_anchors.txt new file mode 100644 index 0000000..9cdfb96 --- /dev/null +++ b/2_Training/src/keras_yolo3/model_data/yolo_anchors.txt @@ -0,0 +1 @@ +10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 diff --git a/2_Training/src/keras_yolo3/train.py b/2_Training/src/keras_yolo3/train.py new file mode 100644 index 0000000..a3c1ba6 --- /dev/null +++ b/2_Training/src/keras_yolo3/train.py @@ -0,0 +1,316 @@ +""" +Retrain the YOLO model for your own dataset. +""" + +import numpy as np +import keras.backend as K +from keras.layers import Input, Lambda +from keras.models import Model +from keras.optimizers import Adam +from keras.callbacks import ( + TensorBoard, + ModelCheckpoint, + ReduceLROnPlateau, + EarlyStopping, +) + +from yolo3.model import preprocess_true_boxes, yolo_body, tiny_yolo_body, yolo_loss +from yolo3.utils import get_random_data + + +def _main(): + annotation_path = "data_train.txt" + log_dir = "logs/003/" + classes_path = "data_classes.txt" + # anchors_path = 'model_data/yolo-tiny_anchors.txt' + anchors_path = "model_data/yolo_anchors.txt" + class_names = get_classes(classes_path) + num_classes = len(class_names) + anchors = get_anchors(anchors_path) + + input_shape = (416, 416) # multiple of 32, hw + epoch1, epoch2 = 40, 40 + + is_tiny_version = len(anchors) == 6 # default setting + if is_tiny_version: + model = create_tiny_model( + input_shape, + anchors, + num_classes, + freeze_body=2, + weights_path="model_data/yolo-tiny.h5", + ) + else: + model = create_model( + input_shape, + anchors, + num_classes, + freeze_body=2, + weights_path="model_data/yolo.h5", + ) # make sure you know what you freeze + + logging = TensorBoard(log_dir=log_dir) + # checkpoint = ModelCheckpoint(log_dir + 'ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5', + # monitor='val_loss', save_weights_only=True, save_best_only=True, period=3) + checkpoint = ModelCheckpoint( + log_dir + "checkpoint.h5", + monitor="val_loss", + save_weights_only=True, + save_best_only=True, + period=5, + ) + reduce_lr = ReduceLROnPlateau(monitor="val_loss", factor=0.1, patience=3, verbose=1) + early_stopping = EarlyStopping( + monitor="val_loss", min_delta=0, patience=10, verbose=1 + ) + + val_split = 0.1 + with open(annotation_path) as f: + lines = f.readlines() + np.random.seed(10101) + np.random.shuffle(lines) + np.random.seed(None) + num_val = int(len(lines) * val_split) + num_train = len(lines) - num_val + + # Train with frozen layers first, to get a stable loss. + # Adjust num epochs to your dataset. This step is enough to obtain a not bad model. + if True: + model.compile( + optimizer=Adam(lr=1e-3), + loss={ + # use custom yolo_loss Lambda layer. + "yolo_loss": lambda y_true, y_pred: y_pred + }, + ) + + batch_size = 32 + print( + "Train on {} samples, val on {} samples, with batch size {}.".format( + num_train, num_val, batch_size + ) + ) + model.fit_generator( + data_generator_wrapper( + lines[:num_train], batch_size, input_shape, anchors, num_classes + ), + steps_per_epoch=max(1, num_train // batch_size), + validation_data=data_generator_wrapper( + lines[num_train:], batch_size, input_shape, anchors, num_classes + ), + validation_steps=max(1, num_val // batch_size), + epochs=epoch1, + initial_epoch=0, + callbacks=[logging, checkpoint], + ) + model.save_weights(log_dir + "trained_weights_stage_1.h5") + + # Unfreeze and continue training, to fine-tune. + # Train longer if the result is not good. + if True: + for i in range(len(model.layers)): + model.layers[i].trainable = True + model.compile( + optimizer=Adam(lr=1e-4), loss={"yolo_loss": lambda y_true, y_pred: y_pred} + ) # recompile to apply the change + print("Unfreeze all of the layers.") + + batch_size = ( + 16 # note that more GPU memory is required after unfreezing the body + ) + print( + "Train on {} samples, val on {} samples, with batch size {}.".format( + num_train, num_val, batch_size + ) + ) + model.fit_generator( + data_generator_wrapper( + lines[:num_train], batch_size, input_shape, anchors, num_classes + ), + steps_per_epoch=max(1, num_train // batch_size), + validation_data=data_generator_wrapper( + lines[num_train:], batch_size, input_shape, anchors, num_classes + ), + validation_steps=max(1, num_val // batch_size), + epochs=epoch1 + epoch2, + initial_epoch=epoch1, + callbacks=[logging, checkpoint, reduce_lr, early_stopping], + ) + model.save_weights(log_dir + "trained_weights_final.h5") + + # Further training if needed. + + +def get_classes(classes_path): + """loads the classes""" + with open(classes_path) as f: + class_names = f.readlines() + class_names = [c.strip() for c in class_names] + return class_names + + +def get_anchors(anchors_path): + """loads the anchors from a file""" + with open(anchors_path) as f: + anchors = f.readline() + anchors = [float(x) for x in anchors.split(",")] + return np.array(anchors).reshape(-1, 2) + + +def create_model( + input_shape, + anchors, + num_classes, + load_pretrained=True, + freeze_body=2, + weights_path="model_data/yolo_weights.h5", +): + """create the training model""" + K.clear_session() # get a new session + image_input = Input(shape=(None, None, 3)) + h, w = input_shape + num_anchors = len(anchors) + + y_true = [ + Input( + shape=( + h // {0: 32, 1: 16, 2: 8}[l], + w // {0: 32, 1: 16, 2: 8}[l], + num_anchors // 3, + num_classes + 5, + ) + ) + for l in range(3) + ] + + model_body = yolo_body(image_input, num_anchors // 3, num_classes) + print( + "Create YOLOv3 model with {} anchors and {} classes.".format( + num_anchors, num_classes + ) + ) + + if load_pretrained: + model_body.load_weights(weights_path, by_name=True, skip_mismatch=True) + print("Load weights {}.".format(weights_path)) + if freeze_body in [1, 2]: + # Freeze darknet53 body or freeze all but 3 output layers. + num = (185, len(model_body.layers) - 3)[freeze_body - 1] + for i in range(num): + model_body.layers[i].trainable = False + print( + "Freeze the first {} layers of total {} layers.".format( + num, len(model_body.layers) + ) + ) + + model_loss = Lambda( + yolo_loss, + output_shape=(1,), + name="yolo_loss", + arguments={ + "anchors": anchors, + "num_classes": num_classes, + "ignore_thresh": 0.5, + }, + )([*model_body.output, *y_true]) + model = Model([model_body.input, *y_true], model_loss) + + return model + + +def create_tiny_model( + input_shape, + anchors, + num_classes, + load_pretrained=True, + freeze_body=2, + weights_path="model_data/tiny_yolo_weights.h5", +): + """create the training model, for Tiny YOLOv3""" + K.clear_session() # get a new session + image_input = Input(shape=(None, None, 3)) + h, w = input_shape + num_anchors = len(anchors) + + y_true = [ + Input( + shape=( + h // {0: 32, 1: 16}[l], + w // {0: 32, 1: 16}[l], + num_anchors // 2, + num_classes + 5, + ) + ) + for l in range(2) + ] + + model_body = tiny_yolo_body(image_input, num_anchors // 2, num_classes) + print( + "Create Tiny YOLOv3 model with {} anchors and {} classes.".format( + num_anchors, num_classes + ) + ) + + if load_pretrained: + model_body.load_weights(weights_path, by_name=True, skip_mismatch=True) + print("Load weights {}.".format(weights_path)) + if freeze_body in [1, 2]: + # Freeze the darknet body or freeze all but 2 output layers. + num = (20, len(model_body.layers) - 2)[freeze_body - 1] + for i in range(num): + model_body.layers[i].trainable = False + print( + "Freeze the first {} layers of total {} layers.".format( + num, len(model_body.layers) + ) + ) + + model_loss = Lambda( + yolo_loss, + output_shape=(1,), + name="yolo_loss", + arguments={ + "anchors": anchors, + "num_classes": num_classes, + "ignore_thresh": 0.7, + }, + )([*model_body.output, *y_true]) + model = Model([model_body.input, *y_true], model_loss) + + return model + + +def data_generator(annotation_lines, batch_size, input_shape, anchors, num_classes): + """data generator for fit_generator""" + n = len(annotation_lines) + i = 0 + while True: + image_data = [] + box_data = [] + for b in range(batch_size): + if i == 0: + np.random.shuffle(annotation_lines) + image, box = get_random_data(annotation_lines[i], input_shape, random=True) + image_data.append(image) + box_data.append(box) + i = (i + 1) % n + image_data = np.array(image_data) + box_data = np.array(box_data) + y_true = preprocess_true_boxes(box_data, input_shape, anchors, num_classes) + yield [image_data, *y_true], np.zeros(batch_size) + + +def data_generator_wrapper( + annotation_lines, batch_size, input_shape, anchors, num_classes +): + n = len(annotation_lines) + if n == 0 or batch_size <= 0: + return None + return data_generator( + annotation_lines, batch_size, input_shape, anchors, num_classes + ) + + +if __name__ == "__main__": + _main() diff --git a/2_Training/src/keras_yolo3/train_bottleneck.py b/2_Training/src/keras_yolo3/train_bottleneck.py new file mode 100644 index 0000000..abbf1a8 --- /dev/null +++ b/2_Training/src/keras_yolo3/train_bottleneck.py @@ -0,0 +1,404 @@ +""" +Retrain the YOLO model for your own dataset. +""" +import os +import numpy as np +import keras.backend as K +from keras.layers import Input, Lambda +from keras.models import Model +from keras.optimizers import Adam +from keras.callbacks import ( + TensorBoard, + ModelCheckpoint, + ReduceLROnPlateau, + EarlyStopping, +) + +from yolo3.model import preprocess_true_boxes, yolo_body, tiny_yolo_body, yolo_loss +from yolo3.utils import get_random_data + + +def _main(): + annotation_path = "train.txt" + log_dir = "logs/000/" + classes_path = "model_data/coco_classes.txt" + anchors_path = "model_data/yolo_anchors.txt" + class_names = get_classes(classes_path) + num_classes = len(class_names) + anchors = get_anchors(anchors_path) + + input_shape = (640, 640) # multiple of 32, hw + + model, bottleneck_model, last_layer_model = create_model( + input_shape, + anchors, + num_classes, + freeze_body=2, + weights_path="model_data/yolo_weights.h5", + ) # make sure you know what you freeze + + logging = TensorBoard(log_dir=log_dir) + checkpoint = ModelCheckpoint( + log_dir + "ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5", + monitor="val_loss", + save_weights_only=True, + save_best_only=True, + period=3, + ) + reduce_lr = ReduceLROnPlateau(monitor="val_loss", factor=0.1, patience=3, verbose=1) + early_stopping = EarlyStopping( + monitor="val_loss", min_delta=0, patience=10, verbose=1 + ) + + val_split = 0.1 + with open(annotation_path) as f: + lines = f.readlines() + np.random.seed(10101) + np.random.shuffle(lines) + np.random.seed(None) + num_val = int(len(lines) * val_split) + num_train = len(lines) - num_val + + # Train with frozen layers first, to get a stable loss. + # Adjust num epochs to your dataset. This step is enough to obtain a not bad model. + if True: + # perform bottleneck training + if not os.path.isfile("bottlenecks.npz"): + print("calculating bottlenecks") + batch_size = 8 + bottlenecks = bottleneck_model.predict_generator( + data_generator_wrapper( + lines, + batch_size, + input_shape, + anchors, + num_classes, + random=False, + verbose=True, + ), + steps=(len(lines) // batch_size) + 1, + max_queue_size=1, + ) + np.savez( + "bottlenecks.npz", + bot0=bottlenecks[0], + bot1=bottlenecks[1], + bot2=bottlenecks[2], + ) + + # load bottleneck features from file + dict_bot = np.load("bottlenecks.npz") + bottlenecks_train = [ + dict_bot["bot0"][:num_train], + dict_bot["bot1"][:num_train], + dict_bot["bot2"][:num_train], + ] + bottlenecks_val = [ + dict_bot["bot0"][num_train:], + dict_bot["bot1"][num_train:], + dict_bot["bot2"][num_train:], + ] + + # train last layers with fixed bottleneck features + batch_size = 8 + print("Training last layers with bottleneck features") + print( + "with {} samples, val on {} samples and batch size {}.".format( + num_train, num_val, batch_size + ) + ) + last_layer_model.compile( + optimizer="adam", loss={"yolo_loss": lambda y_true, y_pred: y_pred} + ) + last_layer_model.fit_generator( + bottleneck_generator( + lines[:num_train], + batch_size, + input_shape, + anchors, + num_classes, + bottlenecks_train, + ), + steps_per_epoch=max(1, num_train // batch_size), + validation_data=bottleneck_generator( + lines[num_train:], + batch_size, + input_shape, + anchors, + num_classes, + bottlenecks_val, + ), + validation_steps=max(1, num_val // batch_size), + epochs=30, + initial_epoch=0, + max_queue_size=1, + ) + model.save_weights(log_dir + "trained_weights_stage_0.h5") + + # train last layers with random augmented data + model.compile( + optimizer=Adam(lr=1e-3), + loss={ + # use custom yolo_loss Lambda layer. + "yolo_loss": lambda y_true, y_pred: y_pred + }, + ) + batch_size = 16 + print( + "Train on {} samples, val on {} samples, with batch size {}.".format( + num_train, num_val, batch_size + ) + ) + model.fit_generator( + data_generator_wrapper( + lines[:num_train], batch_size, input_shape, anchors, num_classes + ), + steps_per_epoch=max(1, num_train // batch_size), + validation_data=data_generator_wrapper( + lines[num_train:], batch_size, input_shape, anchors, num_classes + ), + validation_steps=max(1, num_val // batch_size), + epochs=50, + initial_epoch=0, + callbacks=[logging, checkpoint], + ) + model.save_weights(log_dir + "trained_weights_stage_1.h5") + + # Unfreeze and continue training, to fine-tune. + # Train longer if the result is not good. + if True: + for i in range(len(model.layers)): + model.layers[i].trainable = True + model.compile( + optimizer=Adam(lr=1e-4), loss={"yolo_loss": lambda y_true, y_pred: y_pred} + ) # recompile to apply the change + print("Unfreeze all of the layers.") + + batch_size = ( + 4 # note that more GPU memory is required after unfreezing the body + ) + print( + "Train on {} samples, val on {} samples, with batch size {}.".format( + num_train, num_val, batch_size + ) + ) + model.fit_generator( + data_generator_wrapper( + lines[:num_train], batch_size, input_shape, anchors, num_classes + ), + steps_per_epoch=max(1, num_train // batch_size), + validation_data=data_generator_wrapper( + lines[num_train:], batch_size, input_shape, anchors, num_classes + ), + validation_steps=max(1, num_val // batch_size), + epochs=100, + initial_epoch=50, + callbacks=[logging, checkpoint, reduce_lr, early_stopping], + ) + model.save_weights(log_dir + "trained_weights_final.h5") + + # Further training if needed. + + +def get_classes(classes_path): + """loads the classes""" + with open(classes_path) as f: + class_names = f.readlines() + class_names = [c.strip() for c in class_names] + return class_names + + +def get_anchors(anchors_path): + """loads the anchors from a file""" + with open(anchors_path) as f: + anchors = f.readline() + anchors = [float(x) for x in anchors.split(",")] + return np.array(anchors).reshape(-1, 2) + + +def create_model( + input_shape, + anchors, + num_classes, + load_pretrained=True, + freeze_body=2, + weights_path="model_data/yolo_weights.h5", +): + """create the training model""" + K.clear_session() # get a new session + image_input = Input(shape=(None, None, 3)) + h, w = input_shape + num_anchors = len(anchors) + + y_true = [ + Input( + shape=( + h // {0: 32, 1: 16, 2: 8}[l], + w // {0: 32, 1: 16, 2: 8}[l], + num_anchors // 3, + num_classes + 5, + ) + ) + for l in range(3) + ] + + model_body = yolo_body(image_input, num_anchors // 3, num_classes) + print( + "Create YOLOv3 model with {} anchors and {} classes.".format( + num_anchors, num_classes + ) + ) + + if load_pretrained: + model_body.load_weights(weights_path, by_name=True, skip_mismatch=True) + print("Load weights {}.".format(weights_path)) + if freeze_body in [1, 2]: + # Freeze darknet53 body or freeze all but 3 output layers. + num = (185, len(model_body.layers) - 3)[freeze_body - 1] + for i in range(num): + model_body.layers[i].trainable = False + print( + "Freeze the first {} layers of total {} layers.".format( + num, len(model_body.layers) + ) + ) + + # get output of second last layers and create bottleneck model of it + out1 = model_body.layers[246].output + out2 = model_body.layers[247].output + out3 = model_body.layers[248].output + bottleneck_model = Model([model_body.input, *y_true], [out1, out2, out3]) + + # create last layer model of last layers from yolo model + in0 = Input(shape=bottleneck_model.output[0].shape[1:].as_list()) + in1 = Input(shape=bottleneck_model.output[1].shape[1:].as_list()) + in2 = Input(shape=bottleneck_model.output[2].shape[1:].as_list()) + last_out0 = model_body.layers[249](in0) + last_out1 = model_body.layers[250](in1) + last_out2 = model_body.layers[251](in2) + model_last = Model( + inputs=[in0, in1, in2], outputs=[last_out0, last_out1, last_out2] + ) + model_loss_last = Lambda( + yolo_loss, + output_shape=(1,), + name="yolo_loss", + arguments={ + "anchors": anchors, + "num_classes": num_classes, + "ignore_thresh": 0.5, + }, + )([*model_last.output, *y_true]) + last_layer_model = Model([in0, in1, in2, *y_true], model_loss_last) + + model_loss = Lambda( + yolo_loss, + output_shape=(1,), + name="yolo_loss", + arguments={ + "anchors": anchors, + "num_classes": num_classes, + "ignore_thresh": 0.5, + }, + )([*model_body.output, *y_true]) + model = Model([model_body.input, *y_true], model_loss) + + return model, bottleneck_model, last_layer_model + + +def data_generator( + annotation_lines, + batch_size, + input_shape, + anchors, + num_classes, + random=True, + verbose=False, +): + """data generator for fit_generator""" + n = len(annotation_lines) + i = 0 + while True: + image_data = [] + box_data = [] + for b in range(batch_size): + if i == 0 and random: + np.random.shuffle(annotation_lines) + image, box = get_random_data( + annotation_lines[i], input_shape, random=random + ) + image_data.append(image) + box_data.append(box) + i = (i + 1) % n + image_data = np.array(image_data) + if verbose: + print("Progress: ", i, "/", n) + box_data = np.array(box_data) + y_true = preprocess_true_boxes(box_data, input_shape, anchors, num_classes) + yield [image_data, *y_true], np.zeros(batch_size) + + +def data_generator_wrapper( + annotation_lines, + batch_size, + input_shape, + anchors, + num_classes, + random=True, + verbose=False, +): + n = len(annotation_lines) + if n == 0 or batch_size <= 0: + return None + return data_generator( + annotation_lines, batch_size, input_shape, anchors, num_classes, random, verbose + ) + + +def bottleneck_generator( + annotation_lines, batch_size, input_shape, anchors, num_classes, bottlenecks +): + n = len(annotation_lines) + i = 0 + while True: + box_data = [] + b0 = np.zeros( + ( + batch_size, + bottlenecks[0].shape[1], + bottlenecks[0].shape[2], + bottlenecks[0].shape[3], + ) + ) + b1 = np.zeros( + ( + batch_size, + bottlenecks[1].shape[1], + bottlenecks[1].shape[2], + bottlenecks[1].shape[3], + ) + ) + b2 = np.zeros( + ( + batch_size, + bottlenecks[2].shape[1], + bottlenecks[2].shape[2], + bottlenecks[2].shape[3], + ) + ) + for b in range(batch_size): + _, box = get_random_data( + annotation_lines[i], input_shape, random=False, proc_img=False + ) + box_data.append(box) + b0[b] = bottlenecks[0][i] + b1[b] = bottlenecks[1][i] + b2[b] = bottlenecks[2][i] + i = (i + 1) % n + box_data = np.array(box_data) + y_true = preprocess_true_boxes(box_data, input_shape, anchors, num_classes) + yield [b0, b1, b2, *y_true], np.zeros(batch_size) + + +if __name__ == "__main__": + _main() diff --git a/2_Training/src/keras_yolo3/voc_annotation.py b/2_Training/src/keras_yolo3/voc_annotation.py new file mode 100644 index 0000000..d917662 --- /dev/null +++ b/2_Training/src/keras_yolo3/voc_annotation.py @@ -0,0 +1,65 @@ +import xml.etree.ElementTree as ET +from os import getcwd + +sets = [("2007", "train"), ("2007", "val"), ("2007", "test")] + +classes = [ + "aeroplane", + "bicycle", + "bird", + "boat", + "bottle", + "bus", + "car", + "cat", + "chair", + "cow", + "diningtable", + "dog", + "horse", + "motorbike", + "person", + "pottedplant", + "sheep", + "sofa", + "train", + "tvmonitor", +] + + +def convert_annotation(year, image_id, list_file): + in_file = open("VOCdevkit/VOC%s/Annotations/%s.xml" % (year, image_id)) + tree = ET.parse(in_file) + root = tree.getroot() + + for obj in root.iter("object"): + difficult = obj.find("difficult").text + cls = obj.find("name").text + if cls not in classes or int(difficult) == 1: + continue + cls_id = classes.index(cls) + xmlbox = obj.find("bndbox") + b = ( + int(xmlbox.find("xmin").text), + int(xmlbox.find("ymin").text), + int(xmlbox.find("xmax").text), + int(xmlbox.find("ymax").text), + ) + list_file.write(" " + ",".join([str(a) for a in b]) + "," + str(cls_id)) + + +wd = getcwd() + +for year, image_set in sets: + image_ids = ( + open("VOCdevkit/VOC%s/ImageSets/Main/%s.txt" % (year, image_set)) + .read() + .strip() + .split() + ) + list_file = open("%s_%s.txt" % (year, image_set), "w") + for image_id in image_ids: + list_file.write("%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg" % (wd, year, image_id)) + convert_annotation(year, image_id, list_file) + list_file.write("\n") + list_file.close() diff --git a/2_Training/src/keras_yolo3/yolo.py b/2_Training/src/keras_yolo3/yolo.py new file mode 100644 index 0000000..3f19b2b --- /dev/null +++ b/2_Training/src/keras_yolo3/yolo.py @@ -0,0 +1,285 @@ +# -*- coding: utf-8 -*- +""" +Class definition of YOLO_v3 style detection model on image and video +""" + +import colorsys +import os +from timeit import default_timer as timer + +import numpy as np +from keras import backend as K +from keras.models import load_model +from keras.layers import Input +from PIL import Image, ImageFont, ImageDraw + +from .yolo3.model import yolo_eval, yolo_body, tiny_yolo_body +from .yolo3.utils import letterbox_image +import os +from keras.utils import multi_gpu_model + + +class YOLO(object): + _defaults = { + "model_path": "model_data/yolo.h5", + "anchors_path": "model_data/yolo_anchors.txt", + "classes_path": "model_data/coco_classes.txt", + "score": 0.3, + "iou": 0.45, + "model_image_size": (416, 416), + "gpu_num": 1, + } + + @classmethod + def get_defaults(cls, n): + if n in cls._defaults: + return cls._defaults[n] + else: + return "Unrecognized attribute name '" + n + "'" + + def __init__(self, **kwargs): + self.__dict__.update(self._defaults) # set up default values + self.__dict__.update(kwargs) # and update with user overrides + self.class_names = self._get_class() + self.anchors = self._get_anchors() + self.sess = K.get_session() + self.boxes, self.scores, self.classes = self.generate() + + def _get_class(self): + classes_path = os.path.expanduser(self.classes_path) + with open(classes_path) as f: + class_names = f.readlines() + class_names = [c.strip() for c in class_names] + return class_names + + def _get_anchors(self): + anchors_path = os.path.expanduser(self.anchors_path) + with open(anchors_path) as f: + anchors = f.readline() + anchors = [float(x) for x in anchors.split(",")] + return np.array(anchors).reshape(-1, 2) + + def generate(self): + model_path = os.path.expanduser(self.model_path) + assert model_path.endswith(".h5"), "Keras model or weights must be a .h5 file." + + # Load model, or construct model and load weights. + start = timer() + num_anchors = len(self.anchors) + num_classes = len(self.class_names) + is_tiny_version = num_anchors == 6 # default setting + try: + self.yolo_model = load_model(model_path, compile=False) + except: + self.yolo_model = ( + tiny_yolo_body( + Input(shape=(None, None, 3)), num_anchors // 2, num_classes + ) + if is_tiny_version + else yolo_body( + Input(shape=(None, None, 3)), num_anchors // 3, num_classes + ) + ) + self.yolo_model.load_weights( + self.model_path + ) # make sure model, anchors and classes match + else: + assert self.yolo_model.layers[-1].output_shape[-1] == num_anchors / len( + self.yolo_model.output + ) * ( + num_classes + 5 + ), "Mismatch between model and given anchor and class sizes" + + end = timer() + print( + "{} model, anchors, and classes loaded in {:.2f}sec.".format( + model_path, end - start + ) + ) + + # Generate colors for drawing bounding boxes. + if len(self.class_names) == 1: + self.colors = ["GreenYellow"] + else: + hsv_tuples = [ + (x / len(self.class_names), 1.0, 1.0) + for x in range(len(self.class_names)) + ] + self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)) + self.colors = list( + map( + lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), + self.colors, + ) + ) + np.random.seed(10101) # Fixed seed for consistent colors across runs. + np.random.shuffle( + self.colors + ) # Shuffle colors to decorrelate adjacent classes. + np.random.seed(None) # Reset seed to default. + + # Generate output tensor targets for filtered bounding boxes. + self.input_image_shape = K.placeholder(shape=(2,)) + if self.gpu_num >= 2: + self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num) + boxes, scores, classes = yolo_eval( + self.yolo_model.output, + self.anchors, + len(self.class_names), + self.input_image_shape, + score_threshold=self.score, + iou_threshold=self.iou, + ) + return boxes, scores, classes + + def detect_image(self, image, show_stats=True): + start = timer() + + if self.model_image_size != (None, None): + assert self.model_image_size[0] % 32 == 0, "Multiples of 32 required" + assert self.model_image_size[1] % 32 == 0, "Multiples of 32 required" + boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size))) + else: + new_image_size = ( + image.width - (image.width % 32), + image.height - (image.height % 32), + ) + boxed_image = letterbox_image(image, new_image_size) + image_data = np.array(boxed_image, dtype="float32") + if show_stats: + print(image_data.shape) + image_data /= 255.0 + image_data = np.expand_dims(image_data, 0) # Add batch dimension. + + out_boxes, out_scores, out_classes = self.sess.run( + [self.boxes, self.scores, self.classes], + feed_dict={ + self.yolo_model.input: image_data, + self.input_image_shape: [image.size[1], image.size[0]], + K.learning_phase(): 0, + }, + ) + if show_stats: + print("Found {} boxes for {}".format(len(out_boxes), "img")) + out_prediction = [] + + font_path = os.path.join(os.path.dirname(__file__), "font/FiraMono-Medium.otf") + font = ImageFont.truetype( + font=font_path, size=np.floor(3e-2 * image.size[1] + 0.5).astype("int32") + ) + thickness = (image.size[0] + image.size[1]) // 300 + + for i, c in reversed(list(enumerate(out_classes))): + predicted_class = self.class_names[c] + box = out_boxes[i] + score = out_scores[i] + + label = "{} {:.2f}".format(predicted_class, score) + draw = ImageDraw.Draw(image) + label_size = draw.textsize(label, font) + + top, left, bottom, right = box + top = max(0, np.floor(top + 0.5).astype("int32")) + left = max(0, np.floor(left + 0.5).astype("int32")) + bottom = min(image.size[1], np.floor(bottom + 0.5).astype("int32")) + right = min(image.size[0], np.floor(right + 0.5).astype("int32")) + + # image was expanded to model_image_size: make sure it did not pick + # up any box outside of original image (run into this bug when + # lowering confidence threshold to 0.01) + if top > image.size[1] or right > image.size[0]: + continue + if show_stats: + print(label, (left, top), (right, bottom)) + + # output as xmin, ymin, xmax, ymax, class_index, confidence + out_prediction.append([left, top, right, bottom, c, score]) + + if top - label_size[1] >= 0: + text_origin = np.array([left, top - label_size[1]]) + else: + text_origin = np.array([left, bottom]) + + # My kingdom for a good redistributable image drawing library. + for i in range(thickness): + draw.rectangle( + [left + i, top + i, right - i, bottom - i], outline=self.colors[c] + ) + draw.rectangle( + [tuple(text_origin), tuple(text_origin + label_size)], + fill=self.colors[c], + ) + + draw.text(text_origin, label, fill=(0, 0, 0), font=font) + del draw + + end = timer() + if show_stats: + print("Time spent: {:.3f}sec".format(end - start)) + return out_prediction, image + + def close_session(self): + self.sess.close() + + +def detect_video(yolo, video_path, output_path=""): + import cv2 + + vid = cv2.VideoCapture(video_path) + if not vid.isOpened(): + raise IOError("Couldn't open webcam or video") + video_FourCC = cv2.VideoWriter_fourcc(*"mp4v") # int(vid.get(cv2.CAP_PROP_FOURCC)) + video_fps = vid.get(cv2.CAP_PROP_FPS) + video_size = ( + int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)), + int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT)), + ) + isOutput = True if output_path != "" else False + if isOutput: + print( + "Processing {} with frame size {} at {:.1f} FPS".format( + os.path.basename(video_path), video_size, video_fps + ) + ) + # print("!!! TYPE:", type(output_path), type(video_FourCC), type(video_fps), type(video_size)) + out = cv2.VideoWriter(output_path, video_FourCC, video_fps, video_size) + accum_time = 0 + curr_fps = 0 + fps = "FPS: ??" + prev_time = timer() + while vid.isOpened(): + return_value, frame = vid.read() + if not return_value: + break + # opencv images are BGR, translate to RGB + frame = frame[:, :, ::-1] + image = Image.fromarray(frame) + out_pred, image = yolo.detect_image(image, show_stats=False) + result = np.asarray(image) + curr_time = timer() + exec_time = curr_time - prev_time + prev_time = curr_time + accum_time = accum_time + exec_time + curr_fps = curr_fps + 1 + if accum_time > 1: + accum_time = accum_time - 1 + fps = "FPS: " + str(curr_fps) + curr_fps = 0 + cv2.putText( + result, + text=fps, + org=(3, 15), + fontFace=cv2.FONT_HERSHEY_SIMPLEX, + fontScale=0.50, + color=(255, 0, 0), + thickness=2, + ) + # cv2.namedWindow("result", cv2.WINDOW_NORMAL) + # cv2.imshow("result", result) + if isOutput: + out.write(result[:, :, ::-1]) + # if cv2.waitKey(1) & 0xFF == ord('q'): + # break + vid.release() + out.release() + # yolo.close_session() diff --git a/2_Training/src/keras_yolo3/yolo3/__init__.py b/2_Training/src/keras_yolo3/yolo3/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/2_Training/src/keras_yolo3/yolo3/model.py b/2_Training/src/keras_yolo3/yolo3/model.py new file mode 100644 index 0000000..0bdcc49 --- /dev/null +++ b/2_Training/src/keras_yolo3/yolo3/model.py @@ -0,0 +1,521 @@ +"""YOLO_v3 Model Defined in Keras.""" + +from functools import wraps + +import numpy as np +import tensorflow as tf +from keras import backend as K +from keras.layers import ( + Conv2D, + Add, + ZeroPadding2D, + UpSampling2D, + Concatenate, + MaxPooling2D, +) +from keras.layers.advanced_activations import LeakyReLU +from keras.layers.normalization import BatchNormalization +from keras.models import Model +from keras.regularizers import l2 + +from ..yolo3.utils import compose + + +@wraps(Conv2D) +def DarknetConv2D(*args, **kwargs): + """Wrapper to set Darknet parameters for Convolution2D.""" + darknet_conv_kwargs = {"kernel_regularizer": l2(5e-4)} + darknet_conv_kwargs["padding"] = ( + "valid" if kwargs.get("strides") == (2, 2) else "same" + ) + darknet_conv_kwargs.update(kwargs) + return Conv2D(*args, **darknet_conv_kwargs) + + +def DarknetConv2D_BN_Leaky(*args, **kwargs): + """Darknet Convolution2D followed by BatchNormalization and LeakyReLU.""" + no_bias_kwargs = {"use_bias": False} + no_bias_kwargs.update(kwargs) + return compose( + DarknetConv2D(*args, **no_bias_kwargs), + BatchNormalization(), + LeakyReLU(alpha=0.1), + ) + + +def resblock_body(x, num_filters, num_blocks): + """A series of resblocks starting with a downsampling Convolution2D""" + # Darknet uses left and top padding instead of 'same' mode + x = ZeroPadding2D(((1, 0), (1, 0)))(x) + x = DarknetConv2D_BN_Leaky(num_filters, (3, 3), strides=(2, 2))(x) + for i in range(num_blocks): + y = compose( + DarknetConv2D_BN_Leaky(num_filters // 2, (1, 1)), + DarknetConv2D_BN_Leaky(num_filters, (3, 3)), + )(x) + x = Add()([x, y]) + return x + + +def darknet_body(x): + """Darknent body having 52 Convolution2D layers""" + x = DarknetConv2D_BN_Leaky(32, (3, 3))(x) + x = resblock_body(x, 64, 1) + x = resblock_body(x, 128, 2) + x = resblock_body(x, 256, 8) + x = resblock_body(x, 512, 8) + x = resblock_body(x, 1024, 4) + return x + + +def make_last_layers(x, num_filters, out_filters): + """6 Conv2D_BN_Leaky layers followed by a Conv2D_linear layer""" + x = compose( + DarknetConv2D_BN_Leaky(num_filters, (1, 1)), + DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), + DarknetConv2D_BN_Leaky(num_filters, (1, 1)), + DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), + DarknetConv2D_BN_Leaky(num_filters, (1, 1)), + )(x) + y = compose( + DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), + DarknetConv2D(out_filters, (1, 1)), + )(x) + return x, y + + +def yolo_body(inputs, num_anchors, num_classes): + """Create YOLO_V3 model CNN body in Keras.""" + darknet = Model(inputs, darknet_body(inputs)) + x, y1 = make_last_layers(darknet.output, 512, num_anchors * (num_classes + 5)) + + x = compose(DarknetConv2D_BN_Leaky(256, (1, 1)), UpSampling2D(2))(x) + x = Concatenate()([x, darknet.layers[152].output]) + x, y2 = make_last_layers(x, 256, num_anchors * (num_classes + 5)) + + x = compose(DarknetConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x) + x = Concatenate()([x, darknet.layers[92].output]) + x, y3 = make_last_layers(x, 128, num_anchors * (num_classes + 5)) + + return Model(inputs, [y1, y2, y3]) + + +def tiny_yolo_body(inputs, num_anchors, num_classes): + """Create Tiny YOLO_v3 model CNN body in keras.""" + x1 = compose( + DarknetConv2D_BN_Leaky(16, (3, 3)), + MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding="same"), + DarknetConv2D_BN_Leaky(32, (3, 3)), + MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding="same"), + DarknetConv2D_BN_Leaky(64, (3, 3)), + MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding="same"), + DarknetConv2D_BN_Leaky(128, (3, 3)), + MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding="same"), + DarknetConv2D_BN_Leaky(256, (3, 3)), + )(inputs) + x2 = compose( + MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding="same"), + DarknetConv2D_BN_Leaky(512, (3, 3)), + MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding="same"), + DarknetConv2D_BN_Leaky(1024, (3, 3)), + DarknetConv2D_BN_Leaky(256, (1, 1)), + )(x1) + y1 = compose( + DarknetConv2D_BN_Leaky(512, (3, 3)), + DarknetConv2D(num_anchors * (num_classes + 5), (1, 1)), + )(x2) + + x2 = compose(DarknetConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x2) + y2 = compose( + Concatenate(), + DarknetConv2D_BN_Leaky(256, (3, 3)), + DarknetConv2D(num_anchors * (num_classes + 5), (1, 1)), + )([x2, x1]) + + return Model(inputs, [y1, y2]) + + +def yolo_head(feats, anchors, num_classes, input_shape, calc_loss=False): + """Convert final layer features to bounding box parameters.""" + num_anchors = len(anchors) + # Reshape to batch, height, width, num_anchors, box_params. + anchors_tensor = K.reshape(K.constant(anchors), [1, 1, 1, num_anchors, 2]) + + grid_shape = K.shape(feats)[1:3] # height, width + grid_y = K.tile( + K.reshape(K.arange(0, stop=grid_shape[0]), [-1, 1, 1, 1]), + [1, grid_shape[1], 1, 1], + ) + grid_x = K.tile( + K.reshape(K.arange(0, stop=grid_shape[1]), [1, -1, 1, 1]), + [grid_shape[0], 1, 1, 1], + ) + grid = K.concatenate([grid_x, grid_y]) + grid = K.cast(grid, K.dtype(feats)) + + feats = K.reshape( + feats, [-1, grid_shape[0], grid_shape[1], num_anchors, num_classes + 5] + ) + + # Adjust preditions to each spatial grid point and anchor size. + box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast( + grid_shape[::-1], K.dtype(feats) + ) + box_wh = ( + K.exp(feats[..., 2:4]) + * anchors_tensor + / K.cast(input_shape[::-1], K.dtype(feats)) + ) + box_confidence = K.sigmoid(feats[..., 4:5]) + box_class_probs = K.sigmoid(feats[..., 5:]) + + if calc_loss == True: + return grid, feats, box_xy, box_wh + return box_xy, box_wh, box_confidence, box_class_probs + + +def yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape): + """Get corrected boxes""" + box_yx = box_xy[..., ::-1] + box_hw = box_wh[..., ::-1] + input_shape = K.cast(input_shape, K.dtype(box_yx)) + image_shape = K.cast(image_shape, K.dtype(box_yx)) + new_shape = K.round(image_shape * K.min(input_shape / image_shape)) + offset = (input_shape - new_shape) / 2.0 / input_shape + scale = input_shape / new_shape + box_yx = (box_yx - offset) * scale + box_hw *= scale + + box_mins = box_yx - (box_hw / 2.0) + box_maxes = box_yx + (box_hw / 2.0) + boxes = K.concatenate( + [ + box_mins[..., 0:1], # y_min + box_mins[..., 1:2], # x_min + box_maxes[..., 0:1], # y_max + box_maxes[..., 1:2], # x_max + ] + ) + + # Scale boxes back to original image shape. + boxes *= K.concatenate([image_shape, image_shape]) + return boxes + + +def yolo_boxes_and_scores(feats, anchors, num_classes, input_shape, image_shape): + """Process Conv layer output""" + box_xy, box_wh, box_confidence, box_class_probs = yolo_head( + feats, anchors, num_classes, input_shape + ) + boxes = yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape) + boxes = K.reshape(boxes, [-1, 4]) + box_scores = box_confidence * box_class_probs + box_scores = K.reshape(box_scores, [-1, num_classes]) + return boxes, box_scores + + +def yolo_eval( + yolo_outputs, + anchors, + num_classes, + image_shape, + max_boxes=20, + score_threshold=0.6, + iou_threshold=0.5, +): + """Evaluate YOLO model on given input and return filtered boxes.""" + num_layers = len(yolo_outputs) + anchor_mask = ( + [[6, 7, 8], [3, 4, 5], [0, 1, 2]] if num_layers == 3 else [[3, 4, 5], [1, 2, 3]] + ) # default setting + input_shape = K.shape(yolo_outputs[0])[1:3] * 32 + boxes = [] + box_scores = [] + for l in range(num_layers): + _boxes, _box_scores = yolo_boxes_and_scores( + yolo_outputs[l], + anchors[anchor_mask[l]], + num_classes, + input_shape, + image_shape, + ) + boxes.append(_boxes) + box_scores.append(_box_scores) + boxes = K.concatenate(boxes, axis=0) + box_scores = K.concatenate(box_scores, axis=0) + + mask = box_scores >= score_threshold + max_boxes_tensor = K.constant(max_boxes, dtype="int32") + boxes_ = [] + scores_ = [] + classes_ = [] + for c in range(num_classes): + # TODO: use keras backend instead of tf. + class_boxes = tf.boolean_mask(boxes, mask[:, c]) + class_box_scores = tf.boolean_mask(box_scores[:, c], mask[:, c]) + nms_index = tf.image.non_max_suppression( + class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold + ) + class_boxes = K.gather(class_boxes, nms_index) + class_box_scores = K.gather(class_box_scores, nms_index) + classes = K.ones_like(class_box_scores, "int32") * c + boxes_.append(class_boxes) + scores_.append(class_box_scores) + classes_.append(classes) + boxes_ = K.concatenate(boxes_, axis=0) + scores_ = K.concatenate(scores_, axis=0) + classes_ = K.concatenate(classes_, axis=0) + + return boxes_, scores_, classes_ + + +def preprocess_true_boxes(true_boxes, input_shape, anchors, num_classes): + """Preprocess true boxes to training input format + + Parameters + ---------- + true_boxes: array, shape=(m, T, 5) + Absolute x_min, y_min, x_max, y_max, class_id relative to input_shape. + input_shape: array-like, hw, multiples of 32 + anchors: array, shape=(N, 2), wh + num_classes: integer + + Returns + ------- + y_true: list of array, shape like yolo_outputs, xywh are reletive value + + """ + assert ( + true_boxes[..., 4] < num_classes + ).all(), "class id must be less than num_classes" + num_layers = len(anchors) // 3 # default setting + anchor_mask = ( + [[6, 7, 8], [3, 4, 5], [0, 1, 2]] if num_layers == 3 else [[3, 4, 5], [1, 2, 3]] + ) + + true_boxes = np.array(true_boxes, dtype="float32") + input_shape = np.array(input_shape, dtype="int32") + boxes_xy = (true_boxes[..., 0:2] + true_boxes[..., 2:4]) // 2 + boxes_wh = true_boxes[..., 2:4] - true_boxes[..., 0:2] + true_boxes[..., 0:2] = boxes_xy / input_shape[::-1] + true_boxes[..., 2:4] = boxes_wh / input_shape[::-1] + + m = true_boxes.shape[0] + grid_shapes = [input_shape // {0: 32, 1: 16, 2: 8}[l] for l in range(num_layers)] + y_true = [ + np.zeros( + ( + m, + grid_shapes[l][0], + grid_shapes[l][1], + len(anchor_mask[l]), + 5 + num_classes, + ), + dtype="float32", + ) + for l in range(num_layers) + ] + + # Expand dim to apply broadcasting. + anchors = np.expand_dims(anchors, 0) + anchor_maxes = anchors / 2.0 + anchor_mins = -anchor_maxes + valid_mask = boxes_wh[..., 0] > 0 + + for b in range(m): + # Discard zero rows. + wh = boxes_wh[b, valid_mask[b]] + if len(wh) == 0: + continue + # Expand dim to apply broadcasting. + wh = np.expand_dims(wh, -2) + box_maxes = wh / 2.0 + box_mins = -box_maxes + + intersect_mins = np.maximum(box_mins, anchor_mins) + intersect_maxes = np.minimum(box_maxes, anchor_maxes) + intersect_wh = np.maximum(intersect_maxes - intersect_mins, 0.0) + intersect_area = intersect_wh[..., 0] * intersect_wh[..., 1] + box_area = wh[..., 0] * wh[..., 1] + anchor_area = anchors[..., 0] * anchors[..., 1] + iou = intersect_area / (box_area + anchor_area - intersect_area) + + # Find best anchor for each true box + best_anchor = np.argmax(iou, axis=-1) + + for t, n in enumerate(best_anchor): + for l in range(num_layers): + if n in anchor_mask[l]: + i = np.floor(true_boxes[b, t, 0] * grid_shapes[l][1]).astype( + "int32" + ) + j = np.floor(true_boxes[b, t, 1] * grid_shapes[l][0]).astype( + "int32" + ) + k = anchor_mask[l].index(n) + c = true_boxes[b, t, 4].astype("int32") + y_true[l][b, j, i, k, 0:4] = true_boxes[b, t, 0:4] + y_true[l][b, j, i, k, 4] = 1 + y_true[l][b, j, i, k, 5 + c] = 1 + + return y_true + + +def box_iou(b1, b2): + """Return iou tensor + + Parameters + ---------- + b1: tensor, shape=(i1,...,iN, 4), xywh + b2: tensor, shape=(j, 4), xywh + + Returns + ------- + iou: tensor, shape=(i1,...,iN, j) + + """ + + # Expand dim to apply broadcasting. + b1 = K.expand_dims(b1, -2) + b1_xy = b1[..., :2] + b1_wh = b1[..., 2:4] + b1_wh_half = b1_wh / 2.0 + b1_mins = b1_xy - b1_wh_half + b1_maxes = b1_xy + b1_wh_half + + # Expand dim to apply broadcasting. + b2 = K.expand_dims(b2, 0) + b2_xy = b2[..., :2] + b2_wh = b2[..., 2:4] + b2_wh_half = b2_wh / 2.0 + b2_mins = b2_xy - b2_wh_half + b2_maxes = b2_xy + b2_wh_half + + intersect_mins = K.maximum(b1_mins, b2_mins) + intersect_maxes = K.minimum(b1_maxes, b2_maxes) + intersect_wh = K.maximum(intersect_maxes - intersect_mins, 0.0) + intersect_area = intersect_wh[..., 0] * intersect_wh[..., 1] + b1_area = b1_wh[..., 0] * b1_wh[..., 1] + b2_area = b2_wh[..., 0] * b2_wh[..., 1] + iou = intersect_area / (b1_area + b2_area - intersect_area) + + return iou + + +def yolo_loss(args, anchors, num_classes, ignore_thresh=0.5, print_loss=False): + """Return yolo_loss tensor + + Parameters + ---------- + yolo_outputs: list of tensor, the output of yolo_body or tiny_yolo_body + y_true: list of array, the output of preprocess_true_boxes + anchors: array, shape=(N, 2), wh + num_classes: integer + ignore_thresh: float, the iou threshold whether to ignore object confidence loss + + Returns + ------- + loss: tensor, shape=(1,) + + """ + num_layers = len(anchors) // 3 # default setting + yolo_outputs = args[:num_layers] + y_true = args[num_layers:] + anchor_mask = ( + [[6, 7, 8], [3, 4, 5], [0, 1, 2]] if num_layers == 3 else [[3, 4, 5], [1, 2, 3]] + ) + input_shape = K.cast(K.shape(yolo_outputs[0])[1:3] * 32, K.dtype(y_true[0])) + grid_shapes = [ + K.cast(K.shape(yolo_outputs[l])[1:3], K.dtype(y_true[0])) + for l in range(num_layers) + ] + loss = 0 + m = K.shape(yolo_outputs[0])[0] # batch size, tensor + mf = K.cast(m, K.dtype(yolo_outputs[0])) + + for l in range(num_layers): + object_mask = y_true[l][..., 4:5] + true_class_probs = y_true[l][..., 5:] + + grid, raw_pred, pred_xy, pred_wh = yolo_head( + yolo_outputs[l], + anchors[anchor_mask[l]], + num_classes, + input_shape, + calc_loss=True, + ) + pred_box = K.concatenate([pred_xy, pred_wh]) + + # Darknet raw box to calculate loss. + raw_true_xy = y_true[l][..., :2] * grid_shapes[l][::-1] - grid + raw_true_wh = K.log( + y_true[l][..., 2:4] / anchors[anchor_mask[l]] * input_shape[::-1] + ) + raw_true_wh = K.switch( + object_mask, raw_true_wh, K.zeros_like(raw_true_wh) + ) # avoid log(0)=-inf + box_loss_scale = 2 - y_true[l][..., 2:3] * y_true[l][..., 3:4] + + # Find ignore mask, iterate over each of batch. + ignore_mask = tf.TensorArray(K.dtype(y_true[0]), size=1, dynamic_size=True) + object_mask_bool = K.cast(object_mask, "bool") + + def loop_body(b, ignore_mask): + true_box = tf.boolean_mask( + y_true[l][b, ..., 0:4], object_mask_bool[b, ..., 0] + ) + iou = box_iou(pred_box[b], true_box) + best_iou = K.max(iou, axis=-1) + ignore_mask = ignore_mask.write( + b, K.cast(best_iou < ignore_thresh, K.dtype(true_box)) + ) + return b + 1, ignore_mask + + _, ignore_mask = K.control_flow_ops.while_loop( + lambda b, *args: b < m, loop_body, [0, ignore_mask] + ) + ignore_mask = ignore_mask.stack() + ignore_mask = K.expand_dims(ignore_mask, -1) + + # K.binary_crossentropy is helpful to avoid exp overflow. + xy_loss = ( + object_mask + * box_loss_scale + * K.binary_crossentropy(raw_true_xy, raw_pred[..., 0:2], from_logits=True) + ) + wh_loss = ( + object_mask + * box_loss_scale + * 0.5 + * K.square(raw_true_wh - raw_pred[..., 2:4]) + ) + confidence_loss = ( + object_mask + * K.binary_crossentropy(object_mask, raw_pred[..., 4:5], from_logits=True) + + (1 - object_mask) + * K.binary_crossentropy(object_mask, raw_pred[..., 4:5], from_logits=True) + * ignore_mask + ) + class_loss = object_mask * K.binary_crossentropy( + true_class_probs, raw_pred[..., 5:], from_logits=True + ) + + xy_loss = K.sum(xy_loss) / mf + wh_loss = K.sum(wh_loss) / mf + confidence_loss = K.sum(confidence_loss) / mf + class_loss = K.sum(class_loss) / mf + loss += xy_loss + wh_loss + confidence_loss + class_loss + if print_loss: + loss = tf.Print( + loss, + [ + loss, + xy_loss, + wh_loss, + confidence_loss, + class_loss, + K.sum(ignore_mask), + ], + message="loss: ", + ) + return loss diff --git a/2_Training/src/keras_yolo3/yolo3/utils.py b/2_Training/src/keras_yolo3/yolo3/utils.py new file mode 100644 index 0000000..5016e5d --- /dev/null +++ b/2_Training/src/keras_yolo3/yolo3/utils.py @@ -0,0 +1,165 @@ +"""Miscellaneous utility functions.""" + +from functools import reduce + +from PIL import Image + +# import Image +import numpy as np +from matplotlib.colors import rgb_to_hsv, hsv_to_rgb + +import re + + +def compose(*funcs): + """Compose arbitrarily many functions, evaluated left to right. + + Reference: https://mathieularose.com/function-composition-in-python/ + """ + # return lambda x: reduce(lambda v, f: f(v), funcs, x) + if funcs: + return reduce(lambda f, g: lambda *a, **kw: g(f(*a, **kw)), funcs) + else: + raise ValueError("Composition of empty sequence not supported.") + + +def letterbox_image(image, size): + """resize image with unchanged aspect ratio using padding""" + iw, ih = image.size + w, h = size + scale = min(w / iw, h / ih) + nw = int(iw * scale) + nh = int(ih * scale) + + image = image.resize((nw, nh), Image.BICUBIC) + new_image = Image.new("RGB", size, (128, 128, 128)) + new_image.paste(image, ((w - nw) // 2, (h - nh) // 2)) + return new_image + + +def rand(a=0, b=1): + return np.random.rand() * (b - a) + a + + +def get_random_data( + annotation_line, + input_shape, + random=True, + max_boxes=20, + jitter=0.3, + hue=0.1, + sat=1.5, + val=1.5, + proc_img=True, +): + """random preprocessing for real-time data augmentation""" + + # This type of splitting makes sure that it is compatible with spaces in folder names + # We split at the first space that is followed by a number + tmp_split = re.split("( \d)", annotation_line, maxsplit=1) + if len(tmp_split) > 2: + line = tmp_split[0], tmp_split[1] + tmp_split[2] + else: + line = tmp_split + # line[0] contains the filename + image = Image.open(line[0]) + # The rest of the line includes bounding boxes + line = line[1].split(" ") + iw, ih = image.size + h, w = input_shape + box = np.array([np.array(list(map(int, box.split(",")))) for box in line[1:]]) + + if not random: + # resize image + scale = min(w / iw, h / ih) + nw = int(iw * scale) + nh = int(ih * scale) + dx = (w - nw) // 2 + dy = (h - nh) // 2 + image_data = 0 + if proc_img: + image = image.resize((nw, nh), Image.BICUBIC) + new_image = Image.new("RGB", (w, h), (128, 128, 128)) + new_image.paste(image, (dx, dy)) + image_data = np.array(new_image) / 255.0 + + # correct boxes + box_data = np.zeros((max_boxes, 5)) + if len(box) > 0: + np.random.shuffle(box) + if len(box) > max_boxes: + box = box[:max_boxes] + box[:, [0, 2]] = box[:, [0, 2]] * scale + dx + box[:, [1, 3]] = box[:, [1, 3]] * scale + dy + box_data[: len(box)] = box + + return image_data, box_data + + # resize image + new_ar = w / h * rand(1 - jitter, 1 + jitter) / rand(1 - jitter, 1 + jitter) + scale = rand(0.25, 2) + if new_ar < 1: + nh = int(scale * h) + nw = int(nh * new_ar) + else: + nw = int(scale * w) + nh = int(nw / new_ar) + image = image.resize((nw, nh), Image.BICUBIC) + + # place image + dx = int(rand(0, w - nw)) + dy = int(rand(0, h - nh)) + new_image = Image.new("RGB", (w, h), (128, 128, 128)) + new_image.paste(image, (dx, dy)) + image = new_image + + # flip image or not + flip = rand() < 0.5 + if flip: + image = image.transpose(Image.FLIP_LEFT_RIGHT) + + # distort image + hue = rand(-hue, hue) + sat = rand(1, sat) if rand() < 0.5 else 1 / rand(1, sat) + val = rand(1, val) if rand() < 0.5 else 1 / rand(1, val) + x = rgb_to_hsv(np.array(image) / 255.0) + x[..., 0] += hue + x[..., 0][x[..., 0] > 1] -= 1 + x[..., 0][x[..., 0] < 0] += 1 + x[..., 1] *= sat + x[..., 2] *= val + x[x > 1] = 1 + x[x < 0] = 0 + image_data = hsv_to_rgb(x) # numpy array, 0 to 1 + + # make gray + gray = rand() < 0.2 + if gray: + image_gray = np.dot(image_data, [0.299, 0.587, 0.114]) + # a gray RGB image is GGG + image_data = np.moveaxis(np.stack([image_gray, image_gray, image_gray]), 0, -1) + + # invert colors + invert = rand() < 0.1 + if invert: + image_data = 1.0 - image_data + + # correct boxes + box_data = np.zeros((max_boxes, 5)) + if len(box) > 0: + np.random.shuffle(box) + box[:, [0, 2]] = box[:, [0, 2]] * nw / iw + dx + box[:, [1, 3]] = box[:, [1, 3]] * nh / ih + dy + if flip: + box[:, [0, 2]] = w - box[:, [2, 0]] + box[:, 0:2][box[:, 0:2] < 0] = 0 + box[:, 2][box[:, 2] > w] = w + box[:, 3][box[:, 3] > h] = h + box_w = box[:, 2] - box[:, 0] + box_h = box[:, 3] - box[:, 1] + box = box[np.logical_and(box_w > 1, box_h > 1)] # discard invalid box + if len(box) > max_boxes: + box = box[:max_boxes] + box_data[: len(box)] = box + + return image_data, box_data diff --git a/2_Training/src/keras_yolo3/yolo_video.py b/2_Training/src/keras_yolo3/yolo_video.py new file mode 100644 index 0000000..5d9d619 --- /dev/null +++ b/2_Training/src/keras_yolo3/yolo_video.py @@ -0,0 +1,162 @@ +import sys, os +import argparse +from yolo import YOLO, detect_video +from PIL import Image +import readline + +readline.parse_and_bind("tab: complete") + + +def detect_logo(yolo, img, save_img=True, save_img_path="output"): + try: + image = Image.open(img) + if image.mode != "RGB": + image = image.convert("RGB") + except: + print("File Open Error! Try again!") + return None, None + + prediction, r_image = yolo.detect_image(image) + + if save_img: + r_image.save(os.path.join(save_img_path, os.path.basename(img))) + + return prediction, r_image + + +FLAGS = None + +if __name__ == "__main__": + # class YOLO defines the default value, so suppress any default here + parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS) + """ + Command line options + """ + parser.add_argument( + "--model", + type=str, + dest="model_path", + help="path to model weight file, default " + YOLO.get_defaults("model_path"), + ) + + parser.add_argument( + "--anchors", + type=str, + dest="anchors_path", + help="path to anchor definitions, default " + YOLO.get_defaults("anchors_path"), + ) + + parser.add_argument( + "--classes", + type=str, + dest="classes_path", + help="path to class definitions, default " + YOLO.get_defaults("classes_path"), + ) + + parser.add_argument( + "--gpu_num", + type=int, + help="Number of GPU to use, default " + str(YOLO.get_defaults("gpu_num")), + ) + parser.add_argument( + "--image", + default=False, + action="store_true", + help="Image detection mode, will ignore all positional arguments", + ) + parser.add_argument( + "--batch", + type=str, + help="Image detection mode for each file specified in input txt, will ignore all positional arguments", + ) + parser.add_argument( + "--confidence", + type=float, + dest="score", + default=0.3, + help="Model confidence threshold above which to show predictions", + ) + parser.add_argument( + "--iou_min", + type=float, + dest="iou_thr", + default=0.45, + help="IoU threshold for pruning object candidates with higher IoU than higher score boxes", + ) + parser.add_argument( + "--input", + nargs="?", + type=str, + required=False, + default="input", + help="Image or video input path", + ) + + parser.add_argument( + "--output", + nargs="?", + type=str, + default="output", + help="output path: either directory for single/batch image, or filename for video", + ) + + FLAGS = parser.parse_args() + + if not os.path.isdir("output"): + os.makedirs("output") + + if FLAGS.image: + """ + Image detection mode, either prompt user input or was passed as argument + """ + print("Image detection mode") + + yolo = YOLO(**vars(FLAGS)) + if FLAGS.input == "input": + while True: + FLAGS.input = input("Input image filename (q to quit):") + if FLAGS.input in ["q", "quit"]: + yolo.close_session() + exit() + + img = FLAGS.input + prediction, r_image = detect_logo( + yolo, img, save_img=True, save_img_path=FLAGS.output + ) + if prediction is None: + continue + + else: + img = FLAGS.input + prediction, r_image = detect_logo( + yolo, img, save_img=True, save_img_path=FLAGS.output + ) + + yolo.close_session() + + elif "batch" in FLAGS: + print("Batch image detection mode: reading " + FLAGS.batch) + + with open(FLAGS.batch, "r") as file: + file_list = [line.split(" ")[0] for line in file.read().splitlines()] + out_txtfile = os.path.join(FLAGS.output, "data_pred.txt") + txtfile = open(out_txtfile, "w") + + yolo = YOLO(**vars(FLAGS)) + + for img in file_list[:10]: + prediction, r_image = detect_logo( + yolo, img, save_img=True, save_img_path="output" + ) + + txtfile.write(img + " ") + for pred in prediction: + txtfile.write(",".join([str(p) for p in pred]) + " ") + txtfile.write("\n") + + txtfile.close() + yolo.close_session() + elif "video" in FLAGS: + detect_video(YOLO(**vars(FLAGS)), FLAGS.video, FLAGS.output) + else: + print("Must specify at least --image or --video. See usage with --help.") diff --git a/2_Training/src/keras_yolo3/yolov3-tiny.cfg b/2_Training/src/keras_yolo3/yolov3-tiny.cfg new file mode 100644 index 0000000..b8e96da --- /dev/null +++ b/2_Training/src/keras_yolo3/yolov3-tiny.cfg @@ -0,0 +1,182 @@ +[net] +# Testing +batch=1 +subdivisions=1 +# Training +# batch=64 +# subdivisions=2 +width=640 +height=640 +channels=3 +momentum=0.9 +decay=0.0005 +angle=0 +saturation = 1.5 +exposure = 1.5 +hue=.1 + +learning_rate=0.001 +burn_in=1000 +max_batches = 500200 +policy=steps +steps=400000,450000 +scales=.1,.1 + +[convolutional] +batch_normalize=1 +filters=16 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=32 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=1 + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +########### + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + + + +[yolo] +mask = 3,4,5 +anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 +classes=80 +num=6 +jitter=.3 +ignore_thresh = .7 +truth_thresh = 1 +random=1 + +[route] +layers = -4 + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[upsample] +stride=2 + +[route] +layers = -1, 8 + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + +[yolo] +mask = 1,2,3 +anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 +classes=80 +num=6 +jitter=.3 +ignore_thresh = .7 +truth_thresh = 1 +random=1 diff --git a/2_Training/src/keras_yolo3/yolov3.cfg b/2_Training/src/keras_yolo3/yolov3.cfg new file mode 100644 index 0000000..aa37909 --- /dev/null +++ b/2_Training/src/keras_yolo3/yolov3.cfg @@ -0,0 +1,789 @@ +[net] +# Testing +batch=1 +subdivisions=1 +# Training +# batch=64 +# subdivisions=16 +width=640 +height=640 +channels=3 +momentum=0.9 +decay=0.0005 +angle=0 +saturation = 1.5 +exposure = 1.5 +hue=.1 + +learning_rate=0.001 +burn_in=1000 +max_batches = 500200 +policy=steps +steps=400000,450000 +scales=.1,.1 + +[convolutional] +batch_normalize=1 +filters=32 +size=3 +stride=1 +pad=1 +activation=leaky + +# Downsample + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=32 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=64 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=64 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +###################### + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + + +[yolo] +mask = 6,7,8 +anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 +classes=80 +num=9 +jitter=.3 +ignore_thresh = .5 +truth_thresh = 1 +random=1 + + +[route] +layers = -4 + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[upsample] +stride=2 + +[route] +layers = -1, 61 + + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=512 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=512 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=512 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + + +[yolo] +mask = 3,4,5 +anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 +classes=80 +num=9 +jitter=.3 +ignore_thresh = .5 +truth_thresh = 1 +random=1 + + + +[route] +layers = -4 + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[upsample] +stride=2 + +[route] +layers = -1, 36 + + + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=256 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=256 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=256 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + + +[yolo] +mask = 0,1,2 +anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 +classes=80 +num=9 +jitter=.3 +ignore_thresh = .5 +truth_thresh = 1 +random=1 + diff --git a/3_Inference/Detector.py b/3_Inference/Detector.py new file mode 100644 index 0000000..9502538 --- /dev/null +++ b/3_Inference/Detector.py @@ -0,0 +1,283 @@ +import os +import sys + + +def get_parent_dir(n=1): + """ returns the n-th parent dicrectory of the current + working directory """ + current_path = os.path.dirname(os.path.abspath(__file__)) + for k in range(n): + current_path = os.path.dirname(current_path) + return current_path + + +src_path = os.path.join(get_parent_dir(1), "2_Training", "src") +utils_path = os.path.join(get_parent_dir(1), "Utils") + +sys.path.append(src_path) +sys.path.append(utils_path) + +import argparse +from keras_yolo3.yolo import YOLO, detect_video +from PIL import Image +from timeit import default_timer as timer +from utils import load_extractor_model, load_features, parse_input, detect_object +import test +import utils +import pandas as pd +import numpy as np +from Get_File_Paths import GetFileList +import random + +os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" + +# Set up folder names for default values +data_folder = os.path.join(get_parent_dir(n=1), "Data") + +image_folder = os.path.join(data_folder, "Source_Images") + +image_test_folder = os.path.join(image_folder, "Test_Images") + +detection_results_folder = os.path.join(image_folder, "Test_Image_Detection_Results") +detection_results_file = os.path.join(detection_results_folder, "Detection_Results.csv") + +model_folder = os.path.join(data_folder, "Model_Weights") + +model_weights = os.path.join(model_folder, "trained_weights_final.h5") +model_classes = os.path.join(model_folder, "data_classes.txt") + +anchors_path = os.path.join(src_path, "keras_yolo3", "model_data", "yolo_anchors.txt") + +FLAGS = None + +if __name__ == "__main__": + # Delete all default flags + parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS) + """ + Command line options + """ + + parser.add_argument( + "--input_path", + type=str, + default=image_test_folder, + help="Path to image/video directory. All subdirectories will be included. Default is " + + image_test_folder, + ) + + parser.add_argument( + "--output", + type=str, + default=detection_results_folder, + help="Output path for detection results. Default is " + + detection_results_folder, + ) + + parser.add_argument( + "--no_save_img", + default=False, + action="store_true", + help="Only save bounding box coordinates but do not save output images with annotated boxes. Default is False.", + ) + + parser.add_argument( + "--file_types", + "--names-list", + nargs="*", + default=[], + help="Specify list of file types to include. Default is --file_types .jpg .jpeg .png .mp4", + ) + + parser.add_argument( + "--yolo_model", + type=str, + dest="model_path", + default=model_weights, + help="Path to pre-trained weight files. Default is " + model_weights, + ) + + parser.add_argument( + "--anchors", + type=str, + dest="anchors_path", + default=anchors_path, + help="Path to YOLO anchors. Default is " + anchors_path, + ) + + parser.add_argument( + "--classes", + type=str, + dest="classes_path", + default=model_classes, + help="Path to YOLO class specifications. Default is " + model_classes, + ) + + parser.add_argument( + "--gpu_num", type=int, default=1, help="Number of GPU to use. Default is 1" + ) + + parser.add_argument( + "--confidence", + type=float, + dest="score", + default=0.25, + help="Threshold for YOLO object confidence score to show predictions. Default is 0.25.", + ) + + parser.add_argument( + "--box_file", + type=str, + dest="box", + default=detection_results_file, + help="File to save bounding box results to. Default is " + + detection_results_file, + ) + + parser.add_argument( + "--postfix", + type=str, + dest="postfix", + default="_catface", + help='Specify the postfix for images with bounding boxes. Default is "_catface"', + ) + + FLAGS = parser.parse_args() + + save_img = not FLAGS.no_save_img + + file_types = FLAGS.file_types + + if file_types: + input_paths = GetFileList(FLAGS.input_path, endings=file_types) + else: + input_paths = GetFileList(FLAGS.input_path) + + # Split images and videos + img_endings = (".jpg", ".jpg", ".png") + vid_endings = (".mp4", ".mpeg", ".mpg", ".avi") + + input_image_paths = [] + input_video_paths = [] + for item in input_paths: + if item.endswith(img_endings): + input_image_paths.append(item) + elif item.endswith(vid_endings): + input_video_paths.append(item) + + output_path = FLAGS.output + if not os.path.exists(output_path): + os.makedirs(output_path) + + # define YOLO detector + yolo = YOLO( + **{ + "model_path": FLAGS.model_path, + "anchors_path": FLAGS.anchors_path, + "classes_path": FLAGS.classes_path, + "score": FLAGS.score, + "gpu_num": FLAGS.gpu_num, + "model_image_size": (416, 416), + } + ) + + # Make a dataframe for the prediction outputs + out_df = pd.DataFrame( + columns=[ + "image", + "image_path", + "xmin", + "ymin", + "xmax", + "ymax", + "label", + "confidence", + "x_size", + "y_size", + ] + ) + + # labels to draw on images + class_file = open(FLAGS.classes_path, "r") + input_labels = [line.rstrip("\n") for line in class_file.readlines()] + print("Found {} input labels: {} ...".format(len(input_labels), input_labels)) + + if input_image_paths: + print( + "Found {} input images: {} ...".format( + len(input_image_paths), + [os.path.basename(f) for f in input_image_paths[:5]], + ) + ) + start = timer() + text_out = "" + + # This is for images + for i, img_path in enumerate(input_image_paths): + print(img_path) + prediction, image = detect_object( + yolo, + img_path, + save_img=save_img, + save_img_path=FLAGS.output, + postfix=FLAGS.postfix, + ) + y_size, x_size, _ = np.array(image).shape + for single_prediction in prediction: + out_df = out_df.append( + pd.DataFrame( + [ + [ + os.path.basename(img_path.rstrip("\n")), + img_path.rstrip("\n"), + ] + + single_prediction + + [x_size, y_size] + ], + columns=[ + "image", + "image_path", + "xmin", + "ymin", + "xmax", + "ymax", + "label", + "confidence", + "x_size", + "y_size", + ], + ) + ) + end = timer() + print( + "Processed {} images in {:.1f}sec - {:.1f}FPS".format( + len(input_image_paths), + end - start, + len(input_image_paths) / (end - start), + ) + ) + out_df.to_csv(FLAGS.box, index=False) + + # This is for videos + if input_video_paths: + print( + "Found {} input videos: {} ...".format( + len(input_video_paths), + [os.path.basename(f) for f in input_video_paths[:5]], + ) + ) + start = timer() + for i, vid_path in enumerate(input_video_paths): + output_path = os.path.join( + FLAGS.output, + os.path.basename(vid_path).replace(".", FLAGS.postfix + "."), + ) + detect_video(yolo, vid_path, output_path=output_path) + + end = timer() + print( + "Processed {} videos in {:.1f}sec".format( + len(input_video_paths), end - start + ) + ) + # Close the current yolo session + yolo.close_session() diff --git a/3_Inference/README.md b/3_Inference/README.md new file mode 100644 index 0000000..9fb5306 --- /dev/null +++ b/3_Inference/README.md @@ -0,0 +1,17 @@ +# TrainYourOwnYOLO: Inference +In this step, we test our detector on cat and dog images and videos located in [`TrainYourOwnYOLO/Data/Source_Images/Test_Images`](/Data/Source_Images/Test_Images). If you like to test the detector on your own images or videos, place them in the [`Test_Images`](/Data/Source_Images/Test_Images) folder. + +## Testing Your Detector +To detect objects run the detector script from within the [`TrainYourOwnYOLO/3_Inference`](/3_Inference/) directory:. +``` +python Detector.py +``` +The outputs are saved to [`TrainYourOwnYOLO/Data/Source_Images/Test_Image_Detection_Results`](/Data/Source_Images/Test_Image_Detection_Results). The outputs include the original images with bounding boxes and confidence scores as well as a file called [`Detection_Results.csv`](/Data/Source_Images/Test_Image_Detection_Results/Detection_Results.csv) containing the image file paths and the bounding box coordinates. For videos, the output files are videos with bounding boxes and confidence scores. To list available command line options run `python Detector.py -h`. + +### That's all! +Congratulations on building your own custom YOLOv3 computer vision application. + +I hope you enjoyed this tutorial and I hope it helped you get our own computer vision project off the ground: + +- Please **star** ⭐ this repo to get notifications on future improvements and +- Please **fork** 🍴 this repo if you like to use it as part of your own project. diff --git a/Data/Model_Weights/Download_Weights.py b/Data/Model_Weights/Download_Weights.py new file mode 100644 index 0000000..1cd9014 --- /dev/null +++ b/Data/Model_Weights/Download_Weights.py @@ -0,0 +1,58 @@ +# Modified from https://stackoverflow.com/questions/25010369/wget-curl-large-file-from-google-drive + +# To download houses weights run +# python Download_Weights.py 1aPCwYXFAOmklmNMLMh81Yduw5UrbHqkN Houses/trained_weights_final.h5 + +# To download openeings weights run +# python Download_Weights.py 1FbvHzQWCjucXPbTbI4S1MnBLkAi58Mxv Openings/trained_weights_final.h5 + +import requests +import os +import progressbar + + +def download_file_from_google_drive(id, destination): + def get_confirm_token(response): + for key, value in response.cookies.items(): + if key.startswith("download_warning"): + return value + + return None + + def save_response_content(response, destination): + CHUNK_SIZE = 32768 + + with open(destination, "wb") as f: + bar = progressbar.ProgressBar(max_value=progressbar.UnknownLength) + i = 0 + for chunk in response.iter_content(CHUNK_SIZE): + if chunk: # filter out keep-alive new chunks + bar.update(i) + i += 1 + f.write(chunk) + + URL = "https://docs.google.com/uc?export=download" + + session = requests.Session() + + response = session.get(URL, params={"id": id}, stream=True) + token = get_confirm_token(response) + + if token: + params = {"id": id, "confirm": token} + response = session.get(URL, params=params, stream=True) + + save_response_content(response, destination) + + +if __name__ == "__main__": + import sys + + if len(sys.argv) is not 3: + print("Usage: python google_drive.py drive_file_id destination_file_path") + else: + # TAKE ID FROM SHAREABLE LINK + file_id = sys.argv[1] + # DESTINATION FILE ON YOUR DISK + destination = os.path.join(os.getcwd(), sys.argv[2]) + download_file_from_google_drive(file_id, destination) diff --git a/Data/Model_Weights/Download_Weights.sh b/Data/Model_Weights/Download_Weights.sh new file mode 100644 index 0000000..2bfb094 --- /dev/null +++ b/Data/Model_Weights/Download_Weights.sh @@ -0,0 +1 @@ +python Download_Weights.py 1MGXAP_XD_w4OExPP10UHsejWrMww8Tu7 trained_weights_final.h5 diff --git a/Data/Model_Weights/data_classes.txt b/Data/Model_Weights/data_classes.txt new file mode 100644 index 0000000..eff2dea --- /dev/null +++ b/Data/Model_Weights/data_classes.txt @@ -0,0 +1 @@ +Cat_Face \ No newline at end of file diff --git a/Data/Source_Images/Test_Image_Detection_Results/04ebfcfd_fa70_4e49_84ff_66cf3c5c0407_best_cat_toys_for_older_cats_3_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/04ebfcfd_fa70_4e49_84ff_66cf3c5c0407_best_cat_toys_for_older_cats_3_catface.jpg new file mode 100644 index 0000000..02413f9 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/04ebfcfd_fa70_4e49_84ff_66cf3c5c0407_best_cat_toys_for_older_cats_3_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/0809_Cat_CNN_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/0809_Cat_CNN_catface.jpg new file mode 100644 index 0000000..1c2106c Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/0809_Cat_CNN_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/0_Cat_research_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/0_Cat_research_catface.jpg new file mode 100644 index 0000000..99e4613 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/0_Cat_research_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/0_PAY_GRUMPY_CAT_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/0_PAY_GRUMPY_CAT_catface.jpg new file mode 100644 index 0000000..64072ab Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/0_PAY_GRUMPY_CAT_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/100_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/100_catface.jpg new file mode 100644 index 0000000..351b2b5 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/100_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/10332358_3x2_700x467_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/10332358_3x2_700x467_catface.jpg new file mode 100644 index 0000000..afccdda Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/10332358_3x2_700x467_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/105488_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/105488_catface.jpg new file mode 100644 index 0000000..d39158a Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/105488_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/1451208_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/1451208_catface.jpg new file mode 100644 index 0000000..cd5e4f2 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/1451208_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/14_20190709094206_8966619_large_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/14_20190709094206_8966619_large_catface.jpg new file mode 100644 index 0000000..9d751f8 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/14_20190709094206_8966619_large_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/160825_vod_orig_historyofdogs_16x9_992_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/160825_vod_orig_historyofdogs_16x9_992_catface.jpg new file mode 100644 index 0000000..22db58c Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/160825_vod_orig_historyofdogs_16x9_992_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/17_cat_essentials.w700.h700_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/17_cat_essentials.w700.h700_catface.jpg new file mode 100644 index 0000000..adbd61f Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/17_cat_essentials.w700.h700_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/17_grumpy_cat_nymag_cover.w1200.h630_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/17_grumpy_cat_nymag_cover.w1200.h630_catface.jpg new file mode 100644 index 0000000..8b16150 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/17_grumpy_cat_nymag_cover.w1200.h630_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/190207162239_01_fluffy_frozen_cat_trnd_exlarge_169_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/190207162239_01_fluffy_frozen_cat_trnd_exlarge_169_catface.jpg new file mode 100644 index 0000000..95fbb38 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/190207162239_01_fluffy_frozen_cat_trnd_exlarge_169_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/1_3_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/1_3_catface.jpg new file mode 100644 index 0000000..da8de30 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/1_3_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/356950_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/356950_catface.jpg new file mode 100644 index 0000000..70e6494 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/356950_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/420508170_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/420508170_catface.jpg new file mode 100644 index 0000000..f8cb872 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/420508170_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/49202627_303_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/49202627_303_catface.jpg new file mode 100644 index 0000000..9822d57 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/49202627_303_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/49a87dd8_035e_3f29_22f0_d762051e8f14_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/49a87dd8_035e_3f29_22f0_d762051e8f14_catface.jpg new file mode 100644 index 0000000..85982f2 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/49a87dd8_035e_3f29_22f0_d762051e8f14_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/4e66a4d0_7f81_4bda_882d_d7a18937f061_poster_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/4e66a4d0_7f81_4bda_882d_d7a18937f061_poster_catface.jpg new file mode 100644 index 0000000..d578368 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/4e66a4d0_7f81_4bda_882d_d7a18937f061_poster_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/539814_istock_821264870_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/539814_istock_821264870_catface.jpg new file mode 100644 index 0000000..6382edb Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/539814_istock_821264870_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/5_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/5_catface.jpg new file mode 100644 index 0000000..77311bf Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/5_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/5aa10ca0d877e618008b4678_750_562_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/5aa10ca0d877e618008b4678_750_562_catface.jpg new file mode 100644 index 0000000..6673b10 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/5aa10ca0d877e618008b4678_750_562_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/5b50bd5351dfbe1f008b45c5_750_562_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/5b50bd5351dfbe1f008b45c5_750_562_catface.jpg new file mode 100644 index 0000000..3b77abd Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/5b50bd5351dfbe1f008b45c5_750_562_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/5d261a225562d.image_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/5d261a225562d.image_catface.jpg new file mode 100644 index 0000000..0643eeb Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/5d261a225562d.image_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/633bd23689846b66b7891edea332a350_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/633bd23689846b66b7891edea332a350_catface.jpg new file mode 100644 index 0000000..c7a2e20 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/633bd23689846b66b7891edea332a350_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/66185314_2297595197159603_5846688980096480369_n_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/66185314_2297595197159603_5846688980096480369_n_catface.jpg new file mode 100644 index 0000000..f04b63a Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/66185314_2297595197159603_5846688980096480369_n_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/67056618_500x406_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/67056618_500x406_catface.jpg new file mode 100644 index 0000000..d19cd58 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/67056618_500x406_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/71aqYo6ZBpL._AC_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/71aqYo6ZBpL._AC_catface.jpg new file mode 100644 index 0000000..34e3293 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/71aqYo6ZBpL._AC_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/76DB73722C98408CB576F3C87486B768_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/76DB73722C98408CB576F3C87486B768_catface.jpg new file mode 100644 index 0000000..a6c3420 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/76DB73722C98408CB576F3C87486B768_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/961d1691_dfb88af9_1280w_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/961d1691_dfb88af9_1280w_catface.jpg new file mode 100644 index 0000000..cc458e1 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/961d1691_dfb88af9_1280w_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/Borowitz_BorisJohnsonDog_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/Borowitz_BorisJohnsonDog_catface.jpg new file mode 100644 index 0000000..a85eb74 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/Borowitz_BorisJohnsonDog_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/Carolina_Dog_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/Carolina_Dog_catface.jpg new file mode 100644 index 0000000..31c57b1 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/Carolina_Dog_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/CatVideo_catface.mp4 b/Data/Source_Images/Test_Image_Detection_Results/CatVideo_catface.mp4 new file mode 100644 index 0000000..375b669 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/CatVideo_catface.mp4 differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/Detection_Results.csv b/Data/Source_Images/Test_Image_Detection_Results/Detection_Results.csv new file mode 100644 index 0000000..9d783ec --- /dev/null +++ b/Data/Source_Images/Test_Image_Detection_Results/Detection_Results.csv @@ -0,0 +1,88 @@ +image,image_path,xmin,ymin,xmax,ymax,label,confidence,x_size,y_size +0809_Cat_CNN.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\0809_Cat_CNN.jpg,258,29,574,315,0,0.7358033061027527,810,455 +0_Cat_research.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\0_Cat_research.jpg,275,23,416,132,0,0.9388746023178101,615,409 +0_PAY_GRUMPY_CAT.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\0_PAY_GRUMPY_CAT.jpg,114,15,491,318,0,0.8899086713790894,615,409 +100.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\100.jpg,326,82,611,292,0,0.7353547215461731,750,600 +10332358_3x2_700x467.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\10332358_3x2_700x467.jpg,167,0,557,399,0,0.9846770167350769,700,467 +105488.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\105488.jpg,122,56,333,324,0,0.25304827094078064,550,550 +105488.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\105488.jpg,37,17,423,380,0,0.9925405979156494,550,550 +1451208.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\1451208.jpg,73,0,396,213,0,0.7688924670219421,480,274 +14_20190709094206_8966619_large.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\14_20190709094206_8966619_large.jpg,357,55,1287,637,0,0.8452132940292358,1299,865 +160825_vod_orig_historyofdogs_16x9_992.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\160825_vod_orig_historyofdogs_16x9_992.jpg,174,189,327,332,0,0.2502049505710602,992,558 +160825_vod_orig_historyofdogs_16x9_992.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\160825_vod_orig_historyofdogs_16x9_992.jpg,475,149,585,358,0,0.26399022340774536,992,558 +160825_vod_orig_historyofdogs_16x9_992.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\160825_vod_orig_historyofdogs_16x9_992.jpg,329,143,474,377,0,0.31680208444595337,992,558 +160825_vod_orig_historyofdogs_16x9_992.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\160825_vod_orig_historyofdogs_16x9_992.jpg,21,176,311,349,0,0.568903923034668,992,558 +17_cat_essentials.w700.h700.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\17_cat_essentials.w700.h700.jpg,62,258,276,450,0,0.9233705401420593,700,700 +17_grumpy_cat_nymag_cover.w1200.h630.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\17_grumpy_cat_nymag_cover.w1200.h630.jpg,190,0,991,610,0,0.8651973009109497,1161,610 +190207162239_01_fluffy_frozen_cat_trnd_exlarge_169.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\190207162239_01_fluffy_frozen_cat_trnd_exlarge_169.jpg,419,196,573,338,0,0.7172338366508484,780,438 +1_3.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\1_3.jpg,798,238,1841,1206,0,0.9903472661972046,2620,2620 +356950.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\356950.jpg,213,0,399,213,0,0.6213473081588745,780,520 +420508170.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\420508170.jpg,144,0,250,100,0,0.3462313711643219,250,250 +420508170.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\420508170.jpg,25,17,218,167,0,0.9814057350158691,250,250 +49202627_303.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\49202627_303.jpg,380,6,668,296,0,0.9539755582809448,700,394 +49a87dd8_035e_3f29_22f0_d762051e8f14.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\49a87dd8_035e_3f29_22f0_d762051e8f14.jpg,148,0,316,173,0,0.7422894835472107,350,200 +4e66a4d0_7f81_4bda_882d_d7a18937f061_poster.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\4e66a4d0_7f81_4bda_882d_d7a18937f061_poster.jpg,0,0,1920,1080,0,0.965449333190918,1920,1080 +5.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\5.jpg,0,10,227,226,0,0.9932052493095398,310,465 +539814_istock_821264870.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\539814_istock_821264870.jpg,291,78,828,504,0,0.29192450642585754,1100,619 +539814_istock_821264870.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\539814_istock_821264870.jpg,210,0,1045,619,0,0.9350296258926392,1100,619 +5aa10ca0d877e618008b4678_750_562.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\5aa10ca0d877e618008b4678_750_562.jpg,155,0,691,562,0,0.9463245868682861,750,562 +5d261a225562d.image.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\5d261a225562d.image.jpg,335,0,925,631,0,0.9926040172576904,960,763 +633bd23689846b66b7891edea332a350.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\633bd23689846b66b7891edea332a350.jpg,114,0,387,479,0,0.6012320518493652,780,522 +66185314_2297595197159603_5846688980096480369_n.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\66185314_2297595197159603_5846688980096480369_n.jpg,270,363,470,532,0,0.677074670791626,593,593 +66185314_2297595197159603_5846688980096480369_n.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\66185314_2297595197159603_5846688980096480369_n.jpg,125,117,372,261,0,0.7377004623413086,593,593 +67056618_500x406.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\67056618_500x406.jpg,165,20,412,282,0,0.8582413792610168,500,406 +71aqYo6ZBpL._AC.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\71aqYo6ZBpL._AC.jpg,0,62,1148,961,0,0.39690640568733215,1200,1200 +71aqYo6ZBpL._AC.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\71aqYo6ZBpL._AC.jpg,210,90,787,703,0,0.682583749294281,1200,1200 +76DB73722C98408CB576F3C87486B768.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\76DB73722C98408CB576F3C87486B768.jpg,307,0,1016,570,0,0.9405931830406189,1280,720 +961d1691_dfb88af9_1280w.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\961d1691_dfb88af9_1280w.jpg,208,0,874,639,0,0.8871027231216431,1280,707 +Borowitz_BorisJohnsonDog.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Borowitz_BorisJohnsonDog.jpg,364,247,568,420,0,0.6505229473114014,727,485 +Carolina_Dog.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Carolina_Dog.jpg,328,0,538,210,0,0.28266388177871704,600,400 +Carolina_Dog.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Carolina_Dog.jpg,370,4,483,156,0,0.5948774218559265,600,400 +china_cloned_cat_2_0.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\china_cloned_cat_2_0.jpg,581,56,848,342,0,0.7735435366630554,1024,683 +chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg,116,54,499,339,0,0.4658162295818329,910,511 +chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg,542,88,817,297,0,0.8265590071678162,910,511 +chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg,187,120,431,287,0,0.9021586775779724,910,511 +cute_puppy_body_image.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\cute_puppy_body_image.jpg,104,30,379,212,0,0.7816994786262512,600,408 +dog_landing_hero_lg.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\dog_landing_hero_lg.jpg,0,0,722,447,0,0.9289771318435669,1080,447 +dog_landing_hero_sm.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\dog_landing_hero_sm.jpg,322,0,519,412,0,0.28757601976394653,537,597 +dog_landing_hero_sm.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\dog_landing_hero_sm.jpg,0,0,430,521,0,0.9773207902908325,537,597 +e0dfdbdb_892b_4aad_84d6_03b5729899a1.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\e0dfdbdb_892b_4aad_84d6_03b5729899a1.jpg,61,101,183,265,0,0.3784005045890808,450,330 +e0dfdbdb_892b_4aad_84d6_03b5729899a1.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\e0dfdbdb_892b_4aad_84d6_03b5729899a1.jpg,16,61,217,284,0,0.9891906380653381,450,330 +Easter_Kittens_300x300.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Easter_Kittens_300x300.jpg,236,91,300,160,0,0.3217090964317322,300,300 +Easter_Kittens_300x300.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Easter_Kittens_300x300.jpg,93,71,193,162,0,0.4590582847595215,300,300 +Easter_Kittens_300x300.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Easter_Kittens_300x300.jpg,117,72,167,152,0,0.6096698641777039,300,300 +Easter_Kittens_300x300.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Easter_Kittens_300x300.jpg,177,72,242,129,0,0.9193726181983948,300,300 +Easter_Kittens_300x300.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Easter_Kittens_300x300.jpg,16,38,111,111,0,0.9278220534324646,300,300 +ECgQI_aWsAEBZL_.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\ECgQI_aWsAEBZL_.jpg,268,21,905,558,0,0.9543792605400085,1024,768 +Eloise1.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Eloise1.jpg,253,82,577,245,0,0.6300969123840332,960,640 +Eloise1.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Eloise1.jpg,132,19,682,319,0,0.8653026819229126,960,640 +Featured_Image_for_Cat.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Featured_Image_for_Cat.jpg,176,81,457,387,0,0.8383611440658569,600,600 +feline_3333896_640.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\feline_3333896_640.jpg,40,0,497,406,0,0.9973390102386475,640,480 +golden_retriever_puppy.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\golden_retriever_puppy.jpg,75,0,1020,734,0,0.3537549078464508,1100,734 +golden_retriever_puppy.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\golden_retriever_puppy.jpg,218,98,852,594,0,0.8527566194534302,1100,734 +husky_3380548__340.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\husky_3380548__340.jpg,75,0,288,274,0,0.9822015762329102,371,340 +image.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\image.jpg,24,209,141,252,0,0.5600805878639221,400,339 +image.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\image.jpg,74,110,205,162,0,0.6263542771339417,400,339 +IMG_6115.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\IMG_6115.jpg,158,68,980,966,0,0.9327203631401062,1164,1063 +KTYY2YRXUII6TA3V4POPNNUFLA.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\KTYY2YRXUII6TA3V4POPNNUFLA.jpg,221,0,1429,1153,0,0.9459948539733887,1484,1272 +Lagotto_Romangolo_Tongue_Out.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Lagotto_Romangolo_Tongue_Out.jpg,200,0,728,487,0,0.9349266290664673,729,487 +maxresdefault (1).jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\maxresdefault (1).jpg,307,120,1018,604,0,0.8544464707374573,1280,720 +maxresdefault.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\maxresdefault.jpg,377,18,665,466,0,0.4301752746105194,1280,720 +over_active_dog_211592482.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\over_active_dog_211592482.jpg,192,18,360,149,0,0.8399116396903992,590,428 +pearl_16x9.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\pearl_16x9.jpg,74,0,360,242,0,0.8910990953445435,450,253 +pets_4415649__340.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\pets_4415649__340.jpg,204,128,280,188,0,0.5803194046020508,513,340 +photo_1510771463146_e89e6e86560e.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\photo_1510771463146_e89e6e86560e.jpg,297,907,1061,1419,0,0.45940396189689636,1362,2421 +photo_1510771463146_e89e6e86560e.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\photo_1510771463146_e89e6e86560e.jpg,178,749,1198,1615,0,0.5203132629394531,1362,2421 +pomeranian_68.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\pomeranian_68.jpg,217,126,417,204,0,0.3358507454395294,640,430 +pomeranian_68.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\pomeranian_68.jpg,208,144,550,281,0,0.41130331158638,640,430 +pug.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\pug.jpg,33,5,360,293,0,0.9813269376754761,400,300 +puppy_1903313__340.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\puppy_1903313__340.jpg,181,64,418,217,0,0.43125417828559875,510,340 +puppy_1903313__340.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\puppy_1903313__340.jpg,234,99,370,178,0,0.5488850474357605,510,340 +puppy_dog.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\puppy_dog.jpg,166,100,369,196,0,0.4027504324913025,782,529 +samoyed_puppy_dog_pictures.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\samoyed_puppy_dog_pictures.jpg,125,68,261,233,0,0.8838149309158325,600,400 +Science_husky_1093906290.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Science_husky_1093906290.jpg,878,0,1289,1340,0,0.30920422077178955,2000,1500 +Science_husky_1093906290.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\Science_husky_1093906290.jpg,579,0,1492,1275,0,0.9669162631034851,2000,1500 +sei74187425.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\sei74187425.jpg,149,0,797,681,0,0.9778918623924255,968,681 +single_minded_royalty_free_image_997141470_1558379890.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\single_minded_royalty_free_image_997141470_1558379890.jpg,50,5,467,268,0,0.5080410838127136,640,480 +_107076735_shihtzu976.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\_107076735_shihtzu976.jpg,0,30,628,342,0,0.35563376545906067,660,371 +_107076735_shihtzu976.jpg,C:\Users\Anton\OneDrive\GitHub\TrainYourOwnYOLO\Data\Source_Images\Test_Images\_107076735_shihtzu976.jpg,213,0,541,362,0,0.8478137254714966,660,371 diff --git a/Data/Source_Images/Test_Image_Detection_Results/ECgQI_aWsAEBZL__catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/ECgQI_aWsAEBZL__catface.jpg new file mode 100644 index 0000000..58379e8 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/ECgQI_aWsAEBZL__catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/Easter_Kittens_300x300_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/Easter_Kittens_300x300_catface.jpg new file mode 100644 index 0000000..80b3c0c Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/Easter_Kittens_300x300_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/Eloise1_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/Eloise1_catface.jpg new file mode 100644 index 0000000..ee04177 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/Eloise1_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/Featured_Image_for_Cat_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/Featured_Image_for_Cat_catface.jpg new file mode 100644 index 0000000..c08747b Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/Featured_Image_for_Cat_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/IMG_6115_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/IMG_6115_catface.jpg new file mode 100644 index 0000000..0ecd23c Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/IMG_6115_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/KTYY2YRXUII6TA3V4POPNNUFLA_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/KTYY2YRXUII6TA3V4POPNNUFLA_catface.jpg new file mode 100644 index 0000000..f38b2aa Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/KTYY2YRXUII6TA3V4POPNNUFLA_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/Lagotto_Romangolo_Tongue_Out_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/Lagotto_Romangolo_Tongue_Out_catface.jpg new file mode 100644 index 0000000..da6e697 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/Lagotto_Romangolo_Tongue_Out_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/MonkeyVideo_catface.mp4 b/Data/Source_Images/Test_Image_Detection_Results/MonkeyVideo_catface.mp4 new file mode 100644 index 0000000..cce5420 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/MonkeyVideo_catface.mp4 differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/Science_husky_1093906290_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/Science_husky_1093906290_catface.jpg new file mode 100644 index 0000000..65f478b Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/Science_husky_1093906290_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/_107076735_shihtzu976_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/_107076735_shihtzu976_catface.jpg new file mode 100644 index 0000000..3ec9f1d Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/_107076735_shihtzu976_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/china_cloned_cat_2_0_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/china_cloned_cat_2_0_catface.jpg new file mode 100644 index 0000000..cceacc0 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/china_cloned_cat_2_0_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910_catface.jpg new file mode 100644 index 0000000..9ee252d Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/cute_puppy_body_image_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/cute_puppy_body_image_catface.jpg new file mode 100644 index 0000000..170c1af Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/cute_puppy_body_image_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/dog_landing_hero_lg_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/dog_landing_hero_lg_catface.jpg new file mode 100644 index 0000000..c600ac6 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/dog_landing_hero_lg_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/dog_landing_hero_sm_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/dog_landing_hero_sm_catface.jpg new file mode 100644 index 0000000..10e7df0 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/dog_landing_hero_sm_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/e0dfdbdb_892b_4aad_84d6_03b5729899a1_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/e0dfdbdb_892b_4aad_84d6_03b5729899a1_catface.jpg new file mode 100644 index 0000000..7ab9ba1 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/e0dfdbdb_892b_4aad_84d6_03b5729899a1_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/feline_3333896_640_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/feline_3333896_640_catface.jpg new file mode 100644 index 0000000..d97cce0 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/feline_3333896_640_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/golden_retriever_puppy_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/golden_retriever_puppy_catface.jpg new file mode 100644 index 0000000..3cbe7e6 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/golden_retriever_puppy_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/husky_3380548__340_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/husky_3380548__340_catface.jpg new file mode 100644 index 0000000..4d6b4bd Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/husky_3380548__340_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/image_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/image_catface.jpg new file mode 100644 index 0000000..1429522 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/image_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/maxresdefault (1)_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/maxresdefault (1)_catface.jpg new file mode 100644 index 0000000..23965a9 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/maxresdefault (1)_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/maxresdefault_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/maxresdefault_catface.jpg new file mode 100644 index 0000000..c449b4d Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/maxresdefault_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/over_active_dog_211592482_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/over_active_dog_211592482_catface.jpg new file mode 100644 index 0000000..e4e99f2 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/over_active_dog_211592482_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/pearl_16x9_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/pearl_16x9_catface.jpg new file mode 100644 index 0000000..fbb32a5 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/pearl_16x9_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/pets_4415649__340_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/pets_4415649__340_catface.jpg new file mode 100644 index 0000000..ee534d9 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/pets_4415649__340_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/photo_1510771463146_e89e6e86560e_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/photo_1510771463146_e89e6e86560e_catface.jpg new file mode 100644 index 0000000..beb3c40 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/photo_1510771463146_e89e6e86560e_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/pomeranian_68_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/pomeranian_68_catface.jpg new file mode 100644 index 0000000..2d8f7ed Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/pomeranian_68_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/pug_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/pug_catface.jpg new file mode 100644 index 0000000..93605df Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/pug_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/puppy_1903313__340_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/puppy_1903313__340_catface.jpg new file mode 100644 index 0000000..cb79527 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/puppy_1903313__340_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/puppy_dog_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/puppy_dog_catface.jpg new file mode 100644 index 0000000..0007a93 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/puppy_dog_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/samoyed_puppy_dog_pictures_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/samoyed_puppy_dog_pictures_catface.jpg new file mode 100644 index 0000000..f06977c Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/samoyed_puppy_dog_pictures_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/sei74187425_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/sei74187425_catface.jpg new file mode 100644 index 0000000..f6cdc0f Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/sei74187425_catface.jpg differ diff --git a/Data/Source_Images/Test_Image_Detection_Results/single_minded_royalty_free_image_997141470_1558379890_catface.jpg b/Data/Source_Images/Test_Image_Detection_Results/single_minded_royalty_free_image_997141470_1558379890_catface.jpg new file mode 100644 index 0000000..f61ae12 Binary files /dev/null and b/Data/Source_Images/Test_Image_Detection_Results/single_minded_royalty_free_image_997141470_1558379890_catface.jpg differ diff --git a/Data/Source_Images/Test_Images/04ebfcfd_fa70_4e49_84ff_66cf3c5c0407_best_cat_toys_for_older_cats_3.jpg b/Data/Source_Images/Test_Images/04ebfcfd_fa70_4e49_84ff_66cf3c5c0407_best_cat_toys_for_older_cats_3.jpg new file mode 100644 index 0000000..8376e0a Binary files /dev/null and b/Data/Source_Images/Test_Images/04ebfcfd_fa70_4e49_84ff_66cf3c5c0407_best_cat_toys_for_older_cats_3.jpg differ diff --git a/Data/Source_Images/Test_Images/0809_Cat_CNN.jpg b/Data/Source_Images/Test_Images/0809_Cat_CNN.jpg new file mode 100644 index 0000000..4a8ed5c Binary files /dev/null and b/Data/Source_Images/Test_Images/0809_Cat_CNN.jpg differ diff --git a/Data/Source_Images/Test_Images/0_Cat_research.jpg b/Data/Source_Images/Test_Images/0_Cat_research.jpg new file mode 100644 index 0000000..4ae0c23 Binary files /dev/null and b/Data/Source_Images/Test_Images/0_Cat_research.jpg differ diff --git a/Data/Source_Images/Test_Images/0_PAY_GRUMPY_CAT.jpg b/Data/Source_Images/Test_Images/0_PAY_GRUMPY_CAT.jpg new file mode 100644 index 0000000..aacc1a4 Binary files /dev/null and b/Data/Source_Images/Test_Images/0_PAY_GRUMPY_CAT.jpg differ diff --git a/Data/Source_Images/Test_Images/100.jpg b/Data/Source_Images/Test_Images/100.jpg new file mode 100644 index 0000000..bd69199 Binary files /dev/null and b/Data/Source_Images/Test_Images/100.jpg differ diff --git a/Data/Source_Images/Test_Images/10332358_3x2_700x467.jpg b/Data/Source_Images/Test_Images/10332358_3x2_700x467.jpg new file mode 100644 index 0000000..ce6ff51 Binary files /dev/null and b/Data/Source_Images/Test_Images/10332358_3x2_700x467.jpg differ diff --git a/Data/Source_Images/Test_Images/105488.jpg b/Data/Source_Images/Test_Images/105488.jpg new file mode 100644 index 0000000..f33893e Binary files /dev/null and b/Data/Source_Images/Test_Images/105488.jpg differ diff --git a/Data/Source_Images/Test_Images/105992231_1561667465295gettyimages_521697453.jpeg b/Data/Source_Images/Test_Images/105992231_1561667465295gettyimages_521697453.jpeg new file mode 100644 index 0000000..87c7f0e Binary files /dev/null and b/Data/Source_Images/Test_Images/105992231_1561667465295gettyimages_521697453.jpeg differ diff --git a/Data/Source_Images/Test_Images/1451208.jpg b/Data/Source_Images/Test_Images/1451208.jpg new file mode 100644 index 0000000..633e23e Binary files /dev/null and b/Data/Source_Images/Test_Images/1451208.jpg differ diff --git a/Data/Source_Images/Test_Images/14_20190709094206_8966619_large.jpg b/Data/Source_Images/Test_Images/14_20190709094206_8966619_large.jpg new file mode 100644 index 0000000..186184a Binary files /dev/null and b/Data/Source_Images/Test_Images/14_20190709094206_8966619_large.jpg differ diff --git a/Data/Source_Images/Test_Images/160825_vod_orig_historyofdogs_16x9_992.jpg b/Data/Source_Images/Test_Images/160825_vod_orig_historyofdogs_16x9_992.jpg new file mode 100644 index 0000000..0774d94 Binary files /dev/null and b/Data/Source_Images/Test_Images/160825_vod_orig_historyofdogs_16x9_992.jpg differ diff --git a/Data/Source_Images/Test_Images/17_cat_essentials.w700.h700.jpg b/Data/Source_Images/Test_Images/17_cat_essentials.w700.h700.jpg new file mode 100644 index 0000000..41b246d Binary files /dev/null and b/Data/Source_Images/Test_Images/17_cat_essentials.w700.h700.jpg differ diff --git a/Data/Source_Images/Test_Images/17_grumpy_cat_nymag_cover.w1200.h630.jpg b/Data/Source_Images/Test_Images/17_grumpy_cat_nymag_cover.w1200.h630.jpg new file mode 100644 index 0000000..1dbf002 Binary files /dev/null and b/Data/Source_Images/Test_Images/17_grumpy_cat_nymag_cover.w1200.h630.jpg differ diff --git a/Data/Source_Images/Test_Images/190207162239_01_fluffy_frozen_cat_trnd_exlarge_169.jpg b/Data/Source_Images/Test_Images/190207162239_01_fluffy_frozen_cat_trnd_exlarge_169.jpg new file mode 100644 index 0000000..1b3199e Binary files /dev/null and b/Data/Source_Images/Test_Images/190207162239_01_fluffy_frozen_cat_trnd_exlarge_169.jpg differ diff --git a/Data/Source_Images/Test_Images/1_3.jpg b/Data/Source_Images/Test_Images/1_3.jpg new file mode 100644 index 0000000..6137311 Binary files /dev/null and b/Data/Source_Images/Test_Images/1_3.jpg differ diff --git a/Data/Source_Images/Test_Images/20181204184341.jpeg b/Data/Source_Images/Test_Images/20181204184341.jpeg new file mode 100644 index 0000000..0c166a4 Binary files /dev/null and b/Data/Source_Images/Test_Images/20181204184341.jpeg differ diff --git a/Data/Source_Images/Test_Images/356950.jpg b/Data/Source_Images/Test_Images/356950.jpg new file mode 100644 index 0000000..7e08b5b Binary files /dev/null and b/Data/Source_Images/Test_Images/356950.jpg differ diff --git a/Data/Source_Images/Test_Images/36e85e4998d04dae9ebfc1c143a74b3d_edd828e54bf544d89229429d744d74b7_1_post.jpeg b/Data/Source_Images/Test_Images/36e85e4998d04dae9ebfc1c143a74b3d_edd828e54bf544d89229429d744d74b7_1_post.jpeg new file mode 100644 index 0000000..ca36eac Binary files /dev/null and b/Data/Source_Images/Test_Images/36e85e4998d04dae9ebfc1c143a74b3d_edd828e54bf544d89229429d744d74b7_1_post.jpeg differ diff --git a/Data/Source_Images/Test_Images/420508170.jpg b/Data/Source_Images/Test_Images/420508170.jpg new file mode 100644 index 0000000..52dd08c Binary files /dev/null and b/Data/Source_Images/Test_Images/420508170.jpg differ diff --git a/Data/Source_Images/Test_Images/49202627_303.jpg b/Data/Source_Images/Test_Images/49202627_303.jpg new file mode 100644 index 0000000..221375d Binary files /dev/null and b/Data/Source_Images/Test_Images/49202627_303.jpg differ diff --git a/Data/Source_Images/Test_Images/49a87dd8_035e_3f29_22f0_d762051e8f14.jpg b/Data/Source_Images/Test_Images/49a87dd8_035e_3f29_22f0_d762051e8f14.jpg new file mode 100644 index 0000000..6a9a35e Binary files /dev/null and b/Data/Source_Images/Test_Images/49a87dd8_035e_3f29_22f0_d762051e8f14.jpg differ diff --git a/Data/Source_Images/Test_Images/4e66a4d0_7f81_4bda_882d_d7a18937f061_poster.jpg b/Data/Source_Images/Test_Images/4e66a4d0_7f81_4bda_882d_d7a18937f061_poster.jpg new file mode 100644 index 0000000..63b2999 Binary files /dev/null and b/Data/Source_Images/Test_Images/4e66a4d0_7f81_4bda_882d_d7a18937f061_poster.jpg differ diff --git a/Data/Source_Images/Test_Images/5.jpg b/Data/Source_Images/Test_Images/5.jpg new file mode 100644 index 0000000..93f7eb0 Binary files /dev/null and b/Data/Source_Images/Test_Images/5.jpg differ diff --git a/Data/Source_Images/Test_Images/539814_istock_821264870.jpg b/Data/Source_Images/Test_Images/539814_istock_821264870.jpg new file mode 100644 index 0000000..2ae8ed9 Binary files /dev/null and b/Data/Source_Images/Test_Images/539814_istock_821264870.jpg differ diff --git a/Data/Source_Images/Test_Images/5aa10ca0d877e618008b4678_750_562.jpg b/Data/Source_Images/Test_Images/5aa10ca0d877e618008b4678_750_562.jpg new file mode 100644 index 0000000..3a5f056 Binary files /dev/null and b/Data/Source_Images/Test_Images/5aa10ca0d877e618008b4678_750_562.jpg differ diff --git a/Data/Source_Images/Test_Images/5b50bd5351dfbe1f008b45c5_750_562.jpg b/Data/Source_Images/Test_Images/5b50bd5351dfbe1f008b45c5_750_562.jpg new file mode 100644 index 0000000..fb23386 Binary files /dev/null and b/Data/Source_Images/Test_Images/5b50bd5351dfbe1f008b45c5_750_562.jpg differ diff --git a/Data/Source_Images/Test_Images/5d261a225562d.image.jpg b/Data/Source_Images/Test_Images/5d261a225562d.image.jpg new file mode 100644 index 0000000..10631bc Binary files /dev/null and b/Data/Source_Images/Test_Images/5d261a225562d.image.jpg differ diff --git a/Data/Source_Images/Test_Images/633bd23689846b66b7891edea332a350.jpg b/Data/Source_Images/Test_Images/633bd23689846b66b7891edea332a350.jpg new file mode 100644 index 0000000..7210fae Binary files /dev/null and b/Data/Source_Images/Test_Images/633bd23689846b66b7891edea332a350.jpg differ diff --git a/Data/Source_Images/Test_Images/66185314_2297595197159603_5846688980096480369_n.jpg b/Data/Source_Images/Test_Images/66185314_2297595197159603_5846688980096480369_n.jpg new file mode 100644 index 0000000..7248ff2 Binary files /dev/null and b/Data/Source_Images/Test_Images/66185314_2297595197159603_5846688980096480369_n.jpg differ diff --git a/Data/Source_Images/Test_Images/67056618_500x406.jpg b/Data/Source_Images/Test_Images/67056618_500x406.jpg new file mode 100644 index 0000000..c07992b Binary files /dev/null and b/Data/Source_Images/Test_Images/67056618_500x406.jpg differ diff --git a/Data/Source_Images/Test_Images/71aqYo6ZBpL._AC.jpg b/Data/Source_Images/Test_Images/71aqYo6ZBpL._AC.jpg new file mode 100644 index 0000000..ba5fd5c Binary files /dev/null and b/Data/Source_Images/Test_Images/71aqYo6ZBpL._AC.jpg differ diff --git a/Data/Source_Images/Test_Images/76DB73722C98408CB576F3C87486B768.jpg b/Data/Source_Images/Test_Images/76DB73722C98408CB576F3C87486B768.jpg new file mode 100644 index 0000000..64d4f59 Binary files /dev/null and b/Data/Source_Images/Test_Images/76DB73722C98408CB576F3C87486B768.jpg differ diff --git a/Data/Source_Images/Test_Images/961d1691_dfb88af9_1280w.jpg b/Data/Source_Images/Test_Images/961d1691_dfb88af9_1280w.jpg new file mode 100644 index 0000000..7042a3b Binary files /dev/null and b/Data/Source_Images/Test_Images/961d1691_dfb88af9_1280w.jpg differ diff --git a/Data/Source_Images/Test_Images/Borowitz_BorisJohnsonDog.jpg b/Data/Source_Images/Test_Images/Borowitz_BorisJohnsonDog.jpg new file mode 100644 index 0000000..eac69a0 Binary files /dev/null and b/Data/Source_Images/Test_Images/Borowitz_BorisJohnsonDog.jpg differ diff --git a/Data/Source_Images/Test_Images/Carolina_Dog.jpg b/Data/Source_Images/Test_Images/Carolina_Dog.jpg new file mode 100644 index 0000000..b701889 Binary files /dev/null and b/Data/Source_Images/Test_Images/Carolina_Dog.jpg differ diff --git a/Data/Source_Images/Test_Images/CatVideo.mp4 b/Data/Source_Images/Test_Images/CatVideo.mp4 new file mode 100644 index 0000000..5e6a40b Binary files /dev/null and b/Data/Source_Images/Test_Images/CatVideo.mp4 differ diff --git a/Data/Source_Images/Test_Images/Cookie_4b78befe.JPG b/Data/Source_Images/Test_Images/Cookie_4b78befe.JPG new file mode 100644 index 0000000..e2e88e9 Binary files /dev/null and b/Data/Source_Images/Test_Images/Cookie_4b78befe.JPG differ diff --git a/Data/Source_Images/Test_Images/ECgQI_aWsAEBZL_.jpg b/Data/Source_Images/Test_Images/ECgQI_aWsAEBZL_.jpg new file mode 100644 index 0000000..aca44f0 Binary files /dev/null and b/Data/Source_Images/Test_Images/ECgQI_aWsAEBZL_.jpg differ diff --git a/Data/Source_Images/Test_Images/Easter_Kittens_300x300.jpg b/Data/Source_Images/Test_Images/Easter_Kittens_300x300.jpg new file mode 100644 index 0000000..10de0c4 Binary files /dev/null and b/Data/Source_Images/Test_Images/Easter_Kittens_300x300.jpg differ diff --git a/Data/Source_Images/Test_Images/Eloise1.jpg b/Data/Source_Images/Test_Images/Eloise1.jpg new file mode 100644 index 0000000..3e15014 Binary files /dev/null and b/Data/Source_Images/Test_Images/Eloise1.jpg differ diff --git a/Data/Source_Images/Test_Images/Featured_Image_for_Cat.jpg b/Data/Source_Images/Test_Images/Featured_Image_for_Cat.jpg new file mode 100644 index 0000000..13893ec Binary files /dev/null and b/Data/Source_Images/Test_Images/Featured_Image_for_Cat.jpg differ diff --git a/Data/Source_Images/Test_Images/IMG_6115.jpg b/Data/Source_Images/Test_Images/IMG_6115.jpg new file mode 100644 index 0000000..b79fd8b Binary files /dev/null and b/Data/Source_Images/Test_Images/IMG_6115.jpg differ diff --git a/Data/Source_Images/Test_Images/KTYY2YRXUII6TA3V4POPNNUFLA.jpg b/Data/Source_Images/Test_Images/KTYY2YRXUII6TA3V4POPNNUFLA.jpg new file mode 100644 index 0000000..b5b5641 Binary files /dev/null and b/Data/Source_Images/Test_Images/KTYY2YRXUII6TA3V4POPNNUFLA.jpg differ diff --git a/Data/Source_Images/Test_Images/Lagotto_Romangolo_Tongue_Out.jpg b/Data/Source_Images/Test_Images/Lagotto_Romangolo_Tongue_Out.jpg new file mode 100644 index 0000000..4f0742f Binary files /dev/null and b/Data/Source_Images/Test_Images/Lagotto_Romangolo_Tongue_Out.jpg differ diff --git a/Data/Source_Images/Test_Images/MonkeyVideo.mp4 b/Data/Source_Images/Test_Images/MonkeyVideo.mp4 new file mode 100644 index 0000000..87c4e98 Binary files /dev/null and b/Data/Source_Images/Test_Images/MonkeyVideo.mp4 differ diff --git a/Data/Source_Images/Test_Images/Science_husky_1093906290.jpg b/Data/Source_Images/Test_Images/Science_husky_1093906290.jpg new file mode 100644 index 0000000..c6bf760 Binary files /dev/null and b/Data/Source_Images/Test_Images/Science_husky_1093906290.jpg differ diff --git a/Data/Source_Images/Test_Images/_107076735_shihtzu976.jpg b/Data/Source_Images/Test_Images/_107076735_shihtzu976.jpg new file mode 100644 index 0000000..f0d579f Binary files /dev/null and b/Data/Source_Images/Test_Images/_107076735_shihtzu976.jpg differ diff --git a/Data/Source_Images/Test_Images/china_cloned_cat_2_0.jpg b/Data/Source_Images/Test_Images/china_cloned_cat_2_0.jpg new file mode 100644 index 0000000..b9050d8 Binary files /dev/null and b/Data/Source_Images/Test_Images/china_cloned_cat_2_0.jpg differ diff --git a/Data/Source_Images/Test_Images/chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg b/Data/Source_Images/Test_Images/chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg new file mode 100644 index 0000000..e35d88b Binary files /dev/null and b/Data/Source_Images/Test_Images/chinese_company_that_cloned_a_pet_cat_now_want_to_copy_pets_t3h3.910.jpg differ diff --git a/Data/Source_Images/Test_Images/cute_puppy_body_image.jpg b/Data/Source_Images/Test_Images/cute_puppy_body_image.jpg new file mode 100644 index 0000000..d6b4364 Binary files /dev/null and b/Data/Source_Images/Test_Images/cute_puppy_body_image.jpg differ diff --git a/Data/Source_Images/Test_Images/dog_landing_hero_lg.jpg b/Data/Source_Images/Test_Images/dog_landing_hero_lg.jpg new file mode 100644 index 0000000..656a38e Binary files /dev/null and b/Data/Source_Images/Test_Images/dog_landing_hero_lg.jpg differ diff --git a/Data/Source_Images/Test_Images/dog_landing_hero_sm.jpg b/Data/Source_Images/Test_Images/dog_landing_hero_sm.jpg new file mode 100644 index 0000000..78a5d55 Binary files /dev/null and b/Data/Source_Images/Test_Images/dog_landing_hero_sm.jpg differ diff --git a/Data/Source_Images/Test_Images/e0dfdbdb_892b_4aad_84d6_03b5729899a1.jpg b/Data/Source_Images/Test_Images/e0dfdbdb_892b_4aad_84d6_03b5729899a1.jpg new file mode 100644 index 0000000..725dfc6 Binary files /dev/null and b/Data/Source_Images/Test_Images/e0dfdbdb_892b_4aad_84d6_03b5729899a1.jpg differ diff --git a/Data/Source_Images/Test_Images/feline_3333896_640.jpg b/Data/Source_Images/Test_Images/feline_3333896_640.jpg new file mode 100644 index 0000000..9763fe9 Binary files /dev/null and b/Data/Source_Images/Test_Images/feline_3333896_640.jpg differ diff --git a/Data/Source_Images/Test_Images/golden_retriever_puppy.jpg b/Data/Source_Images/Test_Images/golden_retriever_puppy.jpg new file mode 100644 index 0000000..ce06a14 Binary files /dev/null and b/Data/Source_Images/Test_Images/golden_retriever_puppy.jpg differ diff --git a/Data/Source_Images/Test_Images/husky_3380548__340.jpg b/Data/Source_Images/Test_Images/husky_3380548__340.jpg new file mode 100644 index 0000000..99743d6 Binary files /dev/null and b/Data/Source_Images/Test_Images/husky_3380548__340.jpg differ diff --git a/Data/Source_Images/Test_Images/image.jpg b/Data/Source_Images/Test_Images/image.jpg new file mode 100644 index 0000000..5350230 Binary files /dev/null and b/Data/Source_Images/Test_Images/image.jpg differ diff --git a/Data/Source_Images/Test_Images/maxresdefault (1).jpg b/Data/Source_Images/Test_Images/maxresdefault (1).jpg new file mode 100644 index 0000000..c011861 Binary files /dev/null and b/Data/Source_Images/Test_Images/maxresdefault (1).jpg differ diff --git a/Data/Source_Images/Test_Images/maxresdefault.jpg b/Data/Source_Images/Test_Images/maxresdefault.jpg new file mode 100644 index 0000000..e527e97 Binary files /dev/null and b/Data/Source_Images/Test_Images/maxresdefault.jpg differ diff --git a/Data/Source_Images/Test_Images/over_active_dog_211592482.jpg b/Data/Source_Images/Test_Images/over_active_dog_211592482.jpg new file mode 100644 index 0000000..9d360b3 Binary files /dev/null and b/Data/Source_Images/Test_Images/over_active_dog_211592482.jpg differ diff --git a/Data/Source_Images/Test_Images/pearl_16x9.jpg b/Data/Source_Images/Test_Images/pearl_16x9.jpg new file mode 100644 index 0000000..e38d126 Binary files /dev/null and b/Data/Source_Images/Test_Images/pearl_16x9.jpg differ diff --git a/Data/Source_Images/Test_Images/pets_4415649__340.jpg b/Data/Source_Images/Test_Images/pets_4415649__340.jpg new file mode 100644 index 0000000..a834a8c Binary files /dev/null and b/Data/Source_Images/Test_Images/pets_4415649__340.jpg differ diff --git a/Data/Source_Images/Test_Images/pexels_photo_1108099.jpeg b/Data/Source_Images/Test_Images/pexels_photo_1108099.jpeg new file mode 100644 index 0000000..a2bdd46 Binary files /dev/null and b/Data/Source_Images/Test_Images/pexels_photo_1108099.jpeg differ diff --git a/Data/Source_Images/Test_Images/photo_1510771463146_e89e6e86560e.jpg b/Data/Source_Images/Test_Images/photo_1510771463146_e89e6e86560e.jpg new file mode 100644 index 0000000..1e2e878 Binary files /dev/null and b/Data/Source_Images/Test_Images/photo_1510771463146_e89e6e86560e.jpg differ diff --git a/Data/Source_Images/Test_Images/pomeranian_68.jpg b/Data/Source_Images/Test_Images/pomeranian_68.jpg new file mode 100644 index 0000000..635d4c2 Binary files /dev/null and b/Data/Source_Images/Test_Images/pomeranian_68.jpg differ diff --git a/Data/Source_Images/Test_Images/pug.jpg b/Data/Source_Images/Test_Images/pug.jpg new file mode 100644 index 0000000..0a6376d Binary files /dev/null and b/Data/Source_Images/Test_Images/pug.jpg differ diff --git a/Data/Source_Images/Test_Images/puppy_1903313__340.jpg b/Data/Source_Images/Test_Images/puppy_1903313__340.jpg new file mode 100644 index 0000000..1d8121b Binary files /dev/null and b/Data/Source_Images/Test_Images/puppy_1903313__340.jpg differ diff --git a/Data/Source_Images/Test_Images/puppy_dog.jpg b/Data/Source_Images/Test_Images/puppy_dog.jpg new file mode 100644 index 0000000..4058c9c Binary files /dev/null and b/Data/Source_Images/Test_Images/puppy_dog.jpg differ diff --git a/Data/Source_Images/Test_Images/samoyed_puppy_dog_pictures.jpg b/Data/Source_Images/Test_Images/samoyed_puppy_dog_pictures.jpg new file mode 100644 index 0000000..64351f3 Binary files /dev/null and b/Data/Source_Images/Test_Images/samoyed_puppy_dog_pictures.jpg differ diff --git a/Data/Source_Images/Test_Images/sei74187425.jpg b/Data/Source_Images/Test_Images/sei74187425.jpg new file mode 100644 index 0000000..50645c5 Binary files /dev/null and b/Data/Source_Images/Test_Images/sei74187425.jpg differ diff --git a/Data/Source_Images/Test_Images/single_minded_royalty_free_image_997141470_1558379890.jpg b/Data/Source_Images/Test_Images/single_minded_royalty_free_image_997141470_1558379890.jpg new file mode 100644 index 0000000..8ef339c Binary files /dev/null and b/Data/Source_Images/Test_Images/single_minded_royalty_free_image_997141470_1558379890.jpg differ diff --git a/Data/Source_Images/Training_Images/2Q__%20(1).jpg b/Data/Source_Images/Training_Images/2Q__%20(1).jpg new file mode 100644 index 0000000..b509020 Binary files /dev/null and b/Data/Source_Images/Training_Images/2Q__%20(1).jpg differ diff --git a/Data/Source_Images/Training_Images/2Q__%20(2).jpg b/Data/Source_Images/Training_Images/2Q__%20(2).jpg new file mode 100644 index 0000000..1f7d937 Binary files /dev/null and b/Data/Source_Images/Training_Images/2Q__%20(2).jpg differ diff --git a/Data/Source_Images/Training_Images/2Q__.jpg b/Data/Source_Images/Training_Images/2Q__.jpg new file mode 100644 index 0000000..6cdfa3e Binary files /dev/null and b/Data/Source_Images/Training_Images/2Q__.jpg differ diff --git a/Data/Source_Images/Training_Images/9k_%20(1).jpg b/Data/Source_Images/Training_Images/9k_%20(1).jpg new file mode 100644 index 0000000..4e9612c Binary files /dev/null and b/Data/Source_Images/Training_Images/9k_%20(1).jpg differ diff --git a/Data/Source_Images/Training_Images/9k_%20(2).jpg b/Data/Source_Images/Training_Images/9k_%20(2).jpg new file mode 100644 index 0000000..f79f522 Binary files /dev/null and b/Data/Source_Images/Training_Images/9k_%20(2).jpg differ diff --git a/Data/Source_Images/Training_Images/9k_%20(3).jpg b/Data/Source_Images/Training_Images/9k_%20(3).jpg new file mode 100644 index 0000000..65f9186 Binary files /dev/null and b/Data/Source_Images/Training_Images/9k_%20(3).jpg differ diff --git a/Data/Source_Images/Training_Images/9k_%20(4).jpg b/Data/Source_Images/Training_Images/9k_%20(4).jpg new file mode 100644 index 0000000..9f54eab Binary files /dev/null and b/Data/Source_Images/Training_Images/9k_%20(4).jpg differ diff --git a/Data/Source_Images/Training_Images/9k_%20(5).jpg b/Data/Source_Images/Training_Images/9k_%20(5).jpg new file mode 100644 index 0000000..7a40dee Binary files /dev/null and b/Data/Source_Images/Training_Images/9k_%20(5).jpg differ diff --git a/Data/Source_Images/Training_Images/9k_%20(6).jpg b/Data/Source_Images/Training_Images/9k_%20(6).jpg new file mode 100644 index 0000000..7d7d99c Binary files /dev/null and b/Data/Source_Images/Training_Images/9k_%20(6).jpg differ diff --git a/Data/Source_Images/Training_Images/9k_%20(7).jpg b/Data/Source_Images/Training_Images/9k_%20(7).jpg new file mode 100644 index 0000000..57c072a Binary files /dev/null and b/Data/Source_Images/Training_Images/9k_%20(7).jpg differ diff --git a/Data/Source_Images/Training_Images/9k_.jpg b/Data/Source_Images/Training_Images/9k_.jpg new file mode 100644 index 0000000..224b586 Binary files /dev/null and b/Data/Source_Images/Training_Images/9k_.jpg differ diff --git a/Data/Source_Images/Training_Images/Z%20(1).jpg b/Data/Source_Images/Training_Images/Z%20(1).jpg new file mode 100644 index 0000000..16df506 Binary files /dev/null and b/Data/Source_Images/Training_Images/Z%20(1).jpg differ diff --git a/Data/Source_Images/Training_Images/Z%20(2).jpg b/Data/Source_Images/Training_Images/Z%20(2).jpg new file mode 100644 index 0000000..91f9dc6 Binary files /dev/null and b/Data/Source_Images/Training_Images/Z%20(2).jpg differ diff --git a/Data/Source_Images/Training_Images/Z%20(3).jpg b/Data/Source_Images/Training_Images/Z%20(3).jpg new file mode 100644 index 0000000..2291bb9 Binary files /dev/null and b/Data/Source_Images/Training_Images/Z%20(3).jpg differ diff --git a/Data/Source_Images/Training_Images/Z%20(4).jpg b/Data/Source_Images/Training_Images/Z%20(4).jpg new file mode 100644 index 0000000..2c1361e Binary files /dev/null and b/Data/Source_Images/Training_Images/Z%20(4).jpg differ diff --git a/Data/Source_Images/Training_Images/Z.jpg b/Data/Source_Images/Training_Images/Z.jpg new file mode 100644 index 0000000..35a173a Binary files /dev/null and b/Data/Source_Images/Training_Images/Z.jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(1).jpg b/Data/Source_Images/Training_Images/images%20(1).jpg new file mode 100644 index 0000000..76c117e Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(1).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(10).jpg b/Data/Source_Images/Training_Images/images%20(10).jpg new file mode 100644 index 0000000..a3d0a2a Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(10).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(100).jpg b/Data/Source_Images/Training_Images/images%20(100).jpg new file mode 100644 index 0000000..ea023aa Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(100).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(11).jpg b/Data/Source_Images/Training_Images/images%20(11).jpg new file mode 100644 index 0000000..92c1fd6 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(11).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(12).jpg b/Data/Source_Images/Training_Images/images%20(12).jpg new file mode 100644 index 0000000..54a9dcd Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(12).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(13).jpg b/Data/Source_Images/Training_Images/images%20(13).jpg new file mode 100644 index 0000000..4961eac Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(13).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(14).jpg b/Data/Source_Images/Training_Images/images%20(14).jpg new file mode 100644 index 0000000..d7b1862 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(14).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(15).jpg b/Data/Source_Images/Training_Images/images%20(15).jpg new file mode 100644 index 0000000..6c5a95b Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(15).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(16).jpg b/Data/Source_Images/Training_Images/images%20(16).jpg new file mode 100644 index 0000000..975d02b Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(16).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(17).jpg b/Data/Source_Images/Training_Images/images%20(17).jpg new file mode 100644 index 0000000..5b29d4a Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(17).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(18).jpg b/Data/Source_Images/Training_Images/images%20(18).jpg new file mode 100644 index 0000000..98b0542 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(18).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(19).jpg b/Data/Source_Images/Training_Images/images%20(19).jpg new file mode 100644 index 0000000..ccc332d Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(19).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(2).jpg b/Data/Source_Images/Training_Images/images%20(2).jpg new file mode 100644 index 0000000..6b2ca31 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(2).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(20).jpg b/Data/Source_Images/Training_Images/images%20(20).jpg new file mode 100644 index 0000000..6fa058e Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(20).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(21).jpg b/Data/Source_Images/Training_Images/images%20(21).jpg new file mode 100644 index 0000000..cb4fcf7 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(21).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(22).jpg b/Data/Source_Images/Training_Images/images%20(22).jpg new file mode 100644 index 0000000..1172670 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(22).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(23).jpg b/Data/Source_Images/Training_Images/images%20(23).jpg new file mode 100644 index 0000000..a7bb7a0 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(23).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(24).jpg b/Data/Source_Images/Training_Images/images%20(24).jpg new file mode 100644 index 0000000..14a676b Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(24).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(25).jpg b/Data/Source_Images/Training_Images/images%20(25).jpg new file mode 100644 index 0000000..1c33527 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(25).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(26).jpg b/Data/Source_Images/Training_Images/images%20(26).jpg new file mode 100644 index 0000000..e05729a Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(26).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(27).jpg b/Data/Source_Images/Training_Images/images%20(27).jpg new file mode 100644 index 0000000..087a839 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(27).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(28).jpg b/Data/Source_Images/Training_Images/images%20(28).jpg new file mode 100644 index 0000000..19440e7 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(28).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(29).jpg b/Data/Source_Images/Training_Images/images%20(29).jpg new file mode 100644 index 0000000..d208c3e Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(29).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(3).jpg b/Data/Source_Images/Training_Images/images%20(3).jpg new file mode 100644 index 0000000..4f69378 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(3).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(30).jpg b/Data/Source_Images/Training_Images/images%20(30).jpg new file mode 100644 index 0000000..0739749 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(30).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(31).jpg b/Data/Source_Images/Training_Images/images%20(31).jpg new file mode 100644 index 0000000..f3a57c5 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(31).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(32).jpg b/Data/Source_Images/Training_Images/images%20(32).jpg new file mode 100644 index 0000000..da291b2 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(32).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(33).jpg b/Data/Source_Images/Training_Images/images%20(33).jpg new file mode 100644 index 0000000..2647f54 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(33).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(34).jpg b/Data/Source_Images/Training_Images/images%20(34).jpg new file mode 100644 index 0000000..8296b8c Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(34).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(35).jpg b/Data/Source_Images/Training_Images/images%20(35).jpg new file mode 100644 index 0000000..a892f20 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(35).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(36).jpg b/Data/Source_Images/Training_Images/images%20(36).jpg new file mode 100644 index 0000000..8071c47 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(36).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(37).jpg b/Data/Source_Images/Training_Images/images%20(37).jpg new file mode 100644 index 0000000..329c347 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(37).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(38).jpg b/Data/Source_Images/Training_Images/images%20(38).jpg new file mode 100644 index 0000000..b7bd868 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(38).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(39).jpg b/Data/Source_Images/Training_Images/images%20(39).jpg new file mode 100644 index 0000000..9cf225b Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(39).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(4).jpg b/Data/Source_Images/Training_Images/images%20(4).jpg new file mode 100644 index 0000000..c11a6a1 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(4).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(40).jpg b/Data/Source_Images/Training_Images/images%20(40).jpg new file mode 100644 index 0000000..392db0b Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(40).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(41).jpg b/Data/Source_Images/Training_Images/images%20(41).jpg new file mode 100644 index 0000000..3e17dce Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(41).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(42).jpg b/Data/Source_Images/Training_Images/images%20(42).jpg new file mode 100644 index 0000000..8bcf556 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(42).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(43).jpg b/Data/Source_Images/Training_Images/images%20(43).jpg new file mode 100644 index 0000000..ab5f209 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(43).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(44).jpg b/Data/Source_Images/Training_Images/images%20(44).jpg new file mode 100644 index 0000000..e473286 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(44).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(45).jpg b/Data/Source_Images/Training_Images/images%20(45).jpg new file mode 100644 index 0000000..2ff4481 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(45).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(46).jpg b/Data/Source_Images/Training_Images/images%20(46).jpg new file mode 100644 index 0000000..66e3236 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(46).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(47).jpg b/Data/Source_Images/Training_Images/images%20(47).jpg new file mode 100644 index 0000000..daa3d80 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(47).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(48).jpg b/Data/Source_Images/Training_Images/images%20(48).jpg new file mode 100644 index 0000000..77c45f6 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(48).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(49).jpg b/Data/Source_Images/Training_Images/images%20(49).jpg new file mode 100644 index 0000000..906ff0b Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(49).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(5).jpg b/Data/Source_Images/Training_Images/images%20(5).jpg new file mode 100644 index 0000000..fd4d264 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(5).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(50).jpg b/Data/Source_Images/Training_Images/images%20(50).jpg new file mode 100644 index 0000000..a02e0d8 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(50).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(51).jpg b/Data/Source_Images/Training_Images/images%20(51).jpg new file mode 100644 index 0000000..e21de78 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(51).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(52).jpg b/Data/Source_Images/Training_Images/images%20(52).jpg new file mode 100644 index 0000000..c3f5642 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(52).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(53).jpg b/Data/Source_Images/Training_Images/images%20(53).jpg new file mode 100644 index 0000000..9ff5eed Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(53).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(54).jpg b/Data/Source_Images/Training_Images/images%20(54).jpg new file mode 100644 index 0000000..bac3cce Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(54).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(55).jpg b/Data/Source_Images/Training_Images/images%20(55).jpg new file mode 100644 index 0000000..9106261 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(55).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(56).jpg b/Data/Source_Images/Training_Images/images%20(56).jpg new file mode 100644 index 0000000..c40b55d Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(56).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(57).jpg b/Data/Source_Images/Training_Images/images%20(57).jpg new file mode 100644 index 0000000..79ac208 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(57).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(58).jpg b/Data/Source_Images/Training_Images/images%20(58).jpg new file mode 100644 index 0000000..0e5a9d6 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(58).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(59).jpg b/Data/Source_Images/Training_Images/images%20(59).jpg new file mode 100644 index 0000000..f1c5a89 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(59).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(6).jpg b/Data/Source_Images/Training_Images/images%20(6).jpg new file mode 100644 index 0000000..f35c474 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(6).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(60).jpg b/Data/Source_Images/Training_Images/images%20(60).jpg new file mode 100644 index 0000000..355f572 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(60).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(61).jpg b/Data/Source_Images/Training_Images/images%20(61).jpg new file mode 100644 index 0000000..d8cae10 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(61).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(62).jpg b/Data/Source_Images/Training_Images/images%20(62).jpg new file mode 100644 index 0000000..b4cf9dc Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(62).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(63).jpg b/Data/Source_Images/Training_Images/images%20(63).jpg new file mode 100644 index 0000000..fa2d720 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(63).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(64).jpg b/Data/Source_Images/Training_Images/images%20(64).jpg new file mode 100644 index 0000000..5bacea9 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(64).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(65).jpg b/Data/Source_Images/Training_Images/images%20(65).jpg new file mode 100644 index 0000000..3b63d72 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(65).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(66).jpg b/Data/Source_Images/Training_Images/images%20(66).jpg new file mode 100644 index 0000000..eefa4e6 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(66).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(67).jpg b/Data/Source_Images/Training_Images/images%20(67).jpg new file mode 100644 index 0000000..aeae2a0 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(67).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(68).jpg b/Data/Source_Images/Training_Images/images%20(68).jpg new file mode 100644 index 0000000..15455a6 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(68).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(69).jpg b/Data/Source_Images/Training_Images/images%20(69).jpg new file mode 100644 index 0000000..30c3b3e Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(69).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(7).jpg b/Data/Source_Images/Training_Images/images%20(7).jpg new file mode 100644 index 0000000..851b0e3 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(7).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(70).jpg b/Data/Source_Images/Training_Images/images%20(70).jpg new file mode 100644 index 0000000..03fa4bc Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(70).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(71).jpg b/Data/Source_Images/Training_Images/images%20(71).jpg new file mode 100644 index 0000000..38d8d8f Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(71).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(72).jpg b/Data/Source_Images/Training_Images/images%20(72).jpg new file mode 100644 index 0000000..7f7c86a Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(72).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(73).jpg b/Data/Source_Images/Training_Images/images%20(73).jpg new file mode 100644 index 0000000..70ab5fd Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(73).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(74).jpg b/Data/Source_Images/Training_Images/images%20(74).jpg new file mode 100644 index 0000000..84bf6c7 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(74).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(75).jpg b/Data/Source_Images/Training_Images/images%20(75).jpg new file mode 100644 index 0000000..8731629 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(75).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(76).jpg b/Data/Source_Images/Training_Images/images%20(76).jpg new file mode 100644 index 0000000..01300bd Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(76).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(77).jpg b/Data/Source_Images/Training_Images/images%20(77).jpg new file mode 100644 index 0000000..0622ade Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(77).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(78).jpg b/Data/Source_Images/Training_Images/images%20(78).jpg new file mode 100644 index 0000000..fca3ac4 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(78).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(79).jpg b/Data/Source_Images/Training_Images/images%20(79).jpg new file mode 100644 index 0000000..d6e8ddf Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(79).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(8).jpg b/Data/Source_Images/Training_Images/images%20(8).jpg new file mode 100644 index 0000000..52299d9 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(8).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(80).jpg b/Data/Source_Images/Training_Images/images%20(80).jpg new file mode 100644 index 0000000..95e902d Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(80).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(81).jpg b/Data/Source_Images/Training_Images/images%20(81).jpg new file mode 100644 index 0000000..845aa35 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(81).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(82).jpg b/Data/Source_Images/Training_Images/images%20(82).jpg new file mode 100644 index 0000000..e939214 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(82).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(83).jpg b/Data/Source_Images/Training_Images/images%20(83).jpg new file mode 100644 index 0000000..adddb99 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(83).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(84).jpg b/Data/Source_Images/Training_Images/images%20(84).jpg new file mode 100644 index 0000000..ed38fe9 Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(84).jpg differ diff --git a/Data/Source_Images/Training_Images/images%20(85).jpg b/Data/Source_Images/Training_Images/images%20(85).jpg new file mode 100644 index 0000000..dba6afe Binary files /dev/null and b/Data/Source_Images/Training_Images/images%20(85).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/2Q__%20(1).jpg b/Data/Source_Images/Training_Images/vott-csv-export/2Q__%20(1).jpg new file mode 100644 index 0000000..b509020 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/2Q__%20(1).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/2Q__%20(2).jpg b/Data/Source_Images/Training_Images/vott-csv-export/2Q__%20(2).jpg new file mode 100644 index 0000000..1f7d937 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/2Q__%20(2).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/2Q__.jpg b/Data/Source_Images/Training_Images/vott-csv-export/2Q__.jpg new file mode 100644 index 0000000..6cdfa3e Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/2Q__.jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(1).jpg b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(1).jpg new file mode 100644 index 0000000..4e9612c Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(1).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(2).jpg b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(2).jpg new file mode 100644 index 0000000..f79f522 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(2).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(3).jpg b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(3).jpg new file mode 100644 index 0000000..65f9186 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(3).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(4).jpg b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(4).jpg new file mode 100644 index 0000000..9f54eab Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(4).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(5).jpg b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(5).jpg new file mode 100644 index 0000000..7a40dee Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(5).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(6).jpg b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(6).jpg new file mode 100644 index 0000000..7d7d99c Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(6).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(7).jpg b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(7).jpg new file mode 100644 index 0000000..57c072a Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(7).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/9k_.jpg b/Data/Source_Images/Training_Images/vott-csv-export/9k_.jpg new file mode 100644 index 0000000..224b586 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/9k_.jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/Annotations-export.csv b/Data/Source_Images/Training_Images/vott-csv-export/Annotations-export.csv new file mode 100644 index 0000000..35f6871 --- /dev/null +++ b/Data/Source_Images/Training_Images/vott-csv-export/Annotations-export.csv @@ -0,0 +1,125 @@ +"image","xmin","ymin","xmax","ymax","label" +"9k_%20(1).jpg",79.57432922407541,3.0179032258064513,215.0891950688905,143.72129032258064,"Cat_Face" +"9k_%20(2).jpg",59.43710609243698,6.045714285714285,174.3266619147659,126.4342857142857,"Cat_Face" +"2Q__%20(1).jpg",26.52356780275562,15.133688842482101,106.929659173314,87.18022822195704,"Cat_Face" +"2Q__%20(2).jpg",86.63551136363635,2.3005714285714283,196.61732954545454,124.23085714285713,"Cat_Face" +"2Q__.jpg",3.4578606592465753,0.8868571428571429,106.12652504280823,103.31885714285714,"Cat_Face" +"9k_%20(4).jpg",95.65192168237853,29.751827267303103,150.57868020304568,79.45349791169451,"Cat_Face" +"9k_%20(5).jpg",135.09789702683102,4.32421875,265.69253081943435,130.57421875,"Cat_Face" +"9k_%20(3).jpg",65.82857142857142,48.857142857142854,177.17142857142855,152.74285714285713,"Cat_Face" +"9k_%20(6).jpg",145.25868486352357,54.57142857142857,212.95099255583125,129.22514285714286,"Cat_Face" +"9k_%20(7).jpg",80.65844815083393,39.45290322580645,179.530094271211,137.41790322580647,"Cat_Face" +"9k_%20(7).jpg",148.09064539521393,0,248.48005801305294,100.78306451612903,"Cat_Face" +"9k_.jpg",25.509090909090908,0,185.95369318181815,161.66742857142853,"Cat_Face" +"Z%20(2).jpg",187.30964467005077,0,268.67295141406817,69.77331606217615,"Cat_Face" +"Z%20(3).jpg",13.483670295489889,0,247.25349922239502,170.41142857142862,"Cat_Face" +"Z%20(4).jpg",79.95935828877006,58.28,184.91764705882355,171.61599999999999,"Cat_Face" +"Z%20(1).jpg",46.416052756654,3.7645714285714282,142.6137713878327,100.17942857142856,"Cat_Face" +"Z.jpg",117.18662827557058,22.057142857142857,235.000660397295,127.49028571428573,"Cat_Face" +"Z.jpg",5.550110946745562,84.25828571428572,103.50784551986476,179.54514285714288,"Cat_Face" +"images%20(1).jpg",8.831926323867997,9.252571428571429,194.93323100537222,168.64914285714286,"Cat_Face" +"images%20(10).jpg",55.808,23.296,118.52799999999999,82.176,"Cat_Face" +"images%20(100).jpg",109.02857142857141,86.14285714285714,153.77142857142854,123.94285714285714,"Cat_Face" +"images%20(11).jpg",122.69760696156635,18.85103626943005,193.18346627991298,88.48834196891191,"Cat_Face" +"images%20(14).jpg",6.816997518610422,22.483428571428572,195.0452853598015,182.48685714285713,"Cat_Face" +"images%20(12).jpg",94.72403754752852,51.239999999999995,186.11187024714832,120.04799999999999,"Cat_Face" +"images%20(13).jpg",67.98611408390411,14.411428571428573,183.07258668664383,108.64,"Cat_Face" +"images%20(15).jpg",28.285714285714285,7.971428571428571,137.57142857142856,119.05714285714285,"Cat_Face" +"images%20(15).jpg",66.6,55.028571428571425,195.42857142857142,193.37142857142857,"Cat_Face" +"images%20(16).jpg",22.97155928938356,8.203428571428573,210.3474154537671,181.14057142857143,"Cat_Face" +"images%20(18).jpg",47.20812182741117,4.705958549222798,251.26903553299493,168,"Cat_Face" +"images%20(17).jpg",74.2909429280397,12.224,180.6333746898263,97.57371428571429,"Cat_Face" +"images%20(19).jpg",153.15445975344454,1.8769430051813472,253.87962291515595,100.45725388601036,"Cat_Face" +"images%20(2).jpg",66.70122385931562,15.685714285714285,132.36662309885938,77.17371428571428,"Cat_Face" +"images%20(20).jpg",45.51428571428571,25.71428571428571,132.94285714285712,106.7142857142857,"Cat_Face" +"images%20(20).jpg",132.17142857142855,34.71428571428571,212.65714285714284,106.71428571428571,"Cat_Face" +"images%20(21).jpg",16.71428571428571,76.88571428571427,101.82857142857141,166.88571428571424,"Cat_Face" +"images%20(23).jpg",175.44647100760457,8.156571428571429,228.1460907794677,67.13485714285714,"Cat_Face" +"images%20(22).jpg",149.66062364031907,5.818478260869565,225.75924583031184,95.22717391304349,"Cat_Face" +"images%20(24).jpg",80.27556200145033,2.094559585492228,224.94561276287163,146.37435233160622,"Cat_Face" +"images%20(25).jpg",55.7001303127506,18.90742857142857,145.96476543704892,94.32228571428571,"Cat_Face" +"images%20(26).jpg",81.58375634517768,16.9225768321513,177.11167512690358,115.32446808510639,"Cat_Face" +"images%20(27).jpg",44.14344685242518,61.587428571428575,206.83488132094942,175.02514285714287,"Cat_Face" +"images%20(29).jpg",28.912915955631398,2.3040000000000003,179.93680674061432,154.88,"Cat_Face" +"images%20(28).jpg",162.5743292240754,27.24891304347826,277.87527193618564,112.27934782608696,"Cat_Face" +"images%20(3).jpg",13.096446700507613,9.238636363636363,108.26395939086294,112.22045454545453,"Cat_Face" +"images%20(30).jpg",122.3286002851711,64.62514285714285,158.50730750950572,111.89142857142856,"Cat_Face" +"images%20(31).jpg",153.2944162436548,83.44112903225806,179.74691805656272,109.88758064516128,"Cat_Face" +"images%20(32).jpg",142.19552043726236,21.12342857142857,221.87232652091257,90.768,"Cat_Face" +"images%20(33).jpg",128.5859318346628,16.647780172413793,288.86874546773026,163,"Cat_Face" +"images%20(34).jpg",65.01667875271937,101.86019405241936,85.2095721537346,122.48519405241936,"Cat_Face" +"images%20(34).jpg",93.4198694706309,81.45696824596774,119.16026105873823,104.07793598790323,"Cat_Face" +"images%20(34).jpg",123.82015953589558,82.27822580645162,149.11675126903555,104.74325856854838,"Cat_Face" +"images%20(34).jpg",150.44815083393763,83.896484375,175.3009427121102,107.40454889112902,"Cat_Face" +"images%20(34).jpg",180.1827411167513,84.56180695564517,206.1450326323423,111.61825856854838,"Cat_Face" +"images%20(34).jpg",212.58013052936911,94.6975806451613,238.7643219724438,117.60616179435482,"Cat_Face" +"images%20(34).jpg",242.75852066715012,110.06583921370968,261.84191443074695,132.46503276209677,"Cat_Face" +"images%20(36).jpg",76.53012119771863,23.424,169.80008317490496,110.84571428571428,"Cat_Face" +"images%20(35).jpg",46.265409717186365,24.86982315598549,145.10514865844814,146.05966596130594,"Cat_Face" +"images%20(35).jpg",130.80493110949962,7.827501511487304,249.62291515591005,127.9653491535671,"Cat_Face" +"images%20(37).jpg",95.89557650471356,10.352289903264813,170.97171863669325,74.31359582829505,"Cat_Face" +"images%20(38).jpg",67.328,19.968,172.288,111.104,"Cat_Face" +"images%20(39).jpg",8.45612762871646,9.593027920410783,145.7055837563452,123.2721036585366,"Cat_Face" +"images%20(4).jpg",108.54420206659013,27.257142857142853,188.26865671641792,98.22857142857141,"Cat_Face" +"images%20(40).jpg",171.58230601885424,3.140385230179028,278.5511240029007,109.4677509590793,"Cat_Face" +"images%20(42).jpg",106.16388687454678,6.664507772020725,195.14140681653373,86.96502590673575,"Cat_Face" +"images%20(41).jpg",56.60359801488834,39.728,237.40756823821343,170.26285714285714,"Cat_Face" +"images%20(43).jpg",77.78100072516315,38.006400862068965,106.10587382160986,72.62984913793103,"Cat_Face" +"images%20(44).jpg",55.04,5.12,217.344,176.64000000000001,"Cat_Face" +"images%20(46).jpg",67.2226250906454,55.84585492227979,157.94053662073966,117.64896373056995,"Cat_Face" +"images%20(45).jpg",15.579854757548034,16.53942857142857,243.38589318389756,187.21714285714285,"Cat_Face" +"images%20(47).jpg",54.362820817490494,4.810285714285714,163.73544439163499,101.01599999999999,"Cat_Face" +"images%20(48).jpg",54.766158276450504,41.984,99.56138011945391,86.528,"Cat_Face" +"images%20(49).jpg",195.395398957498,41.03771428571429,265.6728648757017,100.98285714285714,"Cat_Face" +"images%20(50).jpg",94.2829391891892,20.592,118.82197822822823,47.007999999999996,"Cat_Face" +"images%20(50).jpg",179.96161786786786,11.648,202.62903528528528,33.488,"Cat_Face" +"images%20(50).jpg",234.86251876876878,13.936,260.64930555555554,37.232,"Cat_Face" +"images%20(50).jpg",104.8108108108108,101.50399999999998,130.67558183183183,126.04799999999999,"Cat_Face" +"images%20(50).jpg",226.12828453453454,102.96,264.8084647147147,147.88799999999998,"Cat_Face" +"images%20(50).jpg",52.48338963963964,98.384,75.98263888888889,117.104,"Cat_Face" +"images%20(5).jpg",109.27918781725889,7.1366129032258065,212.05366207396668,109.90451612903226,"Cat_Face" +"images%20(51).jpg",20.322515408320495,3.574857142857143,118.33330123266565,83.6937142857143,"Cat_Face" +"images%20(51).jpg",175.96196070878275,46.47314285714286,273,168.22857142857146,"Cat_Face" +"images%20(52).jpg",164.15369534220534,27.18857142857143,223.54533032319392,84.49371428571428,"Cat_Face" +"images%20(53).jpg",0,0,109.929659173314,101.4333870967742,"Cat_Face" +"images%20(53).jpg",154.59535895576505,26.21274193548387,286.4242204496012,147.60629032258063,"Cat_Face" +"images%20(54).jpg",39.13836596385542,1.1142857142857143,205.1925828313253,149.98285714285717,"Cat_Face" +"images%20(56).jpg",62.74285714285713,14.399999999999999,179.2285714285714,123.94285714285712,"Cat_Face" +"images%20(57).jpg",120.89050036258159,58.77355573341094,188.02900652646846,121.61988867869616,"Cat_Face" +"images%20(58).jpg",76.20565530649588,29.633142857142857,224.78479528819764,168.38057142857144,"Cat_Face" +"images%20(59).jpg",95.39999999999999,1.7999999999999998,171.25714285714284,86.39999999999999,"Cat_Face" +"images%20(6).jpg",73.55837563451776,3.2847426470588235,130.746192893401,53.493892973856205,"Cat_Face" +"images%20(6).jpg",184.2233502538071,56.113500816993465,251.6700507614213,112.65337009803922,"Cat_Face" +"images%20(6).jpg",133.36548223350252,25.76970996732026,189.8984771573604,82.74618055555555,"Cat_Face" +"images%20(6).jpg",246.86802030456852,21.403696895424837,288.1218274111675,72.70435049019608,"Cat_Face" +"images%20(6).jpg",10.913705583756345,36.90304330065359,62.42639593908629,91.69650735294118,"Cat_Face" +"images%20(60).jpg",121.6047860768673,20.987942557803468,251.0253807106599,133.57464776011562,"Cat_Face" +"images%20(61).jpg",169.88324873096445,11.939086294416244,238.28426395939084,81.33502538071066,"Cat_Face" +"images%20(62).jpg",99.4198694706309,21.24481865284974,156.41769398114576,80.87176165803109,"Cat_Face" +"images%20(63).jpg",45.57955085551331,30.953142857142854,129.85711739543726,104.98971428571427,"Cat_Face" +"images%20(64).jpg",110.7599505723205,11.250285714285715,217.86713059313217,130.60114285714286,"Cat_Face" +"images%20(65).jpg",51.68571428571428,23.657142857142855,130.62857142857143,118.02857142857142,"Cat_Face" +"images%20(66).jpg",93.67841017110267,38.27314285714286,188.203125,124.44,"Cat_Face" +"images%20(67).jpg",75.64176939811458,2.836704147196262,190.13778100072517,113.0481527453271,"Cat_Face" +"images%20(69).jpg",54.38723712835388,16.892487046632123,237.9985496736766,165.5246113989637,"Cat_Face" +"images%20(68).jpg",119.43131956335617,13.302857142857144,244.2746414811644,136.79771428571428,"Cat_Face" +"images%20(68).jpg",30.067449700342465,22.614857142857144,130.9621414811644,125.04685714285715,"Cat_Face" +"images%20(7).jpg",70.5029535767235,19.65142857142857,121.38064075240919,64.74628571428572,"Cat_Face" +"images%20(70).jpg",176.43219724437998,7.0997409326424865,254.74981870920956,97.62823834196891,"Cat_Face" +"images%20(71).jpg",145.75065351711027,0,254.0776497148289,116.49257142857142,"Cat_Face" +"images%20(73).jpg",62.662073966642495,0,212.48730964467006,130.69790322580644,"Cat_Face" +"images%20(72).jpg",58.228608812074,5.204571428571429,211.31624269717622,153.77142857142857,"Cat_Face" +"images%20(74).jpg",176.6497461928934,53.90488966142684,241.6316171138506,113.02701783555018,"Cat_Face" +"images%20(75).jpg",26.340007129277566,28.652571428571427,165.82669914448672,147.65485714285714,"Cat_Face" +"images%20(76).jpg",15.346363054607508,6.4,84.20301834470989,81.92,"Cat_Face" +"images%20(78).jpg",47.31428571428571,22.37142857142857,183.08571428571426,149.9142857142857,"Cat_Face" +"images%20(77).jpg",82.28571428571428,62.74285714285713,134.2285714285714,119.82857142857142,"Cat_Face" +"images%20(79).jpg",103.43308933933935,5.2,179.54570195195197,55.952,"Cat_Face" +"images%20(8).jpg",86.36693255982597,0,292.8208846990573,162.99481865284974,"Cat_Face" +"images%20(80).jpg",101.83430370722434,64.83428571428571,132.15749762357416,103.31657142857142,"Cat_Face" +"images%20(81).jpg",66.78752719361857,1.4417098445595855,200.1450326323423,146.809585492228,"Cat_Face" +"images%20(82).jpg",76.39005681818182,16.313142857142857,190.3446022727273,138.45257142857142,"Cat_Face" +"images%20(83).jpg",97.09005681818181,5.437714285714286,263.7355113636363,166.26857142857142,"Cat_Face" +"images%20(84).jpg",45.685279187817265,6.882124352331605,147.49818709209572,99.01554404145077,"Cat_Face" +"images%20(85).jpg",54.82233502538071,33.86658031088083,92.67585206671501,78.91321243523316,"Cat_Face" +"images%20(85).jpg",216.02610587382162,31.25518134715026,251.26903553299493,70.20854922279793,"Cat_Face" \ No newline at end of file diff --git a/Data/Source_Images/Training_Images/vott-csv-export/Z%20(1).jpg b/Data/Source_Images/Training_Images/vott-csv-export/Z%20(1).jpg new file mode 100644 index 0000000..16df506 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/Z%20(1).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/Z%20(2).jpg b/Data/Source_Images/Training_Images/vott-csv-export/Z%20(2).jpg new file mode 100644 index 0000000..91f9dc6 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/Z%20(2).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/Z%20(3).jpg b/Data/Source_Images/Training_Images/vott-csv-export/Z%20(3).jpg new file mode 100644 index 0000000..2291bb9 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/Z%20(3).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/Z%20(4).jpg b/Data/Source_Images/Training_Images/vott-csv-export/Z%20(4).jpg new file mode 100644 index 0000000..2c1361e Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/Z%20(4).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/Z.jpg b/Data/Source_Images/Training_Images/vott-csv-export/Z.jpg new file mode 100644 index 0000000..35a173a Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/Z.jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/data_train.txt b/Data/Source_Images/Training_Images/vott-csv-export/data_train.txt new file mode 100644 index 0000000..43362b7 --- /dev/null +++ b/Data/Source_Images/Training_Images/vott-csv-export/data_train.txt @@ -0,0 +1,100 @@ +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(1).jpg 80,3,215,144,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(2).jpg 59,6,174,126,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/2Q__%20(1).jpg 27,15,107,87,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/2Q__%20(2).jpg 87,2,197,124,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/2Q__.jpg 3,1,106,103,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(4).jpg 96,30,151,79,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(5).jpg 135,4,266,131,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(3).jpg 66,49,177,153,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(6).jpg 145,55,213,129,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/9k_%20(7).jpg 81,39,180,137,0 148,0,248,101,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/9k_.jpg 26,0,186,162,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/Z%20(2).jpg 187,0,269,70,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/Z%20(3).jpg 13,0,247,170,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/Z%20(4).jpg 80,58,185,172,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/Z%20(1).jpg 46,4,143,100,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/Z.jpg 117,22,235,127,0 6,84,104,180,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(1).jpg 9,9,195,169,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(10).jpg 56,23,119,82,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(100).jpg 109,86,154,124,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(11).jpg 123,19,193,88,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(14).jpg 7,22,195,182,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(12).jpg 95,51,186,120,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(13).jpg 68,14,183,109,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(15).jpg 28,8,138,119,0 67,55,195,193,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(16).jpg 23,8,210,181,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(18).jpg 47,5,251,168,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(17).jpg 74,12,181,98,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(19).jpg 153,2,254,100,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(2).jpg 67,16,132,77,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(20).jpg 46,26,133,107,0 132,35,213,107,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(21).jpg 17,77,102,167,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(23).jpg 175,8,228,67,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(22).jpg 150,6,226,95,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(24).jpg 80,2,225,146,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(25).jpg 56,19,146,94,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(26).jpg 82,17,177,115,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(27).jpg 44,62,207,175,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(29).jpg 29,2,180,155,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(28).jpg 163,27,278,112,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(3).jpg 13,9,108,112,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(30).jpg 122,65,159,112,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(31).jpg 153,83,180,110,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(32).jpg 142,21,222,91,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(33).jpg 129,17,289,163,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(34).jpg 65,102,85,122,0 93,81,119,104,0 124,82,149,105,0 150,84,175,107,0 180,85,206,112,0 213,95,239,118,0 243,110,262,132,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(36).jpg 77,23,170,111,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(35).jpg 46,25,145,146,0 131,8,250,128,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(37).jpg 96,10,171,74,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(38).jpg 67,20,172,111,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(39).jpg 8,10,146,123,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(4).jpg 109,27,188,98,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(40).jpg 172,3,279,109,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(42).jpg 106,7,195,87,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(41).jpg 57,40,237,170,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(43).jpg 78,38,106,73,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(44).jpg 55,5,217,177,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(46).jpg 67,56,158,118,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(45).jpg 16,17,243,187,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(47).jpg 54,5,164,101,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(48).jpg 55,42,100,87,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(49).jpg 195,41,266,101,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(50).jpg 94,21,119,47,0 180,12,203,33,0 235,14,261,37,0 105,102,131,126,0 226,103,265,148,0 52,98,76,117,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(5).jpg 109,7,212,110,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(51).jpg 20,4,118,84,0 176,46,273,168,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(52).jpg 164,27,224,84,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(53).jpg 0,0,110,101,0 155,26,286,148,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(54).jpg 39,1,205,150,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(56).jpg 63,14,179,124,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(57).jpg 121,59,188,122,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(58).jpg 76,30,225,168,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(59).jpg 95,2,171,86,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(6).jpg 74,3,131,53,0 184,56,252,113,0 133,26,190,83,0 247,21,288,73,0 11,37,62,92,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(60).jpg 122,21,251,134,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(61).jpg 170,12,238,81,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(62).jpg 99,21,156,81,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(63).jpg 46,31,130,105,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(64).jpg 111,11,218,131,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(65).jpg 52,24,131,118,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(66).jpg 94,38,188,124,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(67).jpg 76,3,190,113,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(69).jpg 54,17,238,166,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(68).jpg 119,13,244,137,0 30,23,131,125,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(7).jpg 71,20,121,65,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(70).jpg 176,7,255,98,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(71).jpg 146,0,254,116,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(73).jpg 63,0,212,131,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(72).jpg 58,5,211,154,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(74).jpg 177,54,242,113,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(75).jpg 26,29,166,148,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(76).jpg 15,6,84,82,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(78).jpg 47,22,183,150,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(77).jpg 82,63,134,120,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(79).jpg 103,5,180,56,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(8).jpg 86,0,293,163,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(80).jpg 102,65,132,103,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(81).jpg 67,1,200,147,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(82).jpg 76,16,190,138,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(83).jpg 97,5,264,166,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(84).jpg 46,7,147,99,0 +/home/ubuntu/TrainYourOwnYOLO/Data/Source_Images/Training_Images/vott-csv-export/images%20(85).jpg 55,34,93,79,0 216,31,251,70,0 diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(1).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(1).jpg new file mode 100644 index 0000000..76c117e Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(1).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(10).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(10).jpg new file mode 100644 index 0000000..a3d0a2a Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(10).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(100).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(100).jpg new file mode 100644 index 0000000..ea023aa Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(100).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(11).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(11).jpg new file mode 100644 index 0000000..92c1fd6 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(11).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(12).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(12).jpg new file mode 100644 index 0000000..54a9dcd Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(12).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(13).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(13).jpg new file mode 100644 index 0000000..4961eac Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(13).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(14).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(14).jpg new file mode 100644 index 0000000..d7b1862 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(14).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(15).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(15).jpg new file mode 100644 index 0000000..6c5a95b Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(15).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(16).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(16).jpg new file mode 100644 index 0000000..975d02b Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(16).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(17).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(17).jpg new file mode 100644 index 0000000..5b29d4a Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(17).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(18).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(18).jpg new file mode 100644 index 0000000..98b0542 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(18).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(19).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(19).jpg new file mode 100644 index 0000000..ccc332d Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(19).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(2).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(2).jpg new file mode 100644 index 0000000..6b2ca31 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(2).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(20).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(20).jpg new file mode 100644 index 0000000..6fa058e Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(20).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(21).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(21).jpg new file mode 100644 index 0000000..cb4fcf7 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(21).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(22).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(22).jpg new file mode 100644 index 0000000..1172670 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(22).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(23).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(23).jpg new file mode 100644 index 0000000..a7bb7a0 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(23).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(24).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(24).jpg new file mode 100644 index 0000000..14a676b Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(24).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(25).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(25).jpg new file mode 100644 index 0000000..1c33527 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(25).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(26).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(26).jpg new file mode 100644 index 0000000..e05729a Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(26).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(27).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(27).jpg new file mode 100644 index 0000000..087a839 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(27).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(28).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(28).jpg new file mode 100644 index 0000000..19440e7 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(28).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(29).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(29).jpg new file mode 100644 index 0000000..d208c3e Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(29).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(3).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(3).jpg new file mode 100644 index 0000000..4f69378 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(3).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(30).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(30).jpg new file mode 100644 index 0000000..0739749 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(30).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(31).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(31).jpg new file mode 100644 index 0000000..f3a57c5 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(31).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(32).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(32).jpg new file mode 100644 index 0000000..da291b2 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(32).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(33).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(33).jpg new file mode 100644 index 0000000..2647f54 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(33).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(34).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(34).jpg new file mode 100644 index 0000000..8296b8c Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(34).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(35).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(35).jpg new file mode 100644 index 0000000..a892f20 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(35).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(36).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(36).jpg new file mode 100644 index 0000000..8071c47 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(36).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(37).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(37).jpg new file mode 100644 index 0000000..329c347 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(37).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(38).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(38).jpg new file mode 100644 index 0000000..b7bd868 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(38).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(39).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(39).jpg new file mode 100644 index 0000000..9cf225b Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(39).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(4).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(4).jpg new file mode 100644 index 0000000..c11a6a1 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(4).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(40).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(40).jpg new file mode 100644 index 0000000..392db0b Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(40).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(41).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(41).jpg new file mode 100644 index 0000000..3e17dce Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(41).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(42).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(42).jpg new file mode 100644 index 0000000..8bcf556 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(42).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(43).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(43).jpg new file mode 100644 index 0000000..ab5f209 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(43).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(44).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(44).jpg new file mode 100644 index 0000000..e473286 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(44).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(45).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(45).jpg new file mode 100644 index 0000000..2ff4481 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(45).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(46).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(46).jpg new file mode 100644 index 0000000..66e3236 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(46).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(47).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(47).jpg new file mode 100644 index 0000000..daa3d80 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(47).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(48).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(48).jpg new file mode 100644 index 0000000..77c45f6 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(48).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(49).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(49).jpg new file mode 100644 index 0000000..906ff0b Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(49).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(5).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(5).jpg new file mode 100644 index 0000000..fd4d264 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(5).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(50).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(50).jpg new file mode 100644 index 0000000..a02e0d8 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(50).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(51).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(51).jpg new file mode 100644 index 0000000..e21de78 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(51).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(52).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(52).jpg new file mode 100644 index 0000000..c3f5642 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(52).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(53).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(53).jpg new file mode 100644 index 0000000..9ff5eed Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(53).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(54).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(54).jpg new file mode 100644 index 0000000..bac3cce Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(54).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(55).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(55).jpg new file mode 100644 index 0000000..9106261 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(55).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(56).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(56).jpg new file mode 100644 index 0000000..c40b55d Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(56).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(57).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(57).jpg new file mode 100644 index 0000000..79ac208 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(57).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(58).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(58).jpg new file mode 100644 index 0000000..0e5a9d6 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(58).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(59).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(59).jpg new file mode 100644 index 0000000..f1c5a89 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(59).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(6).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(6).jpg new file mode 100644 index 0000000..f35c474 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(6).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(60).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(60).jpg new file mode 100644 index 0000000..355f572 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(60).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(61).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(61).jpg new file mode 100644 index 0000000..d8cae10 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(61).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(62).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(62).jpg new file mode 100644 index 0000000..b4cf9dc Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(62).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(63).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(63).jpg new file mode 100644 index 0000000..fa2d720 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(63).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(64).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(64).jpg new file mode 100644 index 0000000..5bacea9 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(64).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(65).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(65).jpg new file mode 100644 index 0000000..3b63d72 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(65).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(66).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(66).jpg new file mode 100644 index 0000000..eefa4e6 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(66).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(67).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(67).jpg new file mode 100644 index 0000000..aeae2a0 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(67).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(68).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(68).jpg new file mode 100644 index 0000000..15455a6 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(68).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(69).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(69).jpg new file mode 100644 index 0000000..30c3b3e Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(69).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(7).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(7).jpg new file mode 100644 index 0000000..851b0e3 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(7).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(70).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(70).jpg new file mode 100644 index 0000000..03fa4bc Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(70).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(71).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(71).jpg new file mode 100644 index 0000000..38d8d8f Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(71).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(72).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(72).jpg new file mode 100644 index 0000000..7f7c86a Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(72).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(73).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(73).jpg new file mode 100644 index 0000000..70ab5fd Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(73).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(74).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(74).jpg new file mode 100644 index 0000000..84bf6c7 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(74).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(75).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(75).jpg new file mode 100644 index 0000000..8731629 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(75).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(76).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(76).jpg new file mode 100644 index 0000000..01300bd Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(76).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(77).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(77).jpg new file mode 100644 index 0000000..0622ade Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(77).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(78).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(78).jpg new file mode 100644 index 0000000..fca3ac4 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(78).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(79).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(79).jpg new file mode 100644 index 0000000..d6e8ddf Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(79).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(8).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(8).jpg new file mode 100644 index 0000000..52299d9 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(8).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(80).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(80).jpg new file mode 100644 index 0000000..95e902d Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(80).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(81).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(81).jpg new file mode 100644 index 0000000..845aa35 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(81).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(82).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(82).jpg new file mode 100644 index 0000000..e939214 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(82).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(83).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(83).jpg new file mode 100644 index 0000000..adddb99 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(83).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(84).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(84).jpg new file mode 100644 index 0000000..ed38fe9 Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(84).jpg differ diff --git a/Data/Source_Images/Training_Images/vott-csv-export/images%20(85).jpg b/Data/Source_Images/Training_Images/vott-csv-export/images%20(85).jpg new file mode 100644 index 0000000..dba6afe Binary files /dev/null and b/Data/Source_Images/Training_Images/vott-csv-export/images%20(85).jpg differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5bcdfb4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 AntonMu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Minimal_Example.py b/Minimal_Example.py new file mode 100644 index 0000000..a07ed9f --- /dev/null +++ b/Minimal_Example.py @@ -0,0 +1,73 @@ +import os +import subprocess +import time +import sys + + +def make_call_string(arglist): + result_string = "" + for arg in arglist: + result_string += "".join(["--", arg[0], " ", arg[1], " "]) + return result_string + + +root_folder = os.path.dirname(os.path.abspath(__file__)) +data_folder = os.path.join(root_folder, "Data") +model_folder = os.path.join(data_folder, "Model_Weights") +image_folder = os.path.join(data_folder, "Source_Images") +input_folder = os.path.join(image_folder, "Test_Images") +output_folder = os.path.join(image_folder, "Test_Image_Detection_Results") + + +if not os.path.exists(output_folder): + os.mkdir(output_folder) + +# First download the pre-trained weights +download_script = os.path.join(model_folder, "Download_Weights.py") + +if not os.path.isfile(os.path.join(model_folder, "trained_weights_final.h5")): + print("\n", "Downloading Pretrained Weights", "\n") + start = time.time() + call_string = " ".join( + [ + "python", + download_script, + "1MGXAP_XD_w4OExPP10UHsejWrMww8Tu7", + os.path.join(model_folder, "trained_weights_final.h5"), + ] + ) + + subprocess.call(call_string, shell=True) + + end = time.time() + print("Downloaded Pretrained Weights in {0:.1f} seconds".format(end - start), "\n") + +# Now run the cat face detector +detector_script = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "3_Inference", "Detector.py" +) + + +result_file = os.path.join(output_folder, "Detection_Results.csv") +model_weights = os.path.join(model_folder, "trained_weights_final.h5") +classes_file = os.path.join(model_folder, "data_classes.txt") +anchors = os.path.join( + root_folder, "2_Training", "src", "keras_yolo3", "model_data", "yolo_anchors.txt" +) + +arglist = [ + ["input_path", input_folder], + ["classes", classes_file], + ["output", output_folder], + ["yolo_model", model_weights], + ["box_file", result_file], + ["anchors", anchors], + ["file_types", ".jpg .jpeg .png"], +] +call_string = " ".join(["python", detector_script, make_call_string(arglist)]) + +print("Detecting Cat Faces by calling: \n\n", call_string, "\n") +start = time.time() +subprocess.call(call_string, shell=True) +end = time.time() +print("Detected Cat Faces in {0:.1f} seconds".format(end - start)) diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b6b40d --- /dev/null +++ b/README.md @@ -0,0 +1,183 @@ +# TrainYourOwnYOLO: Building a Custom Object Detector from Scratch [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) + +This repo let's you train a custom image detector using the state-of-the-art [YOLOv3](https://pjreddie.com/darknet/yolo/) computer vision algorithm. For a short write up check out this [medium post](https://medium.com/@muehle/how-to-train-your-own-yolov3-detector-from-scratch-224d10e55de2). + +### Pipeline Overview + +To build and test your YOLO object detection algorithm follow the below steps: + + 1. [Image Annotation](/1_Image_Annotation/) + - Install Microsoft's Visual Object Tagging Tool (VoTT) + - Annotate images + 2. [Training](/2_Training/) + - Download pre-trained weights + - Train your custom YOLO model on annotated images + 3. [Inference](/3_Inference/) + - Detect objects in new images and videos + +## Repo structure ++ [`1_Image_Annotation`](/1_Image_Annotation/): Scripts and instructions on annotating images ++ [`2_Training`](/2_Training/): Scripts and instructions on training your YOLOv3 model ++ [`3_Inference`](/3_Inference/): Scripts and instructions on testing your trained YOLO model on new images and videos ++ [`Data`](/Data/): Input Data, Output Data, Model Weights and Results ++ [`Utils`](/Utils/): Utility scripts used by main scripts + +## Getting Started + +### Requisites +The only hard requirement is a running version of python 3.6 or 3.7. To install python 3.7 go to +- [python.org/downloads](https://www.python.org/downloads/release/python-376/) + +and follow the installation instructions. Note that this repo has only been tested with python 3.6 and python 3.7 thus it is recommened to use either `python3.6` or `python3.7`. + +To speed up training, it is recommended to use a **GPU with CUDA** support. For example on [AWS](/2_Training/AWS/) you can use a `p2.xlarge` instance (Tesla K80 GPU with 12GB memory). Inference is very fast even on a CPU with approximately ~2 images per second. + + +### Installation + +#### Setting up Virtual Environment [Linux or Mac] + +Clone this repo with: +``` +git clone https://github.com/AntonMu/TrainYourOwnYOLO +cd TrainYourOwnYOLO/ +``` +Create Virtual **(Linux/Mac)** Environment: +``` +python3 -m venv env +source env/bin/activate +``` +Make sure that, from now on, you **run all commands from within your virtual environment**. + +#### Setting up Virtual Environment [Windows] +Use the [Github Desktop GUI](https://desktop.github.com/) to clone this repo to your local machine. Navigate to the `TrainYourOwnYOLO` project folder and open a power shell window by pressing **Shift + Right Click** and selecting `Open PowerShell window here` in the drop-down menu. + +Create Virtual **(Windows)** Environment: + +``` +py -m venv env +.\env\Scripts\activate +``` +![PowerShell](/Utils/Screenshots/PowerShell.png) +Make sure that, from now on, you **run all commands from within your virtual environment**. + +#### Install Required Packages [Windows, Mac or Linux] +Install required packages (from within your virtual environment) via: + +``` +pip install -r requirements.txt +``` +If this fails, you may have to upgrade your pip version first with `pip install pip --upgrade`. + +## Quick Start (Inference only) +To test the cat face detector on test images located in [`TrainYourOwnYOLO/Data/Source_Images/Test_Images`](/Data/Source_Images/Test_Images) run the `Minimal_Example.py` script in the root folder with: + +``` +python Minimal_Example.py +``` + +The outputs are saved in [`TrainYourOwnYOLO/Data/Source_Images/Test_Image_Detection_Results`](/Data/Source_Images/Test_Image_Detection_Results). This includes: + - Cat pictures with bounding boxes around faces with confidence scores and + - [`Detection_Results.csv`](/Data/Source_Images/Test_Image_Detection_Results/Detection_Results.csv) file with file names and locations of bounding boxes. + + If you want to detect cat faces in your own pictures, replace the cat images in [`Data/Source_Images/Test_Images`](/Data/Source_Images/Test_Images) with your own images. + +## Full Start (Training and Inference) + +To train your own custom YOLO object detector please follow the instructions detailed in the three numbered subfolders of this repo: +- [`1_Image_Annotation`](/1_Image_Annotation/), +- [`2_Training`](/2_Training/) and +- [`3_Inference`](/3_Inference/). + +**To make everything run smoothly it is highly recommended to keep the original folder structure of this repo!** + +Each `*.py` script has various command line options that help tweak performance and change things such as input and output directories. All scripts are initialized with good default values that help accomplish all tasks as long as the original folder structure is preserved. To learn more about available command line options of a python script `` run: + +``` +python -h +``` + +## License + +Unless explicitly stated otherwise at the top of a file, all code is licensed under the MIT license. This repo makes use of [**ilmonteux/logohunter**](https://github.com/ilmonteux/logohunter) which itself is inspired by [**qqwweee/keras-yolo3**](https://github.com/qqwweee/keras-yolo3). + +## Acknowledgements +Many thanks to [Niklas Wilson](https://github.com/NiklasWilson) for contributing towards making this repo compatible with Tensorflow 2.0. + +## Troubleshooting + +0. If you encounter any error, please make sure you follow the instructions **exactly** (word by word). Once you are familiar with the code, you're welcome to modify it as needed but in order to minimize error, I encourage you to not deviate from the instructions above. If you would like to file an issue, please use the provided template and make sure to fill out all fields. + +1. If you encounter a `FileNotFoundError` or a `Module not found` error, make sure that you did not change the folder structure. In particular, your working directory needs to look like this: + ``` + TrainYourOwnYOLO + └─── 1_Image_Annotation + └─── 2_Training + └─── 3_Inference + └─── Data + └─── Utils + ``` + If you want to use a different folder layout (not recommended) you will have to specify your paths as command line arguments. Also, try to avoid spaces in folder names, i.e. don't use a folder name like this `my folder` but instead use `my_folder`. + +2. If you are using [pipenv](https://github.com/pypa/pipenv) and are having trouble running `python3 -m venv env`, try: + ``` + pipenv shell + ``` + +3. If you are having trouble getting cv2 to run, try: + + ``` + apt-get update + apt-get install -y libsm6 libxext6 libxrender-dev + pip install opencv-python + ``` + +4. If you are a Linux user and having trouble installing `*.snap` package files try: + ``` + snap install --dangerous vott-2.1.0-linux.snap + ``` + See [Snap Tutorial](https://tutorials.ubuntu.com/tutorial/advanced-snap-usage#2) for more information. + +## Need more help? File an Issue! +If you would like to file an issue, please use the provided issue template and make sure to complete all fields. This makes it easier to reproduce the issue for someone trying to help you. + +![Issue](/Utils/Screenshots/Issue.gif) + +Issues without a completed issue template will be closed after 7 days. + +## Stay Up-to-Date + +- ⭐ **star** this repo to get notifications on future improvements and +- 🍴 **fork** this repo if you like to use it as part of your own project. + +![CatVideo](/Utils/Screenshots/CatVideo.gif) + +## Licensing +This work is licensed under a [Creative Commons Attribution 4.0 International +License][cc-by]. This means that you are free to: + + * **Share** — copy and redistribute the material in any medium or format + * **Adapt** — remix, transform, and build upon the material for any purpose, even commercially. + +Under the following terms: + + * **Attribution** + + Cite as: + + ``` + @misc{TrainYourOwnYOLO, + title={TrainYourOwnYOLO: Building a Custom Object Detector from Scratch}, + author={Anton Muehlemann}, + year={2019}, + url={https://github.com/AntonMu/TrainYourOwnYOLO} + } + ``` +If your work doesn't include a citation list, simply link this [github repo](https://github.com/AntonMu/TrainYourOwnYOLO)! + +[![CC BY 4.0][cc-by-image]][cc-by] + +[cc-by]: http://creativecommons.org/licenses/by/4.0/ +[cc-by-image]: https://i.creativecommons.org/l/by/4.0/88x31.png +[cc-by-shield]: https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg + diff --git a/Utils/Convert_Format.py b/Utils/Convert_Format.py new file mode 100644 index 0000000..f510040 --- /dev/null +++ b/Utils/Convert_Format.py @@ -0,0 +1,213 @@ +from os import path, makedirs +import pandas as pd +import numpy as np +import re +import os +from PIL import Image +from Get_File_Paths import GetFileList, ChangeToOtherMachine + + +def convert_vott_csv_to_yolo( + vott_df, + labeldict=dict(zip(["Cat_Face"], [0,])), + path="", + target_name="data_train.txt", + abs_path=False, +): + + # Encode labels according to labeldict if code's don't exist + if not "code" in vott_df.columns: + vott_df["code"] = vott_df["label"].apply(lambda x: labeldict[x]) + # Round float to ints + for col in vott_df[["xmin", "ymin", "xmax", "ymax"]]: + vott_df[col] = (vott_df[col]).apply(lambda x: round(x)) + + # Create Yolo Text file + last_image = "" + txt_file = "" + + for index, row in vott_df.iterrows(): + if not last_image == row["image"]: + if abs_path: + txt_file += "\n" + row["image_path"] + " " + else: + txt_file += "\n" + os.path.join(path, row["image"]) + " " + txt_file += ",".join( + [ + str(x) + for x in (row[["xmin", "ymin", "xmax", "ymax", "code"]].tolist()) + ] + ) + else: + txt_file += " " + txt_file += ",".join( + [ + str(x) + for x in (row[["xmin", "ymin", "xmax", "ymax", "code"]].tolist()) + ] + ) + last_image = row["image"] + file = open(target_name, "w") + file.write(txt_file[1:]) + file.close() + return True + + +def csv_from_xml(directory, path_name=""): + # First get all images and xml files from path and its subfolders + image_paths = GetFileList(directory, ".jpg") + xml_paths = GetFileList(directory, ".xml") + result_df = pd.DataFrame() + if not len(image_paths) == len(xml_paths): + print("number of annotations doesnt match number of images") + return False + for image in image_paths: + target_filename = os.path.join(path_name, image) if path_name else image + source_filename = os.path.join(directory, image) + y_size, x_size, _ = np.array(Image.open(source_filename)).shape + source_xml = image.replace(".jpg", ".xml") + txt = open(source_xml, "r").read() + y_vals = re.findall(r"(?:x>\n)(.*)(?:\n\n)(.*)(?:\n\n)(.*)(?:\n\n)(.*)(?:\n img.shape[0] or xmin > img.shape[1]: + continue + + xmin, ymin = int(xmin // expand), int(ymin // expand) + xmax, ymax = int(np.round(xmax // expand)), int(np.round(ymax // expand)) + + # do not even consider tiny logos + if xmax - xmin > min_logo_size[1] and ymax - ymin > min_logo_size[0]: + candidates.append(img[ymin:ymax, xmin:xmax]) + else: + i_candidates_too_small.append(i) + + return candidates, i_candidates_too_small + + +def draw_annotated_box(image, box_list_list, label_list, color_list): + """ + Draw box and overhead label on image. + + Args: + image: PIL image object + box_list_list: list of lists of bounding boxes, one for each label, each box in + (xmin, ymin, xmax, ymax [, score]) format (where score is an optional float) + label_list: list of string to go above box + color_list: list of RGB tuples + Returns: + image: annotated PIL image object + """ + + font_path = os.path.join( + os.path.dirname(__file__), "keras_yolo3/font/FiraMono-Medium.otf" + ) + font = ImageFont.truetype( + font=font_path, size=np.floor(3e-2 * image.size[1] + 0.5).astype("int32") + ) + thickness = (image.size[0] + image.size[1]) // 300 + + draw = ImageDraw.Draw(image) + + for box_list, label, color in zip(box_list_list, label_list, color_list): + if not isinstance(color, tuple): + color = tuple(color) + for box in box_list: + # deal with empty predictions + if len(box) < 4: + continue + + # if score is also passed, append to label + thelabel = "{}".format(label) + if len(box) > 4: + thelabel += " {:.2f}".format(box[-1]) + label_size = draw.textsize(thelabel, font) + + xmin, ymin, xmax, ymax = box[:4] + ymin = max(0, np.floor(ymin + 0.5).astype("int32")) + xmin = max(0, np.floor(xmin + 0.5).astype("int32")) + ymax = min(image.size[1], np.floor(ymax + 0.5).astype("int32")) + xmax = min(image.size[0], np.floor(xmax + 0.5).astype("int32")) + + if ymin - label_size[1] >= 0: + text_origin = np.array([xmin, ymin - label_size[1]]) + else: + text_origin = np.array([xmin, ymax]) + + for i in range(thickness): + draw.rectangle([xmin + i, ymin + i, xmax - i, ymax - i], outline=color) + draw.rectangle( + [tuple(text_origin), tuple(text_origin + label_size)], fill=color + ) + draw.text(text_origin, thelabel, fill=(0, 0, 0), font=font) + + del draw + + return image diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d1b33ac --- /dev/null +++ b/requirements.txt @@ -0,0 +1,84 @@ +setuptools>=41.0.0 +pip>=19.0.0 +absl-py==0.7.1 +astor==0.8.0 +attrs==19.1.0 +backcall==0.1.0 +bleach==3.1.4 +certifi==2019.6.16 +chardet==3.0.4 +cycler==0.10.0 +decorator==4.4.0 +defusedxml==0.6.0 +progressbar2==3.46.1 +entrypoints==0.3 +gast==0.2.2 +google-pasta==0.1.7 +grpcio==1.22.0 +h5py==2.9.0 +idna==2.8 +ipykernel==5.1.1 +ipython==7.6.1 +ipython-genutils==0.2.0 +ipywidgets==7.5.0 +jedi==0.14.0 +Jinja2==2.10.1 +joblib==0.13.2 +jsonschema==3.0.1 +jupyter==1.0.0 +jupyter-client==5.3.0 +jupyter-console==6.0.0 +jupyter-core==4.5.0 +Keras==2.2.4 +Keras-Applications==1.0.8 +Keras-Preprocessing==1.1.0 +kiwisolver==1.1.0 +Markdown==3.1.1 +MarkupSafe==1.1.1 +matplotlib==3.0.3 +mistune==0.8.4 +mpmath==1.1.0 +nbconvert==5.5.0 +nbformat==4.4.0 +notebook==5.7.8 +numpy==1.16.4 +opencv-python==4.1.0.25 +pandas==0.24.2 +pandocfilters==1.4.2 +parso==0.5.0 +pexpect==4.7.0 +pickleshare==0.7.5 +Pillow==6.2.1 +prometheus-client==0.7.1 +prompt-toolkit==2.0.9 +protobuf==3.8.0 +ptyprocess==0.6.0 +Pygments==2.4.2 +pyparsing==2.4.0 +pyrsistent==0.15.3 +python-dateutil==2.8.0 +pytz==2019.1 +PyYAML==5.1.1 +pyzmq==18.0.2 +qtconsole==4.5.1 +requests==2.22.0 +scikit-learn==0.21.2 +scipy==1.3.0 +Send2Trash==1.5.0 +six==1.12.0 +sklearn==0.0 +sympy==1.4 +tensorboard==1.15.0 +tensorflow==1.15.2 +tensorflow-estimator==1.15.0 +termcolor==1.1.0 +terminado==0.8.2 +testpath==0.4.2 +tornado==6.0.3 +traitlets==4.3.2 +urllib3==1.25.3 +wcwidth==0.1.7 +webencodings==0.5.1 +Werkzeug==0.15.4 +widgetsnbextension==3.5.0 +wrapt==1.11.2