Implementação de Zoom Interativo em Imagens com Gradio Blocks para MiniCPM-o-4.5-nvidia-FlagOS

Em sistemas de inteligência artificial multimodal, como o MiniCPM-o-4.5-nvidia-FlagOS, a visualização detalhada de imagens é crucial para uma análise eficiente. Limitações na interface padrão, como imagens pequenas ou fixas, podem prejudicar a interação do usuário. Este guia demosntra como integrar uma funcionalidade de zoom em imagens utilizando Gradio Blocks, aprimorando significativamente a experiência do usuário.

Motivação para Adicionar Zoom em Imagens

Em cenários onde o usuário precisa examinar detalhes específicos em uma imagem enviada, como texto pequeno ou elementos gráficos complexos, a capacidade de ampliar e navegar na imagem torna-se essencial. Com uma interface baseada em Gradio Blockss, é possível incorporar componentes interativos que permitem zoom, arastar e visualização em tela cheia, tornando a análise de imagens mais intuitiva e eficaz.

Reestruturação da Interface com Gradio Blocks

O ponto de partida é substituir o uso simplificado de gr.ChatInterface por uma estrutura modular com gr.Blocks. Isso oferece controle total sobre o layout e a adição de componentes personalizados. A seguir, um exemplo de como configurar a interface básica:

import gradio as gr
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

# Carregamento do modelo e tokenizador
model_path = "/root/ai-models/FlagRelease/MiniCPM-o-4___5-nvidia-FlagOS"
ai_model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.bfloat16, device_map="auto", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

def process_multimodal_input(user_query, conversation_history, uploaded_image):
    """Processa a entrada do usuário e gera uma resposta."""
    if uploaded_image is None:
        input_tokens = tokenizer(user_query, return_tensors="pt").to(ai_model.device)
    else:
        # Lógica multimodal específica do modelo (exemplo simplificado)
        input_tokens = tokenizer(f"[Imagem processada] {user_query}", return_tensors="pt").to(ai_model.device)
    
    with torch.no_grad():
        generated_output = ai_model.generate(**input_tokens, max_new_tokens=512)
    response = tokenizer.decode(generated_output[0], skip_special_tokens=True)
    conversation_history.append((user_query, response))
    return "", conversation_history, None

with gr.Blocks(title="Assistente Multimodal MiniCPM-o", theme=gr.themes.Soft()) as demo:
    gr.Markdown("# Assistente de IA com Visualização de Imagens Aprimorada")
    
    with gr.Row():
        with gr.Column(scale=2):
            chat_display = gr.Chatbot(height=400, label="Histórico da Conversa")
            input_query = gr.Textbox(label="Digite sua pergunta", placeholder="Faça uma pergunta sobre a imagem...")
            with gr.Row():
                send_button = gr.Button("Enviar", variant="primary")
                clear_button = gr.Button("Limpar Conversa")
        
        with gr.Column(scale=1):
            image_upload = gr.Image(type="pil", label="Carregar Imagem", height=200, elem_id="input_image")
            zoom_preview = gr.HTML(label="Visualização com Zoom", elem_id="zoom_container")
            gr.Markdown("*Use o scroll do mouse para zoom e arraste para navegar.*")

    send_button.click(process_multimodal_input, inputs=[input_query, chat_display, image_upload], outputs=[input_query, chat_display, zoom_preview])
    clear_button.click(lambda: ([], None, ""), outputs=[chat_display, image_upload, zoom_preview])

Integrando Componente de Zoom com Viewer.js

Para habilitar o zoom interativo, utilizamos a biblioteca JavaScript Viewer.js através de um componente gr.HTML. A imagem carregada é convertida para Base64 e incorporada em HTML, permitindo que o Viewer.js forneça funcionalidades avançadas de visualização. Ajuste a função de processamento para atualizar a visualização:

import io
import base64

def update_zoom_view(image):
    if image is None:
        return gr.HTML.update(value="<div style='padding:40px; text-align:center;'>Nenhuma imagem carregada</div>")
    
    # Converter imagem para Base64
    buffered = io.BytesIO()
    image.save(buffered, format="PNG")
    encoded_image = base64.b64encode(buffered.getvalue()).decode()
    image_data_uri = f"data:image/png;base64,{encoded_image}"
    
    # Gerar HTML com Viewer.js
    html_content = f"""
    <div id="zoom_view">
        <img src="{image_data_uri}" style="max-width:100%; cursor:zoom-in;" alt="Imagem para zoom">
    </div>
    <script>
        function initViewer() {{
            const imgElement = document.querySelector('#zoom_view img');
            if (imgElement && typeof Viewer !== 'undefined') {{
                if (window.viewerInstance) window.viewerInstance.destroy();
                window.viewerInstance = new Viewer(imgElement, {{
                    toolbar: {{
                        zoomIn: true,
                        zoomOut: true,
                        reset: true
                    }},
                    navbar: false
                }});
            }}
        }}
        setTimeout(initViewer, 100);
    </script>
    """
    return html_content

# Atualizar eventos para incluir zoom
image_upload.change(update_zoom_view, inputs=image_upload, outputs=zoom_preview)
send_button.click(lambda q, h, i: (process_multimodal_input(q, h, i)[0], process_multimodal_input(q, h, i)[1], update_zoom_view(i)), inputs=[input_query, chat_display, image_upload], outputs=[input_query, chat_display, zoom_preview])

Otimizações e Considerações

Para melhorar o desempenho, considere armazenar imagens em cache ou usar caminhos temporários em vez de codificação Base64 recorrente. Além disso, gerencie instâncias do Viewer.js para evitar conflitos em atualizações dinâmicas. Certifique-se de adaptar a lógica de processamento do modelo de acordo com a API específica do MiniCPM-o, integrando corretamente os recursos multimodais.

Esta abordagem pode ser estendida para outras aplicações baseadas em Gradio que necessitam de visualização detalhada de imagens, proporcionando uma interface mais interativa e profissional.

Tags: MiniCPM-o Gradio Python javascript Viewer.js

Publicado em 7-14 03:50