damndeepesh commited on
Commit
9de653a
·
verified ·
1 Parent(s): 2b91ee4

Uploaded Project Files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ asset/ezgif-5-12682faad5.gif filter=lfs diff=lfs merge=lfs -text
37
+ asset/ezgif-5-28a1705b9b.gif filter=lfs diff=lfs merge=lfs -text
LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
README copy.md ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Real-Time Object Detection with YOLOv8
2
+
3
+ A Streamlit-based web application for real-time object detection in videos using YOLOv8. This application supports multiple YOLO models, real-time detection, object tracking, and video processing with annotated output.
4
+
5
+ ## Demo
6
+ ![me](https://github.com/damndeepesh/QuickTrack/blob/main/asset/ezgif-5-12682faad5.gif)
7
+ ![me](https://github.com/damndeepesh/QuickTrack/blob/main/asset/ezgif-5-28a1705b9b.gif)
8
+
9
+ ## Features
10
+
11
+ - Multiple YOLOv8 model support (Nano to XLarge)
12
+ - Real-time object detection and tracking
13
+ - Support for video files and live streams
14
+ - Unique ID tracking for detected objects
15
+ - Customizable detection confidence
16
+ - Color-coded object categories
17
+ - Downloadable processed videos
18
+ - Interactive web interface
19
+
20
+ ## Installation
21
+
22
+ ### Prerequisites
23
+ - Python 3.8 or higher
24
+ - CUDA-compatible GPU (optional, but recommended for better performance)
25
+
26
+ ### Step 1: Clone the Repository
27
+ - git clone <repository-url>
28
+ - cd <repository-name>
29
+
30
+ ### Step 2: Create a Virtual Environment (Recommended)
31
+
32
+ ## Windows
33
+ - python -m venv venv
34
+ - venv\Scripts\activate
35
+
36
+ ## Linux/Mac
37
+ - python3 -m venv venv
38
+ - source venv/bin/activate
39
+
40
+ ### Step 3: Install Dependencies
41
+ - pip install -r requirements.txt
42
+
43
+ ## Usage
44
+
45
+ ### Starting the Application
46
+ - streamlit run app.py
47
+
48
+
49
+ ### Step-by-Step Guide
50
+
51
+ 1. **Select a Model**:
52
+ - Choose from available YOLOv8 models in the sidebar
53
+ - Models range from Nano (fastest) to XLarge (most accurate)
54
+ - Review model details in the expandable section
55
+ - Click "Load Selected Model" to download and initialize
56
+
57
+ 2. **Configure Settings**:
58
+ - Adjust detection confidence using the slider
59
+ - Lower values detect more objects but may increase false positives
60
+ - Higher values are more selective but might miss some objects
61
+
62
+ 3. **Input Selection**:
63
+ - Choose between "Video File" or "Live Stream URL"
64
+ - For video files: Upload MP4 or AVI format
65
+ - For streams: Enter a valid stream URL
66
+
67
+ 4. **Start Detection**:
68
+ - Click "Start Detection" in the sidebar
69
+ - Watch real-time detection with bounding boxes
70
+ - Each object gets a unique tracking ID
71
+
72
+ 5. **Download Results**:
73
+ - Stop detection when finished
74
+ - Download button appears automatically
75
+ - Processed video includes all annotations
76
+
77
+ ## About YOLO Models
78
+
79
+ ### Available Models
80
+
81
+ 1. **YOLOv8n (Nano)**:
82
+ - Size: 6.7 MB
83
+ - Best for: Real-time applications on CPU
84
+ - Speed: ⚡⚡⚡⚡⚡
85
+ - Accuracy: ⭐⭐
86
+
87
+ 2. **YOLOv8s (Small)**:
88
+ - Size: 22.4 MB
89
+ - Best for: Balanced performance
90
+ - Speed: ⚡⚡⚡⚡
91
+ - Accuracy: ⭐⭐⭐
92
+
93
+ 3. **YOLOv8m (Medium)**:
94
+ - Size: 52.2 MB
95
+ - Best for: Standard detection tasks
96
+ - Speed: ⚡⚡⚡
97
+ - Accuracy: ⭐⭐⭐⭐
98
+
99
+ 4. **YOLOv8l (Large)**:
100
+ - Size: 87.7 MB
101
+ - Best for: High accuracy needs
102
+ - Speed: ⚡⚡
103
+ - Accuracy: ⭐⭐⭐⭐⭐
104
+
105
+ 5. **YOLOv8x (XLarge)**:
106
+ - Size: 131.7 MB
107
+ - Best for: Maximum accuracy
108
+ - Speed: ⚡
109
+ - Accuracy: ⭐⭐⭐⭐⭐⭐
110
+
111
+ ### Model Selection Guide
112
+
113
+ - **CPU Only**: Use Nano or Small models
114
+ - **GPU Available**: Medium to XLarge models recommended
115
+ - **Real-time Needs**: Nano or Small models
116
+ - **Accuracy Priority**: Large or XLarge models
117
+ - **Balanced**: Medium model
118
+
119
+ ## Technical Details
120
+
121
+ - Built with Streamlit and OpenCV
122
+ - Uses Ultralytics YOLOv8 implementation
123
+ - Supports multiple video codecs
124
+ - Real-time frame processing and buffering
125
+ - Unique object tracking with IoU
126
+ - Color-coded object categories
127
+ - Frame buffer for smooth video writing
128
+
129
+ ## Troubleshooting
130
+
131
+ 1. **Video Not Loading**:
132
+ - Check file format (MP4/AVI supported)
133
+ - Ensure file isn't corrupted
134
+ - Try a different video codec
135
+
136
+ 2. **Slow Performance**:
137
+ - Use a smaller YOLO model
138
+ - Reduce input video resolution
139
+ - Check GPU availability
140
+
141
+ 3. **Detection Issues**:
142
+ - Adjust confidence threshold
143
+ - Try a larger YOLO model
144
+ - Ensure good lighting in video
145
+
146
+ 4. **Download Issues**:
147
+ - Wait for processing to complete
148
+ - Check available disk space
149
+ - Try a different browser
150
+
151
+ ## Requirements
152
+
153
+ - streamlit>=1.24.0
154
+ - opencv-python-headless>=4.7.0
155
+ - torch>=2.0.0
156
+ - torchvision>=0.15.0
157
+ - numpy>=1.24.0
158
+ - ultralytics>=8.0.0
159
+ - python-dateutil>=2.8.2
160
+
161
+ ## Acknowledgments
162
+
163
+ - YOLOv8 by Ultralytics - https://docs.ultralytics.com/models/yolov8/
164
+ - Streamlit Framework - https://streamlit.io
165
+ - OpenCV Project - https://docs.opencv.org/4.x/index.html
app.py ADDED
@@ -0,0 +1,313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import cv2
3
+ import torch
4
+ import numpy as np
5
+ import time
6
+ import tempfile
7
+ from pathlib import Path
8
+
9
+ # Import detection utilities
10
+ from detection_utils import load_model, detect_objects, draw_boxes, ObjectTracker
11
+
12
+ def initialize_video_capture(input_source, video_file=None, url=None):
13
+ """Initialize video capture and writer"""
14
+ cap = None
15
+ out = None
16
+ output_path = None
17
+
18
+ if input_source == "Video File" and video_file is not None:
19
+ # Save uploaded file to temp location
20
+ tfile = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
21
+ tfile.write(video_file.read())
22
+ tfile.flush()
23
+ video_path = tfile.name
24
+
25
+ # Open video capture
26
+ cap = cv2.VideoCapture(video_path)
27
+
28
+ if cap.isOpened():
29
+ # Get video properties
30
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
31
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
32
+ fps = int(cap.get(cv2.CAP_PROP_FPS))
33
+
34
+ # Ensure valid FPS
35
+ if fps <= 0:
36
+ fps = 30
37
+
38
+ # Create output path in a temporary directory
39
+ temp_dir = tempfile.gettempdir()
40
+ output_path = str(Path(temp_dir) / 'detected_output.mp4')
41
+
42
+ # Try different codecs in order of preference
43
+ codecs = [
44
+ ('avc1', '.mp4'),
45
+ ('mp4v', '.mp4'),
46
+ ('XVID', '.avi')
47
+ ]
48
+
49
+ for codec, ext in codecs:
50
+ try:
51
+ output_path = str(Path(temp_dir) / f'detected_output{ext}')
52
+ fourcc = cv2.VideoWriter_fourcc(*codec)
53
+ out = cv2.VideoWriter(
54
+ output_path,
55
+ fourcc,
56
+ fps,
57
+ (width, height),
58
+ isColor=True
59
+ )
60
+
61
+ # Test if writer is working
62
+ if out.isOpened():
63
+ break
64
+ except Exception:
65
+ continue
66
+
67
+ if out is None or not out.isOpened():
68
+ st.error("Failed to create video writer")
69
+ return None, None, None
70
+
71
+ elif input_source == "Live Stream URL" and url:
72
+ cap = cv2.VideoCapture(url)
73
+
74
+ return cap, out, output_path
75
+
76
+ def get_model_info():
77
+ """Return information about available YOLO models"""
78
+ return {
79
+ 'yolov8n.pt': {
80
+ 'name': 'YOLOv8 Nano',
81
+ 'description': 'Smallest and fastest model. Best for CPU or low-power devices.',
82
+ 'speed': '⚡⚡⚡⚡⚡',
83
+ 'accuracy': '⭐⭐',
84
+ 'size': '6.7 MB',
85
+ 'details': 'Ideal for real-time applications with limited computing power.'
86
+ },
87
+ 'yolov8s.pt': {
88
+ 'name': 'YOLOv8 Small',
89
+ 'description': 'Small model balancing speed and accuracy.',
90
+ 'speed': '⚡⚡⚡⚡',
91
+ 'accuracy': '⭐⭐⭐',
92
+ 'size': '22.4 MB',
93
+ 'details': 'Good for general purpose detection with decent performance.'
94
+ },
95
+ 'yolov8m.pt': {
96
+ 'name': 'YOLOv8 Medium',
97
+ 'description': 'Medium-sized model with good balance.',
98
+ 'speed': '⚡⚡⚡',
99
+ 'accuracy': '⭐⭐⭐⭐',
100
+ 'size': '52.2 MB',
101
+ 'details': 'Recommended for standard detection tasks with good GPU.'
102
+ },
103
+ 'yolov8l.pt': {
104
+ 'name': 'YOLOv8 Large',
105
+ 'description': 'Large model with high accuracy.',
106
+ 'speed': '⚡⚡',
107
+ 'accuracy': '⭐⭐⭐⭐⭐',
108
+ 'size': '87.7 MB',
109
+ 'details': 'Best for high-accuracy requirements with good computing power.'
110
+ },
111
+ 'yolov8x.pt': {
112
+ 'name': 'YOLOv8 XLarge',
113
+ 'description': 'Extra large model with highest accuracy.',
114
+ 'speed': '⚡',
115
+ 'accuracy': '⭐⭐⭐⭐⭐⭐',
116
+ 'size': '131.7 MB',
117
+ 'details': 'Best for tasks requiring maximum accuracy, requires powerful GPU.'
118
+ }
119
+ }
120
+
121
+ def main():
122
+ st.title("Real-Time Object Detection")
123
+
124
+ # Initialize session state
125
+ if 'tracker' not in st.session_state:
126
+ st.session_state.tracker = ObjectTracker()
127
+ if 'cap' not in st.session_state:
128
+ st.session_state.cap = None
129
+ if 'out' not in st.session_state:
130
+ st.session_state.out = None
131
+ if 'output_path' not in st.session_state:
132
+ st.session_state.output_path = None
133
+ if 'processed_frames' not in st.session_state:
134
+ st.session_state.processed_frames = 0
135
+ if 'selected_model' not in st.session_state:
136
+ st.session_state.selected_model = 'yolov8x.pt'
137
+ if 'model' not in st.session_state:
138
+ st.session_state.model = None
139
+
140
+ # Sidebar settings
141
+ st.sidebar.title("Settings")
142
+
143
+ # Model selection
144
+ st.sidebar.subheader("Model Selection")
145
+ model_info = get_model_info()
146
+ selected_model = st.sidebar.selectbox(
147
+ "Choose YOLO Model",
148
+ options=list(model_info.keys()),
149
+ format_func=lambda x: model_info[x]['name'],
150
+ index=list(model_info.keys()).index(st.session_state.selected_model)
151
+ )
152
+
153
+ # Display model information
154
+ with st.sidebar.expander("Model Details", expanded=True):
155
+ st.markdown(f"**{model_info[selected_model]['name']}**")
156
+ st.write(model_info[selected_model]['description'])
157
+ st.write(f"Speed: {model_info[selected_model]['speed']}")
158
+ st.write(f"Accuracy: {model_info[selected_model]['accuracy']}")
159
+ st.write(f"Size: {model_info[selected_model]['size']}")
160
+ st.write(f"Details: {model_info[selected_model]['details']}")
161
+
162
+ # Add Load Model button
163
+ if st.sidebar.button("Load Selected Model"):
164
+ with st.spinner(f"Loading {model_info[selected_model]['name']}..."):
165
+ st.session_state.model = load_model(selected_model)
166
+ st.session_state.selected_model = selected_model
167
+ st.sidebar.success("Model loaded successfully!")
168
+
169
+ # Detection confidence
170
+ detection_confidence = st.sidebar.slider("Detection Confidence", 0.0, 1.0, 0.5)
171
+
172
+ # Input selection
173
+ input_source = st.radio("Select Input Source", ["Video File", "Live Stream URL"])
174
+
175
+ try:
176
+ # Handle video input
177
+ if input_source == "Video File":
178
+ video_file = st.file_uploader("Upload Video", type=['mp4', 'avi'])
179
+ if video_file is not None:
180
+ st.session_state.cap, st.session_state.out, st.session_state.output_path = initialize_video_capture(input_source, video_file=video_file)
181
+ else:
182
+ url = st.text_input("Enter Stream URL")
183
+ if url:
184
+ st.session_state.cap, st.session_state.out, st.session_state.output_path = initialize_video_capture(input_source, url=url)
185
+
186
+ if st.session_state.cap is not None and not st.session_state.cap.isOpened():
187
+ st.error("Error: Could not open video source")
188
+ st.stop()
189
+
190
+ # Create placeholder for video display
191
+ video_placeholder = st.empty()
192
+
193
+ # Initialize frame buffer in session state
194
+ if 'frame_buffer' not in st.session_state:
195
+ st.session_state.frame_buffer = []
196
+
197
+ # Control buttons - Move them to sidebar to avoid duplication
198
+ st.sidebar.markdown("---")
199
+ st.sidebar.subheader("Controls")
200
+ start_button = st.sidebar.button("Start Detection")
201
+ stop_button = st.sidebar.button("Stop Detection")
202
+
203
+ if start_button:
204
+ if st.session_state.model is None:
205
+ st.error("Please load a model first using the 'Load Selected Model' button")
206
+ st.stop()
207
+ if st.session_state.cap is None:
208
+ st.error("Please upload a video or provide a stream URL first")
209
+ st.stop()
210
+ st.session_state.run_detection = True
211
+ st.session_state.processed_frames = 0
212
+ st.session_state.frame_buffer = [] # Clear buffer on start
213
+ if stop_button:
214
+ st.session_state.run_detection = False
215
+
216
+ # Detection loop
217
+ while (hasattr(st.session_state, 'run_detection') and
218
+ st.session_state.run_detection and
219
+ st.session_state.cap is not None):
220
+
221
+ ret, frame = st.session_state.cap.read()
222
+ if not ret:
223
+ break
224
+
225
+ # Perform detection
226
+ detections = detect_objects(st.session_state.model, frame, detection_confidence)
227
+
228
+ # Draw boxes on frame
229
+ annotated_frame = draw_boxes(frame, detections, st.session_state.tracker)
230
+
231
+ # Add frame to buffer
232
+ st.session_state.frame_buffer.append(annotated_frame)
233
+
234
+ # Write frames to video periodically
235
+ if len(st.session_state.frame_buffer) >= 30: # Write every 30 frames
236
+ for buffered_frame in st.session_state.frame_buffer:
237
+ if st.session_state.out is not None:
238
+ st.session_state.out.write(buffered_frame)
239
+ st.session_state.processed_frames += 1
240
+ st.session_state.frame_buffer.clear()
241
+
242
+ # Update display every 3rd frame
243
+ if st.session_state.processed_frames % 3 == 0:
244
+ video_placeholder.image(annotated_frame, channels="BGR")
245
+
246
+ # Minimal sleep to prevent UI freezing
247
+ time.sleep(0.001)
248
+
249
+ # Write remaining frames in buffer
250
+ if st.session_state.frame_buffer and st.session_state.out is not None:
251
+ for buffered_frame in st.session_state.frame_buffer:
252
+ st.session_state.out.write(buffered_frame)
253
+ st.session_state.processed_frames += 1
254
+ st.session_state.frame_buffer.clear()
255
+
256
+ except Exception as e:
257
+ st.error(f"An error occurred: {str(e)}")
258
+ raise e
259
+
260
+ finally:
261
+ # Ensure proper cleanup and save remaining frames
262
+ if hasattr(st.session_state, 'frame_buffer') and st.session_state.frame_buffer and hasattr(st.session_state, 'out') and st.session_state.out is not None:
263
+ for buffered_frame in st.session_state.frame_buffer:
264
+ st.session_state.out.write(buffered_frame)
265
+ st.session_state.processed_frames += 1
266
+ st.session_state.frame_buffer.clear()
267
+
268
+ # Release resources
269
+ if hasattr(st.session_state, 'cap') and st.session_state.cap is not None:
270
+ st.session_state.cap.release()
271
+
272
+ if hasattr(st.session_state, 'out') and st.session_state.out is not None:
273
+ st.session_state.out.release()
274
+ cv2.destroyAllWindows()
275
+
276
+ # Add a separator
277
+ st.markdown("---")
278
+
279
+ # Download section
280
+ if st.session_state.processed_frames > 0:
281
+ st.subheader("Download Processed Video")
282
+
283
+ # Force flush and wait
284
+ time.sleep(3) # Increased wait time
285
+
286
+ if (st.session_state.output_path and
287
+ Path(st.session_state.output_path).exists()):
288
+
289
+ try:
290
+ with open(st.session_state.output_path, 'rb') as f:
291
+ video_data = f.read()
292
+ if len(video_data) > 1000:
293
+ st.success(f"Successfully processed {st.session_state.processed_frames} frames")
294
+ # Make download button more prominent
295
+ st.download_button(
296
+ label="📥 Download Processed Video",
297
+ data=video_data,
298
+ file_name=f"detected_video_{time.strftime('%Y%m%d_%H%M%S')}.mp4",
299
+ mime="video/mp4",
300
+ key="download_button"
301
+ )
302
+ else:
303
+ st.error("Error: Video file is empty or corrupted")
304
+ st.info("Try processing the video again with different settings")
305
+ except Exception as e:
306
+ st.error(f"Error preparing download: {str(e)}")
307
+ st.info("Please try processing the video again")
308
+ else:
309
+ st.error("Output video file not found")
310
+ st.info("Make sure to complete the video processing before downloading")
311
+
312
+ if __name__ == "__main__":
313
+ main()
asset/ezgif-5-12682faad5.gif ADDED

Git LFS Details

  • SHA256: c2ff2214f48cc1728de93b9b204fef93e3c29f0054867ac4baf4e32b2087100d
  • Pointer size: 132 Bytes
  • Size of remote file: 1.24 MB
asset/ezgif-5-28a1705b9b.gif ADDED

Git LFS Details

  • SHA256: 952bf5acd331642dea3f8806f592ff6a8d03fe705473afb3dc7b65a397a2d853
  • Pointer size: 131 Bytes
  • Size of remote file: 976 kB
detection_utils.py ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import cv2
3
+ import numpy as np
4
+ from collections import defaultdict
5
+ import streamlit as st
6
+
7
+ # Add this color_map dictionary before the draw_boxes function
8
+ # Extended color map for different classes
9
+ color_map = {
10
+ # People and animals
11
+ 'person': (0, 0, 255), # Red
12
+ 'dog': (0, 255, 255), # Cyan
13
+ 'cat': (255, 0, 255), # Magenta
14
+ 'bird': (165, 42, 42), # Brown
15
+ 'horse': (128, 0, 0), # Maroon
16
+ 'sheep': (230, 216, 173), # Beige
17
+ 'cow': (112, 128, 144), # Slate
18
+
19
+ # Vehicles
20
+ 'car': (255, 0, 0), # Blue
21
+ 'truck': (255, 165, 0), # Orange
22
+ 'bicycle': (128, 0, 128), # Purple
23
+ 'motorcycle': (255, 192, 203), # Pink
24
+ 'bus': (255, 255, 0), # Yellow
25
+ 'train': (0, 128, 0), # Dark Green
26
+ 'airplane': (70, 130, 180), # Steel Blue
27
+ 'boat': (0, 165, 255), # Orange-Red
28
+
29
+ # Objects
30
+ 'traffic light': (0, 255, 127), # Spring Green
31
+ 'fire hydrant': (255, 69, 0), # Red-Orange
32
+ 'stop sign': (220, 20, 60), # Crimson
33
+ 'bench': (107, 142, 35), # Olive
34
+ 'chair': (0, 128, 128), # Teal
35
+ 'dining table': (255, 215, 0), # Gold
36
+ 'cell phone': (138, 43, 226), # Blue Violet
37
+ 'laptop': (0, 191, 255), # Deep Sky Blue
38
+ 'keyboard': (255, 127, 80), # Coral
39
+ 'book': (218, 112, 214), # Orchid
40
+ 'clock': (240, 230, 140), # Khaki
41
+
42
+ # Sports
43
+ 'sports ball': (0, 250, 154), # Medium Spring Green
44
+ 'kite': (255, 240, 245), # Lavender
45
+ 'baseball bat': (188, 143, 143), # Rosy Brown
46
+ 'baseball glove': (46, 139, 87), # Sea Green
47
+
48
+ # Food
49
+ 'bottle': (0, 206, 209), # Turquoise
50
+ 'wine glass': (255, 248, 220), # Cornsilk
51
+ 'cup': (147, 112, 219), # Medium Purple
52
+ 'fork': (218, 165, 32), # Goldenrod
53
+ 'sandwich': (210, 105, 30), # Chocolate
54
+ 'pizza': (188, 143, 143), # Rosy Brown
55
+
56
+ # Additional objects
57
+ 'backpack': (0, 100, 0), # Dark Green
58
+ 'umbrella': (255, 182, 193), # Light Pink
59
+ 'handbag': (219, 112, 147), # Pale Violet Red
60
+ 'tie': (106, 90, 205), # Slate Blue
61
+ 'suitcase': (72, 61, 139), # Dark Slate Blue
62
+ 'frisbee': (32, 178, 170), # Light Sea Green
63
+ 'skis': (135, 206, 250), # Light Sky Blue
64
+ 'snowboard': (176, 224, 230), # Powder Blue
65
+ 'tennis racket': (218, 112, 214),# Orchid
66
+ 'surfboard': (0, 139, 139), # Dark Cyan
67
+ 'remote': (143, 188, 143), # Dark Sea Green
68
+ 'mouse': (216, 191, 216), # Thistle
69
+ 'toaster': (255, 222, 173), # Navajo White
70
+ 'sink': (112, 128, 144), # Slate Gray
71
+ 'refrigerator': (47, 79, 79), # Dark Slate Gray
72
+ 'tv': (25, 25, 112), # Midnight Blue
73
+ 'microwave': (0, 139, 139), # Dark Cyan
74
+ 'oven': (160, 82, 45), # Sienna
75
+ 'toothbrush': (199, 21, 133), # Medium Violet Red
76
+ 'scissors': (176, 196, 222), # Light Steel Blue
77
+ }
78
+
79
+ def load_model(model_path='yolov8x.pt'):
80
+ """Load YOLOv8 model"""
81
+ try:
82
+ from ultralytics import YOLO
83
+ import os
84
+ os.environ['NNPACK_FAST_MATH'] = 'OFF'
85
+
86
+ # Load the selected model
87
+ model = YOLO(model_path)
88
+
89
+ # Warmup the model
90
+ model.predict(np.zeros((640, 640, 3)), verbose=False)
91
+
92
+ return model
93
+ except Exception as e:
94
+ st.error(f"Error loading model: {str(e)}")
95
+ st.stop()
96
+
97
+ def detect_objects(model, frame, conf_threshold=0.5):
98
+ """
99
+ Detect objects in a frame using YOLO with optimized processing
100
+ """
101
+ # Convert frame to RGB
102
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
103
+
104
+ # Perform detection with optimized settings
105
+ results = model.predict(
106
+ frame_rgb,
107
+ conf=conf_threshold,
108
+ verbose=False,
109
+ device='0' if torch.cuda.is_available() else 'cpu',
110
+ imgsz=1280, # Increased size for better detection
111
+ iou=0.4, # Adjusted IOU threshold
112
+ max_det=300, # Increase maximum detections
113
+ agnostic_nms=True, # Better handling of objects of different sizes
114
+ )
115
+
116
+ result = results[0]
117
+ detections = []
118
+
119
+ if hasattr(result, 'boxes'):
120
+ boxes = result.boxes.cpu().numpy()
121
+ for box in boxes:
122
+ try:
123
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
124
+ class_id = int(box.cls[0])
125
+ confidence = float(box.conf[0])
126
+ class_name = result.names[class_id]
127
+
128
+ detection = {
129
+ 'bbox': [x1, y1, x2, y2],
130
+ 'class': class_name,
131
+ 'confidence': confidence
132
+ }
133
+ detections.append(detection)
134
+ except Exception as e:
135
+ continue
136
+
137
+ return detections
138
+
139
+ class ObjectTracker:
140
+ def __init__(self):
141
+ self.next_id = 1
142
+ self.object_ids = {}
143
+ self.id_timeout = 30
144
+ self.last_positions = {}
145
+
146
+ def get_object_id(self, bbox, class_name):
147
+ """Assign or retrieve ID for detected object based on position and IoU"""
148
+ center = ((bbox[0] + bbox[2]) // 2, (bbox[1] + bbox[3]) // 2)
149
+
150
+ # Calculate box area
151
+ box_area = (bbox[2] - bbox[0]) * (bbox[3] - bbox[1])
152
+
153
+ best_iou = 0
154
+ best_id = None
155
+
156
+ # Check existing objects
157
+ for obj_id, (old_bbox, old_class, last_seen) in list(self.last_positions.items()):
158
+ if last_seen > self.id_timeout:
159
+ del self.last_positions[obj_id]
160
+ continue
161
+
162
+ # Calculate IoU
163
+ x1 = max(bbox[0], old_bbox[0])
164
+ y1 = max(bbox[1], old_bbox[1])
165
+ x2 = min(bbox[2], old_bbox[2])
166
+ y2 = min(bbox[3], old_bbox[3])
167
+
168
+ if x2 > x1 and y2 > y1:
169
+ intersection = (x2 - x1) * (y2 - y1)
170
+ old_area = (old_bbox[2] - old_bbox[0]) * (old_bbox[3] - old_bbox[1])
171
+ union = box_area + old_area - intersection
172
+ iou = intersection / union
173
+
174
+ if iou > best_iou and iou > 0.3 and class_name == old_class:
175
+ best_iou = iou
176
+ best_id = obj_id
177
+
178
+ if best_id is not None:
179
+ self.last_positions[best_id] = (bbox, class_name, 0)
180
+ return best_id
181
+
182
+ # If no match found, assign new ID
183
+ new_id = self.next_id
184
+ self.next_id += 1
185
+ self.last_positions[new_id] = (bbox, class_name, 0)
186
+ return new_id
187
+
188
+ def update_timeouts(self):
189
+ """Update timeout counters for all tracked objects"""
190
+ for obj_id in self.last_positions:
191
+ bbox, class_name, timeout = self.last_positions[obj_id]
192
+ self.last_positions[obj_id] = (bbox, class_name, timeout + 1)
193
+
194
+ def draw_boxes(frame, detections, tracker):
195
+ """
196
+ Optimized version of drawing bounding boxes and labels with improved visibility
197
+ """
198
+ annotated_frame = frame.copy()
199
+ tracker.update_timeouts()
200
+
201
+ # Thicker lines and larger text for better visibility
202
+ box_thickness = 3
203
+ text_scale = 0.7
204
+ text_thickness = 2
205
+
206
+ for det in detections:
207
+ x1, y1, x2, y2 = det['bbox']
208
+ obj_id = tracker.get_object_id(det['bbox'], det['class'])
209
+
210
+ # Get color with default
211
+ color = color_map.get(det['class'].lower(), (0, 255, 0))
212
+
213
+ # Create label with better formatting
214
+ label = f"#{obj_id} {det['class']} {det['confidence']:.2f}"
215
+
216
+ # Draw box with thicker lines
217
+ cv2.rectangle(annotated_frame, (x1, y1), (x2, y2), color, box_thickness)
218
+
219
+ # Improve text background
220
+ (text_width, text_height), baseline = cv2.getTextSize(
221
+ label, cv2.FONT_HERSHEY_SIMPLEX, text_scale, text_thickness)
222
+
223
+ # Make background rectangle slightly larger
224
+ padding = 5
225
+ cv2.rectangle(annotated_frame,
226
+ (x1, y1 - text_height - baseline - padding * 2),
227
+ (x1 + text_width + padding * 2, y1),
228
+ color, -1)
229
+
230
+ # Add white border around the text for better visibility
231
+ for dx, dy in [(-1,-1), (-1,1), (1,-1), (1,1)]:
232
+ cv2.putText(annotated_frame, label,
233
+ (x1 + padding + dx, y1 - padding + dy),
234
+ cv2.FONT_HERSHEY_SIMPLEX, text_scale,
235
+ (0, 0, 0), text_thickness + 1)
236
+
237
+ # Draw main text
238
+ cv2.putText(annotated_frame, label,
239
+ (x1 + padding, y1 - padding),
240
+ cv2.FONT_HERSHEY_SIMPLEX, text_scale,
241
+ (255, 255, 255), text_thickness)
242
+
243
+ det['id'] = obj_id
244
+
245
+ return annotated_frame
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ opencv-python-headless>=4.7.0
2
+ torch>=2.0.0
3
+ torchvision>=0.15.0
4
+ numpy>=1.24.0
5
+ streamlit>=1.24.0
6
+ ultralytics>=8.0.0
7
+ python-dateutil>=2.8.2