Muhammed Sezer commited on
Commit
34d2ee5
·
1 Parent(s): c1d380f
.kiro/specs/yolov8-gradio-app/design.md ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Design Document
2
+
3
+ ## Overview
4
+
5
+ The YOLOv8 Gradio Object Detection application is a web-based tool that provides real-time object detection capabilities through an intuitive user interface. The system leverages the Ultralytics YOLOv8 model for state-of-the-art object detection and Gradio for creating an interactive web interface. The application follows a simple pipeline: image upload → detection processing → dual output (annotated image + structured data table).
6
+
7
+ ## Architecture
8
+
9
+ The application follows a single-file architecture with clear separation of concerns:
10
+
11
+ ```
12
+ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
13
+ │ Gradio UI │───▶│ Detection Core │───▶│ Output Layer │
14
+ │ │ │ │ │ │
15
+ │ - Image Upload │ │ - YOLOv8 Model │ │ - Annotated Img │
16
+ │ - File Handling │ │ - Preprocessing │ │ - Data Table │
17
+ │ - Display │ │ - Postprocessing │ │ - Error Display │
18
+ └─────────────────┘ └──────────────────┘ └─────────────────┘
19
+ ```
20
+
21
+ ### Key Design Decisions
22
+
23
+ 1. **Single-file Architecture**: Keeps the application simple and self-contained for easy deployment
24
+ 2. **Pretrained Model**: Uses YOLOv8n for balance between speed and accuracy
25
+ 3. **Dual Output**: Provides both visual and structured data outputs to serve different user needs
26
+ 4. **PIL/NumPy Integration**: Ensures compatibility between Gradio, OpenCV, and YOLOv8 image formats
27
+
28
+ ## Components and Interfaces
29
+
30
+ ### 1. Model Management Component
31
+
32
+ **Purpose**: Handle YOLOv8 model loading and initialization
33
+
34
+ ```python
35
+ # Interface
36
+ model = YOLO("yolov8n.pt") # Global model instance
37
+ ```
38
+
39
+ **Responsibilities**:
40
+ - Load pretrained YOLOv8 model on application startup
41
+ - Handle model loading errors and fallbacks
42
+ - Provide access to model class names mapping
43
+
44
+ ### 2. Image Processing Component
45
+
46
+ **Purpose**: Handle image format conversions and preprocessing
47
+
48
+ ```python
49
+ # Interface
50
+ def preprocess_image(image: Image.Image) -> np.ndarray
51
+ def postprocess_results(results, original_image) -> tuple
52
+ ```
53
+
54
+ **Responsibilities**:
55
+ - Convert PIL Image to NumPy array for YOLOv8 processing
56
+ - Handle image format validation
57
+ - Maintain image aspect ratios during processing
58
+
59
+ ### 3. Detection Engine Component
60
+
61
+ **Purpose**: Core object detection logic
62
+
63
+ ```python
64
+ # Interface
65
+ def detect_objects(image: Image.Image) -> tuple[Image.Image, pd.DataFrame]
66
+ ```
67
+
68
+ **Responsibilities**:
69
+ - Execute YOLOv8 inference on input images
70
+ - Parse detection results (boxes, classes, confidence scores)
71
+ - Generate annotated output images
72
+ - Create structured data output
73
+
74
+ ### 4. Gradio Interface Component
75
+
76
+ **Purpose**: Web UI creation and event handling
77
+
78
+ ```python
79
+ # Interface
80
+ demo = gr.Interface(
81
+ fn=detect_objects,
82
+ inputs=gr.Image(type="pil", label="Upload Image"),
83
+ outputs=[gr.Image(type="pil"), gr.Dataframe()]
84
+ )
85
+ ```
86
+
87
+ **Responsibilities**:
88
+ - Create responsive web interface
89
+ - Handle file uploads and validation
90
+ - Display results in appropriate formats
91
+ - Manage user interactions
92
+
93
+ ## Data Models
94
+
95
+ ### Detection Result Model
96
+
97
+ ```python
98
+ {
99
+ "class": str, # Object class name (e.g., "person", "car")
100
+ "confidence": float, # Confidence score (0.0-1.0, rounded to 3 decimals)
101
+ "x1": float, # Top-left x coordinate (rounded to 1 decimal)
102
+ "y1": float, # Top-left y coordinate (rounded to 1 decimal)
103
+ "x2": float, # Bottom-right x coordinate (rounded to 1 decimal)
104
+ "y2": float # Bottom-right y coordinate (rounded to 1 decimal)
105
+ }
106
+ ```
107
+
108
+ ### Image Processing Pipeline
109
+
110
+ ```
111
+ Input: PIL Image → NumPy Array → YOLOv8 Processing → Results Object →
112
+ Output: Annotated PIL Image + Pandas DataFrame
113
+ ```
114
+
115
+ ## Error Handling
116
+
117
+ ### Model Loading Errors
118
+ - **Issue**: YOLOv8 model file not found or corrupted
119
+ - **Handling**: Display clear error message, suggest model download
120
+ - **Fallback**: Graceful degradation with error display in UI
121
+
122
+ ### Image Processing Errors
123
+ - **Issue**: Invalid image format or corrupted file
124
+ - **Handling**: Validate file type before processing
125
+ - **Fallback**: Display user-friendly error message
126
+
127
+ ### Detection Processing Errors
128
+ - **Issue**: YOLOv8 inference failures
129
+ - **Handling**: Catch exceptions during model inference
130
+ - **Fallback**: Return empty results with error notification
131
+
132
+ ### Memory Management
133
+ - **Issue**: Large image files causing memory issues
134
+ - **Handling**: Implement image size validation and resizing if needed
135
+ - **Fallback**: Display memory limitation warnings
136
+
137
+ ## Testing Strategy
138
+
139
+ ### Unit Testing
140
+ - **Model Loading**: Test YOLOv8 model initialization and error handling
141
+ - **Image Processing**: Test format conversions and preprocessing functions
142
+ - **Detection Logic**: Test detection result parsing and data structure creation
143
+ - **Data Formatting**: Test confidence score and coordinate rounding
144
+
145
+ ### Integration Testing
146
+ - **End-to-End Pipeline**: Test complete image upload → detection → output flow
147
+ - **UI Components**: Test Gradio interface functionality and responsiveness
148
+ - **Error Scenarios**: Test various error conditions and fallback behaviors
149
+
150
+ ### Performance Testing
151
+ - **Inference Speed**: Measure detection processing time for various image sizes
152
+ - **Memory Usage**: Monitor memory consumption during processing
153
+ - **Concurrent Users**: Test application behavior with multiple simultaneous users
154
+
155
+ ### User Acceptance Testing
156
+ - **Image Format Support**: Test with various image formats (JPG, PNG, JPEG)
157
+ - **Detection Accuracy**: Validate detection results against known test images
158
+ - **UI Usability**: Test interface responsiveness and user experience
159
+ - **Output Quality**: Verify annotated images and data table accuracy
160
+
161
+ ## Deployment Considerations
162
+
163
+ ### Dependencies
164
+ - **Core**: gradio, ultralytics, opencv-python, pillow, numpy, pandas
165
+ - **Model**: Automatic YOLOv8n.pt download on first run
166
+ - **Python Version**: 3.8+ recommended for compatibility
167
+
168
+ ### Performance Optimization
169
+ - **Model Caching**: Keep model loaded in memory to avoid reload overhead
170
+ - **Image Resizing**: Implement intelligent resizing for very large images
171
+ - **Batch Processing**: Consider batch processing for multiple images (future enhancement)
172
+
173
+ ### Security
174
+ - **File Upload Validation**: Strict image format validation
175
+ - **File Size Limits**: Implement reasonable file size restrictions
176
+ - **Input Sanitization**: Validate all user inputs before processing
.kiro/specs/yolov8-gradio-app/requirements.md ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Requirements Document
2
+
3
+ ## Introduction
4
+
5
+ This feature implements a web-based object detection application using YOLOv8 and Gradio. The application allows users to upload images and receive real-time object detection results with visual annotations and structured data output. The system leverages a pretrained YOLOv8 model to identify and classify objects in uploaded images, providing both visual feedback through bounding boxes and detailed detection information in a tabular format.
6
+
7
+ ## Requirements
8
+
9
+ ### Requirement 1
10
+
11
+ **User Story:** As a user, I want to upload an image to the web application, so that I can get object detection results for analysis.
12
+
13
+ #### Acceptance Criteria
14
+
15
+ 1. WHEN a user accesses the web application THEN the system SHALL display an image upload interface
16
+ 2. WHEN a user selects an image file THEN the system SHALL accept common image formats (JPG, PNG, JPEG)
17
+ 3. WHEN an image is uploaded THEN the system SHALL process the image and display it in the interface
18
+ 4. IF the uploaded file is not a valid image format THEN the system SHALL display an appropriate error message
19
+
20
+ ### Requirement 2
21
+
22
+ **User Story:** As a user, I want the system to detect objects in my uploaded image, so that I can identify what objects are present.
23
+
24
+ #### Acceptance Criteria
25
+
26
+ 1. WHEN an image is uploaded THEN the system SHALL run YOLOv8 object detection on the image
27
+ 2. WHEN objects are detected THEN the system SHALL identify object classes using the pretrained model
28
+ 3. WHEN detection is complete THEN the system SHALL calculate confidence scores for each detection
29
+ 4. WHEN detection is complete THEN the system SHALL determine bounding box coordinates for each object
30
+ 5. IF no objects are detected THEN the system SHALL return an empty results set
31
+
32
+ ### Requirement 3
33
+
34
+ **User Story:** As a user, I want to see visual annotations on my image, so that I can easily identify where objects were detected.
35
+
36
+ #### Acceptance Criteria
37
+
38
+ 1. WHEN objects are detected THEN the system SHALL draw bounding boxes around detected objects
39
+ 2. WHEN bounding boxes are drawn THEN the system SHALL include class labels on each box
40
+ 3. WHEN bounding boxes are drawn THEN the system SHALL include confidence scores on each box
41
+ 4. WHEN annotations are complete THEN the system SHALL display the annotated image to the user
42
+ 5. WHEN displaying results THEN the system SHALL maintain the original image aspect ratio
43
+
44
+ ### Requirement 4
45
+
46
+ **User Story:** As a user, I want to see detection results in a structured table format, so that I can analyze the data programmatically.
47
+
48
+ #### Acceptance Criteria
49
+
50
+ 1. WHEN objects are detected THEN the system SHALL generate a structured data table
51
+ 2. WHEN creating the table THEN the system SHALL include object class names
52
+ 3. WHEN creating the table THEN the system SHALL include confidence scores rounded to 3 decimal places
53
+ 4. WHEN creating the table THEN the system SHALL include bounding box coordinates (x1, y1, x2, y2) rounded to 1 decimal place
54
+ 5. WHEN displaying the table THEN the system SHALL present data in a user-friendly tabular format
55
+
56
+ ### Requirement 5
57
+
58
+ **User Story:** As a developer, I want the application to use a pretrained YOLOv8 model, so that I don't need to train a custom model.
59
+
60
+ #### Acceptance Criteria
61
+
62
+ 1. WHEN the application starts THEN the system SHALL load a pretrained YOLOv8 model (yolov8n.pt)
63
+ 2. WHEN loading the model THEN the system SHALL handle model loading errors gracefully
64
+ 3. WHEN using the model THEN the system SHALL utilize the built-in class name mappings
65
+ 4. IF the model file is missing THEN the system SHALL download it automatically or display an appropriate error
66
+
67
+ ### Requirement 6
68
+
69
+ **User Story:** As a user, I want the web interface to be intuitive and responsive, so that I can easily use the application.
70
+
71
+ #### Acceptance Criteria
72
+
73
+ 1. WHEN the application launches THEN the system SHALL display a clear title and description
74
+ 2. WHEN the interface loads THEN the system SHALL provide clear labels for input and output sections
75
+ 3. WHEN processing an image THEN the system SHALL provide visual feedback during processing
76
+ 4. WHEN results are ready THEN the system SHALL display both the annotated image and data table simultaneously
77
+ 5. WHEN the application is accessed THEN the system SHALL be responsive across different screen sizes
.kiro/specs/yolov8-gradio-app/tasks.md ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Implementation Plan
2
+
3
+ - [x] 1. Set up project structure and implement YOLOv8 model loading
4
+
5
+ - Create project directory structure with app.py and requirements.txt
6
+ - Install dependencies (gradio, ultralytics, opencv-python, pillow, numpy, pandas)
7
+ - Implement YOLOv8 model initialization with error handling and validation
8
+ - Create basic image preprocessing utilities for PIL to NumPy conversion
9
+ - _Requirements: 5.1, 5.2, 5.3, 1.2, 1.4, 2.1_
10
+
11
+ - [x] 2. Implement core object detection and result processing
12
+
13
+
14
+ - Write the main detect_objects function that processes images through YOLOv8
15
+ - Implement detection result parsing to extract classes, confidence scores, and bounding boxes
16
+ - Create structured data formatting with proper rounding (confidence to 3 decimals, coordinates to 1 decimal)
17
+ - Add comprehensive error handling for detection failures and edge cases
18
+ - _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 4.1, 4.2, 4.3, 4.4_
19
+ -
20
+
21
+ - [ ] 3. Create image annotation and Gradio interface
22
+
23
+
24
+
25
+ - Implement annotated image generation using YOLOv8's plot() method with bounding boxes and labels
26
+ - Create Gradio Interface with image upload input and dual output (annotated image + data table)
27
+ - Add appropriate UI labels, descriptions, and user-friendly formatting
28
+ - Ensure proper aspect ratio maintenance and responsive display
29
+ - _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 1.1, 1.3, 4.5, 6.1, 6.2, 6.4_
30
+
31
+ - [ ] 4. Integrate components and finalize application
32
+ - Wire together all components into complete app.py with proper error handling
33
+ - Implement application launcher with demo.launch() and configuration options
34
+ - Add comprehensive validation for file uploads and user inputs
35
+ - Create end-to-end testing and deployment documentation
36
+ - _Requirements: 6.1, 6.2, 6.3, 6.4, 6.5, 1.4, 5.4_
__pycache__/app.cpython-313.pyc ADDED
Binary file (8.82 kB). View file
 
