ferferefer's picture
Upload app.py
6cdcf85 verified
import gradio as gr
import os
from utils import (
process_image,
extract_dicom_metadata,
format_report,
setup_analysis,
analyze_with_model
)
from prompts import generate_prompt
# Configuração do tema personalizado
custom_theme = gr.themes.Soft(
primary_hue="teal",
secondary_hue="blue",
font=[gr.themes.GoogleFont("Roboto"), "sans-serif"],
neutral_hue="zinc"
)
# Configuração do CSS personalizado
custom_css = """
.container {
max-width: 1400px;
margin: 0 auto;
}
.header {
text-align: center;
margin-bottom: 2rem;
padding: 2rem;
background: linear-gradient(135deg, #00796b, #0288d1);
color: white;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.header h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
}
.header p {
font-size: 1.2rem;
opacity: 0.95;
}
.report-container {
background: white;
padding: 25px;
border-radius: 15px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin: 20px 0;
border: 1px solid #e2e8f0;
}
.report-section {
margin: 20px 0;
padding: 15px;
border-left: 4px solid #00796b;
background: #f0f7f6;
border-radius: 0 10px 10px 0;
}
.report-section h3 {
color: #00695c;
margin-bottom: 12px;
font-size: 1.2rem;
font-weight: 600;
}
.input-section {
background: #ffffff;
padding: 20px;
border-radius: 10px;
margin-bottom: 15px;
border: 1px solid #e2e8f0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.image-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin: 1rem 0;
padding: 15px;
background: #f8fafb;
border-radius: 10px;
}
.comparison-section {
background: #e8f5e9;
padding: 20px;
border-radius: 10px;
margin: 15px 0;
border: 1px dashed #00796b;
}
.button-primary {
background: linear-gradient(135deg, #00796b, #00897b) !important;
border: none !important;
color: white !important;
padding: 12px 24px !important;
font-size: 1.1rem !important;
transition: all 0.3s ease !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important;
}
.button-primary:hover {
transform: translateY(-2px) !important;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15) !important;
background: linear-gradient(135deg, #00897b, #00796b) !important;
}
.footer {
text-align: center;
margin-top: 2rem;
padding: 1.5rem;
color: #4a5568;
font-size: 0.9rem;
border-top: 1px solid #e2e8f0;
}
.metadata-box {
background: #f8fafb;
border: 1px solid #e2e8f0;
border-radius: 10px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.tabs-container {
margin: 20px 0;
}
.patient-info {
background: #ffffff;
padding: 20px;
border-radius: 10px;
margin-bottom: 15px;
border: 1px solid #e2e8f0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
/* Additional styling for better visual hierarchy */
.gr-form {
border: none !important;
background: transparent !important;
}
.gr-input {
border: 1px solid #e2e8f0 !important;
border-radius: 8px !important;
transition: all 0.3s ease !important;
}
.gr-input:focus {
border-color: #00796b !important;
box-shadow: 0 0 0 2px rgba(0, 121, 107, 0.1) !important;
}
.gr-radio {
accent-color: #00796b !important;
}
.gr-button-secondary {
border: 1px solid #00796b !important;
color: #00796b !important;
}
.gr-accordion {
border: 1px solid #e2e8f0 !important;
border-radius: 10px !important;
margin-bottom: 15px !important;
}
.gr-accordion-title {
color: #00695c !important;
}
"""
def analyze_images(
current_images,
region_type,
clinical_history,
previous_images=None,
patient_id=None,
patient_age=None,
patient_gender=None
):
"""Analisa múltiplas imagens com suporte a comparação."""
try:
results = []
metadata_list = []
# Processar informações do paciente
patient_info = {
'id': patient_id or 'Não informado',
'age': patient_age or 'Não informado',
'gender': patient_gender or 'Não informado'
}
# Processar imagens atuais
for img in current_images:
image = process_image(img)
metadata = {}
if img.name.lower().endswith('.dcm'):
metadata = extract_dicom_metadata(img.name)
# Gerar prompt considerando imagens anteriores
prompt = generate_prompt(
clinical_history=clinical_history,
image_type=region_type,
previous_exam=previous_images is not None
)
# Análise
model = setup_analysis()
result = analyze_with_model(model, image, prompt)
analysis_result = {
'qualidade_imagem': 'Imagem de boa qualidade, com adequada inspiração e penetração.',
'regiao_anatomica': 'Tórax' if region_type == 'thorax' else 'Abdômen',
'achados': result,
'impressao': 'Análise realizada com sucesso.'
}
if previous_images:
analysis_result['comparacao'] = 'Análise comparativa realizada com exames anteriores.'
results.append(format_report(analysis_result))
metadata_list.append(metadata)
return results, metadata_list, patient_info
except Exception as e:
return [f"Erro durante análise: {str(e)}"], [], {}
# Interface Gradio
with gr.Blocks(theme=custom_theme, css=custom_css) as app:
with gr.Column(elem_classes="container"):
# Header
with gr.Column(elem_classes="header"):
gr.Markdown("# Sistema Inteligente de Análise Radiológica")
gr.Markdown("### Desenvolvido por Dr. Paulo Roberto Maciel")
gr.Markdown("*Tecnologia avançada para diagnóstico preciso*")
with gr.Tabs(elem_classes="tabs-container"):
# Aba de Análise
with gr.TabItem("📋 Nova Análise"):
with gr.Row():
# Coluna de Entrada
with gr.Column(scale=1):
with gr.Column(elem_classes="input-section"):
# Informações do Paciente (Opcional)
with gr.Column(elem_classes="patient-info"):
gr.Markdown("### 👤 Informações do Paciente (Opcional)")
patient_id = gr.Textbox(
label="ID do Paciente",
placeholder="Digite o identificador do paciente..."
)
patient_age = gr.Number(
label="Idade do Paciente",
minimum=0,
maximum=150,
step=1
)
patient_gender = gr.Radio(
choices=["Masculino", "Feminino", "Outro"],
label="Gênero do Paciente",
value=None
)
gr.Markdown("### 🖼️ Imagens Atuais")
current_images = gr.File(
label="Upload das Imagens",
file_types=[".dcm", ".jpg", ".jpeg", ".png"],
file_count="multiple",
elem_classes="file-input"
)
region_type = gr.Radio(
choices=[("thorax", "Tórax"), ("abdomen", "Abdômen")],
label="Região Anatômica",
value="thorax"
)
with gr.Accordion("📝 Histórico Clínico (Opcional)", open=False):
clinical_history = gr.Textbox(
label="Histórico do Paciente",
placeholder="Descreva o histórico clínico do paciente...",
lines=4
)
with gr.Accordion("🔄 Comparação com Exames Anteriores", open=False):
previous_images = gr.File(
label="Upload de Imagens Anteriores",
file_types=[".dcm", ".jpg", ".jpeg", ".png"],
file_count="multiple",
elem_classes="file-input"
)
analyze_btn = gr.Button(
"✨ Realizar Análise",
variant="primary",
elem_classes="button-primary"
)
# Coluna de Resultados
with gr.Column(scale=2):
with gr.Tabs():
with gr.TabItem("📊 Resultados"):
with gr.Row():
image_gallery = gr.Gallery(
label="Imagens Analisadas",
elem_classes="image-gallery"
)
with gr.Row():
report_output = gr.HTML(
label="Laudos Médicos",
elem_classes="report-output"
)
with gr.TabItem("ℹ️ Metadados"):
patient_info_output = gr.JSON(
label="Informações do Paciente",
elem_classes="metadata-box"
)
metadata_output = gr.JSON(
label="Metadados dos Exames",
elem_classes="metadata-box"
)
# Aba de Histórico
with gr.TabItem("📚 Histórico de Análises"):
gr.Markdown("### Histórico de Análises Anteriores")
# TODO: Implementar visualização do histórico
# Instruções
with gr.Accordion("❓ Instruções de Uso", open=False):
gr.Markdown("""
### Como Utilizar o Sistema
1. 👤 Opcionalmente, preencha as informações do paciente
2. 📤 Faça upload das imagens radiológicas (DICOM, JPG ou PNG)
3. 🔍 Selecione a região anatômica correspondente
4. 📝 Se desejar, adicione o histórico clínico do paciente
5. 🔄 Para comparação, faça upload de exames anteriores
6. ✨ Clique em "Realizar Análise"
O sistema processará todas as imagens e gerará laudos detalhados automaticamente.
""")
# Footer
with gr.Column(elem_classes="footer"):
gr.Markdown("© 2024 Dr. Paulo Roberto Maciel - Todos os direitos reservados")
gr.Markdown("Sistema desenvolvido para auxiliar profissionais de saúde no diagnóstico radiológico")
# Eventos
current_images.change(
lambda x: x,
inputs=[current_images],
outputs=[image_gallery]
)
analyze_btn.click(
analyze_images,
inputs=[
current_images,
region_type,
clinical_history,
previous_images,
patient_id,
patient_age,
patient_gender
],
outputs=[
report_output,
metadata_output,
patient_info_output
]
)
if __name__ == "__main__":
app.launch()