Spaces:
Running
on
T4
Running
on
T4
artificialguybr
commited on
Update app.py
Browse files
app.py
CHANGED
@@ -2,7 +2,7 @@ import gradio as gr
|
|
2 |
import logging
|
3 |
import os
|
4 |
import json
|
5 |
-
from PIL import Image
|
6 |
import torch
|
7 |
from surya.ocr import run_ocr
|
8 |
from surya.detection import batch_text_detection
|
@@ -13,17 +13,17 @@ from surya.model.recognition.model import load_model as load_rec_model
|
|
13 |
from surya.model.recognition.processor import load_processor as load_rec_processor
|
14 |
from surya.settings import settings
|
15 |
from surya.model.ordering.processor import load_processor as load_order_processor
|
16 |
-
from surya.model.ordering.model import
|
17 |
-
|
18 |
-
# Configuração do TorchDynamo
|
19 |
-
torch._dynamo.config.capture_scalar_outputs = True
|
20 |
|
21 |
# Configuração de logging
|
22 |
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
|
23 |
logger = logging.getLogger(__name__)
|
24 |
|
|
|
|
|
|
|
25 |
# Configuração de variáveis de ambiente
|
26 |
-
logger.info("Configurando variáveis de ambiente para otimização de performance")
|
27 |
os.environ["RECOGNITION_BATCH_SIZE"] = "512"
|
28 |
os.environ["DETECTOR_BATCH_SIZE"] = "36"
|
29 |
os.environ["ORDER_BATCH_SIZE"] = "32"
|
@@ -31,115 +31,112 @@ os.environ["RECOGNITION_STATIC_CACHE"] = "true"
|
|
31 |
|
32 |
# Carregamento de modelos
|
33 |
logger.info("Iniciando carregamento dos modelos...")
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
logger.error(f"Erro ao carregar modelo de detecção: {e}")
|
41 |
-
raise
|
42 |
-
|
43 |
-
try:
|
44 |
-
logger.debug("Carregando modelo e processador de reconhecimento...")
|
45 |
-
rec_model, rec_processor = load_rec_model(), load_rec_processor()
|
46 |
-
logger.debug("Modelo e processador de reconhecimento carregados com sucesso")
|
47 |
-
except Exception as e:
|
48 |
-
logger.error(f"Erro ao carregar modelo de reconhecimento: {e}")
|
49 |
-
raise
|
50 |
-
|
51 |
-
try:
|
52 |
-
logger.debug("Carregando modelo e processador de layout...")
|
53 |
-
layout_model = load_det_model(checkpoint=settings.LAYOUT_MODEL_CHECKPOINT)
|
54 |
-
layout_processor = load_det_processor(checkpoint=settings.LAYOUT_MODEL_CHECKPOINT)
|
55 |
-
logger.debug("Modelo e processador de layout carregados com sucesso")
|
56 |
-
except Exception as e:
|
57 |
-
logger.error(f"Erro ao carregar modelo de layout: {e}")
|
58 |
-
raise
|
59 |
-
|
60 |
-
try:
|
61 |
-
logger.debug("Carregando modelo e processador de ordenação...")
|
62 |
-
order_model = load_order_model()
|
63 |
-
order_processor = load_order_processor()
|
64 |
-
logger.debug("Modelo e processador de ordenação carregados com sucesso")
|
65 |
-
except Exception as e:
|
66 |
-
logger.error(f"Erro ao carregar modelo de ordenação: {e}")
|
67 |
-
raise
|
68 |
-
|
69 |
-
logger.info("Todos os modelos foram carregados com sucesso")
|
70 |
|
71 |
# Compilação do modelo de reconhecimento
|
72 |
-
logger.info("
|
73 |
-
|
74 |
-
rec_model.decoder.model = torch.compile(rec_model.decoder.model)
|
75 |
-
logger.info("Compilação do modelo de reconhecimento concluída com sucesso")
|
76 |
-
except Exception as e:
|
77 |
-
logger.error(f"Erro durante a compilação do modelo de reconhecimento: {e}")
|
78 |
-
logger.warning("Continuando sem compilação do modelo")
|
79 |
|
80 |
class CustomJSONEncoder(json.JSONEncoder):
|
81 |
def default(self, obj):
|
82 |
if hasattr(obj, '__dict__'):
|
83 |
return obj.__dict__
|
84 |
-
return
|
85 |
|
86 |
def serialize_result(result):
|
87 |
return json.dumps(result, cls=CustomJSONEncoder, indent=2)
|
88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
def ocr_workflow(image, langs):
|
90 |
logger.info(f"Iniciando workflow OCR com idiomas: {langs}")
|
91 |
try:
|
92 |
-
|
93 |
-
|
94 |
-
predictions = run_ocr([image], [langs.split(',')], det_model, det_processor, rec_model, rec_processor)
|
95 |
logger.info("Workflow OCR concluído com sucesso")
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
except Exception as e:
|
98 |
logger.error(f"Erro durante o workflow OCR: {e}")
|
99 |
-
return serialize_result({"error": str(e)})
|
100 |
|
101 |
def text_detection_workflow(image):
|
102 |
logger.info("Iniciando workflow de detecção de texto")
|
103 |
try:
|
104 |
-
|
105 |
-
|
106 |
-
predictions = batch_text_detection([image], det_model, det_processor)
|
107 |
logger.info("Workflow de detecção de texto concluído com sucesso")
|
108 |
-
|
|
|
|
|
|
|
|
|
109 |
except Exception as e:
|
110 |
logger.error(f"Erro durante o workflow de detecção de texto: {e}")
|
111 |
-
return serialize_result({"error": str(e)})
|
112 |
|
113 |
def layout_analysis_workflow(image):
|
114 |
logger.info("Iniciando workflow de análise de layout")
|
115 |
try:
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
logger.debug(f"Detecção de linhas concluída. Número de linhas detectadas: {len(line_predictions[0].bboxes)}")
|
120 |
-
layout_predictions = batch_layout_detection([image], layout_model, layout_processor, line_predictions)
|
121 |
logger.info("Workflow de análise de layout concluído com sucesso")
|
122 |
-
|
|
|
|
|
|
|
|
|
123 |
except Exception as e:
|
124 |
logger.error(f"Erro durante o workflow de análise de layout: {e}")
|
125 |
-
return serialize_result({"error": str(e)})
|
126 |
|
127 |
def reading_order_workflow(image):
|
128 |
logger.info("Iniciando workflow de ordem de leitura")
|
129 |
try:
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
logger.debug(f"Detecção de linhas concluída. Número de linhas detectadas: {len(line_predictions[0].bboxes)}")
|
134 |
-
layout_predictions = batch_layout_detection([image], layout_model, layout_processor, line_predictions)
|
135 |
-
logger.debug(f"Análise de layout concluída. Número de elementos de layout: {len(layout_predictions[0].bboxes)}")
|
136 |
bboxes = [pred.bbox for pred in layout_predictions[0].bboxes]
|
137 |
-
order_predictions = batch_ordering([
|
138 |
logger.info("Workflow de ordem de leitura concluído com sucesso")
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
except Exception as e:
|
141 |
logger.error(f"Erro durante o workflow de ordem de leitura: {e}")
|
142 |
-
return serialize_result({"error": str(e)})
|
143 |
|
144 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
145 |
gr.Markdown("# Análise de Documentos com Surya")
|
@@ -150,25 +147,34 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
150 |
ocr_input = gr.File(label="Carregar Imagem ou PDF")
|
151 |
ocr_langs = gr.Textbox(label="Idiomas (separados por vírgula)", value="en")
|
152 |
ocr_button = gr.Button("Executar OCR")
|
153 |
-
|
154 |
-
|
|
|
|
|
|
|
155 |
|
156 |
with gr.Tab("Detecção de Texto"):
|
157 |
gr.Markdown("## Detecção de Linhas de Texto")
|
158 |
det_input = gr.File(label="Carregar Imagem ou PDF")
|
159 |
det_button = gr.Button("Executar Detecção de Texto")
|
160 |
-
|
161 |
-
|
|
|
|
|
162 |
|
163 |
with gr.Tab("Análise de Layout"):
|
164 |
gr.Markdown("## Análise de Layout e Ordem de Leitura")
|
165 |
layout_input = gr.File(label="Carregar Imagem ou PDF")
|
166 |
layout_button = gr.Button("Executar Análise de Layout")
|
167 |
order_button = gr.Button("Determinar Ordem de Leitura")
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
|
|
172 |
|
173 |
if __name__ == "__main__":
|
174 |
logger.info("Iniciando aplicativo Gradio...")
|
|
|
2 |
import logging
|
3 |
import os
|
4 |
import json
|
5 |
+
from PIL import Image, ImageDraw, ImageFont
|
6 |
import torch
|
7 |
from surya.ocr import run_ocr
|
8 |
from surya.detection import batch_text_detection
|
|
|
13 |
from surya.model.recognition.processor import load_processor as load_rec_processor
|
14 |
from surya.settings import settings
|
15 |
from surya.model.ordering.processor import load_processor as load_order_processor
|
16 |
+
from surya.model.ordering.model import load_order_model
|
17 |
+
import io
|
|
|
|
|
18 |
|
19 |
# Configuração de logging
|
20 |
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
|
21 |
logger = logging.getLogger(__name__)
|
22 |
|
23 |
+
# Configuração do TorchDynamo
|
24 |
+
torch._dynamo.config.capture_scalar_outputs = True
|
25 |
+
|
26 |
# Configuração de variáveis de ambiente
|
|
|
27 |
os.environ["RECOGNITION_BATCH_SIZE"] = "512"
|
28 |
os.environ["DETECTOR_BATCH_SIZE"] = "36"
|
29 |
os.environ["ORDER_BATCH_SIZE"] = "32"
|
|
|
31 |
|
32 |
# Carregamento de modelos
|
33 |
logger.info("Iniciando carregamento dos modelos...")
|
34 |
+
det_processor, det_model = load_det_processor(), load_det_model()
|
35 |
+
rec_model, rec_processor = load_rec_model(), load_rec_processor()
|
36 |
+
layout_model = load_det_model(checkpoint=settings.LAYOUT_MODEL_CHECKPOINT)
|
37 |
+
layout_processor = load_det_processor(checkpoint=settings.LAYOUT_MODEL_CHECKPOINT)
|
38 |
+
order_model = load_order_model()
|
39 |
+
order_processor = load_order_processor()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
# Compilação do modelo de reconhecimento
|
42 |
+
logger.info("Compilando modelo de reconhecimento...")
|
43 |
+
rec_model.decoder.model = torch.compile(rec_model.decoder.model)
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
class CustomJSONEncoder(json.JSONEncoder):
|
46 |
def default(self, obj):
|
47 |
if hasattr(obj, '__dict__'):
|
48 |
return obj.__dict__
|
49 |
+
return str(obj)
|
50 |
|
51 |
def serialize_result(result):
|
52 |
return json.dumps(result, cls=CustomJSONEncoder, indent=2)
|
53 |
|
54 |
+
def draw_boxes(image, predictions):
|
55 |
+
draw = ImageDraw.Draw(image)
|
56 |
+
font = ImageFont.load_default()
|
57 |
+
for idx, pred in enumerate(predictions[0]['text_lines']):
|
58 |
+
bbox = pred['bbox']
|
59 |
+
draw.rectangle(bbox, outline="red", width=2)
|
60 |
+
draw.text((bbox[0], bbox[1] - 10), f"{idx+1}", font=font, fill="red")
|
61 |
+
return image
|
62 |
+
|
63 |
+
def format_ocr_text(predictions):
|
64 |
+
formatted_text = ""
|
65 |
+
for idx, pred in enumerate(predictions[0]['text_lines']):
|
66 |
+
formatted_text += f"{idx+1}. {pred['text']} (Confidence: {pred['confidence']:.2f})\n"
|
67 |
+
return formatted_text
|
68 |
+
|
69 |
def ocr_workflow(image, langs):
|
70 |
logger.info(f"Iniciando workflow OCR com idiomas: {langs}")
|
71 |
try:
|
72 |
+
image_pil = Image.open(image.name)
|
73 |
+
predictions = run_ocr([image_pil], [langs.split(',')], det_model, det_processor, rec_model, rec_processor)
|
|
|
74 |
logger.info("Workflow OCR concluído com sucesso")
|
75 |
+
|
76 |
+
# Desenhar caixas na imagem
|
77 |
+
image_with_boxes = draw_boxes(image_pil.copy(), predictions)
|
78 |
+
|
79 |
+
# Formatar texto OCR
|
80 |
+
formatted_text = format_ocr_text(predictions)
|
81 |
+
|
82 |
+
return serialize_result(predictions), image_with_boxes, formatted_text
|
83 |
except Exception as e:
|
84 |
logger.error(f"Erro durante o workflow OCR: {e}")
|
85 |
+
return serialize_result({"error": str(e)}), None, str(e)
|
86 |
|
87 |
def text_detection_workflow(image):
|
88 |
logger.info("Iniciando workflow de detecção de texto")
|
89 |
try:
|
90 |
+
image_pil = Image.open(image.name)
|
91 |
+
predictions = batch_text_detection([image_pil], det_model, det_processor)
|
|
|
92 |
logger.info("Workflow de detecção de texto concluído com sucesso")
|
93 |
+
|
94 |
+
# Desenhar caixas na imagem
|
95 |
+
image_with_boxes = draw_boxes(image_pil.copy(), [{"text_lines": predictions[0].bboxes}])
|
96 |
+
|
97 |
+
return serialize_result(predictions), image_with_boxes
|
98 |
except Exception as e:
|
99 |
logger.error(f"Erro durante o workflow de detecção de texto: {e}")
|
100 |
+
return serialize_result({"error": str(e)}), None
|
101 |
|
102 |
def layout_analysis_workflow(image):
|
103 |
logger.info("Iniciando workflow de análise de layout")
|
104 |
try:
|
105 |
+
image_pil = Image.open(image.name)
|
106 |
+
line_predictions = batch_text_detection([image_pil], det_model, det_processor)
|
107 |
+
layout_predictions = batch_layout_detection([image_pil], layout_model, layout_processor, line_predictions)
|
|
|
|
|
108 |
logger.info("Workflow de análise de layout concluído com sucesso")
|
109 |
+
|
110 |
+
# Desenhar caixas na imagem
|
111 |
+
image_with_boxes = draw_boxes(image_pil.copy(), [{"text_lines": layout_predictions[0].bboxes}])
|
112 |
+
|
113 |
+
return serialize_result(layout_predictions), image_with_boxes
|
114 |
except Exception as e:
|
115 |
logger.error(f"Erro durante o workflow de análise de layout: {e}")
|
116 |
+
return serialize_result({"error": str(e)}), None
|
117 |
|
118 |
def reading_order_workflow(image):
|
119 |
logger.info("Iniciando workflow de ordem de leitura")
|
120 |
try:
|
121 |
+
image_pil = Image.open(image.name)
|
122 |
+
line_predictions = batch_text_detection([image_pil], det_model, det_processor)
|
123 |
+
layout_predictions = batch_layout_detection([image_pil], layout_model, layout_processor, line_predictions)
|
|
|
|
|
|
|
124 |
bboxes = [pred.bbox for pred in layout_predictions[0].bboxes]
|
125 |
+
order_predictions = batch_ordering([image_pil], [bboxes], order_model, order_processor)
|
126 |
logger.info("Workflow de ordem de leitura concluído com sucesso")
|
127 |
+
|
128 |
+
# Desenhar caixas na imagem com a ordem de leitura
|
129 |
+
image_with_order = image_pil.copy()
|
130 |
+
draw = ImageDraw.Draw(image_with_order)
|
131 |
+
font = ImageFont.load_default()
|
132 |
+
for idx, bbox in enumerate(order_predictions[0]['bboxes']):
|
133 |
+
draw.rectangle(bbox['bbox'], outline="blue", width=2)
|
134 |
+
draw.text((bbox['bbox'][0], bbox['bbox'][1] - 10), f"{idx+1}", font=font, fill="blue")
|
135 |
+
|
136 |
+
return serialize_result(order_predictions), image_with_order
|
137 |
except Exception as e:
|
138 |
logger.error(f"Erro durante o workflow de ordem de leitura: {e}")
|
139 |
+
return serialize_result({"error": str(e)}), None
|
140 |
|
141 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
142 |
gr.Markdown("# Análise de Documentos com Surya")
|
|
|
147 |
ocr_input = gr.File(label="Carregar Imagem ou PDF")
|
148 |
ocr_langs = gr.Textbox(label="Idiomas (separados por vírgula)", value="en")
|
149 |
ocr_button = gr.Button("Executar OCR")
|
150 |
+
with gr.Row():
|
151 |
+
ocr_output = gr.JSON(label="Resultados OCR")
|
152 |
+
ocr_image = gr.Image(label="Imagem com Caixas")
|
153 |
+
ocr_text = gr.Textbox(label="Texto Reconhecido", lines=10)
|
154 |
+
ocr_button.click(ocr_workflow, inputs=[ocr_input, ocr_langs], outputs=[ocr_output, ocr_image, ocr_text])
|
155 |
|
156 |
with gr.Tab("Detecção de Texto"):
|
157 |
gr.Markdown("## Detecção de Linhas de Texto")
|
158 |
det_input = gr.File(label="Carregar Imagem ou PDF")
|
159 |
det_button = gr.Button("Executar Detecção de Texto")
|
160 |
+
with gr.Row():
|
161 |
+
det_output = gr.JSON(label="Resultados da Detecção de Texto")
|
162 |
+
det_image = gr.Image(label="Imagem com Caixas")
|
163 |
+
det_button.click(text_detection_workflow, inputs=det_input, outputs=[det_output, det_image])
|
164 |
|
165 |
with gr.Tab("Análise de Layout"):
|
166 |
gr.Markdown("## Análise de Layout e Ordem de Leitura")
|
167 |
layout_input = gr.File(label="Carregar Imagem ou PDF")
|
168 |
layout_button = gr.Button("Executar Análise de Layout")
|
169 |
order_button = gr.Button("Determinar Ordem de Leitura")
|
170 |
+
with gr.Row():
|
171 |
+
layout_output = gr.JSON(label="Resultados da Análise de Layout")
|
172 |
+
layout_image = gr.Image(label="Imagem com Layout")
|
173 |
+
with gr.Row():
|
174 |
+
order_output = gr.JSON(label="Resultados da Ordem de Leitura")
|
175 |
+
order_image = gr.Image(label="Imagem com Ordem de Leitura")
|
176 |
+
layout_button.click(layout_analysis_workflow, inputs=layout_input, outputs=[layout_output, layout_image])
|
177 |
+
order_button.click(reading_order_workflow, inputs=layout_input, outputs=[order_output, order_image])
|
178 |
|
179 |
if __name__ == "__main__":
|
180 |
logger.info("Iniciando aplicativo Gradio...")
|