annotated_result.jpg ADDED
app.py ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ YOLOv8 Gradio Object Detection Application
3
+
4
+ This application provides a web-based interface for object detection using YOLOv8.
5
+ Users can upload images and receive real-time object detection results with
6
+ visual annotations and structured data output.
7
+ """
8
+
9
+ import logging
10
+ import sys
11
+ from typing import Tuple, Optional
12
+
13
+ import cv2
14
+ import gradio as gr
15
+ import numpy as np
16
+ import pandas as pd
17
+ from PIL import Image
18
+ from ultralytics import YOLO
19
+
20
+ # Configure logging
21
+ logging.basicConfig(level=logging.INFO)
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # Global model instance
25
+ model: Optional[YOLO] = None
26
+
27
+
28
+ def initialize_model() -> bool:
29
+ """
30
+ Initialize YOLOv8 model with error handling and validation.
31
+
32
+ Returns:
33
+ bool: True if model loaded successfully, False otherwise
34
+ """
35
+ global model
36
+ try:
37
+ logger.info("Loading YOLOv8 model...")
38
+ model = YOLO("yolov8n.pt")
39
+ logger.info("YOLOv8 model loaded successfully")
40
+ return True
41
+ except Exception as e:
42
+ logger.error("Failed to load YOLOv8 model: %s", str(e))
43
+ model = None
44
+ return False
45
+
46
+
47
+ def preprocess_image(image: Image.Image) -> np.ndarray:
48
+ """
49
+ Convert PIL Image to NumPy array for YOLOv8 processing.
50
+
51
+ Args:
52
+ image (Image.Image): PIL Image object
53
+
54
+ Returns:
55
+ np.ndarray: NumPy array in RGB format
56
+ """
57
+ try:
58
+ # Convert PIL Image to RGB if not already
59
+ if image.mode != 'RGB':
60
+ image = image.convert('RGB')
61
+
62
+ # Convert to NumPy array
63
+ image_array = np.array(image)
64
+
65
+ logger.info("Image preprocessed: shape %s", image_array.shape)
66
+ return image_array
67
+
68
+ except Exception as e:
69
+ logger.error("Error preprocessing image: %s", str(e))
70
+ raise
71
+
72
+
73
+ def detect_objects(image: Image.Image) -> Tuple[Image.Image, pd.DataFrame]:
74
+ """
75
+ Main object detection function that processes images through YOLOv8.
76
+
77
+ Args:
78
+ image (Image.Image): PIL Image object to process
79
+
80
+ Returns:
81
+ Tuple[Image.Image, pd.DataFrame]: Annotated image and detection results table
82
+ """
83
+ if model is None:
84
+ logger.error("YOLOv8 model not loaded")
85
+ # Return original image and empty dataframe
86
+ empty_df = pd.DataFrame(columns=['class', 'confidence', 'x1', 'y1', 'x2', 'y2'])
87
+ return image, empty_df
88
+
89
+ try:
90
+ # Preprocess the image
91
+ logger.info("Starting object detection...")
92
+ processed_image = preprocess_image(image)
93
+
94
+ # Run YOLOv8 inference
95
+ results = model(processed_image)
96
+
97
+ # Parse detection results
98
+ annotated_image, detection_data = parse_detection_results(results[0], image)
99
+
100
+ logger.info("Object detection completed successfully")
101
+ return annotated_image, detection_data
102
+
103
+ except Exception as e:
104
+ logger.error("Error during object detection: %s", str(e))
105
+ # Return original image and empty dataframe on error
106
+ empty_df = pd.DataFrame(columns=['class', 'confidence', 'x1', 'y1', 'x2', 'y2'])
107
+ return image, empty_df
108
+
109
+
110
+ def parse_detection_results(results, original_image: Image.Image) -> Tuple[Image.Image, pd.DataFrame]:
111
+ """
112
+ Parse YOLOv8 detection results to extract classes, confidence scores, and bounding boxes.
113
+
114
+ Args:
115
+ results: YOLOv8 detection results object
116
+ original_image (Image.Image): Original PIL image for annotation
117
+
118
+ Returns:
119
+ Tuple[Image.Image, pd.DataFrame]: Annotated image and structured detection data
120
+ """
121
+ try:
122
+ # Extract detection data
123
+ detection_list = []
124
+
125
+ # Check if any detections were found
126
+ if results.boxes is not None and len(results.boxes) > 0:
127
+ # Get class names from the model
128
+ class_names = results.names
129
+
130
+ # Extract boxes, classes, and confidence scores
131
+ boxes = results.boxes.xyxy.cpu().numpy() # x1, y1, x2, y2 format
132
+ classes = results.boxes.cls.cpu().numpy()
133
+ confidences = results.boxes.conf.cpu().numpy()
134
+
135
+ # Process each detection
136
+ for i in range(len(boxes)):
137
+ class_id = int(classes[i])
138
+ class_name = class_names[class_id]
139
+ confidence = float(confidences[i])
140
+ x1, y1, x2, y2 = boxes[i]
141
+
142
+ # Create detection record with proper rounding
143
+ detection_record = {
144
+ 'class': class_name,
145
+ 'confidence': round(confidence, 3), # Round to 3 decimal places
146
+ 'x1': round(float(x1), 1), # Round to 1 decimal place
147
+ 'y1': round(float(y1), 1),
148
+ 'x2': round(float(x2), 1),
149
+ 'y2': round(float(y2), 1)
150
+ }
151
+
152
+ detection_list.append(detection_record)
153
+
154
+ logger.info("Parsed %d detections", len(detection_list))
155
+ else:
156
+ logger.info("No objects detected in the image")
157
+
158
+ # Create DataFrame from detection list with proper columns
159
+ if detection_list:
160
+ detection_df = pd.DataFrame(detection_list)
161
+ else:
162
+ # Create empty DataFrame with correct columns
163
+ detection_df = pd.DataFrame(columns=['class', 'confidence', 'x1', 'y1', 'x2', 'y2'])
164
+
165
+ # Generate annotated image using YOLOv8's built-in plotting
166
+ annotated_image = generate_annotated_image(results, original_image)
167
+
168
+ return annotated_image, detection_df
169
+
170
+ except Exception as e:
171
+ logger.error("Error parsing detection results: %s", str(e))
172
+ # Return original image and empty dataframe on error
173
+ empty_df = pd.DataFrame(columns=['class', 'confidence', 'x1', 'y1', 'x2', 'y2'])
174
+ return original_image, empty_df
175
+
176
+
177
+ def generate_annotated_image(results, original_image: Image.Image) -> Image.Image:
178
+ """
179
+ Generate annotated image with bounding boxes and labels using YOLOv8's plot method.
180
+
181
+ Args:
182
+ results: YOLOv8 detection results object
183
+ original_image (Image.Image): Original PIL image
184
+
185
+ Returns:
186
+ Image.Image: Annotated PIL image with bounding boxes and labels
187
+ """
188
+ try:
189
+ # Use YOLOv8's built-in plot method to generate annotations
190
+ # This automatically adds bounding boxes, class labels, and confidence scores
191
+ annotated_array = results.plot(
192
+ conf=True, # Show confidence scores
193
+ labels=True, # Show class labels
194
+ boxes=True, # Show bounding boxes
195
+ line_width=2, # Line width for bounding boxes
196
+ font_size=12 # Font size for labels
197
+ )
198
+
199
+ # Convert BGR to RGB (YOLOv8 plot returns BGR format)
200
+ annotated_rgb = cv2.cvtColor(annotated_array, cv2.COLOR_BGR2RGB)
201
+
202
+ # Convert NumPy array back to PIL Image
203
+ annotated_image = Image.fromarray(annotated_rgb)
204
+
205
+ # Ensure the annotated image maintains aspect ratio
206
+ # The YOLOv8 plot method should preserve the original dimensions
207
+ logger.info("Generated annotated image successfully with dimensions: %s",
208
+ annotated_image.size)
209
+ return annotated_image
210
+
211
+ except Exception as e:
212
+ logger.error("Error generating annotated image: %s", str(e))
213
+ # Return original image on error to maintain aspect ratio
214
+ return original_image
215
+
216
+
217
+ def create_gradio_interface():
218
+ """
219
+ Create Gradio Interface with image upload input and dual output.
220
+
221
+ Returns:
222
+ gr.Interface: Configured Gradio interface
223
+ """
224
+ # Create the Gradio interface
225
+ demo = gr.Interface(
226
+ fn=detect_objects,
227
+ inputs=gr.Image(
228
+ type="pil",
229
+ label="Upload Image for Object Detection",
230
+ sources=["upload", "clipboard"],
231
+ height=400
232
+ ),
233
+ outputs=[
234
+ gr.Image(
235
+ type="pil",
236
+ label="Annotated Image with Detections",
237
+ height=400,
238
+ show_label=True
239
+ ),
240
+ gr.Dataframe(
241
+ label="Detection Results",
242
+ headers=["Class", "Confidence", "X1", "Y1", "X2", "Y2"],
243
+ datatype=["str", "number", "number", "number", "number", "number"],
244
+ col_count=(6, "fixed"),
245
+ row_count=(10, "dynamic"),
246
+ interactive=False
247
+ )
248
+ ],
249
+ title="🎯 YOLOv8 Object Detection",
250
+ description="""
251
+ **Upload an image to detect objects using YOLOv8!**
252
+
253
+ This application uses a pretrained YOLOv8 model to identify and locate objects in your images.
254
+ You'll get both a visual representation with bounding boxes and a detailed data table.
255
+
256
+ **Supported formats:** JPG, PNG, JPEG
257
+ """,
258
+ article="""
259
+ ### How it works:
260
+ 1. **Upload** an image using the interface above
261
+ 2. **View** the annotated image with bounding boxes and labels
262
+ 3. **Analyze** the detection data in the table with confidence scores and coordinates
263
+
264
+ The confidence scores are rounded to 3 decimal places, and coordinates to 1 decimal place for clarity.
265
+ """,
266
+ theme=gr.themes.Soft(),
267
+ css="""
268
+ .gradio-container {
269
+ max-width: 1200px !important;
270
+ }
271
+ .output-image {
272
+ height: 400px !important;
273
+ }
274
+ """,
275
+ examples=[
276
+ # Add example images if available
277
+ ],
278
+ cache_examples=False,
279
+ allow_flagging="never"
280
+ )
281
+
282
+ return demo
283
+
284
+
285
+ if __name__ == "__main__":
286
+ # Initialize model on startup
287
+ if not initialize_model():
288
+ logger.error("Failed to initialize YOLOv8 model. Application cannot start.")
289
+ sys.exit(1)
290
+
291
+ logger.info("YOLOv8 model initialized successfully")
292
+
293
+ # Create and launch Gradio interface
294
+ try:
295
+ demo = create_gradio_interface()
296
+ logger.info("Gradio interface created successfully")
297
+
298
+ # Launch the application
299
+ demo.launch(
300
+ server_name="0.0.0.0",
301
+ server_port=7860,
302
+ share=False,
303
+ debug=False,
304
+ show_error=True,
305
+ quiet=False
306
+ )
307
+
308
+ except Exception as e:
309
+ logger.error("Error launching Gradio interface: %s", str(e))
310
+ sys.exit(1)
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ ultralytics>=8.0.0
3
+ opencv-python>=4.8.0
4
+ pillow>=10.0.0
5
+ numpy>=1.24.0
6
+ pandas>=2.0.0
test_detection.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Test script to verify the object detection functionality with a sample image.
3
+ """
4
+
5
+ import sys
6
+ from PIL import Image, ImageDraw
7
+ import pandas as pd
8
+
9
+ # Import our detection functions
10
+ from app import initialize_model, detect_objects
11
+
12
+ def create_test_image():
13
+ """Create a simple test image with some basic shapes."""
14
+ # Create a white background
15
+ img = Image.new('RGB', (640, 480), 'white')
16
+ draw = ImageDraw.Draw(img)
17
+
18
+ # Draw some simple shapes that might be detected as objects
19
+ # Rectangle (might be detected as a book or similar)
20
+ draw.rectangle([100, 100, 300, 200], fill='blue', outline='black', width=3)
21
+
22
+ # Circle (might be detected as a ball or similar)
23
+ draw.ellipse([400, 150, 500, 250], fill='red', outline='black', width=3)
24
+
25
+ # Another rectangle
26
+ draw.rectangle([200, 300, 400, 400], fill='green', outline='black', width=3)
27
+
28
+ return img
29
+
30
+ def main():
31
+ print("Testing YOLOv8 object detection...")
32
+
33
+ # Initialize model
34
+ if not initialize_model():
35
+ print("Failed to initialize model")
36
+ return
37
+
38
+ # Create test image
39
+ test_img = create_test_image()
40
+ test_img.save("test_image.jpg")
41
+ print("Created test image: test_image.jpg")
42
+
43
+ # Run detection
44
+ annotated_img, detection_df = detect_objects(test_img)
45
+
46
+ # Save results
47
+ annotated_img.save("annotated_result.jpg")
48
+ print("Saved annotated result: annotated_result.jpg")
49
+
50
+ # Print detection results
51
+ print(f"\nDetection Results:")
52
+ print(f"Number of detections: {len(detection_df)}")
53
+
54
+ if len(detection_df) > 0:
55
+ print("\nDetailed results:")
56
+ print(detection_df.to_string(index=False))
57
+
58
+ # Verify data formatting
59
+ print("\nData formatting verification:")
60
+ for _, row in detection_df.iterrows():
61
+ print(f"Class: {row['class']}")
62
+ print(f"Confidence: {row['confidence']} (type: {type(row['confidence'])})")
63
+ print(f"Coordinates: ({row['x1']}, {row['y1']}, {row['x2']}, {row['y2']})")
64
+ print(f"Coordinate types: {type(row['x1'])}, {type(row['y1'])}, {type(row['x2'])}, {type(row['y2'])}")
65
+ print("---")
66
+ else:
67
+ print("No objects detected")
68
+
69
+ print("\nTest completed successfully!")
70
+
71
+ if __name__ == "__main__":
72
+ main()
test_error_handling.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Test script to verify error handling in the object detection functionality.
3
+ """
4
+
5
+ from PIL import Image
6
+ import pandas as pd
7
+ import app
8
+ from app import detect_objects, initialize_model
9
+
10
+ def test_with_none_model():
11
+ """Test detection when model is None."""
12
+ print("Testing with None model...")
13
+
14
+ # Temporarily set model to None
15
+ original_model = app.model
16
+ app.model = None
17
+
18
+ # Create test image
19
+ test_img = Image.new('RGB', (100, 100), 'white')
20
+
21
+ # Run detection
22
+ annotated_img, detection_df = detect_objects(test_img)
23
+
24
+ # Verify results
25
+ print(f"Returned image type: {type(annotated_img)}")
26
+ print(f"Returned DataFrame shape: {detection_df.shape}")
27
+ print(f"DataFrame columns: {list(detection_df.columns)}")
28
+ print(f"DataFrame empty: {detection_df.empty}")
29
+
30
+ # Restore original model
31
+ app.model = original_model
32
+ print("Model restored\n")
33
+
34
+ def test_with_corrupted_image():
35
+ """Test detection with edge case images."""
36
+ print("Testing with very small image...")
37
+
38
+ # Create very small image
39
+ tiny_img = Image.new('RGB', (1, 1), 'black')
40
+
41
+ # Run detection
42
+ annotated_img, detection_df = detect_objects(tiny_img)
43
+
44
+ print(f"Small image - Detections: {len(detection_df)}")
45
+ expected_columns = ['class', 'confidence', 'x1', 'y1', 'x2', 'y2']
46
+ print(f"Small image - DataFrame columns: {list(detection_df.columns)}")
47
+ print(f"Small image - DataFrame columns correct: {list(detection_df.columns) == expected_columns}")
48
+
49
+ print("Testing with large image...")
50
+
51
+ # Create large image
52
+ large_img = Image.new('RGB', (2000, 2000), 'blue')
53
+
54
+ # Run detection
55
+ annotated_img, detection_df = detect_objects(large_img)
56
+
57
+ print(f"Large image - Detections: {len(detection_df)}")
58
+ print(f"Large image - DataFrame columns: {list(detection_df.columns)}")
59
+ print(f"Large image - DataFrame columns correct: {list(detection_df.columns) == expected_columns}")
60
+
61
+ def main():
62
+ print("Testing error handling scenarios...\n")
63
+
64
+ # Initialize model first
65
+ if not initialize_model():
66
+ print("Failed to initialize model for testing")
67
+ return
68
+
69
+ test_with_none_model()
70
+ test_with_corrupted_image()
71
+
72
+ print("Error handling tests completed!")
73
+
74
+ if __name__ == "__main__":
75
+ main()
test_gradio_interface.py ADDED
File without changes
test_image.jpg ADDED
yolov8n.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f59b3d833e2ff32e194b5bb8e08d211dc7c5bdf144b90d2c8412c47ccfc83b36
3
+ size 6549796