Nilay1400 commited on
Commit
3353da4
·
verified ·
1 Parent(s): 45d3fbe

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +13 -0
  2. app.py +146 -0
  3. best.pt +3 -0
  4. requirements.txt +6 -0
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+
7
+ RUN pip install --no-cache-dir -r requirements.txt
8
+
9
+ COPY . .
10
+
11
+ EXPOSE 7860
12
+
13
+ CMD ["streamlit", "run", "app.py", "--server.port=7860", "--server.address=0.0.0.0"]
app.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import cv2
3
+ import numpy as np
4
+ from ultralytics import YOLO
5
+ from PIL import Image
6
+
7
+ st.set_page_config(layout="wide")
8
+ st.title("OPG Segmentation + Midline + Sinus Detection")
9
+
10
+ # -----------------------------
11
+ # Load model (cached)
12
+ # -----------------------------
13
+ @st.cache_resource
14
+ def load_model():
15
+ return YOLO("best.pt")
16
+
17
+ model = load_model()
18
+
19
+ # -----------------------------
20
+ # Upload image
21
+ # -----------------------------
22
+ uploaded_file = st.file_uploader("Upload OPG Image", type=["jpg", "png", "jpeg"])
23
+
24
+ # -----------------------------
25
+ # Preprocessing Function
26
+ # -----------------------------
27
+ def preprocess_image(image):
28
+
29
+ # Convert to grayscale
30
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
31
+
32
+ # Apply CLAHE
33
+ clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
34
+ gray = clahe.apply(gray)
35
+
36
+ # Resize so max dimension = 2048
37
+ h, w = gray.shape
38
+ scale = 2048 / max(h, w)
39
+ gray = cv2.resize(gray, (int(w * scale), int(h * scale)))
40
+
41
+ # Convert back to 3-channel (YOLO expects 3 channels)
42
+ processed = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
43
+
44
+ return processed
45
+
46
+
47
+
48
+ if uploaded_file is not None:
49
+
50
+ # Convert to OpenCV format
51
+ image = Image.open(uploaded_file).convert("RGB")
52
+ image = np.array(image)
53
+ image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
54
+
55
+ image = preprocess_image(image)
56
+
57
+ h, w, _ = image.shape
58
+
59
+ # -----------------------------
60
+ # Run prediction
61
+ # -----------------------------
62
+ results = model(image, conf=0.25)
63
+ result = results[0]
64
+
65
+ tooth_centers_x = []
66
+
67
+ # -----------------------------
68
+ # Collect tooth centers
69
+ # -----------------------------
70
+ for box, cls in zip(result.boxes.xywh, result.boxes.cls):
71
+ cls = int(cls)
72
+ if cls == 0: # tooth class
73
+ x_center = box[0].item()
74
+ tooth_centers_x.append(x_center)
75
+
76
+ if len(tooth_centers_x) == 0:
77
+ st.warning("No teeth detected!")
78
+ st.stop()
79
+
80
+ # -----------------------------
81
+ # Compute midline
82
+ # -----------------------------
83
+ midline_x = int((min(tooth_centers_x) + max(tooth_centers_x)) / 2)
84
+
85
+ # -----------------------------
86
+ # Draw tooth masks
87
+ # -----------------------------
88
+ if result.masks is not None:
89
+ for mask, cls in zip(result.masks.xy, result.boxes.cls):
90
+ cls = int(cls)
91
+ if cls == 0:
92
+ polygon = np.array(mask, dtype=np.int32)
93
+ cv2.polylines(image, [polygon], True, (0, 255, 0), 2)
94
+
95
+ # -----------------------------
96
+ # Process sinus
97
+ # -----------------------------
98
+ for box, cls in zip(result.boxes.xywh, result.boxes.cls):
99
+ cls = int(cls)
100
+ if cls == 1: # sinus class
101
+ x, y, bw, bh = box
102
+ x_center = x.item()
103
+
104
+ if x_center < midline_x:
105
+ label = "Right Sinus"
106
+ color = (255, 0, 0)
107
+ else:
108
+ label = "Left Sinus"
109
+ color = (0, 0, 255)
110
+
111
+ x1 = int(x - bw / 2)
112
+ y1 = int(y - bh / 2)
113
+ x2 = int(x + bw / 2)
114
+ y2 = int(y + bh / 2)
115
+
116
+ cv2.rectangle(image, (x1, y1), (x2, y2), color, 2)
117
+ cv2.putText(image, label, (x1, y1 - 10),
118
+ cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)
119
+
120
+ # -----------------------------
121
+ # Draw midline
122
+ # -----------------------------
123
+ cv2.line(image, (midline_x, 0), (midline_x, h),
124
+ (0, 255, 255), 2)
125
+
126
+ # Convert back to RGB for display
127
+ display_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
128
+
129
+ col1, col2 = st.columns(2)
130
+
131
+ with col1:
132
+ st.image(uploaded_file, caption="Original Image")
133
+
134
+ with col2:
135
+ st.image(display_image, caption="Segmented Output")
136
+
137
+ # -----------------------------
138
+ # Download button
139
+ # -----------------------------
140
+ result_pil = Image.fromarray(display_image)
141
+ st.download_button(
142
+ label="Download Result Image",
143
+ data=result_pil.tobytes(),
144
+ file_name="output_with_midline.jpg",
145
+ mime="image/jpeg"
146
+ )
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:687d06e6ffb97dbf9d39b4a91cb7f9c8cdc36b3b8af660441170eca2d4d699f1
3
+ size 54849237
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ streamlit
2
+ ultralytics
3
+ opencv-python-headless
4
+ numpy
5
+ pillow
6
+ torch