File size: 5,341 Bytes
fcf6ad5
ed878d7
a300468
ed878d7
 
a300468
ed878d7
c5bbcf3
fcf6ad5
3fe33be
fcf6ad5
 
8f29306
fcf6ad5
3fe33be
ed878d7
 
 
 
979a90f
ed878d7
 
 
 
 
979a90f
ed878d7
 
 
979a90f
ed878d7
 
979a90f
3fe33be
 
 
1ea7f62
 
 
 
cb1e9a1
1ea7f62
 
 
 
 
fcf6ad5
ed878d7
6b64c3f
ed878d7
 
 
 
 
 
6b64c3f
ed878d7
6b64c3f
3fe33be
ed878d7
3fe33be
ed878d7
 
 
a300468
3fe33be
ed878d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3fe33be
ed878d7
 
3fe33be
ed878d7
 
 
 
 
 
 
3fe33be
ed878d7
a300468
3fe33be
c5bbcf3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a300468
3fe33be
ed878d7
 
a300468
3fe33be
ed878d7
 
 
fcf6ad5
 
 
 
 
3fe33be
ed878d7
fcf6ad5
ed878d7
6b64c3f
3fe33be
3e8a5f8
 
ed878d7
fcf6ad5
3fe33be
fcf6ad5
3fe33be
 
 
 
fcf6ad5
 
3fe33be
ed878d7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import gradio as gr
from roboflow import Roboflow
import tempfile
import os
from sahi.slicing import slice_image
import numpy as np
import cv2
from PIL import Image, ImageDraw

# Initialize Roboflow
rf = Roboflow(api_key="Otg64Ra6wNOgDyjuhMYU")
project = rf.workspace("alat-pelindung-diri").project("nescafe-4base")
model = project.version(16).model

# Apply NMS (Non-Maximum Suppression)
def apply_nms(predictions, iou_threshold=0.5):
    boxes = []
    scores = []
    classes = []

    # Extract boxes, scores, and class info
    for prediction in predictions:
        boxes.append(prediction['bbox'])
        scores.append(prediction['confidence'])
        classes.append(prediction['class'])

    boxes = np.array(boxes)
    scores = np.array(scores)
    classes = np.array(classes)

    # Perform NMS using OpenCV
    indices = cv2.dnn.NMSBoxes(boxes.tolist(), scores.tolist(), score_threshold=0.25, nms_threshold=iou_threshold)

    print(f"Predictions before NMS: {predictions}")
    print(f"Indices after NMS: {indices}")

    # Check if indices is empty or invalid
    if not indices or not isinstance(indices, tuple) or len(indices) == 0:
        print("No valid indices returned from NMS.")
        return []  # Return an empty list if no valid indices are found

    # Extract the indices if they are valid
    indices = indices[0]  # Extracting the first element which contains the indices

    # Flatten indices array (if returned as a tuple)
    indices = indices.flatten() if isinstance(indices, np.ndarray) else np.array(indices).flatten()

    nms_predictions = []

    for i in indices:
        nms_predictions.append({
            'class': classes[i],
            'bbox': boxes[i],
            'confidence': scores[i]
        })

    return nms_predictions

# Detect objects and annotate the image
def detect_objects(image):
    # Save the image temporarily
    with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file:
        image.save(temp_file, format="JPEG")
        temp_file_path = temp_file.name

    # Slice the image into smaller pieces
    slice_image_result = slice_image(
        image=temp_file_path,
        output_file_name="sliced_image",
        output_dir="/tmp/sliced/",
        slice_height=256,
        slice_width=256,
        overlap_height_ratio=0.1,
        overlap_width_ratio=0.1
    )

    # Print to check the available attributes of the slice_image_result object
    print(f"Slice result: {slice_image_result}")

    # Try accessing the sliced image paths from the result object
    try:
        sliced_image_paths = slice_image_result.sliced_image_paths  # Assuming this is the correct attribute
        print(f"Sliced image paths: {sliced_image_paths}")
    except AttributeError:
        print("Failed to access sliced_image_paths attribute.")
        sliced_image_paths = []

    # Save all predictions for each sliced image
    all_predictions = []

    # Predict on each sliced image
    for sliced_image_path in sliced_image_paths:
        if isinstance(sliced_image_path, str):
            predictions = model.predict(image_path=sliced_image_path).json()
            all_predictions.extend(predictions['predictions'])
        else:
            print(f"Skipping invalid image path: {sliced_image_path}")
    
    # Apply NMS to remove duplicate detections
    postprocessed_predictions = apply_nms(all_predictions, iou_threshold=0.5)

    # Annotate the image with prediction results using OpenCV
    img = cv2.imread(temp_file_path)
    for prediction in postprocessed_predictions:
        class_name = prediction['class']
        bbox = prediction['bbox']
        confidence = prediction['confidence']
        
        # Unpack the bounding box coordinates
        x, y, w, h = map(int, bbox)

        # Draw the bounding box and label on the image
        color = (0, 255, 0)  # Green color for the box
        thickness = 2
        cv2.rectangle(img, (x, y), (x + w, y + h), color, thickness)

        label = f"{class_name}: {confidence:.2f}"
        cv2.putText(img, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, thickness)

    # Convert the image from BGR to RGB for PIL compatibility
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    annotated_image = Image.fromarray(img_rgb)

    # Save the annotated image
    output_image_path = "/tmp/prediction.jpg"
    annotated_image.save(output_image_path)

    # Count objects per class
    class_count = {}
    for detection in postprocessed_predictions:
        class_name = detection['class']
        if class_name in class_count:
            class_count[class_name] += 1
        else:
            class_count[class_name] = 1

    # Object count result
    result_text = "Jumlah objek per kelas:\n"
    for class_name, count in class_count.items():
        result_text += f"{class_name}: {count} objek\n"

    # Remove temporary file
    os.remove(temp_file_path)

    return output_image_path, result_text

# Gradio interface
iface = gr.Interface(
    fn=detect_objects,                         # Function called when image is uploaded
    inputs=gr.Image(type="pil"),               # Input is an image
    outputs=[gr.Image(), gr.Textbox()],        # Output is an image and text
    live=True                                    # Display results live
)

# Run the interface
iface.launch()