muhammadsalmanalfaridzi commited on
Commit
49fea9e
·
verified ·
1 Parent(s): 9f16ddc

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -0
app.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from dotenv import load_dotenv
3
+ from roboflow import Roboflow
4
+ import tempfile
5
+ import os
6
+ import requests
7
+ import cv2
8
+ import numpy as np
9
+ import subprocess
10
+
11
+ # ========== Konfigurasi ==========
12
+ load_dotenv()
13
+
14
+ # Roboflow Config
15
+ rf_api_key = os.getenv("ROBOFLOW_API_KEY")
16
+ workspace = os.getenv("ROBOFLOW_WORKSPACE")
17
+ project_name = os.getenv("ROBOFLOW_PROJECT")
18
+ model_version = int(os.getenv("ROBOFLOW_MODEL_VERSION"))
19
+
20
+ # Landing AI CountGD Config
21
+ COUNTGD_API_KEY = os.getenv("COUNTGD_API_KEY")
22
+ COUNTGD_URL = "https://api.landing.ai/v1/tools/text-to-object-detection"
23
+ COUNTGD_PROMPT = ["beverage", "bottle", "cans", "mixed box"] # Sesuaikan prompt
24
+
25
+ # Inisialisasi Model
26
+ rf = Roboflow(api_key=rf_api_key)
27
+ project = rf.workspace(workspace).project(project_name)
28
+ yolo_model = project.version(model_version).model
29
+
30
+ # ========== Fungsi Deteksi Kombinasi ==========
31
+ def detect_combined(image):
32
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file:
33
+ image.save(temp_file, format="JPEG")
34
+ temp_path = temp_file.name
35
+
36
+ try:
37
+ # ========== [1] YOLO: Deteksi Produk Nestlé ==========
38
+ yolo_pred = yolo_model.predict(temp_path, confidence=50, overlap=80).json()
39
+
40
+ nestle_class_count = {}
41
+ nestle_boxes = []
42
+ for pred in yolo_pred['predictions']:
43
+ class_name = pred['class']
44
+ nestle_class_count[class_name] = nestle_class_count.get(class_name, 0) + 1
45
+ nestle_boxes.append((pred['x'], pred['y'], pred['width'], pred['height']))
46
+
47
+ total_nestle = sum(nestle_class_count.values())
48
+
49
+ # ========== [2] CountGD: Deteksi Kompetitor ==========
50
+ with open(temp_path, 'rb') as img_file:
51
+ files = {"image": img_file}
52
+ data = {"prompts": COUNTGD_PROMPT, "model": "countgd"}
53
+ headers = {"Authorization": f"Basic {COUNTGD_API_KEY}"}
54
+ response = requests.post(COUNTGD_URL, files=files, data=data, headers=headers)
55
+ countgd_pred = response.json()
56
+
57
+ competitor_class_count = {}
58
+ competitor_boxes = []
59
+ for obj in countgd_pred.get("objects", []):
60
+ class_name = obj['category'].strip().lower()
61
+ competitor_class_count[class_name] = competitor_class_count.get(class_name, 0) + 1
62
+ competitor_boxes.append({
63
+ "class": class_name,
64
+ "box": obj['bbox'],
65
+ "confidence": obj['score']
66
+ })
67
+
68
+ total_competitor = sum(competitor_class_count.values())
69
+
70
+ # ========== [3] Format Output ==========
71
+ result_text = "Product Nestlé\n\n"
72
+ for class_name, count in nestle_class_count.items():
73
+ result_text += f"{class_name}: {count}\n"
74
+ result_text += f"\nTotal Products Nestlé: {total_nestle}\n\n"
75
+
76
+ if competitor_class_count:
77
+ result_text += f"Total Unclassified Products: {total_competitor}\n"
78
+ else:
79
+ result_text += "No Unclassified Products detected\n"
80
+
81
+ # ========== [4] Visualisasi ==========
82
+ img = cv2.imread(temp_path)
83
+
84
+ # Nestlé (Hijau)
85
+ for pred in yolo_pred['predictions']:
86
+ x, y, w, h = pred['x'], pred['y'], pred['width'], pred['height']
87
+ cv2.rectangle(img, (int(x-w/2), int(y-h/2)), (int(x+w/2), int(y+h/2)), (0,255,0), 2)
88
+ cv2.putText(img, pred['class'], (int(x-w/2), int(y-h/2-10)),
89
+ cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 2)
90
+
91
+ # Kompetitor (Merah)
92
+ for comp in competitor_boxes:
93
+ x1, y1, x2, y2 = comp['box']
94
+ cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 0, 255), 2)
95
+ cv2.putText(img, f"{comp['class']} {comp['confidence']:.2f}",
96
+ (int(x1), int(y1-10)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
97
+
98
+ output_path = "/tmp/combined_output.jpg"
99
+ cv2.imwrite(output_path, img)
100
+
101
+ return output_path, result_text
102
+
103
+ except Exception as e:
104
+ return temp_path, f"Error: {str(e)}"
105
+ finally:
106
+ os.remove(temp_path)
107
+
108
+ # ========== Gradio Interface ==========
109
+ with gr.Blocks(theme=gr.themes.Base(primary_hue="teal", secondary_hue="teal", neutral_hue="slate")) as iface:
110
+ gr.Markdown("""<div style="text-align: center;"><h1>NESTLE - STOCK COUNTING</h1></div>""")
111
+
112
+ with gr.Row():
113
+ with gr.Column():
114
+ input_image = gr.Image(type="pil", label="Input Image")
115
+ detect_image_button = gr.Button("Detect Image")
116
+ output_image = gr.Image(label="Detect Object")
117
+ output_text = gr.Textbox(label="Counting Object")
118
+ detect_image_button.click(fn=detect_combined, inputs=input_image, outputs=[output_image, output_text])
119
+
120
+ iface.launch()