samuellimabraz's picture
refactor: separação dos módulos e diretorios
eaa7aa4 unverified
raw
history blame
10.5 kB
import os
import gradio as gr
import pandas as pd
from PIL import Image
from constants import MODEL_PATH, DATABASE_DIR, DATABASE_PATH
from detector import SignatureDetector, download_model
def create_gradio_interface():
# Download model if it doesn't exist
if not os.path.exists(MODEL_PATH):
download_model()
# Initialize the detector
detector = SignatureDetector(MODEL_PATH)
css = """
.custom-button {
background-color: #b0ffb8 !important;
color: black !important;
}
.custom-button:hover {
background-color: #b0ffb8b3 !important;
}
.container {
max-width: 1200px !important;
margin: auto !important;
}
.main-container {
gap: 20px !important;
}
.metrics-container {
padding: 1.5rem !important;
border-radius: 0.75rem !important;
background-color: #1f2937 !important;
margin: 1rem 0 !important;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) !important;
}
.metrics-title {
font-size: 1.25rem !important;
font-weight: 600 !important;
color: #1f2937 !important;
margin-bottom: 1rem !important;
}
.metrics-row {
display: flex !important;
gap: 1rem !important;
margin-top: 0.5rem !important;
}
"""
def process_image(image, conf_thres, iou_thres):
if image is None:
return None, None, None, None, None, None
output_image, metrics = detector.detect(image, conf_thres, iou_thres)
# Create plots data
hist_data = pd.DataFrame({"Tempo (ms)": metrics["times"]})
indices = range(
metrics["start_index"], metrics["start_index"] + len(metrics["times"])
)
line_data = pd.DataFrame(
{
"Inferência": indices,
"Tempo (ms)": metrics["times"],
"Média": [metrics["avg_time"]] * len(metrics["times"]),
}
)
# Criar plots
hist_fig, line_fig = detector.create_plots(hist_data, line_data)
return (
output_image,
gr.update(
value=f"Total de Inferências: {metrics['total_inferences']}",
container=True,
),
hist_fig,
line_fig,
f"{metrics['avg_time']:.2f}",
f"{metrics['times'][-1]:.2f}",
)
def process_folder(files_path, conf_thres, iou_thres):
if not files_path:
return None, None, None, None, None, None
valid_extensions = [".jpg", ".jpeg", ".png"]
image_files = [
f for f in files_path if os.path.splitext(f.lower())[1] in valid_extensions
]
if not image_files:
return None, None, None, None, None, None
for img_file in image_files:
image = Image.open(img_file)
yield process_image(image, conf_thres, iou_thres)
with gr.Blocks(
theme=gr.themes.Soft(
primary_hue="indigo", secondary_hue="gray", neutral_hue="gray"
),
css=css,
) as iface:
gr.Markdown(
"""
# Tech4Humans - Detector de Assinaturas
Este sistema utiliza o modelo [**YOLOv8s**](https://huggingface.co/tech4humans/yolov8s-signature-detector), especialmente ajustado para a detecção de assinaturas manuscritas em imagens de documentos.
Com este detector, é possível identificar assinaturas em documentos digitais com elevada precisão em tempo real, sendo ideal para
aplicações que envolvem validação, organização e processamento de documentos.
---
"""
)
with gr.Row(equal_height=True, elem_classes="main-container"):
# Coluna da esquerda para controles e informações
with gr.Column(scale=1):
with gr.Tab("Imagem Única"):
input_image = gr.Image(
label="Faça o upload do seu documento", type="pil"
)
with gr.Row():
clear_single_btn = gr.ClearButton([input_image], value="Limpar")
detect_single_btn = gr.Button(
"Detectar", elem_classes="custom-button"
)
with gr.Tab("Pasta de Imagens"):
input_folder = gr.File(
label="Faça o upload de uma pasta com imagens",
file_count="directory",
type="filepath",
)
with gr.Row():
clear_folder_btn = gr.ClearButton(
[input_folder], value="Limpar"
)
detect_folder_btn = gr.Button(
"Detectar", elem_classes="custom-button"
)
with gr.Group():
confidence_threshold = gr.Slider(
minimum=0.0,
maximum=1.0,
value=0.25,
step=0.05,
label="Limiar de Confiança",
info="Ajuste a pontuação mínima de confiança necessária para detecção.",
)
iou_threshold = gr.Slider(
minimum=0.0,
maximum=1.0,
value=0.5,
step=0.05,
label="Limiar de IoU",
info="Ajuste o limiar de Interseção sobre União para Non Maximum Suppression (NMS).",
)
with gr.Column(scale=1):
output_image = gr.Image(label="Resultados da Detecção")
with gr.Accordion("Exemplos", open=True):
gr.Examples(
label="Exemplos de Imagens",
examples=[
["assets/images/example_{i}.jpg".format(i=i)]
for i in range(
0, len(os.listdir(os.path.join("assets", "images")))
)
],
inputs=input_image,
outputs=output_image,
fn=detector.detect_example,
cache_examples=True,
cache_mode="lazy",
)
with gr.Row(elem_classes="metrics-container"):
with gr.Column(scale=1):
total_inferences = gr.Textbox(
label="Total de Inferências", show_copy_button=True, container=True
)
hist_plot = gr.Plot(label="Distribuição dos Tempos", container=True)
with gr.Column(scale=1):
line_plot = gr.Plot(label="Histórico de Tempos", container=True)
with gr.Row(elem_classes="metrics-row"):
avg_inference_time = gr.Textbox(
label="Tempo Médio de Inferência (ms)",
show_copy_button=True,
container=True,
)
last_inference_time = gr.Textbox(
label="Último Tempo de Inferência (ms)",
show_copy_button=True,
container=True,
)
with gr.Row(elem_classes="container"):
gr.Markdown(
"""
---
## Sobre o Projeto
Este projeto utiliza o modelo YOLOv8s ajustado para detecção de assinaturas manuscritas em imagens de documentos. Ele foi treinado com dados provenientes dos conjuntos [Tobacco800](https://paperswithcode.com/dataset/tobacco-800) e [signatures-xc8up](https://universe.roboflow.com/roboflow-100/signatures-xc8up), passando por processos de pré-processamento e aumentação de dados.
### Principais Métricas:
- **Precisão (Precision):** 94,74%
- **Revocação (Recall):** 89,72%
- **mAP@50:** 94,50%
- **mAP@50-95:** 67,35%
- **Tempo de Inferência (CPU):** 171,56 ms
O processo completo de treinamento, ajuste de hiperparâmetros, e avaliação do modelo pode ser consultado em detalhes no repositório abaixo.
[Leia o README completo no Hugging Face Models](https://huggingface.co/tech4humans/yolov8s-signature-detector)
---
**Desenvolvido por [Tech4Humans](https://www.tech4h.com.br/)** | **Modelo:** [YOLOv8s](https://huggingface.co/tech4humans/yolov8s-signature-detector) | **Datasets:** [Tobacco800](https://paperswithcode.com/dataset/tobacco-800), [signatures-xc8up](https://universe.roboflow.com/roboflow-100/signatures-xc8up)
"""
)
clear_single_btn.add([output_image])
clear_folder_btn.add([output_image])
detect_single_btn.click(
fn=process_image,
inputs=[input_image, confidence_threshold, iou_threshold],
outputs=[
output_image,
total_inferences,
hist_plot,
line_plot,
avg_inference_time,
last_inference_time,
],
)
detect_folder_btn.click(
fn=process_folder,
inputs=[input_folder, confidence_threshold, iou_threshold],
outputs=[
output_image,
total_inferences,
hist_plot,
line_plot,
avg_inference_time,
last_inference_time,
],
)
# Carregar métricas iniciais ao carregar a página
iface.load(
fn=detector.load_initial_metrics,
inputs=None,
outputs=[
output_image,
total_inferences,
hist_plot,
line_plot,
avg_inference_time,
last_inference_time,
],
)
return iface
if __name__ == "__main__":
if not os.path.exists(DATABASE_PATH):
os.makedirs(DATABASE_DIR, exist_ok=True)
iface = create_gradio_interface()
iface.launch()