Update app.py
Browse files
app.py
CHANGED
@@ -28,10 +28,10 @@ yolo_model = project.version(model_version).model
|
|
28 |
|
29 |
# ========== Fungsi Deteksi Kombinasi ==========
|
30 |
def detect_combined(image):
|
31 |
-
# Konversi gambar ke format numpy array
|
32 |
image_np = np.array(image)
|
33 |
|
34 |
-
# Resize gambar ke 640x640
|
35 |
image_resized = cv2.resize(image_np, (640, 640))
|
36 |
|
37 |
# Simpan gambar input yang sudah di-resize ke file sementara
|
@@ -43,7 +43,7 @@ def detect_combined(image):
|
|
43 |
# ========== [1] YOLO: Deteksi Produk Nestlé ==========
|
44 |
yolo_pred = yolo_model.predict(temp_path, confidence=50, overlap=80).json()
|
45 |
|
46 |
-
# Hitung per kelas dan simpan bounding box
|
47 |
nestle_class_count = {}
|
48 |
nestle_boxes = []
|
49 |
for pred in yolo_pred['predictions']:
|
@@ -54,16 +54,13 @@ def detect_combined(image):
|
|
54 |
total_nestle = sum(nestle_class_count.values())
|
55 |
|
56 |
# ========== [2] OWLv2: Deteksi Kompetitor ==========
|
57 |
-
headers = {
|
58 |
-
|
59 |
-
|
60 |
-
data = {
|
61 |
-
"prompts": OWLV2_PROMPTS,
|
62 |
-
"model": "owlv2"
|
63 |
-
}
|
64 |
with open(temp_path, "rb") as f:
|
65 |
files = {"image": f}
|
66 |
response = requests.post("https://api.landing.ai/v1/tools/text-to-object-detection", files=files, data=data, headers=headers)
|
|
|
67 |
result = response.json()
|
68 |
owlv2_objects = result['data'][0] if 'data' in result else []
|
69 |
|
@@ -72,7 +69,6 @@ def detect_combined(image):
|
|
72 |
for obj in owlv2_objects:
|
73 |
if 'bounding_box' in obj:
|
74 |
bbox = obj['bounding_box'] # Format: [x1, y1, x2, y2]
|
75 |
-
# Filter objek yang sudah terdeteksi oleh YOLO (Overlap detection)
|
76 |
if not is_overlap(bbox, nestle_boxes):
|
77 |
class_name = obj.get('label', 'unknown').strip().lower()
|
78 |
competitor_class_count[class_name] = competitor_class_count.get(class_name, 0) + 1
|
@@ -89,13 +85,14 @@ def detect_combined(image):
|
|
89 |
for class_name, count in nestle_class_count.items():
|
90 |
result_text += f"{class_name}: {count}\n"
|
91 |
result_text += f"\nTotal Products Nestle: {total_nestle}\n\n"
|
|
|
92 |
if competitor_class_count:
|
93 |
result_text += f"Total Unclassified Products: {total_competitor}\n"
|
94 |
else:
|
95 |
result_text += "No Unclassified Products detected\n"
|
96 |
|
97 |
# ========== [4] Visualisasi ==========
|
98 |
-
img =
|
99 |
|
100 |
# Gambar bounding box untuk produk Nestlé (Hijau)
|
101 |
for pred in yolo_pred['predictions']:
|
@@ -104,7 +101,7 @@ def detect_combined(image):
|
|
104 |
cv2.putText(img, pred['class'], (int(x - w/2), int(y - h/2 - 10)),
|
105 |
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
|
106 |
|
107 |
-
# Gambar bounding box untuk kompetitor (Merah)
|
108 |
for comp in competitor_boxes:
|
109 |
x1, y1, x2, y2 = comp['box']
|
110 |
unclassified_classes = ["cans"]
|
@@ -113,6 +110,7 @@ def detect_combined(image):
|
|
113 |
cv2.putText(img, f"{display_name} {comp['confidence']:.2f}",
|
114 |
(int(x1), int(y1 - 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
|
115 |
|
|
|
116 |
output_path = "/tmp/combined_output.jpg"
|
117 |
cv2.imwrite(output_path, img)
|
118 |
|
|
|
28 |
|
29 |
# ========== Fungsi Deteksi Kombinasi ==========
|
30 |
def detect_combined(image):
|
31 |
+
# Konversi gambar PIL ke format numpy array
|
32 |
image_np = np.array(image)
|
33 |
|
34 |
+
# Resize gambar ke 640x640 tanpa mengubah warna atau format
|
35 |
image_resized = cv2.resize(image_np, (640, 640))
|
36 |
|
37 |
# Simpan gambar input yang sudah di-resize ke file sementara
|
|
|
43 |
# ========== [1] YOLO: Deteksi Produk Nestlé ==========
|
44 |
yolo_pred = yolo_model.predict(temp_path, confidence=50, overlap=80).json()
|
45 |
|
46 |
+
# Hitung jumlah objek per kelas dan simpan bounding box
|
47 |
nestle_class_count = {}
|
48 |
nestle_boxes = []
|
49 |
for pred in yolo_pred['predictions']:
|
|
|
54 |
total_nestle = sum(nestle_class_count.values())
|
55 |
|
56 |
# ========== [2] OWLv2: Deteksi Kompetitor ==========
|
57 |
+
headers = {"Authorization": "Basic " + OWLV2_API_KEY}
|
58 |
+
data = {"prompts": OWLV2_PROMPTS, "model": "owlv2"}
|
59 |
+
|
|
|
|
|
|
|
|
|
60 |
with open(temp_path, "rb") as f:
|
61 |
files = {"image": f}
|
62 |
response = requests.post("https://api.landing.ai/v1/tools/text-to-object-detection", files=files, data=data, headers=headers)
|
63 |
+
|
64 |
result = response.json()
|
65 |
owlv2_objects = result['data'][0] if 'data' in result else []
|
66 |
|
|
|
69 |
for obj in owlv2_objects:
|
70 |
if 'bounding_box' in obj:
|
71 |
bbox = obj['bounding_box'] # Format: [x1, y1, x2, y2]
|
|
|
72 |
if not is_overlap(bbox, nestle_boxes):
|
73 |
class_name = obj.get('label', 'unknown').strip().lower()
|
74 |
competitor_class_count[class_name] = competitor_class_count.get(class_name, 0) + 1
|
|
|
85 |
for class_name, count in nestle_class_count.items():
|
86 |
result_text += f"{class_name}: {count}\n"
|
87 |
result_text += f"\nTotal Products Nestle: {total_nestle}\n\n"
|
88 |
+
|
89 |
if competitor_class_count:
|
90 |
result_text += f"Total Unclassified Products: {total_competitor}\n"
|
91 |
else:
|
92 |
result_text += "No Unclassified Products detected\n"
|
93 |
|
94 |
# ========== [4] Visualisasi ==========
|
95 |
+
img = image_resized.copy()
|
96 |
|
97 |
# Gambar bounding box untuk produk Nestlé (Hijau)
|
98 |
for pred in yolo_pred['predictions']:
|
|
|
101 |
cv2.putText(img, pred['class'], (int(x - w/2), int(y - h/2 - 10)),
|
102 |
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
|
103 |
|
104 |
+
# Gambar bounding box untuk kompetitor (Merah) dengan label 'unclassified' jika sesuai
|
105 |
for comp in competitor_boxes:
|
106 |
x1, y1, x2, y2 = comp['box']
|
107 |
unclassified_classes = ["cans"]
|
|
|
110 |
cv2.putText(img, f"{display_name} {comp['confidence']:.2f}",
|
111 |
(int(x1), int(y1 - 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
|
112 |
|
113 |
+
# Simpan gambar hasil deteksi
|
114 |
output_path = "/tmp/combined_output.jpg"
|
115 |
cv2.imwrite(output_path, img)
|
116 |
|