ggun6883 commited on
Commit
f4c2633
·
verified ·
1 Parent(s): 3d98546

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -0
app.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ import cv2
3
+ import numpy as np
4
+ from fastapi import FastAPI
5
+ from pydantic import BaseModel
6
+ from collections import defaultdict
7
+ import uvicorn
8
+ import os
9
+
10
+ app = FastAPI()
11
+
12
+ class InputData(BaseModel):
13
+ image_base64: str
14
+
15
+ def save_base64_image_cv(base64_str, output_path="final.png"):
16
+ image_data = base64.b64decode(base64_str)
17
+ nparr = np.frombuffer(image_data, np.uint8)
18
+ img = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED)
19
+
20
+ # jika RGBA → tempelkan ke background putih
21
+ if img is not None and img.shape[2] == 4:
22
+ alpha = img[:, :, 3] / 255.0
23
+ rgb = img[:, :, :3]
24
+ white_bg = np.ones_like(rgb, dtype=np.uint8) * 255
25
+ img = (rgb * alpha[:, :, None] + white_bg * (1 - alpha[:, :, None])).astype(np.uint8)
26
+
27
+ cv2.imwrite(output_path, img)
28
+ return output_path
29
+
30
+ def extract_icon_positions(image_path="final.png"):
31
+ img = cv2.imread(image_path)
32
+ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
33
+
34
+ _, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
35
+ contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
36
+
37
+ icon_features = []
38
+ positions = []
39
+
40
+ for cnt in contours:
41
+ x, y, w, h = cv2.boundingRect(cnt)
42
+ if w > 10 and h > 10:
43
+ roi = thresh[y:y+h, x:x+w]
44
+ roi_resized = cv2.resize(roi, (50, 50))
45
+ icon_features.append(roi_resized)
46
+ positions.append((x, y))
47
+
48
+ return icon_features, positions
49
+
50
+ def img_hash(img):
51
+ resized = cv2.resize(img, (8, 8))
52
+ mean = resized.mean()
53
+ return (resized > mean).astype(np.uint8).flatten()
54
+
55
+ def find_rarest_icon_position(icon_features, positions):
56
+ hashes = [img_hash(icon) for icon in icon_features]
57
+ groups = defaultdict(list)
58
+
59
+ for i, h in enumerate(hashes):
60
+ found = False
61
+ for label, group in groups.items():
62
+ dist = np.sum(h != hashes[group[0]])
63
+ if dist < 3:
64
+ group.append(i)
65
+ found = True
66
+ break
67
+ if not found:
68
+ groups[len(groups)] = [i]
69
+
70
+ rarest_group = min(groups.values(), key=len)
71
+ idx = rarest_group[0]
72
+
73
+ return positions[idx][0], positions[idx][1]
74
+
75
+ @app.post("/predict")
76
+ async def predict(data: InputData):
77
+ try:
78
+ save_base64_image_cv(data.image_base64, "final.png")
79
+
80
+ icon_features, positions = extract_icon_positions("final.png")
81
+
82
+ if not positions:
83
+ return {"error": "No icons detected"}
84
+
85
+ x, y = find_rarest_icon_position(icon_features, positions)
86
+
87
+ # hapus file temp
88
+ if os.path.exists("final.png"):
89
+ os.remove("final.png")
90
+
91
+ return {"x": x, "y": y}
92
+
93
+ except Exception as e:
94
+ return {"error": str(e)}
95
+
96
+ if __name__ == "__main__":
97
+ uvicorn.run(app, host="0.0.0.0", port=7860)