nmariotto commited on
Commit
4d30f7f
·
verified ·
1 Parent(s): 17ad7de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -17
app.py CHANGED
@@ -9,13 +9,17 @@ from shapely.geometry import Polygon
9
  from PIL import Image
10
  from io import BytesIO
11
  from concurrent.futures import ThreadPoolExecutor
 
 
 
 
 
12
 
13
  # 🔥 Inicializar Roboflow
14
  API_KEY = "mGkz7QhkhD90YfeiaOxV"
15
  rf = roboflow.Roboflow(api_key=API_KEY)
16
  project = rf.workspace().project("pre-eclampsia-vhaot")
17
  model = project.version("20").model
18
-
19
  model.confidence = 80
20
  model.overlap = 25
21
  dpi_value = 300
@@ -23,31 +27,64 @@ dpi_value = 300
23
  with st.expander("⚙️ Configurações Avançadas", expanded=True):
24
  model.confidence = st.slider("Confiança do Modelo (%)", 20, 100, 80)
25
 
 
 
 
 
 
 
 
 
26
  def calculate_polygon_area(points):
27
  polygon = Polygon([(p['x'], p['y']) for p in points])
28
  return polygon.area
29
 
30
  def safe_predict(image_path):
31
- import time
32
  for attempt in range(3):
33
  try:
34
  return model.predict(image_path)
35
- except Exception as e:
36
- if attempt == 2:
37
- raise e
38
  time.sleep(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  def process_image(uploaded_file):
41
  try:
42
- # 🛡️ Sanitização do nome do arquivo
43
  safe_name = uploaded_file.name.replace(" ", "_")
44
-
45
- # 🔁 Conversão leve para garantir compatibilidade
46
  image = Image.open(uploaded_file).convert("RGB")
47
 
48
  with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as temp_file:
49
  image.save(temp_file.name)
50
  prediction = safe_predict(temp_file.name)
 
 
51
  prediction_data = prediction.json()
52
 
53
  if not prediction_data["predictions"]:
@@ -55,7 +92,6 @@ def process_image(uploaded_file):
55
 
56
  points = prediction_data["predictions"][0]["points"]
57
  area = calculate_polygon_area(points)
58
-
59
  x = [p['x'] for p in points] + [points[0]['x']]
60
  y = [p['y'] for p in points] + [points[0]['y']]
61
 
@@ -88,11 +124,10 @@ def process_image(uploaded_file):
88
  "Exibir": image
89
  }
90
 
91
- except Exception as e:
92
- st.error(f"Erro ao processar {uploaded_file.name}: {e}")
93
  return None
94
 
95
- # 🖼️ Interface principal
96
  st.title("Segmentação de Imagens - Roboflow")
97
  upload_option = st.radio("Escolha o tipo de upload:", ["Imagem única", "Pasta de imagens"])
98
  results = []
@@ -123,15 +158,14 @@ elif upload_option == "Pasta de imagens":
123
  st.image(result["Segmentada"], caption="Segmentação", use_container_width=True)
124
  st.image(result["Poligono"], caption="Polígono", use_container_width=True)
125
  st.write(f"📏 **Área segmentada:** {result['Área Segmentada (px²)']:.2f} pixels²")
 
126
  zip_file.writestr(f"segmentada_{result['Imagem']}.png", result["Segmentada"].getvalue())
127
  zip_file.writestr(f"poligono_{result['Imagem']}.png", result["Poligono"].getvalue())
 
128
  zip_images_buffer.seek(0)
129
 
130
  if results:
131
- df = pd.DataFrame([{
132
- "Imagem": r["Imagem"],
133
- "Área Segmentada (px²)": r["Área Segmentada (px²)"]
134
- } for r in results])
135
  st.markdown("### 📊 Tabela de Resultados")
136
  st.dataframe(df)
137
 
@@ -140,4 +174,35 @@ elif upload_option == "Pasta de imagens":
140
  excel_buffer.seek(0)
141
 
