Automatización por Visión Artificial
La Automatización por Visión Artificial (Computer Vision) de Heptora permite interactuar con cualquier aplicación visible en pantalla mediante reconocimiento visual de elementos, simulación de teclado y ratón, y lectura de texto. Es la solución perfecta para automatizar aplicaciones legacy, sistemas sin APIs, mainframes y software propietario.
Control Visual de Aplicaciones
Sección titulada «Control Visual de Aplicaciones»Heptora utiliza tecnología avanzada de visión artificial para “ver” la pantalla como lo haría un humano, identificar elementos visuales, y ejecutar acciones precisas sobre ellos. Esto elimina la dependencia de APIs o interfaces programáticas.
Ventajas de la Automatización Visual
Sección titulada «Ventajas de la Automatización Visual»- 🎯 Compatibilidad Universal: Funciona con cualquier aplicación visible, sin necesidad de APIs
- 🖼️ Reconocimiento Inteligente: Identifica botones, campos, iconos y elementos de interfaz
- 📝 OCR Integrado: Lee y extrae texto directamente de la pantalla
- 🎮 Control Completo: Simula clicks, teclas, arrastre y cualquier acción de usuario
- 🔍 Precisión Pixel-Perfect: Localización exacta de elementos en pantalla
- 🏢 Ideal para Legacy: Automatiza sistemas antiguos sin modernizar
- 🚀 Sin Modificaciones: No requiere cambios en las aplicaciones objetivo
- 🔄 Resiliente: Se adapta a cambios menores en la interfaz
Capacidades de Reconocimiento Visual
Sección titulada «Capacidades de Reconocimiento Visual»Identificación de Elementos UI
Sección titulada «Identificación de Elementos UI»El sistema de visión artificial reconoce múltiples tipos de elementos en pantalla:
Componentes Estándar
Sección titulada «Componentes Estándar»Botones y Controles:
- Botones con texto
- Botones con iconos
- Botones de radio
- Casillas de verificación (checkboxes)
- Selectores y dropdowns
- Sliders y controles deslizantes
Campos de Entrada:
- Campos de texto
- Áreas de texto multi-línea
- Campos de contraseña
- Campos numéricos
- Selectores de fecha
- Campos de búsqueda
Elementos de Navegación:
- Menús y submenús
- Pestañas (tabs)
- Barras de herramientas
- Breadcrumbs
- Enlaces y hipervínculos
- Iconos de navegación
Elementos Visuales
Sección titulada «Elementos Visuales»Reconocimiento de Imágenes:
# Buscar un botón específico por su imagenboton_guardar = vision.find_image( template="imagenes/boton_guardar.png", confidence=0.9)
if boton_guardar: vision.click(boton_guardar.center) print(f"Botón encontrado en: {boton_guardar.coordinates}")else: print("Botón no encontrado en pantalla")Características del reconocimiento:
- Tolerancia a variaciones de color
- Detección con diferentes escalas
- Resistencia a cambios de iluminación
- Coincidencia parcial configurable
- Búsqueda en regiones específicas
OCR - Reconocimiento de Texto
Sección titulada «OCR - Reconocimiento de Texto»Extrae texto directamente de cualquier área de la pantalla:
Lectura de Texto Simple
Sección titulada «Lectura de Texto Simple»# Leer texto de un área específicaregion = {"x": 100, "y": 200, "width": 300, "height": 50}texto = vision.read_text(region=region)print(f"Texto encontrado: {texto}")Búsqueda de Texto en Pantalla
Sección titulada «Búsqueda de Texto en Pantalla»# Buscar una palabra o frase específicaresultado = vision.find_text( text="Total a pagar", exact_match=False)
if resultado: # Leer el valor numérico a la derecha region_valor = { "x": resultado.x + resultado.width + 10, "y": resultado.y, "width": 100, "height": resultado.height } valor = vision.read_text(region=region_valor) print(f"Valor encontrado: {valor}")Extracción Estructurada
Sección titulada «Extracción Estructurada»Tablas y Cuadrículas:
# Extraer datos de una tabla visualtabla = vision.extract_table( region={"x": 50, "y": 100, "width": 800, "height": 400}, has_header=True)
for fila in tabla.rows: print(f"ID: {fila[0]}, Nombre: {fila[1]}, Importe: {fila[2]}")Formularios:
# Extraer todos los campos de un formularioformulario = vision.extract_form_fields( region="pantalla_completa")
for campo, valor in formulario.items(): print(f"{campo}: {valor}")Detección de Cambios en Pantalla
Sección titulada «Detección de Cambios en Pantalla»Monitoriza áreas específicas para detectar actualizaciones:
# Esperar a que aparezca un elementovision.wait_for_image( template="imagenes/mensaje_exito.png", timeout=30)
# Esperar a que desaparezca un elemento (ej: spinner de carga)vision.wait_until_gone( template="imagenes/spinner.png", timeout=60)
# Esperar a que cambie un área de la pantallavision.wait_for_change( region={"x": 500, "y": 200, "width": 300, "height": 100}, timeout=10)Validación Visual
Sección titulada «Validación Visual»Verifica el estado de la aplicación mediante inspección visual:
# Verificar que estamos en la pantalla correctaif vision.image_exists("imagenes/logo_aplicacion.png"): print("Pantalla de inicio confirmada")else: raise Exception("No estamos en la pantalla esperada")
# Validar que un proceso se completóif vision.text_exists("Proceso completado exitosamente"): log.info("Operación finalizada correctamente")else: log.warning("No se encontró mensaje de confirmación")
# Verificar color de un elemento (ej: indicador de estado)color_indicador = vision.get_pixel_color(x=850, y=120)if color_indicador == (0, 255, 0): # Verde print("Estado: Activo")elif color_indicador == (255, 0, 0): # Rojo print("Estado: Error")Control de Teclado y Ratón
Sección titulada «Control de Teclado y Ratón»Acciones de Ratón
Sección titulada «Acciones de Ratón»Clicks y Movimientos
Sección titulada «Clicks y Movimientos»# Click simple en coordenadas específicasvision.mouse.click(x=500, y=300)
# Click derechovision.mouse.right_click(x=500, y=300)
# Doble clickvision.mouse.double_click(x=500, y=300)
# Mover el cursor sin hacer clickvision.mouse.move_to(x=500, y=300)
# Click en el centro de una imagen encontradaboton = vision.find_image("boton_aceptar.png")vision.mouse.click(boton.center)Arrastre (Drag & Drop)
Sección titulada «Arrastre (Drag & Drop)»# Arrastrar desde un punto a otrovision.mouse.drag_to( from_x=200, from_y=300, to_x=400, to_y=300)
# Arrastrar un elemento encontradoelemento = vision.find_image("archivo.png")destino = vision.find_image("carpeta.png")vision.mouse.drag_to( from_x=elemento.center.x, from_y=elemento.center.y, to_x=destino.center.x, to_y=destino.center.y)Scroll y Desplazamiento
Sección titulada «Scroll y Desplazamiento»# Scroll vertical (positivo hacia abajo, negativo hacia arriba)vision.mouse.scroll(clicks=-5) # Scroll hacia arriba
# Scroll horizontalvision.mouse.horizontal_scroll(clicks=3) # Scroll a la derecha
# Scroll en una región específicavision.mouse.move_to(x=600, y=400)vision.mouse.scroll(clicks=10) # Scroll en esa áreaAcciones de Teclado
Sección titulada «Acciones de Teclado»Teclas y Combinaciones
Sección titulada «Teclas y Combinaciones»# Escribir textovision.keyboard.type("Hola Mundo")
# Teclas especialesvision.keyboard.press("Enter")vision.keyboard.press("Tab")vision.keyboard.press("Escape")
# Combinaciones de teclasvision.keyboard.hotkey("Ctrl", "C") # Copiarvision.keyboard.hotkey("Ctrl", "V") # Pegarvision.keyboard.hotkey("Ctrl", "S") # Guardarvision.keyboard.hotkey("Alt", "F4") # Cerrar ventana
# Mantener tecla presionadavision.keyboard.key_down("Shift")vision.keyboard.press("A")vision.keyboard.press("B")vision.keyboard.press("C")vision.keyboard.key_up("Shift") # Escribe "ABC"Escritura Inteligente
Sección titulada «Escritura Inteligente»# Escribir con pausa entre caracteres (más natural)vision.keyboard.type("usuario@ejemplo.com", interval=0.1)
# Escribir con teclas especiales intercaladasvision.keyboard.type("Nombre: ")vision.keyboard.type("Juan Pérez")vision.keyboard.press("Tab")vision.keyboard.type("Email: ")vision.keyboard.type("juan@ejemplo.com")
# Limpiar campo y escribirvision.keyboard.hotkey("Ctrl", "A") # Seleccionar todovision.keyboard.press("Delete") # Borrarvision.keyboard.type("Nuevo texto") # EscribirAtajos de Teclado por Sistema
Sección titulada «Atajos de Teclado por Sistema»# Windowsvision.keyboard.hotkey("Win", "R") # Ejecutarvision.keyboard.type("notepad")vision.keyboard.press("Enter")
# Operaciones de ventanavision.keyboard.hotkey("Alt", "Tab") # Cambiar ventanavision.keyboard.hotkey("Win", "D") # Mostrar escritoriovision.keyboard.hotkey("Ctrl", "Shift", "Escape") # Administrador de tareas
# Operaciones de textovision.keyboard.hotkey("Ctrl", "Z") # Deshacervision.keyboard.hotkey("Ctrl", "Y") # Rehacervision.keyboard.hotkey("Ctrl", "F") # BuscarCombinación de Acciones
Sección titulada «Combinación de Acciones»Crea secuencias complejas combinando mouse y teclado:
# Copiar texto visible en pantalladef copiar_texto_en_pantalla(region): # Hacer triple click para seleccionar todo el párrafo center_x = region["x"] + region["width"] // 2 center_y = region["y"] + region["height"] // 2
vision.mouse.move_to(center_x, center_y) vision.mouse.triple_click(center_x, center_y)
# Copiar al portapapeles vision.keyboard.hotkey("Ctrl", "C") time.sleep(0.5)
# Leer del portapapeles return clipboard.paste()
# Rellenar formulario completodef rellenar_formulario(datos): # Hacer click en primer campo primer_campo = vision.find_text("Nombre:") vision.mouse.click(primer_campo.x + 100, primer_campo.y)
# Rellenar campos con Tab entre ellos vision.keyboard.type(datos["nombre"]) vision.keyboard.press("Tab")
vision.keyboard.type(datos["apellido"]) vision.keyboard.press("Tab")
vision.keyboard.type(datos["email"]) vision.keyboard.press("Tab")
vision.keyboard.type(datos["telefono"])
# Enviar formulario vision.keyboard.press("Enter")Automatización de Aplicaciones Legacy
Sección titulada «Automatización de Aplicaciones Legacy»Sistemas de Terminal y Mainframes
Sección titulada «Sistemas de Terminal y Mainframes»La visión artificial es ideal para automatizar aplicaciones de terminal que no tienen APIs modernas:
Emuladores de Terminal (AS/400, IBM 3270)
Sección titulada «Emuladores de Terminal (AS/400, IBM 3270)»Escenario: Entrada de pedidos en sistema mainframe
# Esperar a que cargue la pantalla de loginvision.wait_for_text("SISTEMA PRINCIPAL", timeout=10)
# Ingresar credencialesvision.keyboard.type(usuario)vision.keyboard.press("Tab")vision.keyboard.type(contraseña)vision.keyboard.press("Enter")
# Esperar menú principalvision.wait_for_text("MENU PRINCIPAL", timeout=5)
# Navegar al módulo de pedidos (opción 2)vision.keyboard.type("2")vision.keyboard.press("Enter")
# Esperar pantalla de entrada de pedidosvision.wait_for_text("ENTRADA DE PEDIDOS", timeout=5)
# Rellenar formulario de pedidovision.keyboard.type(codigo_cliente)vision.keyboard.press("Tab")vision.keyboard.type(numero_pedido)vision.keyboard.press("Tab")
# Ingresar líneas de pedidofor item in items_pedido: vision.keyboard.type(item["codigo"]) vision.keyboard.press("Tab") vision.keyboard.type(str(item["cantidad"])) vision.keyboard.press("Tab") vision.keyboard.press("Enter") # Confirmar línea
# Confirmar pedido (F5)vision.keyboard.press("F5")
# Verificar mensaje de confirmaciónif vision.text_exists("PEDIDO REGISTRADO"): # Extraer número de pedido confirmado region_numero = vision.find_text("PEDIDO NRO:") numero_confirmado = vision.read_text( region={ "x": region_numero.x + 150, "y": region_numero.y, "width": 100, "height": 20 } ) log.info(f"Pedido confirmado: {numero_confirmado}")else: raise Exception("No se recibió confirmación del pedido")
# Volver al menú principalvision.keyboard.press("F3")Aplicaciones DOS
Sección titulada «Aplicaciones DOS»# Lanzar aplicación DOSos.system("start dosbox app_legacy.exe")
# Esperar que cargue la aplicaciónvision.wait_for_text("SISTEMA INVENTARIO V3.2", timeout=15)
# Navegar por menús (número + Enter)vision.keyboard.type("1") # Consultasvision.keyboard.press("Enter")
vision.keyboard.type("3") # Consulta por códigovision.keyboard.press("Enter")
# Ingresar código de productovision.keyboard.type("PROD-12345")vision.keyboard.press("Enter")
# Extraer información de la pantallanombre = vision.read_text(region={"x": 150, "y": 100, "width": 300, "height": 20})stock = vision.read_text(region={"x": 150, "y": 140, "width": 100, "height": 20})precio = vision.read_text(region={"x": 150, "y": 180, "width": 100, "height": 20})
print(f"Producto: {nombre}")print(f"Stock: {stock}")print(f"Precio: {precio}")
# Salir (Escape múltiple)for _ in range(3): vision.keyboard.press("Escape") time.sleep(0.5)Aplicaciones Citrix y Escritorio Remoto
Sección titulada «Aplicaciones Citrix y Escritorio Remoto»Automatiza aplicaciones que se ejecutan en sesiones remotas:
Conexión y Navegación
Sección titulada «Conexión y Navegación»# Conectar a sesión Citrixdef conectar_citrix(aplicacion): # Abrir Citrix Workspace vision.keyboard.hotkey("Win", "R") vision.keyboard.type("citrix workspace") vision.keyboard.press("Enter")
# Esperar que cargue vision.wait_for_image("citrix_workspace_logo.png", timeout=10)
# Buscar aplicación campo_busqueda = vision.find_image("icono_buscar.png") vision.mouse.click(campo_busqueda.center) vision.keyboard.type(aplicacion) time.sleep(1)
# Hacer click en el primer resultado primer_resultado = vision.find_image(f"{aplicacion}_icono.png") vision.mouse.click(primer_resultado.center)
# Esperar que se lance la aplicación vision.wait_for_text("Cargando...", timeout=5) vision.wait_until_gone("Cargando...", timeout=30)
# Usar la aplicación remotaconectar_citrix("ERP Financiero")
# Ahora interactuar normalmentevision.wait_for_text("MENU PRINCIPAL")# ... resto de la automatizaciónManejo de Latencia
Sección titulada «Manejo de Latencia»# En conexiones remotas, aumenta los tiempos de esperaTIEMPO_ESPERA_REMOTO = 2.0
def click_remoto(x, y): vision.mouse.click(x, y) time.sleep(TIEMPO_ESPERA_REMOTO)
def type_remoto(texto): vision.keyboard.type(texto, interval=0.15) # Más lento time.sleep(TIEMPO_ESPERA_REMOTO)
def verificar_cambio_pantalla_remoto(texto_esperado, timeout=30): inicio = time.time() while time.time() - inicio < timeout: if vision.text_exists(texto_esperado): time.sleep(TIEMPO_ESPERA_REMOTO) # Espera adicional return True time.sleep(1) return FalseAplicaciones Propietarias sin APIs
Sección titulada «Aplicaciones Propietarias sin APIs»Automatiza software cerrado o sin documentación:
Aplicaciones de Escritorio Windows
Sección titulada «Aplicaciones de Escritorio Windows»# Ejemplo: Software de gestión médica propietariodef registrar_paciente(datos_paciente): # Asegurarse que la aplicación esté en primer plano ventana_app = vision.find_image("logo_aplicacion.png") if not ventana_app: # Lanzar aplicación si no está abierta vision.keyboard.hotkey("Win", "R") vision.keyboard.type("C:\\Programa\\MediGest\\mediges.exe") vision.keyboard.press("Enter") vision.wait_for_image("logo_aplicacion.png", timeout=20)
# Navegar al módulo de pacientes boton_pacientes = vision.find_image("botones/pacientes.png") vision.mouse.click(boton_pacientes.center)
# Click en "Nuevo Paciente" vision.wait_for_image("botones/nuevo_paciente.png", timeout=5) boton_nuevo = vision.find_image("botones/nuevo_paciente.png") vision.mouse.click(boton_nuevo.center)
# Esperar que se abra el formulario vision.wait_for_text("DATOS DEL PACIENTE", timeout=3)
# Rellenar formulario campos = [ datos_paciente["nombre"], datos_paciente["apellido"], datos_paciente["dni"], datos_paciente["fecha_nacimiento"], datos_paciente["telefono"], datos_paciente["email"], datos_paciente["direccion"] ]
for campo in campos: vision.keyboard.type(str(campo)) vision.keyboard.press("Tab") time.sleep(0.3)
# Guardar boton_guardar = vision.find_image("botones/guardar.png") vision.mouse.click(boton_guardar.center)
# Verificar confirmación if vision.wait_for_text("PACIENTE REGISTRADO", timeout=5): # Extraer número de historia clínica region_numero = vision.find_text("Historia Nro:") historia_clinica = vision.read_text( region={ "x": region_numero.x + 120, "y": region_numero.y, "width": 100, "height": 20 } ) return historia_clinica else: raise Exception("No se pudo confirmar el registro")Software con Interfaz Poco Estándar
Sección titulada «Software con Interfaz Poco Estándar»# Ejemplo: Aplicación con controles custom dibujadosdef click_en_boton_custom(color_boton, region_busqueda): """ Encuentra y hace click en botones dibujados personalizadamente basándose en su color distintivo """ # Capturar pantalla de la región screenshot = vision.capture_region(region_busqueda)
# Buscar píxeles del color del botón ubicaciones = vision.find_color( color=color_boton, tolerance=10, region=region_busqueda )
if ubicaciones: # Calcular centro del grupo de píxeles centro = calcular_centro_cluster(ubicaciones) vision.mouse.click(centro.x, centro.y) return True return False
# UsoVERDE_ACEPTAR = (0, 200, 50)ROJO_CANCELAR = (200, 50, 50)
region_botones = {"x": 400, "y": 500, "width": 300, "height": 100}
if click_en_boton_custom(VERDE_ACEPTAR, region_botones): print("Botón Aceptar presionado")SAP GUI
Sección titulada «SAP GUI»Aunque SAP tiene scripting, la visión artificial puede ser útil en entornos restringidos:
# Lanzar transacción SAPdef ejecutar_transaccion_sap(codigo_transaccion): # Focus en campo de comando campo_comando = vision.find_image("sap_campo_comando.png") vision.mouse.click(campo_comando.center)
# Limpiar cualquier texto previo vision.keyboard.hotkey("Ctrl", "A") vision.keyboard.press("Delete")
# Ingresar transacción vision.keyboard.type(f"/n{codigo_transaccion}") vision.keyboard.press("Enter")
# Esperar que cargue time.sleep(2)
# Extraer datos de tabla SAPdef extraer_tabla_sap(region_tabla): # Hacer click en la primera celda vision.mouse.click( region_tabla["x"] + 50, region_tabla["y"] + 50 )
filas = [] fila_actual = 0 max_filas = 50
while fila_actual < max_filas: # Seleccionar toda la fila vision.keyboard.hotkey("Shift", "End") vision.keyboard.hotkey("Ctrl", "C") time.sleep(0.3)
# Obtener datos del portapapeles texto_fila = clipboard.paste()
if not texto_fila or texto_fila in filas: break # Fin de la tabla o fila repetida
filas.append(texto_fila)
# Ir a la siguiente fila vision.keyboard.press("Down") vision.keyboard.press("Home") time.sleep(0.2)
fila_actual += 1
return filasTécnicas Avanzadas
Sección titulada «Técnicas Avanzadas»Manejo de Múltiples Monitores
Sección titulada «Manejo de Múltiples Monitores»# Especificar en qué monitor buscarmonitor_principal = vision.get_monitor(0)monitor_secundario = vision.get_monitor(1)
# Buscar elemento en monitor específicoboton = vision.find_image( "boton.png", region=monitor_secundario.bounds)
# Mover cursor entre monitoresvision.mouse.move_to( monitor_secundario.x + 500, monitor_secundario.y + 300)Captura y Comparación
Sección titulada «Captura y Comparación»# Capturar estado actual de un áreacaptura_inicial = vision.capture_region( region={"x": 100, "y": 100, "width": 400, "height": 300})
# Realizar alguna acciónvision.mouse.click(500, 400)time.sleep(2)
# Capturar nuevo estadocaptura_final = vision.capture_region( region={"x": 100, "y": 100, "width": 400, "height": 300})
# Comparar si cambióif vision.images_are_different(captura_inicial, captura_final, threshold=0.95): print("La pantalla cambió después de la acción")else: print("No se detectaron cambios")Reconocimiento Adaptativo
Sección titulada «Reconocimiento Adaptativo»# Buscar elemento con múltiples variantesvariantes = [ "boton_guardar_es.png", "boton_guardar_en.png", "boton_guardar_alternativo.png"]
boton_encontrado = Nonefor variante in variantes: boton = vision.find_image(variante, confidence=0.85) if boton: boton_encontrado = boton break
if boton_encontrado: vision.mouse.click(boton_encontrado.center)else: # Intentar buscar por texto como fallback if vision.text_exists("Guardar"): region = vision.find_text("Guardar") vision.mouse.click(region.center)Coordinación con Otras Automatizaciones
Sección titulada «Coordinación con Otras Automatizaciones»# Combinar visión artificial con automatización webdef proceso_hibrido(): # Parte 1: Extraer datos de aplicación legacy con visión datos_legacy = extraer_datos_mainframe()
# Parte 2: Procesar en aplicación web moderna browser = heptora.browser.create() browser.navigate("https://erp-moderno.empresa.com") browser.fill_form(datos_legacy)
# Parte 3: Verificar resultado con visión artificial vision.wait_for_text("Sincronización completada")
return TrueCasos de Uso Prácticos
Sección titulada «Casos de Uso Prácticos»Migración de Datos desde Sistema Legacy
Sección titulada «Migración de Datos desde Sistema Legacy»Escenario: Extraer catálogo de productos de software DOS antiguo
def extraer_catalogo_completo(): productos = []
# Abrir sistema legacy abrir_sistema_inventario()
# Ir a consulta de productos vision.keyboard.type("1") # Menú productos vision.keyboard.press("Enter") vision.keyboard.type("2") # Listar todos vision.keyboard.press("Enter")
# Extraer página por página pagina = 1 while True: # Leer productos de la pantalla actual for linea in range(5, 20): # 15 productos por página # Posición de cada campo y = 80 + (linea * 25)
codigo = vision.read_text( region={"x": 50, "y": y, "width": 100, "height": 20} ).strip()
if not codigo: break # Fin de productos
nombre = vision.read_text( region={"x": 160, "y": y, "width": 300, "height": 20} ).strip()
precio = vision.read_text( region={"x": 470, "y": y, "width": 80, "height": 20} ).strip()
stock = vision.read_text( region={"x": 560, "y": y, "width": 60, "height": 20} ).strip()
productos.append({ "codigo": codigo, "nombre": nombre, "precio": precio, "stock": stock })
# Intentar ir a siguiente página vision.keyboard.press("PageDown") time.sleep(1)
# Verificar si hay más páginas (buscar indicador) if vision.text_exists("FIN DE LISTA"): break
pagina += 1
if pagina > 100: # Seguridad break
return productos
# Exportar a formato modernoproductos = extraer_catalogo_completo()df = pandas.DataFrame(productos)df.to_excel("catalogo_migrado.xlsx", index=False)print(f"Extraídos {len(productos)} productos")Automatización de Aplicación Médica
Sección titulada «Automatización de Aplicación Médica»Escenario: Registro de resultados de laboratorio
def procesar_resultados_laboratorio(archivo_resultados): # Leer resultados del archivo resultados = leer_excel(archivo_resultados)
# Abrir aplicación de gestión hospitalaria abrir_aplicacion_hospital()
for resultado in resultados: # Buscar paciente buscar_paciente(resultado["dni"])
# Ir a módulo de laboratorio boton_lab = vision.find_image("modulos/laboratorio.png") vision.mouse.click(boton_lab.center)
# Nuevo resultado vision.keyboard.hotkey("Ctrl", "N") vision.wait_for_text("NUEVO RESULTADO")
# Rellenar formulario vision.keyboard.type(resultado["tipo_analisis"]) vision.keyboard.press("Tab")
vision.keyboard.type(resultado["fecha"]) vision.keyboard.press("Tab")
# Ingresar valores for valor in resultado["valores"]: vision.keyboard.type(valor["parametro"]) vision.keyboard.press("Tab") vision.keyboard.type(str(valor["resultado"])) vision.keyboard.press("Tab") vision.keyboard.type(valor["unidad"]) vision.keyboard.press("Enter")
# Guardar vision.keyboard.hotkey("Ctrl", "S")
# Verificar guardado if vision.wait_for_text("RESULTADO GUARDADO", timeout=5): log.info(f"Resultado guardado para paciente {resultado['dni']}") else: log.error(f"Error al guardar resultado para {resultado['dni']}") screenshot = vision.capture_screen() vision.save_image(screenshot, f"error_{resultado['dni']}.png")
# Volver al menú principal vision.keyboard.press("Escape") vision.keyboard.press("Escape")Validación de Procesos
Sección titulada «Validación de Procesos»Escenario: Verificar que un proceso batch se ejecutó correctamente
def verificar_proceso_batch(nombre_proceso): # Abrir monitor de procesos abrir_monitor_sistema()
# Buscar proceso específico campo_busqueda = vision.find_image("icono_buscar.png") vision.mouse.click(campo_busqueda.center) vision.keyboard.type(nombre_proceso) vision.keyboard.press("Enter") time.sleep(2)
# Verificar estado region_estado = vision.find_text("Estado:") estado_texto = vision.read_text( region={ "x": region_estado.x + 80, "y": region_estado.y, "width": 150, "height": 25 } )
# Verificar visualmente el color del indicador color_indicador = vision.get_pixel_color( x=region_estado.x - 30, y=region_estado.y + 10 )
if "COMPLETADO" in estado_texto.upper() and color_indicador[1] > 200: # Verde log.info(f"Proceso {nombre_proceso} completado exitosamente")
# Extraer estadísticas registros = vision.read_text_after_label("Registros procesados:") errores = vision.read_text_after_label("Errores:") duracion = vision.read_text_after_label("Duración:")
return { "estado": "COMPLETADO", "registros": registros, "errores": errores, "duracion": duracion } else: log.error(f"Proceso {nombre_proceso} falló o está pendiente") return {"estado": "ERROR"}Mejores Prácticas
Sección titulada «Mejores Prácticas»Estrategias de Búsqueda
Sección titulada «Estrategias de Búsqueda»-
Usar referencias estables
- Busca elementos que no cambian (logos, títulos)
- Evita elementos dinámicos como timestamps
-
Combinar métodos
# Método robusto: intentar imagen, luego textoboton = vision.find_image("boton_siguiente.png")if not boton:boton = vision.find_text("Siguiente")if boton:vision.mouse.click(boton.center) -
Usar regiones de búsqueda
# Más rápido y precisoboton = vision.find_image("boton.png",region={"x": 700, "y": 400, "width": 200, "height": 100})
Manejo de Errores
Sección titulada «Manejo de Errores»def accion_robusta(max_intentos=3): for intento in range(max_intentos): try: # Intentar la acción vision.mouse.click_image("boton.png")
# Verificar que funcionó if vision.wait_for_text("Confirmación", timeout=5): return True except ElementNotFoundError: if intento < max_intentos - 1: log.warning(f"Intento {intento + 1} falló, reintentando...") time.sleep(2) else: # Capturar evidencia del error screenshot = vision.capture_screen() vision.save_image(screenshot, "error_final.png") raise
return FalseOptimización de Rendimiento
Sección titulada «Optimización de Rendimiento»-
Cachear imágenes de plantilla
# Cargar plantillas al inicioPLANTILLAS = {"guardar": vision.load_template("botones/guardar.png"),"cancelar": vision.load_template("botones/cancelar.png"),"aceptar": vision.load_template("botones/aceptar.png")}# Usar plantillas cacheadasboton = vision.find_template(PLANTILLAS["guardar"]) -
Reducir área de búsqueda
# Definir regiones comunesREGIONES = {"botones_inferiores": {"x": 0, "y": 700, "width": 1920, "height": 280},"menu_superior": {"x": 0, "y": 0, "width": 1920, "height": 100},"panel_derecho": {"x": 1400, "y": 100, "width": 520, "height": 900}} -
Ajustar niveles de confianza
# Para elementos estables, usa alta confianzalogo = vision.find_image("logo.png", confidence=0.95)# Para elementos variables, reduce confianzaboton = vision.find_image("boton_dinamico.png", confidence=0.75)
Captura de Evidencias
Sección titulada «Captura de Evidencias»def ejecutar_con_evidencia(nombre_proceso): timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") carpeta_evidencias = f"evidencias/{nombre_proceso}_{timestamp}" os.makedirs(carpeta_evidencias, exist_ok=True)
paso = 0
def capturar_paso(descripcion): nonlocal paso paso += 1 screenshot = vision.capture_screen() ruta = f"{carpeta_evidencias}/paso_{paso:02d}_{descripcion}.png" vision.save_image(screenshot, ruta) log.info(f"Capturado: {descripcion}")
try: capturar_paso("inicio")
# Ejecutar proceso abrir_aplicacion() capturar_paso("aplicacion_abierta")
realizar_operacion() capturar_paso("operacion_completada")
capturar_paso("fin_exitoso")
except Exception as e: capturar_paso("error") log.error(f"Error: {str(e)}") raiseSolución de Problemas
Sección titulada «Solución de Problemas»Elemento No Encontrado
Sección titulada «Elemento No Encontrado»Síntomas: vision.find_image() o vision.find_text() retorna None
Soluciones:
- Verificar que el elemento esté visible en pantalla
- Reducir nivel de confianza:
confidence=0.8en lugar de0.9 - Capturar nueva plantilla en condiciones actuales
- Usar región de búsqueda más específica
- Intentar buscar por texto en lugar de imagen
Clicks No Registrados
Sección titulada «Clicks No Registrados»Síntomas: El click se ejecuta pero no tiene efecto
Soluciones:
- Agregar
time.sleep(0.5)después del click - Verificar que la aplicación tenga el foco
- Usar
double_click()si es necesario - Verificar coordenadas del click con captura de pantalla
OCR Impreciso
Sección titulada «OCR Impreciso»Síntomas: Texto leído incorrectamente
Soluciones:
- Aumentar contraste de la región capturada
- Especificar idioma del OCR:
vision.read_text(lang='spa') - Preprocesar imagen (escala de grises, umbralización)
- Usar región más ajustada al texto específico
Rendimiento Lento
Sección titulada «Rendimiento Lento»Síntomas: Búsquedas tardan mucho tiempo
Soluciones:
- Usar regiones de búsqueda limitadas
- Reducir resolución de plantillas
- Cachear plantillas cargadas
- Evitar búsquedas en pantalla completa
Preguntas Frecuentes
Sección titulada «Preguntas Frecuentes»¿La visión artificial funciona en cualquier resolución?
Sección titulada «¿La visión artificial funciona en cualquier resolución?»Sí, pero es recomendable capturar plantillas en la misma resolución donde se ejecutará el proceso. Para multi-resolución, usa búsqueda por texto en lugar de imagen cuando sea posible.
¿Puedo automatizar aplicaciones en modo headless?
Sección titulada «¿Puedo automatizar aplicaciones en modo headless?»No, la visión artificial requiere que la aplicación sea visible en pantalla. Para automatización en segundo plano, considera usar el robot en una máquina virtual con escritorio visible.
¿Funciona con aplicaciones en múltiples idiomas?
Sección titulada «¿Funciona con aplicaciones en múltiples idiomas?»Sí, pero debes capturar plantillas para cada idioma o usar reconocimiento de texto con el idioma apropiado especificado.
¿Qué pasa si cambia ligeramente la interfaz?
Sección titulada «¿Qué pasa si cambia ligeramente la interfaz?»Puedes ajustar el nivel de confianza para tolerar variaciones menores. Para cambios mayores, necesitarás actualizar las plantillas de imagen.
¿Puedo combinar visión artificial con automatización web?
Sección titulada «¿Puedo combinar visión artificial con automatización web?»Absolutamente. Es común usar visión artificial para sistemas legacy y automatización web para sistemas modernos en el mismo proceso.
¿Cómo manejo pop-ups inesperados?
Sección titulada «¿Cómo manejo pop-ups inesperados?»Implementa verificaciones periódicas:
if vision.image_exists("popup_error.png"): vision.mouse.click_image("boton_cerrar_popup.png")¿Necesitas más ayuda?
Sección titulada «¿Necesitas más ayuda?»Si esta guía no resolvió tu problema o encontraste algún error en la documentación:
- Soporte técnico: help@heptora.com
- Describe la aplicación que intentas automatizar
- Incluye capturas de pantalla de la interfaz
- Indica qué elemento no puedes localizar o interactuar
- Menciona el sistema operativo y resolución de pantalla
Nuestro equipo te ayudará a diseñar la mejor estrategia de automatización visual para tu caso específico.
Recursos Relacionados
Sección titulada «Recursos Relacionados»- Procesador de Grabación - Graba acciones visuales automáticamente
- OCR y Procesamiento de Documentos - OCR avanzado para documentos
- Constructor de Procesos - Cómo crear automatizaciones visuales
- Gestión de Secretos - Protege credenciales de sistemas legacy