├── .gitignore ├── README.md ├── SmartApi ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── YoloObjectDetectionAPI ├── __init__.py ├── admin.py ├── apps.py ├── detection_models │ ├── __pycache__ │ │ └── yolov8.cpython-311.pyc │ └── yolov8.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_alter_detections_object_detection_and_more.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-311.pyc │ │ ├── 0002_alter_detections_object_detection_and_more.cpython-311.pyc │ │ └── __init__.cpython-311.pyc ├── models.py ├── serializers.py ├── tests.py ├── urls.py └── views.py ├── db.sqlite3 ├── examples ├── example_1_webcam.py ├── example_2_images.py └── example_images │ ├── pexels-arnie-chou-1877271.jpg │ ├── pexels-charlotte-may-5824498.jpg │ ├── pexels-cowomen-2041627.jpg │ ├── pexels-fauxels-3184435.jpg │ ├── pexels-jane-doan-1132040.jpg │ ├── pexels-joey-lu-186537.jpg │ ├── pexels-jonathan-borba-3316924.jpg │ ├── pexels-julie-aagaard-2294477.jpg │ ├── pexels-oleksandr-p-1031698.jpg │ ├── pexels-pixabay-161164.jpg │ ├── pexels-pixabay-38631.jpg │ ├── pexels-sergio-souza-2293649.jpg │ ├── pexels-terry-magallanes-3623785.jpg │ └── pexels-vecislavas-popa-1668860.jpg ├── manage.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.pt 2 | *.sqlite3 3 | images/ 4 | 5 | # Created by https://www.toptal.com/developers/gitignore/api/python 6 | # Edit at https://www.toptal.com/developers/gitignore?templates=python 7 | 8 | ### Python ### 9 | # Byte-compiled / optimized / DLL files 10 | __pycache__/ 11 | *.py[cod] 12 | *$py.class 13 | 14 | # C extensions 15 | *.so 16 | 17 | # Distribution / packaging 18 | .Python 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | downloads/ 23 | eggs/ 24 | .eggs/ 25 | lib/ 26 | lib64/ 27 | parts/ 28 | sdist/ 29 | var/ 30 | wheels/ 31 | share/python-wheels/ 32 | *.egg-info/ 33 | .installed.cfg 34 | *.egg 35 | MANIFEST 36 | 37 | # PyInstaller 38 | # Usually these files are written by a python script from a template 39 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 40 | *.manifest 41 | *.spec 42 | 43 | # Installer logs 44 | pip-log.txt 45 | pip-delete-this-directory.txt 46 | 47 | # Unit test / coverage reports 48 | htmlcov/ 49 | .tox/ 50 | .nox/ 51 | .coverage 52 | .coverage.* 53 | .cache 54 | nosetests.xml 55 | coverage.xml 56 | *.cover 57 | *.py,cover 58 | .hypothesis/ 59 | .pytest_cache/ 60 | cover/ 61 | 62 | # Translations 63 | *.mo 64 | *.pot 65 | 66 | # Django stuff: 67 | *.log 68 | local_settings.py 69 | db.sqlite3 70 | db.sqlite3-journal 71 | 72 | # Flask stuff: 73 | instance/ 74 | .webassets-cache 75 | 76 | # Scrapy stuff: 77 | .scrapy 78 | 79 | # Sphinx documentation 80 | docs/_build/ 81 | 82 | # PyBuilder 83 | .pybuilder/ 84 | target/ 85 | 86 | # Jupyter Notebook 87 | .ipynb_checkpoints 88 | 89 | # IPython 90 | profile_default/ 91 | ipython_config.py 92 | 93 | # pyenv 94 | # For a library or package, you might want to ignore these files since the code is 95 | # intended to run in multiple environments; otherwise, check them in: 96 | # .python-version 97 | 98 | # pipenv 99 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 100 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 101 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 102 | # install all needed dependencies. 103 | #Pipfile.lock 104 | 105 | # poetry 106 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 107 | # This is especially recommended for binary packages to ensure reproducibility, and is more 108 | # commonly ignored for libraries. 109 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 110 | #poetry.lock 111 | 112 | # pdm 113 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 114 | #pdm.lock 115 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 116 | # in version control. 117 | # https://pdm.fming.dev/#use-with-ide 118 | .pdm.toml 119 | 120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 121 | __pypackages__/ 122 | 123 | # Celery stuff 124 | celerybeat-schedule 125 | celerybeat.pid 126 | 127 | # SageMath parsed files 128 | *.sage.py 129 | 130 | # Environments 131 | .env 132 | .venv 133 | env/ 134 | venv/ 135 | ENV/ 136 | env.bak/ 137 | venv.bak/ 138 | 139 | # Spyder project settings 140 | .spyderproject 141 | .spyproject 142 | 143 | # Rope project settings 144 | .ropeproject 145 | 146 | # mkdocs documentation 147 | /site 148 | 149 | # mypy 150 | .mypy_cache/ 151 | .dmypy.json 152 | dmypy.json 153 | 154 | # Pyre type checker 155 | .pyre/ 156 | 157 | # pytype static type analyzer 158 | .pytype/ 159 | 160 | # Cython debug symbols 161 | cython_debug/ 162 | 163 | # PyCharm 164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 166 | # and can be added to the global gitignore or merged into this file. For a more nuclear 167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 168 | #.idea/ 169 | 170 | ### Python Patch ### 171 | # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration 172 | poetry.toml 173 | 174 | # ruff 175 | .ruff_cache/ 176 | 177 | # LSP config files 178 | pyrightconfig.json 179 | 180 | # End of https://www.toptal.com/developers/gitignore/api/python -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YOLOv8 Object Detection API 2 | 3 | This project implements an object detection API using the YOLOv8 model, integrated into a Django-based web application. It allows users to upload images and run object detection, returning detected objects with labels, confidence scores, and bounding box coordinates. 4 | 5 | Watch it here: https://youtu.be/xh0hZDpHU9o 6 | 7 | ## Features 8 | 9 | - **Image Upload**: Users can upload images for object detection. 10 | - **Object Detection**: Utilizes YOLOv8 for efficient and accurate object detection. 11 | - **Admin Interface**: Django admin interface to view and manage image uploads and detections. 12 | - **RESTful API**: Provides an API endpoint for uploading images and retrieving detection results. 13 | 14 | ## Installation 15 | 16 | 1. Clone the repository. 17 | 2. Install required dependencies: 18 | 19 | ``` 20 | pip install -r requirements.txt 21 | ``` 22 | 23 | 3. Run the Django migrations: 24 | 25 | ``` 26 | python manage.py migrate 27 | ``` 28 | 29 | 4. Start the Django server: 30 | 31 | ``` 32 | python manage.py runserver 33 | ``` 34 | 35 | 36 | ## Usage 37 | 38 | ### Uploading Images for Detection 39 | 40 | - Send a POST request to `/yolov8/upload/` with the image file and the desired confidence threshold. 41 | - The API will return the detection results with labels, confidence scores, and bounding box coordinates. 42 | 43 | ### Admin Interface 44 | 45 | - Access the Django admin interface to manage and view uploaded images and their corresponding detection results. 46 | 47 | ## API Endpoints 48 | 49 | - `POST /upload/`: Endpoint to upload images for object detection. 50 | 51 | ## Models 52 | 53 | - `ImageUpload`: Model to store image uploads, confidence thresholds, and status. 54 | - `Detections`: Model to store detection results for each uploaded image. 55 | 56 | ## Admin Models 57 | 58 | - `ImageUploadAdmin`: Admin model to manage image uploads. 59 | - `DetectionsAdmin`: Admin model to view and manage detection results. 60 | 61 | ## Serializer 62 | 63 | - `ImageUploadSerializer`: Serializer for image upload data. 64 | 65 | ## Views 66 | 67 | - `UploadImageView`: API view to handle image upload requests and run object detection. 68 | 69 | ## Dependencies 70 | 71 | - Django 72 | - djangorestframework 73 | - PyTorch 74 | - Ultralytics YOLOv8 75 | 76 | ## Contributing 77 | 78 | Contributions, issues, and feature requests are welcome! 79 | 80 | ## License 81 | 82 | [MIT License](LICENSE) 83 | 84 | ## Acknowledgments 85 | 86 | - Ultralytics for the YOLOv8 model. 87 | - Django and DRF teams for the web framework and API toolkit. 88 | -------------------------------------------------------------------------------- /SmartApi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/SmartApi/__init__.py -------------------------------------------------------------------------------- /SmartApi/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for SmartApi project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SmartApi.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /SmartApi/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for SmartApi project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.2.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.2/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import os 15 | 16 | 17 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 18 | BASE_DIR = Path(__file__).resolve().parent.parent 19 | 20 | 21 | # Quick-start development settings - unsuitable for production 22 | # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ 23 | 24 | # SECURITY WARNING: keep the secret key used in production secret! 25 | SECRET_KEY = 'django-insecure-1nbu%8#5_5*axju-*%f!tm&qxo3f+&$5ub8y#*(e7!=-&d8nl5' 26 | 27 | # SECURITY WARNING: don't run with debug turned on in production! 28 | DEBUG = True 29 | 30 | ALLOWED_HOSTS = [] 31 | 32 | 33 | # Application definition 34 | 35 | INSTALLED_APPS = [ 36 | 'django.contrib.admin', 37 | 'django.contrib.auth', 38 | 'django.contrib.contenttypes', 39 | 'django.contrib.sessions', 40 | 'django.contrib.messages', 41 | 'django.contrib.staticfiles', 42 | "YoloObjectDetectionAPI", 43 | ] 44 | 45 | MIDDLEWARE = [ 46 | 'django.middleware.security.SecurityMiddleware', 47 | 'django.contrib.sessions.middleware.SessionMiddleware', 48 | 'django.middleware.common.CommonMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 51 | 'django.contrib.messages.middleware.MessageMiddleware', 52 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 53 | ] 54 | 55 | ROOT_URLCONF = 'SmartApi.urls' 56 | 57 | TEMPLATES = [ 58 | { 59 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 60 | 'DIRS': [], 61 | 'APP_DIRS': True, 62 | 'OPTIONS': { 63 | 'context_processors': [ 64 | 'django.template.context_processors.debug', 65 | 'django.template.context_processors.request', 66 | 'django.contrib.auth.context_processors.auth', 67 | 'django.contrib.messages.context_processors.messages', 68 | ], 69 | }, 70 | }, 71 | ] 72 | 73 | WSGI_APPLICATION = 'SmartApi.wsgi.application' 74 | 75 | 76 | # Database 77 | # https://docs.djangoproject.com/en/4.2/ref/settings/#databases 78 | 79 | DATABASES = { 80 | 'default': { 81 | 'ENGINE': 'django.db.backends.sqlite3', 82 | 'NAME': BASE_DIR / 'db.sqlite3', 83 | } 84 | } 85 | 86 | 87 | # Password validation 88 | # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators 89 | 90 | AUTH_PASSWORD_VALIDATORS = [ 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 93 | }, 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 99 | }, 100 | { 101 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 102 | }, 103 | ] 104 | 105 | 106 | # Internationalization 107 | # https://docs.djangoproject.com/en/4.2/topics/i18n/ 108 | 109 | LANGUAGE_CODE = 'en-us' 110 | 111 | TIME_ZONE = 'UTC' 112 | 113 | USE_I18N = True 114 | 115 | USE_TZ = True 116 | 117 | 118 | # Static files (CSS, JavaScript, Images) 119 | # https://docs.djangoproject.com/en/4.2/howto/static-files/ 120 | 121 | STATIC_URL = 'static/' 122 | 123 | # Default primary key field type 124 | # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field 125 | 126 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 127 | 128 | MEDIA_URL = '/media/' 129 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 130 | -------------------------------------------------------------------------------- /SmartApi/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URL configuration for SmartApi project. 3 | 4 | The `urlpatterns` list routes URLs to views. For more information please see: 5 | https://docs.djangoproject.com/en/4.2/topics/http/urls/ 6 | Examples: 7 | Function views 8 | 1. Add an import: from my_app import views 9 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 10 | Class-based views 11 | 1. Add an import: from other_app.views import Home 12 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 13 | Including another URLconf 14 | 1. Import the include() function: from django.urls import include, path 15 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 16 | """ 17 | from django.contrib import admin 18 | from django.urls import path, include 19 | 20 | from django.conf import settings 21 | from django.conf.urls.static import static 22 | 23 | urlpatterns = [ 24 | path('admin/', admin.site.urls), 25 | path('yolov8/', include(('YoloObjectDetectionAPI.urls', 'yolov8'), namespace='yolov8')), 26 | ] 27 | 28 | if settings.DEBUG: 29 | urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -------------------------------------------------------------------------------- /SmartApi/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for SmartApi project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SmartApi.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/YoloObjectDetectionAPI/__init__.py -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import ImageUpload, Detections 3 | from django.utils.html import format_html 4 | 5 | @admin.register(ImageUpload) 6 | class ImageUploadAdmin(admin.ModelAdmin): 7 | list_display = ('thumbnail', 'image_file', 'upload_timestamp', 'confidence_threshold', 'status') 8 | list_editable = ('status',) 9 | list_filter = ('status', 'upload_timestamp') 10 | search_fields = ('image_file', 'status') 11 | 12 | def thumbnail(self, obj): 13 | if obj.image_file: 14 | return format_html('', obj.image_file.url) 15 | return "-" 16 | thumbnail.short_description = "Thumbnail" 17 | 18 | 19 | @admin.register(Detections) 20 | class DetectionsAdmin(admin.ModelAdmin): 21 | list_display = ('object_detection', 'label', 'confidence', 'x_min', 'x_max', 'y_min', 'y_max', 'detection_date') 22 | list_filter = ('object_detection', 'label', 'detection_date') 23 | search_fields = ('label', 'object_detection__linked_image__image_file') 24 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class YoloobjectdetectionapiConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'YoloObjectDetectionAPI' 7 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/detection_models/__pycache__/yolov8.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/YoloObjectDetectionAPI/detection_models/__pycache__/yolov8.cpython-311.pyc -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/detection_models/yolov8.py: -------------------------------------------------------------------------------- 1 | from ultralytics import YOLO 2 | 3 | class YOLOv8Detector: 4 | def __init__(self, model_path): 5 | """ 6 | Initialize the YOLOv8 model. 7 | :param model_path: The path to the YOLOv8 model file (e.g., 'yolov8n.pt'). 8 | """ 9 | # Load the pretrained YOLOv8 model 10 | self.model = YOLO(model_path) 11 | 12 | def run_detection(self, image_path, confidence_threshold=0.42): 13 | """ 14 | Run object detection on the provided image. 15 | :param image_path: The path to the image file. 16 | :return: A list of detected objects with their labels, confidence scores, and bounding boxes. 17 | """ 18 | # Perform detection 19 | results = self.model(image_path, conf=confidence_threshold, stream=False)[0] 20 | 21 | # Process results 22 | detected_objects = [] 23 | for det in results.boxes: # Loop through each detection 24 | label_index = int(det.cls) 25 | label = self.model.names[label_index] 26 | confidence = float(det.conf) 27 | bbox = det.xyxy.cpu().numpy()[0] 28 | x_min, y_min, x_max, y_max = bbox[:4] 29 | 30 | detected_objects.append({ 31 | 'label': label, 32 | 'confidence': confidence, 33 | 'x_min': x_min, 34 | 'y_min': y_min, 35 | 'x_max': x_max, 36 | 'y_max': y_max, 37 | }) 38 | 39 | return detected_objects 40 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.5 on 2023-11-16 07:30 2 | 3 | import django.core.validators 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='ImageUpload', 18 | fields=[ 19 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('image_file', models.ImageField(upload_to='images/')), 21 | ('upload_timestamp', models.DateTimeField(auto_now_add=True)), 22 | ('confidence_threshold', models.FloatField(validators=[django.core.validators.MinValueValidator(0.0), django.core.validators.MaxValueValidator(1.0)])), 23 | ('status', models.CharField(choices=[('pending', 'Pending'), ('processing', 'Processing'), ('completed', 'Completed'), ('failed', 'Failed')], default='pending', max_length=50)), 24 | ], 25 | ), 26 | migrations.CreateModel( 27 | name='ObjectDetection', 28 | fields=[ 29 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 30 | ('linked_image', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='object_detections', to='YoloObjectDetectionAPI.imageupload')), 31 | ], 32 | ), 33 | migrations.CreateModel( 34 | name='Detections', 35 | fields=[ 36 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 37 | ('label', models.CharField(max_length=100)), 38 | ('confidence', models.FloatField()), 39 | ('x_min', models.FloatField()), 40 | ('x_max', models.FloatField()), 41 | ('y_min', models.FloatField()), 42 | ('y_max', models.FloatField()), 43 | ('detection_date', models.DateTimeField(auto_now_add=True)), 44 | ('object_detection', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='detections', to='YoloObjectDetectionAPI.objectdetection')), 45 | ], 46 | ), 47 | ] 48 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/migrations/0002_alter_detections_object_detection_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.5 on 2023-11-16 07:41 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('YoloObjectDetectionAPI', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='detections', 16 | name='object_detection', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='detections', to='YoloObjectDetectionAPI.imageupload'), 18 | ), 19 | migrations.DeleteModel( 20 | name='ObjectDetection', 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/YoloObjectDetectionAPI/migrations/__init__.py -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/migrations/__pycache__/0001_initial.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/YoloObjectDetectionAPI/migrations/__pycache__/0001_initial.cpython-311.pyc -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/migrations/__pycache__/0002_alter_detections_object_detection_and_more.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/YoloObjectDetectionAPI/migrations/__pycache__/0002_alter_detections_object_detection_and_more.cpython-311.pyc -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/migrations/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/YoloObjectDetectionAPI/migrations/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.core.validators import MinValueValidator, MaxValueValidator 3 | 4 | class ImageUpload(models.Model): 5 | STATUS_PENDING = 'pending' 6 | STATUS_PROCESSING = 'processing' 7 | STATUS_COMPLETED = 'completed' 8 | STATUS_FAILED = 'failed' 9 | 10 | STATUS_CHOICES = [ 11 | (STATUS_PENDING, 'Pending'), 12 | (STATUS_PROCESSING, 'Processing'), 13 | (STATUS_COMPLETED, 'Completed'), 14 | (STATUS_FAILED, 'Failed'), 15 | ] 16 | 17 | image_file = models.ImageField(upload_to='media/images/') 18 | upload_timestamp = models.DateTimeField(auto_now_add=True) 19 | confidence_threshold = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(1.0)]) 20 | status = models.CharField( 21 | max_length=50, 22 | choices=STATUS_CHOICES, 23 | default=STATUS_PENDING 24 | ) 25 | 26 | 27 | class Detections(models.Model): 28 | object_detection = models.ForeignKey(ImageUpload, on_delete=models.CASCADE, related_name='detections') 29 | label = models.CharField(max_length=100) 30 | confidence = models.FloatField() 31 | x_min = models.FloatField() 32 | x_max = models.FloatField() 33 | y_min = models.FloatField() 34 | y_max = models.FloatField() 35 | detection_date = models.DateTimeField(auto_now_add=True) 36 | 37 | def __str__(self): 38 | return f"{self.label} ({self.confidence})" -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from .models import ImageUpload 3 | 4 | class ImageUploadSerializer(serializers.ModelSerializer): 5 | class Meta: 6 | model = ImageUpload 7 | fields = ['image_file', 'confidence_threshold'] 8 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from .views import UploadImageView 3 | 4 | urlpatterns = [ 5 | path('upload/', UploadImageView.as_view(), name='upload-image'), 6 | ] 7 | -------------------------------------------------------------------------------- /YoloObjectDetectionAPI/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework.views import APIView 2 | from rest_framework.response import Response 3 | from rest_framework import status 4 | from .models import ImageUpload, Detections 5 | from .serializers import ImageUploadSerializer 6 | from .detection_models.yolov8 import YOLOv8Detector 7 | 8 | class UploadImageView(APIView): 9 | detector = YOLOv8Detector("yolov8x.pt") 10 | 11 | def post(self, request, format=None): 12 | serializer = ImageUploadSerializer(data=request.data) 13 | if serializer.is_valid(): 14 | image_upload = serializer.save() 15 | 16 | try: 17 | detection_result = self.detector.run_detection(image_path=image_upload.image_file.path, confidence_threshold=image_upload.confidence_threshold) 18 | image_upload.status = ImageUpload.STATUS_COMPLETED 19 | image_upload.save() 20 | except Exception as e: 21 | image_upload.status = ImageUpload.STATUS_FAILED 22 | image_upload.save() 23 | return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) 24 | 25 | for detection in detection_result: 26 | Detections.objects.create( 27 | object_detection=image_upload, 28 | label=detection['label'], 29 | confidence=detection['confidence'], 30 | x_min=detection['x_min'], 31 | x_max=detection['x_max'], 32 | y_min=detection['y_min'], 33 | y_max=detection['y_max'] 34 | ) 35 | 36 | return Response({'detections': detection_result}, status=status.HTTP_201_CREATED) 37 | return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 38 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/db.sqlite3 -------------------------------------------------------------------------------- /examples/example_1_webcam.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import requests 3 | import time 4 | import datetime 5 | 6 | def draw_labels(image, detections): 7 | for det in detections: 8 | x_min, y_min, x_max, y_max = int(det['x_min']), int(det['y_min']), int(det['x_max']), int(det['y_max']) 9 | label = det['label'] 10 | cv2.rectangle(image, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2) 11 | cv2.putText(image, label, (x_min, y_min - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2) 12 | return image 13 | 14 | # Initialize webcam 15 | cap = cv2.VideoCapture(0) 16 | 17 | try: 18 | while True: 19 | # Capture frame-by-frame 20 | ret, frame = cap.read() 21 | if not ret: 22 | break 23 | 24 | # Save the captured frame to a file 25 | frame_name = 'frame.jpg' 26 | cv2.imwrite(frame_name, frame) 27 | 28 | # Open the saved image file in binary mode 29 | with open(frame_name, 'rb') as image_file: 30 | files = {'image_file': image_file} 31 | payload = {'confidence_threshold': 0.42} 32 | response = requests.post('http://localhost:8000/yolov8/upload/', files=files, data=payload) 33 | 34 | if response.status_code == 201: 35 | print("Upload Successful") 36 | detection_result = response.json().get('detections', []) 37 | # Draw labels on the frame 38 | labeled_frame = draw_labels(frame, detection_result) 39 | # Save the labeled frame with a timestamp 40 | timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') 41 | cv2.imwrite(f'labeled_frame_{timestamp}.jpg', labeled_frame) 42 | else: 43 | print("Upload Failed", response.text) 44 | 45 | finally: 46 | # When everything done, release the capture 47 | cap.release() 48 | cv2.destroyAllWindows() 49 | -------------------------------------------------------------------------------- /examples/example_2_images.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import requests 3 | import os 4 | import datetime 5 | 6 | def draw_labels(image, detections): 7 | for det in detections: 8 | x_min, y_min, x_max, y_max = int(det['x_min']), int(det['y_min']), int(det['x_max']), int(det['y_max']) 9 | label = det['label'] 10 | cv2.rectangle(image, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2) 11 | cv2.putText(image, label, (x_min, y_min - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2) 12 | return image 13 | 14 | def process_images(input_folder, output_folder): 15 | if not os.path.exists(output_folder): 16 | os.makedirs(output_folder) 17 | 18 | for image_name in os.listdir(input_folder): 19 | image_path = os.path.join(input_folder, image_name) 20 | image = cv2.imread(image_path) 21 | if image is None: 22 | continue 23 | 24 | with open(image_path, 'rb') as image_file: 25 | files = {'image_file': image_file} 26 | payload = {'confidence_threshold': 0.02} 27 | response = requests.post('http://localhost:8000/yolov8/upload/', files=files, data=payload) 28 | 29 | if response.status_code == 201: 30 | print(f"Upload Successful for {image_name}") 31 | detection_result = response.json().get('detections', []) 32 | labeled_image = draw_labels(image, detection_result) 33 | output_path = os.path.join(output_folder, f'labeled_{image_name}') 34 | cv2.imwrite(output_path, labeled_image) 35 | else: 36 | print(f"Upload Failed for {image_name}", response.text) 37 | 38 | input_folder = 'example_images' 39 | output_folder = 'example_images_output' 40 | process_images(input_folder, output_folder) 41 | -------------------------------------------------------------------------------- /examples/example_images/pexels-arnie-chou-1877271.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-arnie-chou-1877271.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-charlotte-may-5824498.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-charlotte-may-5824498.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-cowomen-2041627.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-cowomen-2041627.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-fauxels-3184435.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-fauxels-3184435.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-jane-doan-1132040.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-jane-doan-1132040.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-joey-lu-186537.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-joey-lu-186537.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-jonathan-borba-3316924.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-jonathan-borba-3316924.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-julie-aagaard-2294477.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-julie-aagaard-2294477.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-oleksandr-p-1031698.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-oleksandr-p-1031698.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-pixabay-161164.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-pixabay-161164.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-pixabay-38631.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-pixabay-38631.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-sergio-souza-2293649.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-sergio-souza-2293649.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-terry-magallanes-3623785.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-terry-magallanes-3623785.jpg -------------------------------------------------------------------------------- /examples/example_images/pexels-vecislavas-popa-1668860.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sezer-muhammed/Django-Yolov8-API-App/8248397f919bcfd90083256be69176e9d7081fc0/examples/example_images/pexels-vecislavas-popa-1668860.jpg -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SmartApi.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==4.2.5 2 | djangorestframework==3.14.0 3 | opencv_python==4.8.0.76 4 | Requests==2.31.0 5 | ultralytics==8.0.210 6 | --------------------------------------------------------------------------------