import gradio as gr import torch import cv2 import numpy as np from matplotlib import pyplot as plt from PIL import Image, ImageDraw from transformers import AutoProcessor from modeling_florence2 import Florence2ForConditionalGeneration import io import matplotlib.pyplot as plt import matplotlib.patches as patches from matplotlib.patches import Polygon import numpy as np import random import json with open("config.json", "r") as f: config = json.load(f) d_model = config['text_config']['d_model'] num_layers = config['text_config']['encoder_layers'] attention_heads = config['text_config']['encoder_attention_heads'] vocab_size = config['text_config']['vocab_size'] max_length = config['text_config']['max_length'] beam_size = config['text_config']['num_beams'] dropout = config['text_config']['dropout'] activation_function = config['text_config']['activation_function'] no_repeat_ngram_size = config['text_config']['no_repeat_ngram_size'] patch_size = config['vision_config']['patch_size'][0] temporal_embeddings = config['vision_config']['visual_temporal_embedding']['max_temporal_embeddings'] title = """# 🙋🏻‍♂️Bem-vindo ao ÓUSI PREMIUM/florence""" description = """ Este aplicativo apresenta o modelo **ÓUSI PREMIUM/florence**, um poderoso sistema de IA projetado para tarefas de **geração de texto e imagem**. O modelo é capaz de lidar com tarefas complexas como detecção de objetos, legendagem de imagens, OCR (Reconhecimento Óptico de Caracteres) e análise detalhada de imagens baseadas em regiões. ### Uso e Flexibilidade do Modelo - **Sem Repetição de N-Gramas**: Para reduzir a repetição na geração de texto, o modelo é configurado com um **no_repeat_ngram_size** de **{no_repeat_ngram_size}**, garantindo saídas mais diversificadas e significativas. - **Estratégias de Amostragem**: ÓUSI PREMIUM/florence oferece estratégias de amostragem flexíveis, incluindo **top-k** e **top-p (nucleus) sampling**, permitindo tanto geração criativa quanto restrita, com base nas necessidades do usuário. 📸📈✍🏻florence é um modelo robusto capaz de lidar com várias tarefas de **texto e imagem** com alta precisão e flexibilidade, tornando-se uma ferramenta valiosa para pesquisas acadêmicas e aplicações práticas. ### **Como Usar**: 1. **Faça o Upload de uma Imagem**: Selecione uma imagem para processamento. 2. **Escolha uma Tarefa**: Escolha uma tarefa no menu suspenso, como "Legenda", "Detecção de Objetos", "OCR", etc. 3. **Processar**: Clique no botão "Processar" para permitir que ÓUSI PREMIUM/florence analise a imagem e gere a saída. 4. **Ver Resultados**: Dependendo da tarefa, você verá uma imagem processada (por exemplo, com caixas delimitadoras ou rótulos) ou um resultado baseado em texto (por exemplo, uma legenda gerada ou texto extraído). Você pode redefinir a interface a qualquer momento clicando no botão **Redefinir**. ### **Tarefas Disponíveis**: - **✍🏻Legenda**: Gere uma descrição concisa da imagem. - **📸Detecção de Objetos**: Identifique e rotule objetos dentro da imagem. - **📸✍🏻OCR**: Extraia texto da imagem. - **📸Proposta de Região**: Detecte regiões-chave na imagem para legendagem detalhada. """ model_presentation = f""" O modelo **ÓUSI PREMIUM/florence** é um modelo de ponta para tarefas de geração condicional, projetado para ser altamente eficaz em tarefas de **texto** e **visão**. É construído como uma arquitetura de **codificador-decodificador**, que permite maior flexibilidade e desempenho na geração de saídas com base em entradas diversificadas. ### Principais Características - **Arquitetura do Modelo**: ÓUSI PREMIUM/florence usa uma estrutura de codificador-decodificador, o que o torna eficaz em tarefas como **geração de texto**, **resumo** e **tradução**. Ele possui **{num_layers} camadas** tanto para o codificador quanto para o decodificador, com uma dimensão do modelo (`d_model`) de **{d_model}**. - **Geração Condicional**: O modelo pode gerar texto condicionalmente, com um comprimento máximo de **{max_length} tokens** para cada sequência gerada, tornando-o ideal para tarefas que exigem saída concisa. - **Busca em Feixe**: ÓUSI PREMIUM/florence suporta **busca em feixe** com até **{beam_size} feixes**, permitindo geração de texto mais diversa e precisa explorando múltiplas potenciais saídas antes de selecionar a melhor. - **Tokenização**: Inclui um tokenizador com um vocabulário de **{vocab_size} tokens**. Tokens especiais como **bos_token_id (0)** e **eos_token_id (2)** ajudam a controlar o processo de geração, marcando o início e o fim de uma sequência. - **Mecanismo de Atenção**: Tanto o codificador quanto o decodificador utilizam **{attention_heads} cabeças de atenção** por camada, garantindo que o modelo possa focar em partes relevantes da entrada ao gerar texto. - **Dropout e Ativação**: ÓUSI PREMIUM/florence emprega uma **função de ativação {activation_function}** e uma **taxa de dropout de {dropout}**, o que melhora o desempenho do modelo prevenindo overfitting e melhorando a generalização. - **Configuração de Treinamento**: O modelo usa precisão **float32** para treinamento e suporta fine-tuning para tarefas específicas ao configurar `finetuning_task` apropriadamente. ### Integração de Visão Além das tarefas de texto, ÓUSI PREMIUM/florence também incorpora **capacidades de visão**: - **Processamento de Imagem Baseado em Patches**: O componente de visão opera em patches de imagem com um tamanho de patch de **{patch_size}x{patch_size}**. - **Embedding Temporal**: Tarefas visuais se beneficiam de embeddings temporais com até **{temporal_embeddings} passos**, tornando o florence bem adequado para análise de vídeo. """ joinus = """ÓUSI PREMIUM/florence é um modelo de IA de ponta que oferece uma ampla gama de recursos para tarefas de texto e visão. Se você deseja colaborar, contribuir ou saber mais sobre o projeto, sinta-se à vontade para entrar em contato conosco! Junte-se a nós para explorar o potencial da IA e criar soluções inovadoras para o futuro. """ how_to_use = """As configurações avançadas permitem que você ajuste o processo de geração de texto. Aqui está o que cada configuração faz e como usá-la: ### Top-k (Padrão: 50) A amostragem top-k limita a seleção do próximo token aos k tokens mais prováveis. - **Valores mais baixos** (por exemplo, 10) tornam a saída mais focada e determinística. - **Valores mais altos** (por exemplo, 100) permitem saídas mais diversificadas. **Exemplo:** Para uma tarefa de escrita criativa, tente definir top-k para 80 para uma linguagem mais variada. ### Top-p (Padrão: 1.0) A amostragem top-p (ou nucleus) seleciona do menor conjunto de tokens cuja probabilidade cumulativa excede p. - **Valores mais baixos** (por exemplo, 0.5) tornam a saída mais focada e coerente. - **Valores mais altos** (por exemplo, 0.9) permitem saídas mais diversificadas e potencialmente criativas. **Exemplo:** Para uma legenda factual, defina top-p para 0.7 para equilibrar precisão e criatividade. ### Penalidade de Repetição (Padrão: 1.0) Esta penaliza a repetição no texto gerado. - **Valores próximos a 1.0** têm efeito mínimo na repetição. - **Valores mais altos** (por exemplo, 1.5) desencorajam mais fortemente a repetição. **Exemplo:** Se você notar frases repetidas, tente aumentar para 1.2 para um texto mais variado. ### Número de Feixes (Padrão: 3) A busca em feixe explora múltiplas sequências possíveis em paralelo. - **Valores mais altos** (por exemplo, 5) podem levar a melhor qualidade, mas geração mais lenta. - **Valores mais baixos** (por exemplo, 1) são mais rápidos, mas podem produzir resultados de menor qualidade. **Exemplo:** Para tarefas complexas como legendagem densa, tente aumentar para 5 feixes. ### Máximo de Tokens (Padrão: 512) Define o comprimento máximo do texto gerado. - **Valores mais baixos** (por exemplo, 100) para saídas concisas. - **Valores mais altos** (por exemplo, 1000) para descrições mais detalhadas. **Exemplo:** Para uma descrição detalhada da imagem, defina o máximo de tokens para 800 para uma saída abrangente. Lembre-se, essas configurações interagem entre si, então experimentar diferentes combinações pode levar a resultados interessantes! """ device = "cuda" if torch.cuda.is_available() else "cpu" torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32 model = Florence2ForConditionalGeneration.from_pretrained("PleIAs/Florence-PDF", torch_dtype=torch_dtype, trust_remote_code=True).to(device) processor = AutoProcessor.from_pretrained("PleIAs/Florence-PDF", trust_remote_code=True) TASK_PROMPTS = { "✍🏻Caption": "", "✍🏻✍🏻Caption": "", "✍🏻✍🏻✍🏻Caption": "", "📸Object Detection": "", "📸Dense Region Caption": "", "📸✍🏻OCR": "", "📸✍🏻OCR with Region": "", "📸Region Proposal": "", "📸✍🏻Object Detection with Description": "", # Start with Object Detection # We will handle the detailed description separately in the code } # Update IMAGE_TASKS and TEXT_TASKS IMAGE_TASKS = ["📸Object Detection", "📸Dense Region Caption", "📸Region Proposal", "📸✍🏻OCR with Region", "📸✍🏻Object Detection with Description"] TEXT_TASKS = ["✍🏻Caption", "✍🏻✍🏻Caption", "✍🏻✍🏻✍🏻Caption", "📸✍🏻OCR", "📸✍🏻OCR with Region", "📸✍🏻Object Detection with Description"] colormap = ['blue','orange','green','purple','brown','pink','gray','olive','cyan','red', 'lime','indigo','violet','aqua','magenta','coral','gold','tan','skyblue'] def fig_to_pil(fig): buf = io.BytesIO() fig.savefig(buf, format='png') buf.seek(0) return Image.open(buf) def plot_bbox(image, data, use_quad_boxes=False): fig, ax = plt.subplots() ax.imshow(image) if use_quad_boxes: for quad_box, label in zip(data.get('quad_boxes', []), data.get('labels', [])): quad_box = np.array(quad_box).reshape(-1, 2) poly = Polygon(quad_box, linewidth=1, edgecolor='r', facecolor='none') ax.add_patch(poly) plt.text(quad_box[0][0], quad_box[0][1], label, color='white', fontsize=8, bbox=dict(facecolor='red', alpha=0.5)) else: bboxes = data.get('bboxes', []) labels = data.get('labels', []) for bbox, label in zip(bboxes, labels): x1, y1, x2, y2 = bbox rect = patches.Rectangle((x1, y1), x2 - x1, y2 - y1, linewidth=1, edgecolor='r', facecolor='none') ax.add_patch(rect) plt.text(x1, y1, label, color='white', fontsize=8, bbox=dict(facecolor='red', alpha=0.5)) ax.axis('off') return fig def draw_ocr_bboxes(image, prediction): scale = 1 draw = ImageDraw.Draw(image) bboxes, labels = prediction['quad_boxes'], prediction['labels'] for box, label in zip(bboxes, labels): color = random.choice(colormap) new_box = (np.array(box) * scale).tolist() draw.polygon(new_box, width=3, outline=color) draw.text((new_box[0]+8, new_box[1]+2), "{}".format(label), align="right", fill=color) return image def draw_bounding_boxes(image, quad_boxes, labels, color=(0, 255, 0), thickness=2): """ Draws quadrilateral bounding boxes on the image. """ for i, quad in enumerate(quad_boxes): points = np.array(quad, dtype=np.int32).reshape((-1, 1, 2)) # Reshape the quad points for drawing image = cv2.polylines(image, [points], isClosed=True, color=color, thickness=thickness) label_pos = (int(quad[0]), int(quad[1]) - 10) cv2.putText(image, labels[i], label_pos, cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, thickness) return image def process_image(image, task): prompt = TASK_PROMPTS[task] inputs = processor(text=prompt, images=image, return_tensors="pt").to(device, torch_dtype) generated_ids = model.generate( **inputs, max_new_tokens=1024, num_beams=3, do_sample=False ) generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0] parsed_answer = processor.post_process_generation(generated_text, task=prompt, image_size=(image.width, image.height)) return parsed_answer def main_process(image, task, top_k, top_p, repetition_penalty, num_beams, max_tokens): prompt = TASK_PROMPTS[task] inputs = processor(text=prompt, images=image, return_tensors="pt").to(device, torch_dtype) generated_ids = model.generate( **inputs, max_new_tokens=max_tokens, num_beams=num_beams, do_sample=True, top_k=top_k, top_p=top_p, repetition_penalty=repetition_penalty ) generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0] parsed_answer = processor.post_process_generation(generated_text, task=prompt, image_size=(image.width, image.height)) return parsed_answer def process_and_update(image, task, top_k, top_p, repetition_penalty, num_beams, max_tokens): if image is None: return None, gr.update(visible=False), "Please upload an image first.", gr.update(visible=True) if task == "📸✍🏻Object Detection with Description": # Perform Object Detection first od_prompt = TASK_PROMPTS["📸Object Detection"] od_inputs = processor(text=od_prompt, images=image, return_tensors="pt").to(device, torch_dtype) od_generated_ids = model.generate( **od_inputs, max_new_tokens=max_tokens, num_beams=num_beams, do_sample=True, top_k=top_k, top_p=top_p, repetition_penalty=repetition_penalty ) od_generated_text = processor.batch_decode(od_generated_ids, skip_special_tokens=False)[0] od_parsed_answer = processor.post_process_generation(od_generated_text, task=od_prompt, image_size=(image.width, image.height)) # Display Bounding Boxes fig = plot_bbox(image, od_parsed_answer.get('', {})) output_image = fig_to_pil(fig) # Then perform Detailed Description dd_prompt = TASK_PROMPTS["✍🏻✍🏻✍🏻Caption"] dd_inputs = processor(text=dd_prompt, images=image, return_tensors="pt").to(device, torch_dtype) dd_generated_ids = model.generate( **dd_inputs, max_new_tokens=max_tokens, num_beams=num_beams, do_sample=True, top_k=top_k, top_p=top_p, repetition_penalty=repetition_penalty ) dd_generated_text = processor.batch_decode(dd_generated_ids, skip_special_tokens=False)[0] dd_parsed_answer = processor.post_process_generation(dd_generated_text, task=dd_prompt, image_size=(image.width, image.height)) text_output = str(dd_parsed_answer) return output_image, gr.update(visible=True), text_output, gr.update(visible=True) else: # Existing processing for other tasks result = main_process(image, task, top_k, top_p, repetition_penalty, num_beams, max_tokens) if task in IMAGE_TASKS: if task == "📸✍🏻OCR with Region": fig = plot_bbox(image, result.get('', {}), use_quad_boxes=True) output_image = fig_to_pil(fig) text_output = result.get('', {}).get('recognized_text', 'No text found') return output_image, gr.update(visible=True), text_output, gr.update(visible=True) else: fig = plot_bbox(image, result.get(TASK_PROMPTS[task], {})) output_image = fig_to_pil(fig) return output_image, gr.update(visible=True), None, gr.update(visible=False) else: return None, gr.update(visible=False), str(result), gr.update(visible=True) def reset_outputs(): return None, gr.update(visible=False), None, gr.update(visible=True) with gr.Blocks(title="Tonic's 🙏🏻PLeIAs/📸📈✍🏻Florence-PDF") as iface: with gr.Column(): with gr.Row(): gr.Markdown(title) with gr.Row(): with gr.Column(scale=1): with gr.Group(): gr.Markdown(model_presentation) with gr.Column(scale=1): with gr.Group(): gr.Markdown(description) with gr.Row(): with gr.Accordion("🫱🏻‍🫲🏻Join Us", open=True): gr.Markdown(joinus) with gr.Row(): with gr.Column(scale=1): image_input = gr.Image(type="pil", label="Input Image") task_dropdown = gr.Dropdown(list(TASK_PROMPTS.keys()), label="Task", value="✍🏻Caption") with gr.Row(): submit_button = gr.Button("📸📈✍🏻Process") reset_button = gr.Button("♻️Reset") with gr.Accordion("🧪Advanced Settings", open=False): with gr.Accordion("🏗️How To Use", open=True): gr.Markdown(how_to_use) top_k = gr.Slider(minimum=1, maximum=100, value=50, step=1, label="Top-k") top_p = gr.Slider(minimum=0.0, maximum=1.0, value=1.0, step=0.01, label="Top-p") repetition_penalty = gr.Slider(minimum=1.0, maximum=2.0, value=1.0, step=0.01, label="Repetition Penalty") num_beams = gr.Slider(minimum=1, maximum=6, value=3, step=1, label="Number of Beams") max_tokens = gr.Slider(minimum=1, maximum=1024, value=1000, step=1, label="Max Tokens") with gr.Column(scale=1): output_image = gr.Image(label="🙏🏻PLeIAs/📸📈✍🏻Florence-PDF", visible=False) output_text = gr.Textbox(label="🙏🏻PLeIAs/📸📈✍🏻Florence-PDF", visible=False) submit_button.click( fn=process_and_update, inputs=[image_input, task_dropdown, top_k, top_p, repetition_penalty, num_beams, max_tokens], outputs=[output_image, output_image, output_text, output_text] ) reset_button.click( fn=reset_outputs, inputs=[], outputs=[output_image, output_image, output_text, output_text] ) task_dropdown.change( fn=lambda task: (gr.update(visible=task in IMAGE_TASKS), gr.update(visible=task in TEXT_TASKS)), inputs=[task_dropdown], outputs=[output_image, output_text] ) iface.launch()