luisabwk commited on
Commit
10f436f
·
verified ·
1 Parent(s): 982acb8

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -0
app.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Gradio app wrapping the official `commonforms` package to convert PDFs
2
+ into fillable forms using jbarrow's FFDNet-L object detector (CPU ONNX).
3
+
4
+ - Paper: <https://arxiv.org/abs/2509.16506>
5
+ - Model: <https://huggingface.co/jbarrow/FFDNet-L-cpu>
6
+ - Package: <https://pypi.org/project/commonforms/>
7
+
8
+ Detecta 3 classes de campos: text boxes, checkboxes (choice buttons) e signatures.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import os
13
+
14
+ # Força CPU antes de qualquer import que possa inicializar CUDA.
15
+ os.environ.setdefault("CUDA_VISIBLE_DEVICES", "")
16
+ os.environ.setdefault("NVIDIA_VISIBLE_DEVICES", "")
17
+
18
+ import inspect
19
+ import tempfile
20
+ from pathlib import Path
21
+
22
+ import gradio as gr
23
+ from commonforms import prepare_form
24
+
25
+ _PARAMS = inspect.signature(prepare_form).parameters
26
+ print(f"[commonforms] prepare_form signature: {list(_PARAMS.keys())}")
27
+
28
+
29
+ def detect_fields(
30
+ pdf_path: str | None,
31
+ image_size: int,
32
+ use_signature_fields: bool,
33
+ keep_existing_fields: bool,
34
+ ) -> str:
35
+ if not pdf_path:
36
+ raise gr.Error("Envie um PDF.")
37
+
38
+ src = Path(pdf_path)
39
+ if not src.exists():
40
+ raise gr.Error(f"Arquivo não encontrado: {src}")
41
+
42
+ _, out_str = tempfile.mkstemp(suffix="_fillable.pdf")
43
+ out = Path(out_str)
44
+
45
+ optional = {
46
+ "image_size": int(image_size),
47
+ "use_signature_fields": bool(use_signature_fields),
48
+ "keep_existing_fields": bool(keep_existing_fields),
49
+ "device": "cpu",
50
+ "model_or_path": "FFDNet-L-cpu",
51
+ }
52
+ accepted = {k: v for k, v in optional.items() if k in _PARAMS}
53
+ print(f"[commonforms] calling prepare_form with kwargs: {accepted}")
54
+
55
+ try:
56
+ # input/output passados posicionalmente — robusto ao nome real do param
57
+ prepare_form(str(src), str(out), **accepted)
58
+ except Exception as exc:
59
+ raise gr.Error(f"Falha ao processar PDF: {exc}") from exc
60
+
61
+ return str(out)
62
+
63
+
64
+ with gr.Blocks(title="CommonForms — Form Field Detector") as demo:
65
+ gr.Markdown(
66
+ "# CommonForms — Form Field Detector\n"
67
+ "Converte um PDF em formulário preenchível usando **FFDNet-L** "
68
+ "(`jbarrow/FFDNet-L-cpu`, Object Detection ONNX em CPU). "
69
+ "Detecta *text boxes*, *checkboxes* e *signature fields*.\n\n"
70
+ "Paper: [arxiv 2509.16506](<https://arxiv.org/abs/2509.16506>) · "
71
+ "Modelo: [jbarrow/FFDNet-L-cpu](<https://huggingface.co/jbarrow/FFDNet-L-cpu>)"
72
+ )
73
+ with gr.Row():
74
+ with gr.Column():
75
+ pdf_in = gr.File(
76
+ label="PDF de entrada",
77
+ file_types=[".pdf"],
78
+ type="filepath",
79
+ )
80
+ image_size = gr.Slider(
81
+ minimum=512,
82
+ maximum=2048,
83
+ value=1600,
84
+ step=32,
85
+ label="Image size (px)",
86
+ info="Tamanho usado na inferência. Maior = mais preciso, mais lento.",
87
+ )
88
+ use_sig = gr.Checkbox(
89
+ value=False,
90
+ label="Incluir signature fields",
91
+ info="Detecta áreas de assinatura além de text/checkbox.",
92
+ )
93
+ keep = gr.Checkbox(
94
+ value=False,
95
+ label="Manter campos já existentes",
96
+ info="Preserva widgets AcroForm que já estavam no PDF.",
97
+ )
98
+ btn = gr.Button("Detectar campos", variant="primary")
99
+ with gr.Column():
100
+ pdf_out = gr.File(label="PDF preenchível")
101
+
102
+ btn.click(
103
+ fn=detect_fields,
104
+ inputs=[pdf_in, image_size, use_sig, keep],
105
+ outputs=pdf_out,
106
+ api_name="detect",
107
+ )
108
+
109
+
110
+ if __name__ == "__main__":
111
+ demo.queue(max_size=4).launch()