142
  st.download_button("📥 Baixar Tabela (Excel)", data=excel_buffer, file_name="resultados_segmentacao.xlsx", mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
143
- st.download_button("📥 Baixar Todas as Imagens Segmentadas e Polígonos", data=zip_images_buffer, file_name="imagens_segmentadas.zip", mime="application/zip")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  from PIL import Image
10
  from io import BytesIO
11
  from concurrent.futures import ThreadPoolExecutor
12
+ from google.oauth2 import service_account
13
+ from googleapiclient.discovery import build
14
+ from googleapiclient.http import MediaIoBaseUpload
15
+ import gspread
16
+ import time
17
 
18
  # 🔥 Inicializar Roboflow
19
  API_KEY = "mGkz7QhkhD90YfeiaOxV"
20
  rf = roboflow.Roboflow(api_key=API_KEY)
21
  project = rf.workspace().project("pre-eclampsia-vhaot")
22
  model = project.version("20").model
 
23
  model.confidence = 80
24
  model.overlap = 25
25
  dpi_value = 300
 
27
  with st.expander("⚙️ Configurações Avançadas", expanded=True):
28
  model.confidence = st.slider("Confiança do Modelo (%)", 20, 100, 80)
29
 
30
+ # 📁 Setup Google Drive e Sheets
31
+ scope = ["https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/spreadsheets"]
32
+ credentials = service_account.Credentials.from_service_account_info(st.secrets["gcp_service_account"], scopes=scope)
33
+ drive_service = build("drive", "v3", credentials=credentials)
34
+ sheets_client = gspread.authorize(credentials)
35
+ sheet = sheets_client.open_by_url(st.secrets["feedback_sheet_url"]).sheet1
36
+
37
+ # 📌 Funções auxiliares
38
  def calculate_polygon_area(points):
39
  polygon = Polygon([(p['x'], p['y']) for p in points])
40
  return polygon.area
41
 
42
  def safe_predict(image_path):
 
43
  for attempt in range(3):
44
  try:
45
  return model.predict(image_path)
46
+ except:
 
 
47
  time.sleep(1)
48
+ return None
49
+
50
+ def resize_image(image):
51
+ return image.resize((640, 640))
52
+
53
+ def upload_to_drive(image_bytes, filename, folder_id):
54
+ media = MediaIoBaseUpload(image_bytes, mimetype='image/png')
55
+ drive_service.files().create(
56
+ body={"name": filename, "parents": [folder_id]},
57
+ media_body=media,
58
+ fields='id'
59
+ ).execute()
60
+
61
+ def find_or_create_folder(folder_name, parent=None):
62
+ query = f"name='{folder_name}' and mimeType='application/vnd.google-apps.folder' and trashed=false"
63
+ if parent:
64
+ query += f" and '{parent}' in parents"
65
+ results = drive_service.files().list(q=query, spaces='drive', fields='files(id, name)').execute()
66
+ folders = results.get('files', [])
67
+ if folders:
68
+ return folders[0]['id']
69
+ file_metadata = {
70
+ 'name': folder_name,
71
+ 'mimeType': 'application/vnd.google-apps.folder'
72
+ }
73
+ if parent:
74
+ file_metadata['parents'] = [parent]
75
+ file = drive_service.files().create(body=file_metadata, fields='id').execute()
76
+ return file.get('id')
77
 
78
  def process_image(uploaded_file):
79
  try:
 
80
  safe_name = uploaded_file.name.replace(" ", "_")
 
 
81
  image = Image.open(uploaded_file).convert("RGB")
82
 
83
  with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as temp_file:
84
  image.save(temp_file.name)
85
  prediction = safe_predict(temp_file.name)
86
+ if not prediction:
87
+ return None
88
  prediction_data = prediction.json()
89
 
90
  if not prediction_data["predictions"]:
 
92
 
93
  points = prediction_data["predictions"][0]["points"]
94
  area = calculate_polygon_area(points)
 
95
  x = [p['x'] for p in points] + [points[0]['x']]
96
  y = [p['y'] for p in points] + [points[0]['y']]
97
 
 
124
  "Exibir": image
125
  }
126
 
127
+ except:
 
128
  return None
129
 
130
+ # Interface principal
131
  st.title("Segmentação de Imagens - Roboflow")
132
  upload_option = st.radio("Escolha o tipo de upload:", ["Imagem única", "Pasta de imagens"])
133
  results = []
 
158
  st.image(result["Segmentada"], caption="Segmentação", use_container_width=True)
159
  st.image(result["Poligono"], caption="Polígono", use_container_width=True)
160
  st.write(f"📏 **Área segmentada:** {result['Área Segmentada (px²)']:.2f} pixels²")
161
+
162
  zip_file.writestr(f"segmentada_{result['Imagem']}.png", result["Segmentada"].getvalue())
163
  zip_file.writestr(f"poligono_{result['Imagem']}.png", result["Poligono"].getvalue())
164
+
165
  zip_images_buffer.seek(0)
166
 
167
  if results:
168
+ df = pd.DataFrame([{ "Imagem": r["Imagem"], "Área Segmentada (px²)": r["Área Segmentada (px²)"] } for r in results])
 
 
 
169
  st.markdown("### 📊 Tabela de Resultados")
170
  st.dataframe(df)
171
 
 
174
  excel_buffer.seek(0)
175
 
176
  st.download_button("📥 Baixar Tabela (Excel)", data=excel_buffer, file_name="resultados_segmentacao.xlsx", mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
177
+ st.download_button("📥 Baixar Todas as Imagens Segmentadas e Polígonos", data=zip_images_buffer, file_name="imagens_segmentadas.zip", mime="application/zip")
178
+
179
+ # Feedback manual
180
+ if results:
181
+ st.markdown("## 📝 Feedback")
182
+ imagem_escolhida = st.selectbox("Selecione uma imagem para avaliar:", [r["Imagem"] for r in results])
183
+ avaliacao = st.radio("Como você avalia essa segmentação?", ["Ótima", "Aceitável", "Ruim"], horizontal=True)
184
+ observacao = st.text_area("Observações (opcional):")
185
+
186
+ if st.button("Salvar Feedback"):
187
+ row = [imagem_escolhida, avaliacao, observacao]
188
+ sheet.append_row(row)
189
+
190
+ if avaliacao in ["Aceitável", "Ruim"]:
191
+ sufixo = "aceitavel" if avaliacao == "Aceitável" else "ruim"
192
+ parent_folder = find_or_create_folder("Feedback Segmentacoes")
193
+ subfolder = find_or_create_folder(imagem_escolhida.replace(".png", ""), parent_folder)
194
+
195
+ for r in results:
196
+ if r["Imagem"] == imagem_escolhida:
197
+ resized_original = resize_image(Image.open(r["Original"]))
198
+ resized_segmented = resize_image(Image.open(r["Segmentada"]))
199
+ resized_polygon = resize_image(Image.open(r["Poligono"]))
200
+
201
+ for img_obj, nome in zip([resized_original, resized_segmented, resized_polygon], ["original", "segmentada", "poligono"]):
202
+ buffer = BytesIO()
203
+ img_obj.save(buffer, format="PNG")
204
+ buffer.seek(0)
205
+ upload_to_drive(buffer, f"{nome}_{sufixo}.png", subfolder)
206
+ break
207
+
208
+ st.success("✅ Feedback salvo com sucesso!")