<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://globaldevlog.com/es/blog</id>
    <title>Global Dev Blog Blog</title>
    <updated>2026-10-18T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://globaldevlog.com/es/blog"/>
    <subtitle>Global Dev Blog Blog</subtitle>
    <icon>https://globaldevlog.com/es/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[De 45 Vulnerabilidades en npm a Riesgo Cero: Por Qué No Debes Ejecutar npm audit fix --force a Ciegas en Sitios Estáticos]]></title>
        <id>https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth</id>
        <link href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth"/>
        <updated>2026-10-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Un análisis profundo sobre el modelo de amenazas en sitios estáticos (SSG), explicando por qué 45 advertencias de npm en herramientas de empaquetado no suponen riesgo en producción.]]></summary>
        <content type="html"><![CDATA[<p>Todo desarrollador web moderno ha experimentado ese sobresalto: ejecutas <code>npm audit</code> en tu repositorio y la terminal responde con un mensaje alarmante en rojo:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">45 vulnerabilities (15 moderate, 15 high, 15 critical)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">To address all issues (including breaking changes), run:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  npm audit fix --force</span><br></div></code></pre></div></div>
<p>Al ver palabras como <strong>Critical</strong>, <strong>Remote Code Execution (RCE)</strong> y <strong>Prototype Pollution</strong>, el instinto natural es escribir <code>npm audit fix --force</code> para eliminar las advertencias.</p>
<p>Sin embargo, en el mundo de los <strong>Generadores de Sitios Estáticos (SSG)</strong> como Docusaurus o Next.js alojados en GitHub Pages o AWS S3, hacer esto a ciegas es un error común que rompe la compilación de producción sin mejorar la seguridad real.</p>
<p>En este artículo, definimos el <strong>modelo de amenazas en sitios estáticos</strong>, explicamos por qué las vulnerabilidades en herramientas de construcción difieren radicalmente de las vulnerabilidades en tiempo de ejecución, y compartimos un plan práctico de <strong>seguridad en 4 capas</strong>.</p>
<!-- -->
<hr>
<p><img decoding="async" loading="lazy" alt="Comparativa del modelo de amenazas: Servidor Dinámico vs Sitio Estático" src="https://globaldevlog.com/es/assets/images/01_threat_model-4770df6c58430b3bba205124a37d91ab.png" width="2000" height="1000" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-resumen-ejecutivo-el-criterio-de-ingeniería">1. Resumen Ejecutivo: El Criterio de Ingeniería<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#1-resumen-ejecutivo-el-criterio-de-ingenier%C3%ADa" class="hash-link" aria-label="Enlace directo al 1. Resumen Ejecutivo: El Criterio de Ingeniería" title="Enlace directo al 1. Resumen Ejecutivo: El Criterio de Ingeniería" translate="no">​</a></h2>
<ol>
<li class=""><strong>Herramientas de Compilación != Tiempo de Ejecución en Producción</strong>: Paquetes señalados en <code>npm audit</code> (como <code>tinypool</code> o <code>serialize-javascript</code>) son dependencias que solo se ejecutan localmente al compilar con <code>npm run build</code>.</li>
<li class=""><strong>Cero Servidores Activos en la CDN</strong>: Tras la compilación, GitHub Pages solo aloja archivos estáticos (HTML, CSS, JS). <strong>No hay ningún proceso Node.js en ejecución, ni puertos abiertos, ni conexiones a bases de datos.</strong></li>
<li class=""><strong>El Peligro de <code>--force</code></strong>: Forzar la resolución degrada frameworks como <code>@docusaurus/core</code> a versiones antiguas (3.7.0), rompiendo la compatibilidad con React 19 y plugins modernos.</li>
<li class=""><strong>Las Amenazas Reales</strong>: Los verdaderos riesgos en blogs estáticos son la <strong>fuga de claves API en Git</strong>, la <strong>exposición de datos personales (PII)</strong> y la <strong>fuga de privacidad en el cliente</strong>.</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-la-realidad-tras-las-45-vulnerabilidades">2. La Realidad tras las 45 Vulnerabilidades<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#2-la-realidad-tras-las-45-vulnerabilidades" class="hash-link" aria-label="Enlace directo al 2. La Realidad tras las 45 Vulnerabilidades" title="Enlace directo al 2. La Realidad tras las 45 Vulnerabilidades" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-tinypool-y-la-polución-de-prototipos-ghsa-5gmw-xhrv-c9v3---critical">A. Tinypool y la Polución de Prototipos (<code>GHSA-5gmw-xhrv-c9v3</code> - Critical)<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#a-tinypool-y-la-poluci%C3%B3n-de-prototipos-ghsa-5gmw-xhrv-c9v3---critical" class="hash-link" aria-label="Enlace directo al a-tinypool-y-la-polución-de-prototipos-ghsa-5gmw-xhrv-c9v3---critical" title="Enlace directo al a-tinypool-y-la-polución-de-prototipos-ghsa-5gmw-xhrv-c9v3---critical" translate="no">​</a></h3>
<ul>
<li class=""><code>tinypool</code> se utiliza internamente para paralelizar tareas de compilación entre los núcleos de tu CPU local. Las entradas provienen únicamente de tu archivo <code>docusaurus.config.ts</code>. Ningún visitante externo puede enviar cargas útiles HTTP a tu entorno local.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="b-serialize-javascript-y-rce-ghsa-5c6j-r48x-rmvq---high">B. Serialize-JavaScript y RCE (<code>GHSA-5c6j-r48x-rmvq</code> - High)<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#b-serialize-javascript-y-rce-ghsa-5c6j-r48x-rmvq---high" class="hash-link" aria-label="Enlace directo al b-serialize-javascript-y-rce-ghsa-5c6j-r48x-rmvq---high" title="Enlace directo al b-serialize-javascript-y-rce-ghsa-5c6j-r48x-rmvq---high" translate="no">​</a></h3>
<ul>
<li class="">Webpack utiliza este paquete para generar fragmentos de código estáticos. En el directorio <code>build/</code>, los archivos son activos pasivos distribuidos por HTTPS; no existe deserialización en servidor.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="c-postcss-selector-parser-ghsa-rj75-hqrm-r3gf---moderate">C. PostCSS Selector Parser (<code>GHSA-rj75-hqrm-r3gf</code> - Moderate)<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#c-postcss-selector-parser-ghsa-rj75-hqrm-r3gf---moderate" class="hash-link" aria-label="Enlace directo al c-postcss-selector-parser-ghsa-rj75-hqrm-r3gf---moderate" title="Enlace directo al c-postcss-selector-parser-ghsa-rj75-hqrm-r3gf---moderate" translate="no">​</a></h3>
<ul>
<li class="">El CSS analizado corresponde a las hojas de estilo del propio autor (<code>custom.css</code>). Salvo que alguien comprometa los permisos de tu repositorio Git, no se procesa CSS externo malicioso.</li>
</ul>
<p>Degradar librerías con <code>--force</code> en este contexto equivale a <strong>introducir fallos reales en tu aplicación para solucionar exploits que físicamente no pueden ocurrir en tu arquitectura</strong>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-seguridad-práctica-en-4-capas-para-sitios-estáticos">3. Seguridad Práctica en 4 Capas para Sitios Estáticos<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#3-seguridad-pr%C3%A1ctica-en-4-capas-para-sitios-est%C3%A1ticos" class="hash-link" aria-label="Enlace directo al 3. Seguridad Práctica en 4 Capas para Sitios Estáticos" title="Enlace directo al 3. Seguridad Práctica en 4 Capas para Sitios Estáticos" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Canal de seguridad en 4 capas para blogs estáticos" src="https://globaldevlog.com/es/assets/images/02_security_pipeline-120240a37282a9b3b578a5dc4f6231c0.png" width="2000" height="900" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="capa-1-escaneo-automatizado-de-secretos-previo-al-commit">Capa 1: Escaneo Automatizado de Secretos Previo al Commit<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#capa-1-escaneo-automatizado-de-secretos-previo-al-commit" class="hash-link" aria-label="Enlace directo al Capa 1: Escaneo Automatizado de Secretos Previo al Commit" title="Enlace directo al Capa 1: Escaneo Automatizado de Secretos Previo al Commit" translate="no">​</a></h3>
<p>El mayor peligro es subir por error una clave de OpenAI (<code>sk-...</code>), un token de GitHub (<code>ghp_...</code>) o credenciales de AWS (<code>AKIA...</code>). Implementamos un script de auditoría (<code>tools/audit_security.py</code>) que analiza los archivos con expresiones regulares de alta entropía antes de cada despliegue.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="capa-2-protección-de-datos-personales-pii">Capa 2: Protección de Datos Personales (PII)<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#capa-2-protecci%C3%B3n-de-datos-personales-pii" class="hash-link" aria-label="Enlace directo al Capa 2: Protección de Datos Personales (PII)" title="Enlace directo al Capa 2: Protección de Datos Personales (PII)" translate="no">​</a></h3>
<p>En proyectos de IA y visión por computador, utilizamos <strong>datos sintéticos (<code>synth_gen</code>)</strong> generados con modelos de lenguaje para garantizar el cumplimiento ético y la privacidad médica y personal.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="capa-3-configuración-blindada-de-gitignore">Capa 3: Configuración Blindada de <code>.gitignore</code><a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#capa-3-configuraci%C3%B3n-blindada-de-gitignore" class="hash-link" aria-label="Enlace directo al capa-3-configuración-blindada-de-gitignore" title="Enlace directo al capa-3-configuración-blindada-de-gitignore" translate="no">​</a></h3>
<p>Ampliamos <code>.gitignore</code> para bloquear exhaustivamente archivos <code>.env</code>, certificados privados (<code>*.pem</code>, <code>*.key</code>) y volcados de métricas (<code>*.csv</code>).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="capa-4-privacidad-en-cliente-y-sandboxing">Capa 4: Privacidad en Cliente y Sandboxing<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#capa-4-privacidad-en-cliente-y-sandboxing" class="hash-link" aria-label="Enlace directo al Capa 4: Privacidad en Cliente y Sandboxing" title="Enlace directo al Capa 4: Privacidad en Cliente y Sandboxing" translate="no">​</a></h3>
<ul>
<li class=""><strong>Política de Referrer Estricta</strong>: Configuramos <code>strict-origin-when-cross-origin</code> para evitar que la ruta completa de navegación se transmita a dominios externos.</li>
<li class=""><strong>Iframe de Giscus Aislado</strong>: Comentarios configurados con <code>emitMetadata="0"</code> y <code>loading="lazy"</code> para prevenir la fuga de metadatos entre orígenes.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-conclusiones-para-desarrolladores">4. Conclusiones para Desarrolladores<a href="https://globaldevlog.com/es/blog/static-site-security-npm-audit-truth#4-conclusiones-para-desarrolladores" class="hash-link" aria-label="Enlace directo al 4. Conclusiones para Desarrolladores" title="Enlace directo al 4. Conclusiones para Desarrolladores" translate="no">​</a></h2>
<ul>
<li class=""><strong>No entres en pánico con <code>npm audit</code></strong>: Distingue siempre entre dependencias de compilación y dependencias en tiempo de ejecución.</li>
<li class=""><strong>Evita el uso ciego de <code>--force</code></strong>: Las degradaciones automáticas suelen introducir errores reales mientras mitigan riesgos teóricos inexistentes en una CDN.</li>
<li class=""><strong>Protege lo que de verdad importa</strong>: Automatiza el escaneo de secretos, protege la privacidad de tus datos y asegura tu historial en Git.</li>
</ul>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="seguridad-web" term="seguridad-web"/>
        <category label="npm-audit" term="npm-audit"/>
        <category label="docusaurus" term="docusaurus"/>
        <category label="devops" term="devops"/>
        <category label="cadena-de-suministro" term="cadena-de-suministro"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Vision AI] Optimización de OCR para Matrículas Coreanas, Normalización con Regex y Votación Mayoritaria Temporal (Evolución v01 a v11) (#5)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-06-29-vision-anpr-5</id>
        <link href="https://globaldevlog.com/es/blog/2026-06-29-vision-anpr-5"/>
        <updated>2026-06-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Validación de sintaxis para matrículas coreanas, EasyOCR, motor de votación por mayoría temporal y la evolución en 11 iteraciones de v01 a v11.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Votación Mayoritaria Temporal y Confirmación Definitiva" src="https://globaldevlog.com/es/assets/images/01_voting_evolution-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (Puntos Clave)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: El OCR de fotograma único genera lecturas erróneas transitorias debido a reflejos y vibraciones.</li>
<li class=""><strong>Solución</strong>: Validación de sintaxis regex (<code>^\d{2,3}[가-힣]\d{4}$</code>) combinada con un motor de votación por mayoría temporal en una ventana deslizante de 7 fotogramas.</li>
<li class=""><strong>Resultado</strong>: Evolución a través de 11 iteraciones técnicas (v01 a v11) desde ruido inicial (<code>ACCIIXOY...</code>) hasta la confirmación determinista de <code>64가1511</code>.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-sintaxis-de-matrículas-coreanas-y-easyocr">1. Sintaxis de Matrículas Coreanas y EasyOCR<a href="https://globaldevlog.com/es/blog/2026-06-29-vision-anpr-5#1-sintaxis-de-matr%C3%ADculas-coreanas-y-easyocr" class="hash-link" aria-label="Enlace directo al 1. Sintaxis de Matrículas Coreanas y EasyOCR" title="Enlace directo al 1. Sintaxis de Matrículas Coreanas y EasyOCR" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> easyocr</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> re</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> collections </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> deque</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Counter</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">reader </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> easyocr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Reader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'ko'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'en'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> gpu</span><span class="token operator" style="color:#393A34">=</span><span class="token boolean" style="color:#36acaa">True</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">parse_korean_plate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plate_img</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    results </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> reader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">readtext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plate_img</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> detail</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    raw_text </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">results</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">replace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">" "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    pattern </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">r'(\d{2,3}[가-힣]\d{4})'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> re</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">search</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pattern</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> raw_text</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">match</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">group</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-motor-de-votación-por-mayoría-temporal">2. Motor de Votación por Mayoría Temporal<a href="https://globaldevlog.com/es/blog/2026-06-29-vision-anpr-5#2-motor-de-votaci%C3%B3n-por-mayor%C3%ADa-temporal" class="hash-link" aria-label="Enlace directo al 2. Motor de Votación por Mayoría Temporal" title="Enlace directo al 2. Motor de Votación por Mayoría Temporal" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">plate_history </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> deque</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">maxlen</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">CONFIG</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"plate_history_size"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">confirmed_plate </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">update_plate_voting</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">detected_text</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">global</span><span class="token plain"> confirmed_plate</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> detected_text</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        plate_history</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">append</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">detected_text</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token builtin">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plate_history</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> CONFIG</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"plate_confirm_threshold"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        counts </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> Counter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plate_history</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        most_common_plate</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> counts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">most_common</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> CONFIG</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"plate_confirm_threshold"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            confirmed_plate </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> most_common_plate</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> confirmed_plate</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-la-evolución-de-v01-a-v11">3. La Evolución de v01 a v11<a href="https://globaldevlog.com/es/blog/2026-06-29-vision-anpr-5#3-la-evoluci%C3%B3n-de-v01-a-v11" class="hash-link" aria-label="Enlace directo al 3. La Evolución de v01 a v11" title="Enlace directo al 3. La Evolución de v01 a v11" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Sistema Integrado v11 en Operación" src="https://globaldevlog.com/es/assets/images/02_final_system-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<table><thead><tr><th style="text-align:left">Fecha y Hora</th><th style="text-align:left">Registro de Matrícula</th><th style="text-align:left">Hito Técnico Clave</th></tr></thead><tbody><tr><td style="text-align:left"><strong>06-05 01:13</strong></td><td style="text-align:left"><code>ACCIIXOY-1Z01V1t145V...</code></td><td style="text-align:left"><strong>v01</strong>: OCR sobre fotograma completo sin filtrar</td></tr><tr><td style="text-align:left"><strong>06-06 00:13</strong></td><td style="text-align:left"><code>fa이</code>, <code>ealan</code>, <code>cai</code></td><td style="text-align:left"><strong>v04</strong>: Detección de vehículos con YOLOv3</td></tr><tr><td style="text-align:left"><strong>06-06 01:40</strong></td><td style="text-align:left"><code>64115114</code>, <code>16416114</code></td><td style="text-align:left"><strong>v07</strong>: Detector especializado de matrículas YOLOv5</td></tr><tr><td style="text-align:left"><strong>06-06 16:35</strong></td><td style="text-align:left"><code>64아1511</code> -&gt; <code>64가1511</code></td><td style="text-align:left"><strong>v09</strong>: Superresolución EDSR_x4 resuelve caracteres Hangul</td></tr><tr><td style="text-align:left"><strong>06-07 01:27</strong></td><td style="text-align:left"><code>24가1511</code> -&gt; <code>64가1511</code></td><td style="text-align:left"><strong>v10</strong>: Apilamiento multifotograma elimina ruido</td></tr><tr><td style="text-align:left"><strong>06-07 18:20</strong></td><td style="text-align:left"><strong><code>64가1511</code></strong></td><td style="text-align:left"><strong>v11 Final</strong>: Votación mayoritaria asegura confirmación al 100%</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-conclusión">4. Conclusión<a href="https://globaldevlog.com/es/blog/2026-06-29-vision-anpr-5#4-conclusi%C3%B3n" class="hash-link" aria-label="Enlace directo al 4. Conclusión" title="Enlace directo al 4. Conclusión" translate="no">​</a></h2>
<p>Concluimos una serie de 5 artículos integrando <strong>detección de carril, IoU de invasión, detección jerárquica YOLO, seguimiento CSRT, superresolución EDSR y votación OCR</strong>.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="computer-vision" term="computer-vision"/>
        <category label="anpr" term="anpr"/>
        <category label="easyocr" term="easyocr"/>
        <category label="regex" term="regex"/>
        <category label="voting-ensemble" term="voting-ensemble"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Vision AI] Superación de Artefactos Borrosos de Caja Negra: Superresolución Profunda (EDSR vs FSRCNN) y Apilamiento Multifotograma (#4)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-06-28-vision-anpr-4</id>
        <link href="https://globaldevlog.com/es/blog/2026-06-28-vision-anpr-4"/>
        <updated>2026-06-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Reconstrucción de parches de matrículas de baja resolución mediante superresolución 4x con EDSR y apilamiento multifotograma.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Resultados de Superresolución EDSR" src="https://globaldevlog.com/es/assets/images/01_edsr_sr_comparison-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (Puntos Clave)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: Las matrículas recortadas suelen medir menos de 40x20 píxeles; la interpolación bicúbica estándar desenfoca los trazos impidiendo el OCR.</li>
<li class=""><strong>Solución</strong>: Red residual profunda EDSR_x4 (EDSR_x4.pb) combinada con apilamiento de 3 a 5 fotogramas consecutivos.</li>
<li class=""><strong>Resultado</strong>: Densidad de píxeles cuadruplicada y precisión de EasyOCR mejorada del 32% a más del 91%.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-motor-de-superresolución-edsr_x4">1. Motor de Superresolución EDSR_x4<a href="https://globaldevlog.com/es/blog/2026-06-28-vision-anpr-4#1-motor-de-superresoluci%C3%B3n-edsr_x4" class="hash-link" aria-label="Enlace directo al 1. Motor de Superresolución EDSR_x4" title="Enlace directo al 1. Motor de Superresolución EDSR_x4" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> cv2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> cv2 </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> dnn_superres</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">sr </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dnn_superres</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DnnSuperResImpl_create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">sr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">readModel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"EDSR_x4.pb"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">sr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">setModel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"edsr"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">enhanced_plate </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">upsample</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plate_roi</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-apilamiento-de-imágenes-multifotograma">2. Apilamiento de Imágenes Multifotograma<a href="https://globaldevlog.com/es/blog/2026-06-28-vision-anpr-4#2-apilamiento-de-im%C3%A1genes-multifotograma" class="hash-link" aria-label="Enlace directo al 2. Apilamiento de Imágenes Multifotograma" title="Enlace directo al 2. Apilamiento de Imágenes Multifotograma" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Comparación de Apilamiento Multifotograma" src="https://globaldevlog.com/es/assets/images/02_frame_stacking-0ce024bbbafb08d7449c40abec7b6dc2.png" width="2149" height="1599" class="img_ev3q"></p>
<p>Promediar parches alineados a lo largo del tiempo cancela el ruido del sensor y mejora la nitidez de los caracteres.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-próxima-entrega">3. Próxima Entrega<a href="https://globaldevlog.com/es/blog/2026-06-28-vision-anpr-4#3-pr%C3%B3xima-entrega" class="hash-link" aria-label="Enlace directo al 3. Próxima Entrega" title="Enlace directo al 3. Próxima Entrega" translate="no">​</a></h2>
<p>En la Entrega #5, concluiremos con la <strong>optimización de EasyOCR, el filtrado regex</strong> y el <strong>motor de votación temporal mayoritaria (evolución v01 a v11)</strong>.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="computer-vision" term="computer-vision"/>
        <category label="super-resolution" term="super-resolution"/>
        <category label="edsr" term="edsr"/>
        <category label="image-stacking" term="image-stacking"/>
        <category label="anpr" term="anpr"/>
        <category label="deep-learning" term="deep-learning"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Vision AI] Detección Jerárquica de Objetos: ROI de Vehículo YOLOv3, Detector de Matrículas YOLOv5 y Seguimiento CSRT (#3)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-06-27-vision-anpr-3</id>
        <link href="https://globaldevlog.com/es/blog/2026-06-27-vision-anpr-3"/>
        <updated>2026-06-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Estrategia jerárquica en dos etapas: detección general de vehículos con YOLOv3, localización precisa con YOLOv5 y seguimiento por filtro de correlación CSRT.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Localización de Matrícula con YOLOv5" src="https://globaldevlog.com/es/assets/images/01_plate_localization-e3a163202d7a73e57bdf504aafdd6919.png" width="957" height="766" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (Puntos Clave)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: Detectar matrículas diminutas (30x15 píxeles) en todo el fotograma de 640x480 provoca falsos positivos con carteles viales y reduce el rendimiento a menos de 10 FPS.</li>
<li class=""><strong>Solución</strong>: Diseñamos una arquitectura en dos etapas (YOLOv3 para vehículos -&gt; YOLOv5 solo en el ROI del vehículo) combinada con el rastreador CSRT cada 15 fotogramas.</li>
<li class=""><strong>Resultado</strong>: Eliminación del 98% de falsos positivos y reducción del 80% en carga de GPU, manteniendo más de 50 FPS.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-detección-jerárquica-en-dos-etapas">1. Detección Jerárquica en Dos Etapas<a href="https://globaldevlog.com/es/blog/2026-06-27-vision-anpr-3#1-detecci%C3%B3n-jer%C3%A1rquica-en-dos-etapas" class="hash-link" aria-label="Enlace directo al 1. Detección Jerárquica en Dos Etapas" title="Enlace directo al 1. Detección Jerárquica en Dos Etapas" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">vehicle_boxes </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> detect_vehicles_yolov3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">frame</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> net</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">vehicle_net</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> conf_thresh</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> box </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> vehicle_boxes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    x1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> y1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> x2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> y2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> box</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    vehicle_roi </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> frame</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">y1</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">y2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> x1</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">x2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    plate_boxes </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> plate_model</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">vehicle_roi</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> pbox </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> plate_boxes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        px1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> py1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> px2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> py2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pbox</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        global_plate_box </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">x1 </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> px1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> y1 </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> py1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> x1 </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> px2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> y1 </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> py2</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-seguimiento-en-tiempo-real-con-csrt">2. Seguimiento en Tiempo Real con CSRT<a href="https://globaldevlog.com/es/blog/2026-06-27-vision-anpr-3#2-seguimiento-en-tiempo-real-con-csrt" class="hash-link" aria-label="Enlace directo al 2. Seguimiento en Tiempo Real con CSRT" title="Enlace directo al 2. Seguimiento en Tiempo Real con CSRT" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Seguimiento Continuo con OpenCV CSRT" src="https://globaldevlog.com/es/assets/images/02_csrt_tracking-bea82f7c3eb5c74b33968501166fbe5a.png" width="2139" height="1599" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-próxima-entrega">3. Próxima Entrega<a href="https://globaldevlog.com/es/blog/2026-06-27-vision-anpr-3#3-pr%C3%B3xima-entrega" class="hash-link" aria-label="Enlace directo al 3. Próxima Entrega" title="Enlace directo al 3. Próxima Entrega" translate="no">​</a></h2>
<p>En la Entrega #4, abordaremos la <strong>superresolución profunda EDSR_x4</strong> y el <strong>apilamiento multifotograma</strong> para recuperar contornos alfanuméricos nítidos.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="computer-vision" term="computer-vision"/>
        <category label="anpr" term="anpr"/>
        <category label="yolo" term="yolo"/>
        <category label="csrt-tracker" term="csrt-tracker"/>
        <category label="object-detection" term="object-detection"/>
        <category label="opencv" term="opencv"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Vision AI] Extracción Dinámica de Carriles y Criterio Geométrico de Invasión Basado en IoU (#2)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-06-26-vision-anpr-2</id>
        <link href="https://globaldevlog.com/es/blog/2026-06-26-vision-anpr-2"/>
        <updated>2026-06-26T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Filtro de bordes Canny, transformada probabilística de Hough, umbrales de pendiente y cálculo geométrico de invasión IoU.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Superposición de Detección Dinámica de Carril" src="https://globaldevlog.com/es/assets/images/01_lane_detection-0ce024bbbafb08d7449c40abec7b6dc2.png" width="2149" height="1599" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (Puntos Clave)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: Los reflejos viales y las grietas causan falsos positivos; las simples comprobaciones por coordenadas puntuales no detectan el momento exacto de invasión de carril.</li>
<li class=""><strong>Solución</strong>: Máscara ROI trapezoidal, filtrado por pendiente (|slope| &gt; 0.5) y cola temporal de media móvil de 7 fotogramas. Criterio de invasión definido como IoU geométrico entre la base del vehículo y el carril.</li>
<li class=""><strong>Resultado</strong>: Eliminación del 95% del ruido de textura vial y detección precisa de invasión con fiabilidad subfotograma.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-detección-dinámica-de-carriles-con-canny-y-hough">1. Detección Dinámica de Carriles con Canny y Hough<a href="https://globaldevlog.com/es/blog/2026-06-26-vision-anpr-2#1-detecci%C3%B3n-din%C3%A1mica-de-carriles-con-canny-y-hough" class="hash-link" aria-label="Enlace directo al 1. Detección Dinámica de Carriles con Canny y Hough" title="Enlace directo al 1. Detección Dinámica de Carriles con Canny y Hough" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">detect_lanes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">frame</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> width </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> frame</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">shape</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    gray </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cvtColor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">frame</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">COLOR_BGR2GRAY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    blur </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">GaussianBlur</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">gray</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    edges </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Canny</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">blur</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">150</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    mask </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> np</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">zeros_like</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">edges</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    roi_polygon </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> np</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">array</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token builtin">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">width </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token builtin">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">width </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.45</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">height </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.6</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token builtin">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">width </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.55</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">height </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.6</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token builtin">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">width </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.9</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> np</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">int32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fillPoly</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mask</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> roi_polygon</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">255</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    masked_edges </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">bitwise_and</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">edges</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mask</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">HoughLinesP</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">masked_edges</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> np</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">pi</span><span class="token operator" style="color:#393A34">/</span><span class="token number" style="color:#36acaa">180</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> minLineLength</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> maxLineGap</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-filtrado-de-pendientes-y-suavizado-temporal">2. Filtrado de Pendientes y Suavizado Temporal<a href="https://globaldevlog.com/es/blog/2026-06-26-vision-anpr-2#2-filtrado-de-pendientes-y-suavizado-temporal" class="hash-link" aria-label="Enlace directo al 2. Filtrado de Pendientes y Suavizado Temporal" title="Enlace directo al 2. Filtrado de Pendientes y Suavizado Temporal" translate="no">​</a></h2>
<p>Cálculo de pendiente <code>m = (y2 - y1) / (x2 - x1)</code>:</p>
<ul>
<li class=""><strong>Carril Izquierdo</strong>: <code>m &lt; -0.5</code></li>
<li class=""><strong>Carril Derecho</strong>: <code>m &gt; 0.5</code></li>
<li class=""><strong>Ruido Horizontal</strong>: <code>|m| &lt;= 0.5</code> se descarta.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-criterio-de-invasión-basado-en-iou">3. Criterio de Invasión Basado en IoU<a href="https://globaldevlog.com/es/blog/2026-06-26-vision-anpr-2#3-criterio-de-invasi%C3%B3n-basado-en-iou" class="hash-link" aria-label="Enlace directo al 3. Criterio de Invasión Basado en IoU" title="Enlace directo al 3. Criterio de Invasión Basado en IoU" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Evaluación de IoU de Invasión de Carril" src="https://globaldevlog.com/es/assets/images/02_intrusion_iou-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Footprint = [x_min, y_min + 0.7*h, x_max, y_max]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">IoU = Area(Footprint ∩ Lane_Polygon) / Area(Footprint)</span><br></div></code></pre></div></div>
<p>Si <code>IoU &gt; 0.05</code>, se dispara el evento de infracción y se inicia la localización de matrícula con YOLOv5.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-próxima-entrega">4. Próxima Entrega<a href="https://globaldevlog.com/es/blog/2026-06-26-vision-anpr-2#4-pr%C3%B3xima-entrega" class="hash-link" aria-label="Enlace directo al 4. Próxima Entrega" title="Enlace directo al 4. Próxima Entrega" translate="no">​</a></h2>
<p>En la Entrega #3, analizaremos la <strong>detección jerárquica con YOLOv5 (<code>lp_det.pt</code>)</strong> y el <strong>seguimiento en tiempo real con CSRT</strong>.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="computer-vision" term="computer-vision"/>
        <category label="anpr" term="anpr"/>
        <category label="lane-detection" term="lane-detection"/>
        <category label="hough-transform" term="hough-transform"/>
        <category label="iou" term="iou"/>
        <category label="opencv" term="opencv"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Vision AI] Detección de Invasión de Carril en Caja Negra y ANPR con Superresolución: Pipeline de 6 Etapas y Desafíos en Tiempo Real (#1)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-06-25-vision-anpr-1</id>
        <link href="https://globaldevlog.com/es/blog/2026-06-25-vision-anpr-1"/>
        <updated>2026-06-25T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Diseño de un pipeline de visión de 6 etapas que combina detección dinámica de carril, métricas de invasión IoU, detección de matrículas YOLOv5, superresolución EDSR y votación OCR.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Diagrama del Pipeline ANPR de 6 Etapas" src="https://globaldevlog.com/es/assets/images/01_pipeline_diagram-fb1b5567c4acb0cd59bd89773f15c5c8.png" width="2200" height="900" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (Puntos Clave)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: Las grabaciones de baja resolución de cámaras de tablero sufren vibraciones, contraluces y desenfoque de movimiento, lo que hace que el reconocimiento de matrículas y el monitoreo de invasión de carril fallen con frecuencia.</li>
<li class=""><strong>Solución</strong>: Diseñamos una arquitectura desacoplada de 6 etapas: extracción de carril Canny/Hough -&gt; detección de vehículos YOLOv3 -&gt; IoU de invasión -&gt; localización de matrícula YOLOv5 -&gt; superresolución EDSR_x4 -&gt; votación temporal EasyOCR.</li>
<li class=""><strong>Resultado</strong>: Construimos un pipeline en Python de alto rendimiento que mantiene más de 30 FPS identificando con precisión matrículas infractoras bajo condiciones ópticas severas.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-contexto-del-proyecto-por-qué-la-visión-en-dashcams-es-difícil">1. Contexto del Proyecto: Por qué la Visión en Dashcams es Difícil<a href="https://globaldevlog.com/es/blog/2026-06-25-vision-anpr-1#1-contexto-del-proyecto-por-qu%C3%A9-la-visi%C3%B3n-en-dashcams-es-dif%C3%ADcil" class="hash-link" aria-label="Enlace directo al 1. Contexto del Proyecto: Por qué la Visión en Dashcams es Difícil" title="Enlace directo al 1. Contexto del Proyecto: Por qué la Visión en Dashcams es Difícil" translate="no">​</a></h2>
<p>En sistemas de transporte inteligente (ITS), la <strong>detección en tiempo real de invasión de carril y el reconocimiento automático de matrículas (ANPR)</strong> son desafíos esenciales. Las grabaciones reales presentan barreras ópticas críticas:</p>
<ol>
<li class=""><strong>Baja Resolución Extrema</strong>: La matrícula del vehículo objetivo a menudo ocupa apenas 30x15 a 50x25 píxeles dentro de un fotograma de 640x480.</li>
<li class=""><strong>Vibración de Calzada y Distorsión de Perspectiva</strong>: Las irregularidades del asfalto deforman las líneas viales rectas.</li>
<li class=""><strong>Cuellos de Botella de Cómputo</strong>: Aplicar modelos masivos en cada fotograma completo colapsa la tasa de FPS.</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-arquitectura-jerárquica-de-6-etapas">2. Arquitectura Jerárquica de 6 Etapas<a href="https://globaldevlog.com/es/blog/2026-06-25-vision-anpr-1#2-arquitectura-jer%C3%A1rquica-de-6-etapas" class="hash-link" aria-label="Enlace directo al 2. Arquitectura Jerárquica de 6 Etapas" title="Enlace directo al 2. Arquitectura Jerárquica de 6 Etapas" translate="no">​</a></h2>
<div class="language-mermaid codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-mermaid codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">flowchart TD</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Raw["Fotograma Dashcam 640x480"] --&gt; L1["Etapa 1: Extracción Dinámica de Carril Canny + Hough"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Raw --&gt; L2["Etapa 2: Detección Rápida de Vehículos YOLOv3-tiny"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L1 &amp; L2 --&gt; L3["Etapa 3: Métrica IoU entre Base del Vehículo y Polígono de Carril"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L3 -- Si Ocurre Invasión --&gt; L4["Etapa 4: Detección Localizada de Matrícula YOLOv5"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L4 --&gt; L5["Etapa 5: Superresolución Profunda 4x con EDSR_x4"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L5 --&gt; L6["Etapa 6: EasyOCR + Regex + Votación Temporal por Mayoría"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L6 --&gt; Result["Matrícula Final Confirmada: 64가1511"]</span><br></div></code></pre></div></div>
<p><img decoding="async" loading="lazy" alt="Salida de Detección y Reconocimiento ANPR" src="https://globaldevlog.com/es/assets/images/02_final_result-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-parámetros-principales-del-sistema-config">3. Parámetros Principales del Sistema (<code>CONFIG</code>)<a href="https://globaldevlog.com/es/blog/2026-06-25-vision-anpr-1#3-par%C3%A1metros-principales-del-sistema-config" class="hash-link" aria-label="Enlace directo al 3-parámetros-principales-del-sistema-config" title="Enlace directo al 3-parámetros-principales-del-sistema-config" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">CONFIG </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"output_width"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">640</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"output_height"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">480</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"conf_threshold_vehicle"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"nms_threshold_vehicle"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"min_vehicle_w"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">70</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"min_vehicle_h"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">70</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"lane_iou_threshold"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.05</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"detection_interval"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"min_plate_area_for_ocr"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1200</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"plate_history_size"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">7</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"plate_confirm_threshold"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"sr_model"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"EDSR_x4.pb"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"yolo_plate_model"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"lp_det.pt"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-próxima-entrega">4. Próxima Entrega<a href="https://globaldevlog.com/es/blog/2026-06-25-vision-anpr-1#4-pr%C3%B3xima-entrega" class="hash-link" aria-label="Enlace directo al 4. Próxima Entrega" title="Enlace directo al 4. Próxima Entrega" translate="no">​</a></h2>
<p>En la Entrega #2, exploraremos a fondo las matemáticas de la <strong>transformada probabilística de Hough, el filtrado de pendientes</strong> y el <strong>criterio geométrico de invasión basado en IoU</strong>.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="computer-vision" term="computer-vision"/>
        <category label="anpr" term="anpr"/>
        <category label="object-detection" term="object-detection"/>
        <category label="super-resolution" term="super-resolution"/>
        <category label="opencv" term="opencv"/>
        <category label="deep-learning" term="deep-learning"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #23] Safety Wrapper y Presentación Final del Semestre]]></title>
        <id>https://globaldevlog.com/es/blog/2026-06-18-maeumjigi-23</id>
        <link href="https://globaldevlog.com/es/blog/2026-06-18-maeumjigi-23"/>
        <updated>2026-06-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Hito final: Construcción de la arquitectura de salvaguardas Safety Wrapper y despliegue del modelo en producción sobre GPUs de AWS EC2.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-5db6b43f8eb8d83178d8ba6f56f13f4f.png" width="720" height="405" class="img_ev3q"></p>
<p>Al entrar en junio, el equipo completó los desarrollos principales del primer semestre y se enfocó en construir <strong>redes de seguridad</strong> y preparar la <strong>presentación final</strong>.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="el-modelo-21-y-el-safety-wrapper">El Modelo 2:1 y el Safety Wrapper<a href="https://globaldevlog.com/es/blog/2026-06-18-maeumjigi-23#el-modelo-21-y-el-safety-wrapper" class="hash-link" aria-label="Enlace directo al El Modelo 2:1 y el Safety Wrapper" title="Enlace directo al El Modelo 2:1 y el Safety Wrapper" translate="no">​</a></h3>
<blockquote>
<p>"Decidimos la proporción 2:1. Ahora diseña un safety_wrapper como bloqueo de seguridad."</p>
</blockquote>
<p>Seleccionamos el modelo mezclado con una proporción de 2:1 de chat 'emocional' a 'cotidiano'. Sin embargo, para prevenir cualquier alucinación en nuestro chatbot de prevención del suicidio, introdujimos un <strong>Safety Wrapper</strong>. Este módulo verifica las entradas y salidas, cambiando instantáneamente a un protocolo de crisis si se detecta alto riesgo.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="presupuesto-de-servidor-ec2-y-presentación-final">Presupuesto de Servidor (EC2) y Presentación Final<a href="https://globaldevlog.com/es/blog/2026-06-18-maeumjigi-23#presupuesto-de-servidor-ec2-y-presentaci%C3%B3n-final" class="hash-link" aria-label="Enlace directo al Presupuesto de Servidor (EC2) y Presentación Final" title="Enlace directo al Presupuesto de Servidor (EC2) y Presentación Final" translate="no">​</a></h3>
<blockquote>
<p>"¿Cuál es el presupuesto para 5 meses de AWS EC2 g5.2xlarge?"</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Presentación Final" src="https://globaldevlog.com/es/assets/images/02_presentation-4d633f8f7c1e0375cfa80546d37e3291.png" width="720" height="405" class="img_ev3q"></p>
<p>Calculamos el presupuesto del servidor AWS EC2 para ejecutar el chatbot. El 18 de junio, reunimos todos los logros del backend, frontend e IA para completar la <strong>Presentación Final del 1er Semestre (PPTX)</strong>.</p>
<p>¡El primer semestre ha concluido con éxito! Regresaremos con un servicio más avanzado en el segundo semestre.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="safety wrapper" term="safety wrapper"/>
        <category label="cloud" term="cloud"/>
        <category label="capstone" term="capstone"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #22] ¡4to Fine-Tuning Completo! Arquitectura e Informe Final]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-30-maeumjigi-22</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-30-maeumjigi-22"/>
        <updated>2026-05-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[4ª ronda de fine-tuning: aplicación de enmascaramiento de prompts y regularización para evitar respuestas robóticas y sobreajuste.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-5fcc23c7f36696eb5311e706c9d9eede.png" width="2495" height="1393" class="img_ev3q"></p>
<p>En la última semana de mayo, nos dedicamos a concluir los resultados del tan esperado <strong>4to Fine-Tuning (fine_tuning_4)</strong> y solidificar la estructura del sistema.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="checkpoint-final-4400-y-análisis">Checkpoint Final 4400 y Análisis<a href="https://globaldevlog.com/es/blog/2026-05-30-maeumjigi-22#checkpoint-final-4400-y-an%C3%A1lisis" class="hash-link" aria-label="Enlace directo al Checkpoint Final 4400 y Análisis" title="Enlace directo al Checkpoint Final 4400 y Análisis" translate="no">​</a></h3>
<blockquote>
<p>"Qwen35-9B_mixed_7_3/checkpoints/checkpoint-4400/adapter_config.json"</p>
</blockquote>
<p>El cuarto modelo, entrenado con una mezcla de chat casual y datos de consejería emocional, finalmente terminó el entrenamiento y produjo el peso óptimo: <code>checkpoint-4400</code>.</p>
<p>Al experimentar con la proporción de mezcla de datos, el modelo finalmente renació como un chatbot perceptivo que distingue perfectamente entre conversaciones diarias y consejería de crisis seria.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="arquitectura-del-sistema-e-informe-final">Arquitectura del Sistema e Informe Final<a href="https://globaldevlog.com/es/blog/2026-05-30-maeumjigi-22#arquitectura-del-sistema-e-informe-final" class="hash-link" aria-label="Enlace directo al Arquitectura del Sistema e Informe Final" title="Enlace directo al Arquitectura del Sistema e Informe Final" translate="no">​</a></h3>
<blockquote>
<p>"Generación de chatbot_architecture.html completa"</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Arquitectura del Sistema" src="https://globaldevlog.com/es/assets/images/02_architecture-41f5095033492354eaf45a8553f49ff6.png" width="2541" height="1390" class="img_ev3q"></p>
<p>Para servir el modelo verificado como una aplicación real, diseñamos la arquitectura de todo el sistema y el plan de integración de Gráficos de Conocimiento (Knowledge Graph) bajo el nombre <code>chatbot_architecture.html</code>.</p>
<p>Y el 30 de mayo generamos automáticamente el <code>informe_fine_tuning_4.docx</code>. El informe contiene comparaciones de respuestas reales entre el modelo original y el nuestro, ¡demostrando que nuestro arduo trabajo no fue en vano!</p>
<p>Con esto concluyen los registros de desarrollo de mayo.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="architecture" term="architecture"/>
        <category label="capstone" term="capstone"/>
        <category label="final report" term="final report"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #21] Optimizando Proporciones de Datos y el 4to Fine-Tuning]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-22-maeumjigi-21</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-22-maeumjigi-21"/>
        <updated>2026-05-22T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Alcance del rendimiento óptimo mediante la proporción 2:1 entre diálogo emocional y cotidiano, logrando empatía y coherencia.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-a335ed829194fe04a7f1886ca95deda9.png" width="2531" height="1378" class="img_ev3q"></p>
<p>El 21 y 22 de mayo, el equipo de Maeumjigi se embarcó en la generación masiva de datos y la preparación para el <strong>Cuarto Fine-Tuning (fine_tuning_4)</strong>.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="conversaciones-emocionales-vs-cotidianas">Conversaciones Emocionales vs. Cotidianas<a href="https://globaldevlog.com/es/blog/2026-05-22-maeumjigi-21#conversaciones-emocionales-vs-cotidianas" class="hash-link" aria-label="Enlace directo al Conversaciones Emocionales vs. Cotidianas" title="Enlace directo al Conversaciones Emocionales vs. Cotidianas" translate="no">​</a></h3>
<p>Mientras probaba el modelo del tercer fine-tuning, descubrí un problema crítico.</p>
<blockquote>
<p>"Las respuestas están demasiado inclinadas hacia la consejería emocional. ¿Cómo mantenemos las habilidades de conversación cotidiana del modelo?"</p>
</blockquote>
<p>Nuestro modelo mostraba signos de sobreajuste, dando respuestas excesivamente serias a preguntas mundanas. Para resolver esto, planeamos mezclar datos emocionales y cotidianos.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="generando-10000-datos-emocionales-v6">Generando 10,000 Datos Emocionales (v6)<a href="https://globaldevlog.com/es/blog/2026-05-22-maeumjigi-21#generando-10000-datos-emocionales-v6" class="hash-link" aria-label="Enlace directo al Generando 10,000 Datos Emocionales (v6)" title="Enlace directo al Generando 10,000 Datos Emocionales (v6)" translate="no">​</a></h3>
<p>Utilicé el modo Batch de la Interfaz de Programación de Aplicaciones (API) de Anthropic (Haiku) para generar 10,000 entradas de datos de conversaciones emocionales. Completé las entradas faltantes con un script adicional para asegurar la calidad.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="buscando-la-proporción-dorada">Buscando la Proporción Dorada<a href="https://globaldevlog.com/es/blog/2026-05-22-maeumjigi-21#buscando-la-proporci%C3%B3n-dorada" class="hash-link" aria-label="Enlace directo al Buscando la Proporción Dorada" title="Enlace directo al Buscando la Proporción Dorada" translate="no">​</a></h3>
<blockquote>
<p>"Genera un dataset de 7:3, otro de 2:1 y otro de 5:5."
"Este cuarto fine-tuning se basará en la proporción de mezcla (mixed_2_1, mixed_5_5, mixed_7_3)."</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Experimento de Proporción" src="https://globaldevlog.com/es/assets/images/02_ratio-aa49284ad0e0859f6efd82a31aa871ce.png" width="2507" height="1395" class="img_ev3q"></p>
<p>El 4to fine-tuning ahora verifica qué proporción armoniza la 'casualidad diaria' con la 'consejería profesional'. ¡Comenzamos a inyectar estos 3 datasets en el modelo Qwen3.5-9B!</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="dataset" term="dataset"/>
        <category label="prompt" term="prompt"/>
        <category label="capstone" term="capstone"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Robótica Webots] Sim-to-Real: Transferencia a hardware con Arduino Uno, HC-06 Bluetooth y rastreo visual ArUco (#5)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5"/>
        <updated>2026-05-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Despliegue de la política Q-Learning de 648 estados discretos en un robot físico de 2 ruedas con Arduino Uno, calibración por homografía de cámara cenital y rastreo de marcadores ArUco.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Rastreo visual con marcadores ArUco" src="https://globaldevlog.com/es/assets/images/01_aruco_vision-b5bd404f0b35979c465be925a4fac943.png" width="1280" height="720" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Puntos Clave (TL;DR)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: Severas restricciones computacionales en microcontroladores (Arduino Uno ATmega328P con solo 2KB de SRAM), deslizamiento de ruedas, ruido ultrasónico y la brecha de la realidad (<strong>Reality Gap</strong>) entre la física de Webots y el hardware real.</li>
<li class=""><strong>Solución</strong>: Arquitectura de <strong>E/S distribuida (HC-06 Bluetooth a 115,200 baudios)</strong> donde una PC procesa la visión OpenCV y la inferencia de Q-Table mientras Arduino controla los motores mediante PWM. Corrección de distorsión de lente y <strong>homografía con marcadores ArUco (<code>vision.py</code>)</strong> para seguimiento de pose (x, y, θ) en tiempo real.</li>
<li class=""><strong>Resultado</strong>: Transferencia directa (zero-shot) de la Q-Table de 648 estados que alcanzó un <strong>86.7% de tasa de éxito (26/30 pruebas)</strong> en una arena física de 1.2m × 1.2m, superando la brecha de realidad sin reentrenamiento in situ.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-el-desafío-sim-to-real-superando-la-brecha-de-la-realidad">1. El desafío Sim-to-Real: Superando la brecha de la realidad<a href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5#1-el-desaf%C3%ADo-sim-to-real-superando-la-brecha-de-la-realidad" class="hash-link" aria-label="Enlace directo al 1. El desafío Sim-to-Real: Superando la brecha de la realidad" title="Enlace directo al 1. El desafío Sim-to-Real: Superando la brecha de la realidad" translate="no">​</a></h2>
<p>En el simulador Webots, la fricción superficial es uniforme, los motores de las ruedas responden exactamente a la velocidad indicada y los sensores de proximidad no tienen reflexiones parásitas. Sin embargo, el hardware físico presenta serios desafíos:</p>
<ol>
<li class=""><strong>Limitaciones extremas de memoria y cómputo</strong>: El <strong>Arduino Uno (ATmega328P)</strong> dispone de solo 32KB de memoria flash y 2KB de SRAM, imposibilitando redes neuronales o cálculos matriciales complejos en el chip.</li>
<li class=""><strong>Ruido sensorial y ángulos ciegos</strong>: Los sensores ultrasónicos económicos sufren de rebotes especulares cuando inciden en ángulos oblicuos contra paredes de acrílico, arrojando valores de 0 o lecturas falsas al máximo alcance.</li>
<li class=""><strong>Deslizamiento de ruedas y deriva odométrica</strong>: Variaciones mínimas de fricción y caída de voltaje de la batería causan diferencias de RPM en los motores, desviando al robot incluso al recibir comandos de línea recta.</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-arquitectura-de-control-distribuido-pc-anfitrión-cerebro--arduino-músculo">2. Arquitectura de control distribuido: PC anfitrión (Cerebro) ↔ Arduino (Músculo)<a href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5#2-arquitectura-de-control-distribuido-pc-anfitri%C3%B3n-cerebro--arduino-m%C3%BAsculo" class="hash-link" aria-label="Enlace directo al 2. Arquitectura de control distribuido: PC anfitrión (Cerebro) ↔ Arduino (Músculo)" title="Enlace directo al 2. Arquitectura de control distribuido: PC anfitrión (Cerebro) ↔ Arduino (Músculo)" translate="no">​</a></h2>
<p>Para solventar estas limitaciones, separamos la toma de decisiones del control de bajo nivel: <strong>"La PC es el cerebro, Arduino es el músculo."</strong></p>
<div class="language-mermaid codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-mermaid codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">flowchart TD</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    subgraph CeilingCam["Sistema de visión cenital (Cámara superior)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Cam["Cámara Web FHD (30 FPS)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Aruco["Detección ArUco (DICT_4X4_50)&lt;br&gt;Homografía de perspectiva (homography.npy)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Cam --&gt; Aruco</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    subgraph PC["PC Anfitrión (Motor Python)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Pose["Estimación de pose del robot (x, y, θ)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Disc["Discretizador de 648 estados"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        QL["Q-Table entrenada (ε=0)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        BT_Host["HC-06 Bluetooth SPP (115200 baudios)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Aruco --&gt; Pose --&gt; Disc --&gt; QL --&gt; BT_Host</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    subgraph Robot["Robot móvil físico (Hardware real)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        BT_Slave["Receptor Bluetooth HC-06"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        MCU["Arduino Uno (Firmware)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Motors["Controlador L298N + Motores DC con reducción"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        BT_Host &lt;--&gt;|"Action Byte [0..3]&lt;br&gt;Ack/Status"| BT_Slave --&gt; MCU --&gt; Motors</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Canalización en la PC</strong>: La cámara cenital observa toda la arena, rastreando a 30 FPS el marcador ArUco ubicado sobre el robot. Se calcula la pose planar <code>(x, y, θ)</code> y se discretiza en 648 estados para extraer la acción codiciosa óptima de la Q-Table.</li>
<li class=""><strong>Comunicación serial HC-06</strong>: Para minimizar la latencia de ida y vuelta (RTT) sobre el perfil SPP de Bluetooth, se aumentó la velocidad de transmisión de 9,600 a <strong>115,200 baudios</strong>, logrando un ciclo de control de 30~50Hz.</li>
<li class=""><strong>Firmware de Arduino (<code>arduino_firmware.ino</code>)</strong>: Al recibir un byte de acción (<code>0: Avanzar</code>, <code>1: Retroceder</code>, <code>2: Giro izquierda</code>, <code>3: Giro derecha</code>), el microcontrolador aplica señales PWM a los pines del puente H L298N por ticks calibrados.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-homografía-de-cámara-cenital-y-rastreo-visual-aruco">3. Homografía de cámara cenital y rastreo visual ArUco<a href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5#3-homograf%C3%ADa-de-c%C3%A1mara-cenital-y-rastreo-visual-aruco" class="hash-link" aria-label="Enlace directo al 3. Homografía de cámara cenital y rastreo visual ArUco" title="Enlace directo al 3. Homografía de cámara cenital y rastreo visual ArUco" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Configuración de hardware y calibración de la arena" src="https://globaldevlog.com/es/assets/images/02_hardware_setup-fddea6cef90bd71036b2aff5eef38f33.png" width="1707" height="1067" class="img_ev3q"></p>
<p>Para medir con precisión milimétrica la posición del robot y la distancia a los obstáculos en la arena real, implementamos una <strong>canalización de visión por computadora con OpenCV</strong>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-calibración-de-perspectiva-y-homografía-calib_autopy">📐 Calibración de perspectiva y homografía (<code>calib_auto.py</code>)<a href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5#-calibraci%C3%B3n-de-perspectiva-y-homograf%C3%ADa-calib_autopy" class="hash-link" aria-label="Enlace directo al -calibración-de-perspectiva-y-homografía-calib_autopy" title="Enlace directo al -calibración-de-perspectiva-y-homografía-calib_autopy" translate="no">​</a></h3>
<ol>
<li class=""><strong>Corrección de distorsión con tablero de ajedrez</strong>: Para eliminar la distorsión de barril de la lente gran angular, se calibraron la matriz intrínseca (K) y los coeficientes de distorsión (D) con un patrón de 9×6.</li>
<li class=""><strong>Transformación homográfica (Perspective Transform)</strong>: Para proyectar la vista inclinada de la cámara en una vista superior plana canónica de 1.2m × 1.2m, se generó la matriz de transformación 3×3 (<code>homography.npy</code>) basada en las 4 esquinas de la arena.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-implementación-del-rastreo-aruco-visionpy">💻 Implementación del rastreo ArUco (<code>vision.py</code>)<a href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5#-implementaci%C3%B3n-del-rastreo-aruco-visionpy" class="hash-link" aria-label="Enlace directo al -implementación-del-rastreo-aruco-visionpy" title="Enlace directo al -implementación-del-rastreo-aruco-visionpy" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> cv2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> numpy </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> np</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Inicializar diccionario ArUco y parámetros de detección</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">aruco_dict </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">aruco</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">getPredefinedDictionary</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">aruco</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DICT_4X4_50</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">parameters </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">aruco</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">DetectorParameters</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">detector </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">aruco</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ArucoDetector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">aruco_dict</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> parameters</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">get_robot_pose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">frame</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> homography_matrix</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:#e3116c">"""Calcula las coordenadas (x, y) y el ángulo de orientación (theta) desde la imagen rectificada."""</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    warped </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cv2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">warpPerspective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">frame</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> homography_matrix</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">600</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">600</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    corners</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ids</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> _ </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> detector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">detectMarkers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">warped</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> ids </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">not</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">and</span><span class="token plain"> </span><span class="token builtin">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ids</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        c </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> corners</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        center_x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token builtin">float</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">np</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">mean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">c</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        center_y </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token builtin">float</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">np</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">mean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">c</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic"># Calcular ángulo de rumbo (theta) a partir del vector frontal del marcador</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        front_x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">c</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        front_y </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">c</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2.0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        theta </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> np</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">arctan2</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">front_y </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> center_y</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> front_x </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> center_x</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> center_x</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> center_y</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> theta</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-resolución-de-problemas-en-hardware-y-resultados-de-despliegue">4. Resolución de problemas en hardware y resultados de despliegue<a href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5#4-resoluci%C3%B3n-de-problemas-en-hardware-y-resultados-de-despliegue" class="hash-link" aria-label="Enlace directo al 4. Resolución de problemas en hardware y resultados de despliegue" title="Enlace directo al 4. Resolución de problemas en hardware y resultados de despliegue" translate="no">​</a></h2>
<p>Durante la transición de la simulación al hardware real surgieron desafíos imprevistos que se resolvieron mediante ingeniería:</p>
<table><thead><tr><th style="text-align:left">Síntoma (Troubleshooting)</th><th style="text-align:left">Causa raíz</th><th style="text-align:left">Solución de ingeniería (Solution)</th></tr></thead><tbody><tr><td style="text-align:left"><strong>Desvío lateral al avanzar recto</strong></td><td style="text-align:left">Diferencias de fricción y tolerancia mecánica en motores DC</td><td style="text-align:left">Script de calibración (<code>ble_vision_turn_calib.py</code>) para compensar dinámicamente el PWM de cada rueda</td></tr><tr><td style="text-align:left"><strong>Comportamiento descontrolado al perder Bluetooth</strong></td><td style="text-align:left">Pérdida de paquetes por interferencia que mantenía el último comando</td><td style="text-align:left">Perro guardián (Watchdog) de 200ms en el firmware para detener motores si no hay señal</td></tr><tr><td style="text-align:left"><strong>Pérdida intermitente de detección de marcador</strong></td><td style="text-align:left">Destellos de luces fluorescentes en la superficie reflectante del acrílico</td><td style="text-align:left">Ajuste de umbral adaptativo (Adaptive Threshold) y filtro de Kalman para interpolar posiciones</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-rendimiento-final-en-hardware-real">🏆 Rendimiento final en hardware real<a href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5#-rendimiento-final-en-hardware-real" class="hash-link" aria-label="Enlace directo al 🏆 Rendimiento final en hardware real" title="Enlace directo al 🏆 Rendimiento final en hardware real" translate="no">​</a></h3>
<ul>
<li class=""><strong>Tasa de llegada al objetivo</strong>: Tras 30 pruebas completas en la arena con obstáculos de 1.2m × 1.2m, el robot alcanzó un <strong>86.7% de éxito (26/30 llegadas satisfactorias)</strong>.</li>
<li class="">Utilizando únicamente <strong>2,592 parámetros de la Q-Table (~2.5 KB)</strong> entrenada en simulación, el robot sorteó los obstáculos físicos sin requerir entrenamiento adicional en el mundo real.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-conclusión-de-la-serie-rl-q-learning">5. Conclusión de la serie RL Q-Learning<a href="https://globaldevlog.com/es/blog/2026-05-21-rl-qlearning-5#5-conclusi%C3%B3n-de-la-serie-rl-q-learning" class="hash-link" aria-label="Enlace directo al 5. Conclusión de la serie RL Q-Learning" title="Enlace directo al 5. Conclusión de la serie RL Q-Learning" translate="no">​</a></h2>
<p>Con este hito de transferencia a hardware real concluye la serie de 5 artículos sobre el <strong>proyecto RL Q-Learning</strong>:</p>
<ol>
<li class=""><strong>#1</strong>: Discretización del espacio de estados (648 bins) y arquitectura IPC con sockets TCP</li>
<li class=""><strong>#2</strong>: Tabular Q-Learning con decaimiento ε y diseño de recompensas multidimensionales</li>
<li class=""><strong>#3</strong>: Superación de mínimos locales en arenas de 12 paredes y aceleración en modo Headless</li>
<li class=""><strong>#4</strong>: Evaluación cuantitativa determinista con <code>evaluate_qlearning</code> vs. SARSA y DQN</li>
<li class=""><strong>#5</strong>: Sim-to-Real: Despliegue en Arduino Uno, Bluetooth HC-06 y visión ArUco</li>
</ol>
<p>Desde el modelado en simulación y la fundamentación algorítmica, hasta la automatización headless y la transferencia a sistemas embebidos reales, esta serie documentó todo el ciclo de vida del aprendizaje por refuerzo aplicado a la robótica. ¡Nos vemos en los próximos proyectos de desarrollo!</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="aprendizaje-por-refuerzo" term="aprendizaje-por-refuerzo"/>
        <category label="sim-to-real" term="sim-to-real"/>
        <category label="arduino" term="arduino"/>
        <category label="robotica" term="robotica"/>
        <category label="vision-por-computadora" term="vision-por-computadora"/>
        <category label="aruco" term="aruco"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #20] 3er Fine-Tuning y Mejoras del Backend]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-20-maeumjigi-20</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-20-maeumjigi-20"/>
        <updated>2026-05-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Estrategia para el 3º fine-tuning: calibración de la proporción entre charla casual y diálogo de crisis para evitar respuestas exageradas.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-ac5e0126cfa930b87e044dbc1b82cc03.png" width="2519" height="1373" class="img_ev3q"></p>
<p>Durante el 19 y 20 de mayo, la evaluación del tercer fine-tuning (<code>fine_tuning_3</code>) y la mejora de las características de backend y frontend procedieron en paralelo.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="concluyendo-el-3er-fine-tuning">Concluyendo el 3er Fine-Tuning<a href="https://globaldevlog.com/es/blog/2026-05-20-maeumjigi-20#concluyendo-el-3er-fine-tuning" class="hash-link" aria-label="Enlace directo al Concluyendo el 3er Fine-Tuning" title="Enlace directo al Concluyendo el 3er Fine-Tuning" translate="no">​</a></h3>
<p>El entrenamiento para el 3er fine-tuning, configurado con conceptos de gráficos de conocimiento en mente, se completó.</p>
<blockquote>
<p>"Selecciona el checkpoint con el mejor eval, reemplaza los archivos en la carpeta adapter."</p>
</blockquote>
<p>En lugar de copiar checkpoints manualmente, le indiqué a la IA que escribiera un script que extrajera automáticamente los mejores pesos del modelo y los configurara. Luego, ejecuté el script de inferencia paralela en el servidor.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="backend-y-frontend-base-de-datos-y-foro">Backend y Frontend: Base de Datos y Foro<a href="https://globaldevlog.com/es/blog/2026-05-20-maeumjigi-20#backend-y-frontend-base-de-datos-y-foro" class="hash-link" aria-label="Enlace directo al Backend y Frontend: Base de Datos y Foro" title="Enlace directo al Backend y Frontend: Base de Datos y Foro" translate="no">​</a></h3>
<p>Mientras los modelos trabajaban en el servidor, aceleré el trabajo de integración de la aplicación y la BD.</p>
<p>Para resolver el frustrante error <code>401 Unauthorized</code> de la última vez, examiné <code>seed_data.sql</code> para verificar las contraseñas. Como resultado, logré un importante commit en Git:
<code>feat: Añadido guardado de chatbot en BD, paginación de foro y filtro de diario de emociones</code></p>
<p><img decoding="async" loading="lazy" alt="Características de la App" src="https://globaldevlog.com/es/assets/images/02_app_feature-26d976bed8544fa566bd187f86d90617.png" width="2522" height="1384" class="img_ev3q"></p>
<p>¡Finalmente, los registros de conversación de nuestro chatbot comenzaron a guardarse oficialmente en la base de datos! Además, se añadieron la paginación para el foro comunitario y el filtro del diario de emociones.</p>
<p>Fue un momento emocionante cuando el modelo finalmente comenzó a servirse en una aplicación móvil.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="backend" term="backend"/>
        <category label="frontend" term="frontend"/>
        <category label="database" term="database"/>
        <category label="capstone" term="capstone"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Robótica Webots] Evaluación Determinista con evaluate_qlearning y Comparativa frente a DQN y SARSA (#4)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-20-rl-qlearning-4</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-20-rl-qlearning-4"/>
        <updated>2026-05-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Canalización de evaluación determinista sin exploración (ε=0) con evaluate_qlearning.py, analizando eficiencia de ruta, situaciones de riesgo (near-miss) y comparativas frente a DQN y SARSA.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Comparativa de Éxito y Pasos" src="https://globaldevlog.com/es/assets/images/01_eval_success_steps-1434c5fba2793b6877d335bf289ef59b.png" width="1170" height="650" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Puntos Clave (TL;DR)</strong></p>
<ul>
<li class=""><strong>Objetivo</strong>: Medir el desempeño puro y determinista de la política voraz aprendida (ε=0) sin ruido exploratorio, validando su viabilidad de despliegue.</li>
<li class=""><strong>Metodología</strong>: Implementación de <code>evaluate_qlearning.py</code> con 30 pruebas independientes distribuidas en 5 semillas de evaluación, monitoreando tasa de éxito, eficiencia de ruta frente a la distancia mínima teórica y conteo de aproximaciones críticas (near-miss).</li>
<li class=""><strong>Resultado</strong>: Q-Learning tabular alcanzó un 93.3% de éxito determinista en el cuadrilátero con 12 paredes con una latencia de inferencia ultrabaja de 0.02 ms, superando a modelos más pesados como DQN y SARSA.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-canalización-de-evaluación-cuantitativa-evaluate_qlearningpy">1. Canalización de Evaluación Cuantitativa (<code>evaluate_qlearning.py</code>)<a href="https://globaldevlog.com/es/blog/2026-05-20-rl-qlearning-4#1-canalizaci%C3%B3n-de-evaluaci%C3%B3n-cuantitativa-evaluate_qlearningpy" class="hash-link" aria-label="Enlace directo al 1-canalización-de-evaluación-cuantitativa-evaluate_qlearningpy" title="Enlace directo al 1-canalización-de-evaluación-cuantitativa-evaluate_qlearningpy" translate="no">​</a></h2>
<p>Para medir la capacidad real de navegación del robot cargamos la tabla Q entrenada (<code>qlearning_qtable.npy</code>) y evaluamos con $\epsilon = 0$ a través de 5 semillas de prueba.</p>
<div class="language-mermaid codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-mermaid codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">flowchart LR</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Model["Tabla Q Entrenada&lt;br&gt;(qlearning_qtable.npy)"] --&gt; Agent["Agente Voraz&lt;br&gt;(ε = 0 Fijo)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    EvalSeeds["5 Semillas de Prueba&lt;br&gt;(EVAL_SEEDS 0..4)"] --&gt; Webots["Simulador Webots&lt;br&gt;(30 Pruebas)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Agent &lt;--&gt; Webots</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Webots --&gt; CSV["Registro de Datos&lt;br&gt;(eval_log.csv / traces)"]</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-comparativa-de-algoritmos-q-learning-vs-sarsa-vs-dqn">2. Comparativa de Algoritmos: Q-Learning vs. SARSA vs. DQN<a href="https://globaldevlog.com/es/blog/2026-05-20-rl-qlearning-4#2-comparativa-de-algoritmos-q-learning-vs-sarsa-vs-dqn" class="hash-link" aria-label="Enlace directo al 2. Comparativa de Algoritmos: Q-Learning vs. SARSA vs. DQN" title="Enlace directo al 2. Comparativa de Algoritmos: Q-Learning vs. SARSA vs. DQN" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Calidad de Trayectoria" src="https://globaldevlog.com/es/assets/images/02_eval_quality-42dd1fc5e31c5e63d48c26ece24e8936.png" width="1625" height="585" class="img_ev3q"></p>
<p>Evaluación en el mismo escenario de 12 paredes en Webots:</p>
<table><thead><tr><th style="text-align:left">Métrica</th><th style="text-align:center">Q-Learning Tabular (Propuesto)</th><th style="text-align:center">SARSA (On-policy)</th><th style="text-align:center">Deep Q-Network (DQN)</th></tr></thead><tbody><tr><td style="text-align:left"><strong>Paradigma</strong></td><td style="text-align:center">Off-policy TD(0)</td><td style="text-align:center">On-policy TD(0)</td><td style="text-align:center">Red Neuronal Profunda</td></tr><tr><td style="text-align:left"><strong>Tamaño de Modelo</strong></td><td style="text-align:center"><strong>~2.5 KB (2,592 valores)</strong></td><td style="text-align:center">~2.5 KB</td><td style="text-align:center">~600 KB (~150k pesos)</td></tr><tr><td style="text-align:left"><strong>Tasa de Éxito (<code>obstacle12</code>)</strong></td><td style="text-align:center"><strong>93.3%</strong></td><td style="text-align:center">86.7%</td><td style="text-align:center">90.0%</td></tr><tr><td style="text-align:left"><strong>Pasos Promedio por Episodio</strong></td><td style="text-align:center"><strong>41.2 pasos</strong></td><td style="text-align:center">48.5 pasos</td><td style="text-align:center">44.7 pasos</td></tr><tr><td style="text-align:left"><strong>Latencia por Inferencia</strong></td><td style="text-align:center"><strong>0.02 ms</strong> (consulta en array)</td><td style="text-align:center">0.02 ms</td><td style="text-align:center">2.15 ms (PyTorch)</td></tr><tr><td style="text-align:left"><strong>Aproximación Crítica a Paredes</strong></td><td style="text-align:center">Moderada (desvío balanceado)</td><td style="text-align:center">Mínima (excesivamente conservador)</td><td style="text-align:center">Media</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-próximos-pasos">3. Próximos Pasos<a href="https://globaldevlog.com/es/blog/2026-05-20-rl-qlearning-4#3-pr%C3%B3ximos-pasos" class="hash-link" aria-label="Enlace directo al 3. Próximos Pasos" title="Enlace directo al 3. Próximos Pasos" translate="no">​</a></h2>
<p>En el episodio final #5, presentaremos la transferencia a hardware real (<strong>Sim-to-Real</strong>): <strong>integración en un robot Arduino Uno de 2 ruedas, comunicación Bluetooth HC-06, calibración de distorsión con tablero de ajedrez y seguimiento visual con marcadores ArUco</strong>.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="aprendizaje-por-refuerzo" term="aprendizaje-por-refuerzo"/>
        <category label="q-learning" term="q-learning"/>
        <category label="evaluacion" term="evaluacion"/>
        <category label="benchmark" term="benchmark"/>
        <category label="dqn" term="dqn"/>
        <category label="sarsa" term="sarsa"/>
        <category label="robotica" term="robotica"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Robótica Webots] Superando Mínimos Locales en 12 Obstáculos: Simulación Headless Multi-Semilla (#3)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-19-rl-qlearning-3</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-19-rl-qlearning-3"/>
        <updated>2026-05-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Resolviendo el dilema de los mínimos locales en entornos complejos de 12 paredes (obstacle12) y automatizando simulaciones de alta velocidad en modo Headless con múltiples semillas.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Entorno de Simulación obstacle12" src="https://globaldevlog.com/es/assets/images/01_obstacle12_arena-bc2bc496b7ff2cdfe32dd9630f39bd68.png" width="1438" height="966" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Puntos Clave (TL;DR)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: Cuando el objetivo está detrás de un obstáculo, la búsqueda codiciosa de recompensas por delta de distancia (+0.1 × Δdist) empuja al robot a colisionar frontalmente, atrapándolo en un <strong>mínimo local (Local Minima)</strong>.</li>
<li class=""><strong>Solución</strong>: Integración de percepción ultrasónica en 3 direcciones con barrido (frontal/izq/der) y propagación de valor a largo plazo (γ=0.99), junto con una canalización automatizada en PowerShell (<strong><code>headless_run.ps1</code></strong>) para entrenar en modo Headless con 3 semillas (0, 1, 2).</li>
<li class=""><strong>Resultado</strong>: El robot aprendió políticas de desvío efectivas en el cuadrilátero con 12 paredes, superando el 90% de tasa de éxito tras 600 episodios.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-el-desafío-de-los-obstáculos-la-trampa-de-los-mínimos-locales">1. El Desafío de los Obstáculos: La Trampa de los Mínimos Locales<a href="https://globaldevlog.com/es/blog/2026-05-19-rl-qlearning-3#1-el-desaf%C3%ADo-de-los-obst%C3%A1culos-la-trampa-de-los-m%C3%ADnimos-locales" class="hash-link" aria-label="Enlace directo al 1. El Desafío de los Obstáculos: La Trampa de los Mínimos Locales" title="Enlace directo al 1. El Desafío de los Obstáculos: La Trampa de los Mínimos Locales" translate="no">​</a></h2>
<p>En un cuadrilátero despejado (<code>no_obstacle</code>), navegar consiste simplemente en alinearse hacia el objetivo. Sin embargo, al incorporar <strong>12 paredes interiores (<code>obstacle12</code>)</strong>, surgió un cuello de botella crítico:</p>
<div class="language-mermaid codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-mermaid codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">flowchart TD</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Start["Inicio (Robot)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Wall["Pared Obstáculo"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Goal["Objetivo"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Start --&gt;|"Avance directo (recompensa voraz)"| Wall</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Wall -.-&gt;|"Colisión y bloqueo (Mínimo Local)"| Wall</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Start ==&gt;|"Política de desvío (Detour)&lt;br&gt;Acepta alejarse temporalmente"| Goal</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Dilema</strong>: Si la meta está al otro lado de una pared, avanzar en línea recta resulta en colisión inevitable.</li>
<li class=""><strong>Conflicto de recompensas</strong>: Rodear la pared requiere alejarse momentáneamente del objetivo (delta de distancia negativo), provocando que un agente ingenuo quede atrapado rotando sin fin ante el obstáculo.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-estrategia-de-solución-percepción-head-scan-y-retropropagación-de-valor">2. Estrategia de Solución: Percepción Head-Scan y Retropropagación de Valor<a href="https://globaldevlog.com/es/blog/2026-05-19-rl-qlearning-3#2-estrategia-de-soluci%C3%B3n-percepci%C3%B3n-head-scan-y-retropropagaci%C3%B3n-de-valor" class="hash-link" aria-label="Enlace directo al 2. Estrategia de Solución: Percepción Head-Scan y Retropropagación de Valor" title="Enlace directo al 2. Estrategia de Solución: Percepción Head-Scan y Retropropagación de Valor" translate="no">​</a></h2>
<p>Superar esta trampa requirió combinar la <strong>percepción ultrasónica tridireccional</strong> con un <strong>alto factor de descuento (γ = 0.99)</strong>:</p>
<ol>
<li class=""><strong>Ampliación de estados</strong>: Ante un obstáculo frontal (<code>front_distance = Danger</code>), el barrido del sensor revela corredores libres (<code>left_distance = Safe</code> o <code>right_distance = Safe</code>), induciendo giros laterales.</li>
<li class=""><strong>Asignación temporal de crédito</strong>: Aunque alejarse reduce la recompensa inmediata, bordear el obstáculo y llegar a la meta otorga la recompensa terminal (+1.0). El factor γ = 0.99 propaga este retorno hacia atrás, consolidando la política de desvío.</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-automatización-headless-en-webots">3. Automatización Headless en Webots<a href="https://globaldevlog.com/es/blog/2026-05-19-rl-qlearning-3#3-automatizaci%C3%B3n-headless-en-webots" class="hash-link" aria-label="Enlace directo al 3. Automatización Headless en Webots" title="Enlace directo al 3. Automatización Headless en Webots" translate="no">​</a></h2>
<p>Para agilizar el entrenamiento repetido con múltiples semillas (Seeds 0, 1, 2), implementamos <strong><code>headless_run.ps1</code></strong>, ejecutando Webots sin renderizado visual a máxima velocidad (<code>--mode=fast --no-rendering</code>).</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-análisis-comparativo-de-curvas-de-aprendizaje">4. Análisis Comparativo de Curvas de Aprendizaje<a href="https://globaldevlog.com/es/blog/2026-05-19-rl-qlearning-3#4-an%C3%A1lisis-comparativo-de-curvas-de-aprendizaje" class="hash-link" aria-label="Enlace directo al 4. Análisis Comparativo de Curvas de Aprendizaje" title="Enlace directo al 4. Análisis Comparativo de Curvas de Aprendizaje" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Comparación de Curvas" src="https://globaldevlog.com/es/assets/images/02_comparison_curves-0d241e07d5b445acc1866d00247179b7.png" width="1625" height="585" class="img_ev3q"></p>
<ul>
<li class=""><strong>Tasa de éxito final</strong>: Del 98.5% en <code>no_obstacle</code> a un sólido <strong>91.4% ~ 94.8%</strong> en <code>obstacle12</code>.</li>
<li class=""><strong>Pasos promedio</strong>: Adaptación de trayectorias directas (15<del>22 pasos) a rutas de desvío (38</del>52 pasos).</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-próximos-pasos">5. Próximos Pasos<a href="https://globaldevlog.com/es/blog/2026-05-19-rl-qlearning-3#5-pr%C3%B3ximos-pasos" class="hash-link" aria-label="Enlace directo al 5. Próximos Pasos" title="Enlace directo al 5. Próximos Pasos" translate="no">​</a></h2>
<p>En el episodio #4, evaluaremos los modelos guardados (<code>models/*.npy</code>) mediante <strong><code>evaluate_qlearning.py</code> para medir el rendimiento determinista y comparar métricas frente a DQN y SARSA</strong>.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="aprendizaje-por-refuerzo" term="aprendizaje-por-refuerzo"/>
        <category label="q-learning" term="q-learning"/>
        <category label="webots" term="webots"/>
        <category label="evasion-de-obstaculos" term="evasion-de-obstaculos"/>
        <category label="minimos-locales" term="minimos-locales"/>
        <category label="headless" term="headless"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Robótica Webots] Implementación de Q-Learning Tabular y Ajuste de la Función de Recompensa (#2)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-18-rl-qlearning-2</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-18-rl-qlearning-2"/>
        <updated>2026-05-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Análisis en profundidad de las fórmulas de actualización TD(0) de Q-Learning tabular, la estrategia de exploración con decaimiento de epsilon y el modelado de recompensas densas para navegación robótica.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Curva de Recompensa" src="https://globaldevlog.com/es/assets/images/01_reward_curve-dafe6b9a6b58ab351aa0d2717b504f0a.png" width="800" height="400" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Puntos Clave (TL;DR)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: Las recompensas dispersas (+1.0 en la meta, -1.0 en colisión) generan grandes retrasos de exploración, provocando que el robot deambule durante miles de episodios antes de encontrar el objetivo.</li>
<li class=""><strong>Solución</strong>: Diseño de un esquema de <strong>Recompensas Densas (Reward Shaping)</strong> que combina recompensas proporcionales a la reducción de distancia euclidiana (+0.1 × Δdist) con penalizaciones por paso (-0.01), giro (-0.01) y retroceso (-0.05), junto con decaimiento exponencial de epsilon (1.0 → 0.05).</li>
<li class=""><strong>Resultado</strong>: La recompensa promedio móvil alcanzó valores positivos estables (0.7+) antes de los 500 episodios en el escenario <code>no_obstacle</code>, superando el 98% de tasa de éxito.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-fórmula-de-actualización-de-q-learning-tabular">1. Fórmula de Actualización de Q-Learning Tabular<a href="https://globaldevlog.com/es/blog/2026-05-18-rl-qlearning-2#1-f%C3%B3rmula-de-actualizaci%C3%B3n-de-q-learning-tabular" class="hash-link" aria-label="Enlace directo al 1. Fórmula de Actualización de Q-Learning Tabular" title="Enlace directo al 1. Fórmula de Actualización de Q-Learning Tabular" translate="no">​</a></h2>
<p>Q-Learning tabular es un algoritmo <strong>fuera de política (Off-policy) de Diferencia Temporal (TD(0))</strong> basado en la ecuación de optimalidad de Bellman.</p>
<p>El agente mantiene una tabla Q(s, a) de dimensiones $648 \times 4$, actualizando los valores $Q$ en tiempo real:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-regla-de-actualización-td0">📐 Regla de Actualización TD(0)<a href="https://globaldevlog.com/es/blog/2026-05-18-rl-qlearning-2#-regla-de-actualizaci%C3%B3n-td0" class="hash-link" aria-label="Enlace directo al 📐 Regla de Actualización TD(0)" title="Enlace directo al 📐 Regla de Actualización TD(0)" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Target = r + γ * max_a' Q(s', a') * (1 - done)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">TD Error = Target - Q(s, a)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Q(s, a) &lt;- Q(s, a) + α * TD Error</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Tasa de aprendizaje (α = 0.1)</strong>: Regula la incorporación de nueva experiencia.</li>
<li class=""><strong>Factor de descuento (γ = 0.99)</strong>: Pondera el valor de las recompensas futuras a largo plazo.</li>
<li class=""><strong>Máscara de estado terminal (<code>1 - done</code>)</strong>: Anula el valor futuro al alcanzar el objetivo o colisionar.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-estrategia-de-decaimiento-de-epsilon-greedy">2. Estrategia de Decaimiento de Epsilon-Greedy<a href="https://globaldevlog.com/es/blog/2026-05-18-rl-qlearning-2#2-estrategia-de-decaimiento-de-epsilon-greedy" class="hash-link" aria-label="Enlace directo al 2. Estrategia de Decaimiento de Epsilon-Greedy" title="Enlace directo al 2. Estrategia de Decaimiento de Epsilon-Greedy" translate="no">​</a></h2>
<p>Iniciamos con <strong>ε = 1.0 (100% exploración aleatoria)</strong> y aplicamos decaimiento exponencial al final de cada episodio:</p>
<p><strong>ε_(ep+1) = max(ε_min, ε_ep × 0.995)</strong></p>
<ul>
<li class=""><strong>Episodio 1</strong>: ε = 1.0 (Exploración completa)</li>
<li class=""><strong>Episodio 300</strong>: ε ≈ 0.22 (Transición a explotación de valores Q)</li>
<li class=""><strong>Episodio 600</strong>: ε = 0.05 (Tasa mínima ε_min, 95% de acciones voraces/greedy)</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-ajuste-de-recompensas-densas">3. Ajuste de Recompensas Densas<a href="https://globaldevlog.com/es/blog/2026-05-18-rl-qlearning-2#3-ajuste-de-recompensas-densas" class="hash-link" aria-label="Enlace directo al 3. Ajuste de Recompensas Densas" title="Enlace directo al 3. Ajuste de Recompensas Densas" translate="no">​</a></h2>
<table><thead><tr><th style="text-align:left">Componente</th><th style="text-align:center">Valor</th><th style="text-align:left">Propósito y Efecto Físico</th></tr></thead><tbody><tr><td style="text-align:left"><strong>Meta alcanzada (<code>REWARD_GOAL</code>)</strong></td><td style="text-align:center"><strong>+1.0</strong></td><td style="text-align:left">Recompensa terminal al llegar con éxito</td></tr><tr><td style="text-align:left"><strong>Colisión (<code>REWARD_COLLISION</code>)</strong></td><td style="text-align:center"><strong>-1.0</strong></td><td style="text-align:left">Penalización estricta por impacto contra la pared</td></tr><tr><td style="text-align:left"><strong>Delta de distancia (<code>REWARD_DELTA_SCALE</code>)</strong></td><td style="text-align:center"><strong>+0.1 × Δdist</strong></td><td style="text-align:left">Recompensa inmediata por reducir la distancia al objetivo</td></tr><tr><td style="text-align:left"><strong>Paso de tiempo (<code>REWARD_STEP</code>)</strong></td><td style="text-align:center"><strong>-0.01</strong></td><td style="text-align:left">Penaliza la inactividad y promueve la ruta más corta</td></tr><tr><td style="text-align:left"><strong>Giro (<code>REWARD_TURN</code>)</strong></td><td style="text-align:center"><strong>-0.01</strong></td><td style="text-align:left">Evita rotaciones innecesarias sobre el propio eje</td></tr><tr><td style="text-align:left"><strong>Retroceso (<code>REWARD_BACKWARD</code>)</strong></td><td style="text-align:center"><strong>-0.05</strong></td><td style="text-align:left">Desalienta la marcha atrás ineficiente</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-evaluación-de-curvas-de-aprendizaje">4. Evaluación de Curvas de Aprendizaje<a href="https://globaldevlog.com/es/blog/2026-05-18-rl-qlearning-2#4-evaluaci%C3%B3n-de-curvas-de-aprendizaje" class="hash-link" aria-label="Enlace directo al 4. Evaluación de Curvas de Aprendizaje" title="Enlace directo al 4. Evaluación de Curvas de Aprendizaje" translate="no">​</a></h2>
<p>Tras 1,500 episodios de entrenamiento en el entorno <code>no_obstacle</code>:</p>
<p><img decoding="async" loading="lazy" alt="Curva de Éxito" src="https://globaldevlog.com/es/assets/images/02_success_curve-a47390e774a7a40ace8869f29884f2bd.png" width="800" height="400" class="img_ev3q"></p>
<p>La tasa de éxito promedio móvil a 100 episodios superó el <strong>98.5%</strong>, y los pasos promedio por episodio se redujeron de 150 (tiempo límite) a solo <strong>15 ~ 22 pasos</strong>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-próximos-pasos">5. Próximos Pasos<a href="https://globaldevlog.com/es/blog/2026-05-18-rl-qlearning-2#5-pr%C3%B3ximos-pasos" class="hash-link" aria-label="Enlace directo al 5. Próximos Pasos" title="Enlace directo al 5. Próximos Pasos" translate="no">​</a></h2>
<p>En el episodio #3, abordaremos los escenarios con 12 obstáculos de pared (<strong><code>obstacle12</code> y <code>obstacle_hard</code></strong>), analizando cómo el agente supera los mínimos locales mediante simulaciones paralelas con múltiples semillas.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="aprendizaje-por-refuerzo" term="aprendizaje-por-refuerzo"/>
        <category label="q-learning" term="q-learning"/>
        <category label="funcion-de-recompensa" term="funcion-de-recompensa"/>
        <category label="webots" term="webots"/>
        <category label="robotica" term="robotica"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #19] Automatización de Informes y Problemas de BD]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-17-maeumjigi-19</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-17-maeumjigi-19"/>
        <updated>2026-05-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Automatización del resumen de resultados de evaluación y generación de presentaciones de diapositivas con python-pptx para el examen intermedio.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-12712349ddac15465e60572918ef40de.png" width="720" height="405" class="img_ev3q"></p>
<p>¡Debo corregir mi suposición de que el 13 de mayo fue el último día! El 17 de mayo hubo una ola masiva de pruebas de backend y redacción de informes.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="automatizando-el-informe-con-ia">Automatizando el Informe con IA<a href="https://globaldevlog.com/es/blog/2026-05-17-maeumjigi-19#automatizando-el-informe-con-ia" class="hash-link" aria-label="Enlace directo al Automatizando el Informe con IA" title="Enlace directo al Automatizando el Informe con IA" translate="no">​</a></h3>
<p>No había tiempo suficiente para analizar manualmente los gráficos masivos del segundo fine-tuning.</p>
<blockquote>
<p>"Crea un prompt para escribir un informe comparando los resultados. Guárdalo y escribe el informe."</p>
</blockquote>
<p>Intenté utilizar ingeniería de prompts para que la IA interpretara las métricas. La IA analizó los pros y contras de cada modelo, generando un excelente borrador en Word (.docx).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="integración-de-base-de-datos-y-el-error-401">Integración de Base de Datos y el Error 401<a href="https://globaldevlog.com/es/blog/2026-05-17-maeumjigi-19#integraci%C3%B3n-de-base-de-datos-y-el-error-401" class="hash-link" aria-label="Enlace directo al Integración de Base de Datos y el Error 401" title="Enlace directo al Integración de Base de Datos y el Error 401" translate="no">​</a></h3>
<p>Comencé a insertar datos de <code>backup.sql</code> en la BD local de PostgreSQL para probar la estabilidad.</p>
<blockquote>
<p>"Contraseña incorrecta... POST /auth/login 401 Unauthorized"</p>
</blockquote>
<p>Caí en un infierno de errores de inicio de sesión. Creé scripts de depuración y reinicié el servidor uvicorn sin fin.</p>
<p><img decoding="async" loading="lazy" alt="Problemas de BD" src="https://globaldevlog.com/es/assets/images/02_db-1d0bb76370f8508377e9472ff5cb15c8.png" width="1373" height="5225" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="gráficos-de-conocimiento-knowledge-graphs">Gráficos de Conocimiento (Knowledge Graphs)<a href="https://globaldevlog.com/es/blog/2026-05-17-maeumjigi-19#gr%C3%A1ficos-de-conocimiento-knowledge-graphs" class="hash-link" aria-label="Enlace directo al Gráficos de Conocimiento (Knowledge Graphs)" title="Enlace directo al Gráficos de Conocimiento (Knowledge Graphs)" translate="no">​</a></h3>
<p>A altas horas de la noche, para superar las limitaciones del simple Modelo de Lenguaje Grande (LLM), comencé a diseñar un plan para explorar la fusión de ontologías y Gráficos de Conocimiento. ¡El proyecto se está volviendo masivo!</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="report" term="report"/>
        <category label="backend" term="backend"/>
        <category label="Base de Datos (DB)" term="Base de Datos (DB)"/>
        <category label="troubleshooting" term="troubleshooting"/>
        <category label="capstone" term="capstone"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Robótica Webots] Navegación Autónoma con Q-Learning: Discretización de 648 Estados y Arquitectura de Sockets (#1)]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-17-rl-qlearning-1</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-17-rl-qlearning-1"/>
        <updated>2026-05-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Diseño de un discretizador de espacio de estados de 648 bins y una arquitectura IPC por sockets TCP para la navegación autónoma de robots móviles con Q-Learning tabular en Webots.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Entorno de Simulación Webots" src="https://globaldevlog.com/es/assets/images/01_webots_arena-b49bd821fb90ed1d7e619add024bb5e7.png" width="1721" height="1033" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Puntos Clave (TL;DR)</strong></p>
<ul>
<li class=""><strong>Problema</strong>: Las lecturas continuas de sensores (distancia y orientación) provocan una explosión del espacio de estados para el Q-Learning tabular, y la sincronización con el simulador Webots requiere una comunicación de baja latencia.</li>
<li class=""><strong>Solución</strong>: Diseño de un mapeador de sensores continuos en 5 dimensiones que produce 3 × 8 × 3 × 3 × 3 = 648 estados discretos (<code>discretizer.py</code>) y una canalización IPC mediante sockets TCP (puerto 5000, JSON delimitado por líneas).</li>
<li class=""><strong>Resultado</strong>: Indexación ultrarrápida de la tabla Q en tiempo O(1) y sincronización física estable en pasos de 32 ms entre el simulador y el agente Python.</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-contexto-del-proyecto-por-qué-webots-y-q-learning">1. Contexto del Proyecto: ¿Por qué Webots y Q-Learning?<a href="https://globaldevlog.com/es/blog/2026-05-17-rl-qlearning-1#1-contexto-del-proyecto-por-qu%C3%A9-webots-y-q-learning" class="hash-link" aria-label="Enlace directo al 1. Contexto del Proyecto: ¿Por qué Webots y Q-Learning?" title="Enlace directo al 1. Contexto del Proyecto: ¿Por qué Webots y Q-Learning?" translate="no">​</a></h2>
<p>Permitir que un robot móvil con tracción diferencial navegue en un entorno interior desconocido y alcance un objetivo evitando obstáculos es un desafío clásico de la robótica. Aunque el aprendizaje por refuerzo profundo (DQN, PPO) maneja entradas complejas, demanda grandes recursos de cómputo y carece de interpretabilidad directa.</p>
<p>En este proyecto, aplicamos <strong>Q-Learning Tabular clásico (Off-policy TD(0))</strong> a un robot móvil en el motor de física 3D Webots, con el objetivo de obtener una política de navegación y evasión de obstáculos verificable matemáticamente en un cuadrilátero interior de 1.2m × 1.2m.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-arquitectura-del-sistema-webots--python-ipc">2. Arquitectura del Sistema (Webots ↔ Python IPC)<a href="https://globaldevlog.com/es/blog/2026-05-17-rl-qlearning-1#2-arquitectura-del-sistema-webots--python-ipc" class="hash-link" aria-label="Enlace directo al 2. Arquitectura del Sistema (Webots ↔ Python IPC)" title="Enlace directo al 2. Arquitectura del Sistema (Webots ↔ Python IPC)" translate="no">​</a></h2>
<p>El sistema está dividido en dos niveles: el <strong>servidor de simulación Webots</strong> y el <strong>cliente de aprendizaje por refuerzo en Python</strong>.</p>
<div class="language-mermaid codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-mermaid codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">flowchart LR</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    subgraph Webots["Simulador 3D Webots (localhost:5000)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Robot["Robot Supervisor&lt;br&gt;(Sensor ultrasónico + ruedas)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        HeadScan["Mecanismo Head-Scan&lt;br&gt;(Servo rotación izq/der 1.1 rad)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Server["Servidor Socket TCP&lt;br&gt;(JSON delimitado por líneas)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Robot -→ HeadScan -→ Server</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    subgraph Python["Motor RL en Python (Cliente)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Env["WebotsEnv (estilo gym)&lt;br&gt;reset() / step()"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Disc["Discretizador&lt;br&gt;(Valores continuos → Bins 0~647)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Agent["QLearningAgent&lt;br&gt;(Tabla Q 648x4)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Env -→ Disc -→ Agent</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Server &lt;-→|"petición: {type: step, action: 0..3}&lt;br&gt;respuesta: {state: [...], reward, done}"| Env</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Controlador Webots (<code>RL_controller.py</code>)</strong>: Ejecuta acciones durante 480 ms (15 pasos de simulación × 32 ms) y gira el sensor ultrasónico montado en la cabeza hacia la izquierda y la derecha en 1.1 rad ($\approx 63°$) para eliminar puntos ciegos.</li>
<li class=""><strong>Protocolo de Sockets</strong>: JSON delimitado por líneas sobre TCP localhost:5000 para minimizar la sobrecarga.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-discretización-de-sensores-continuos-en-648-estados">3. Discretización de Sensores Continuos en 648 Estados<a href="https://globaldevlog.com/es/blog/2026-05-17-rl-qlearning-1#3-discretizaci%C3%B3n-de-sensores-continuos-en-648-estados" class="hash-link" aria-label="Enlace directo al 3. Discretización de Sensores Continuos en 648 Estados" title="Enlace directo al 3. Discretización de Sensores Continuos en 648 Estados" translate="no">​</a></h2>
<p>Para aplicar Q-Learning tabular, las variables continuas se asignan a 5 factores clave:</p>
<table><thead><tr><th style="text-align:left">Variable de Observación</th><th style="text-align:center">Bins</th><th style="text-align:left">Umbrales (Thresholds)</th><th style="text-align:left">Significado Físico</th></tr></thead><tbody><tr><td style="text-align:left"><strong>Distancia al objetivo (<code>goal_distance</code>)</strong></td><td style="text-align:center"><strong>3</strong></td><td style="text-align:left"><code>[0.6m, 1.2m]</code></td><td style="text-align:left">Cerca (Near), Medio (Mid), Lejos (Far)</td></tr><tr><td style="text-align:left"><strong>Orientación relativa (<code>goal_heading</code>)</strong></td><td style="text-align:center"><strong>8</strong></td><td style="text-align:left">[-π, π] (8 sectores de 45°)</td><td style="text-align:left">Frente, Frente-Der, Der, Atrás-Der, Atrás, Atrás-Izq, Izq, Frente-Izq</td></tr><tr><td style="text-align:left"><strong>Obstáculo frontal (<code>front_distance</code>)</strong></td><td style="text-align:center"><strong>3</strong></td><td style="text-align:left"><code>[0.15m, 0.30m]</code></td><td style="text-align:left">Peligro/Inminente, Precaución, Seguro</td></tr><tr><td style="text-align:left"><strong>Obstáculo izquierdo (<code>left_distance</code>)</strong></td><td style="text-align:center"><strong>3</strong></td><td style="text-align:left"><code>[0.15m, 0.30m]</code></td><td style="text-align:left">Peligro, Precaución, Seguro</td></tr><tr><td style="text-align:left"><strong>Obstáculo derecho (<code>right_distance</code>)</strong></td><td style="text-align:center"><strong>3</strong></td><td style="text-align:left"><code>[0.15m, 0.30m]</code></td><td style="text-align:left">Peligro, Precaución, Seguro</td></tr></tbody></table>
<p>Número total de estados:
<strong>N_estados = 3 × 8 × 3 × 3 × 3 = 648</strong></p>
<p>La tabla Q resultante contiene solo <strong>648 × 4 = 2,592 parámetros</strong>, permitiendo actualizaciones en submilisegundos en memoria sin requerir GPU.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-mecanismo-head-scan-y-criterios-de-finalización">4. Mecanismo Head-Scan y Criterios de Finalización<a href="https://globaldevlog.com/es/blog/2026-05-17-rl-qlearning-1#4-mecanismo-head-scan-y-criterios-de-finalizaci%C3%B3n" class="hash-link" aria-label="Enlace directo al 4. Mecanismo Head-Scan y Criterios de Finalización" title="Enlace directo al 4. Mecanismo Head-Scan y Criterios de Finalización" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Arquitectura del Sistema" src="https://globaldevlog.com/es/assets/images/02_architecture-83a0cdfb8297ac248797b32bbc7fd69b.png" width="2000" height="900" class="img_ev3q"></p>
<ol>
<li class=""><strong>Ejecución del paso</strong>: Motores a 3.0 rad/s durante 480 ms.</li>
<li class=""><strong>Rotación de la cabeza</strong>: Barrido a +1.1 rad para medir distancia izquierda, luego -1.1 rad para distancia derecha.</li>
<li class=""><strong>Centrado</strong>: Regreso a 0 rad para refrescar distancia frontal.</li>
<li class=""><strong>Condiciones de fin de episodio</strong>:<!-- -->
<ul>
<li class=""><strong>Objetivo alcanzado</strong>: Distancia euclidiana ≤ 0.10m → Éxito (<code>done = True</code>, recompensa $+1.0$).</li>
<li class=""><strong>Colisión con pared</strong>: Cualquier distancia ≤ 0.08m → Fallo (<code>done = True</code>, recompensa $-1.0$).</li>
</ul>
</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-próximos-pasos">5. Próximos Pasos<a href="https://globaldevlog.com/es/blog/2026-05-17-rl-qlearning-1#5-pr%C3%B3ximos-pasos" class="hash-link" aria-label="Enlace directo al 5. Próximos Pasos" title="Enlace directo al 5. Próximos Pasos" translate="no">​</a></h2>
<p>Con el entorno de Webots, la interfaz IPC por sockets TCP y la discretización en 648 estados listos, el robot puede comenzar su aprendizaje.</p>
<p>En el episodio #2, abordaremos la <strong>implementación matemática de Tabular Q-Learning, la política de exploración ε-greedy con decaimiento y el ajuste de la función de recompensa</strong>!</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="aprendizaje-por-refuerzo" term="aprendizaje-por-refuerzo"/>
        <category label="q-learning" term="q-learning"/>
        <category label="webots" term="webots"/>
        <category label="robotica" term="robotica"/>
        <category label="discretizacion" term="discretizacion"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #18] Expandiendo Tokens de Inferencia y Comparando Resultados]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-13-maeumjigi-18</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-13-maeumjigi-18"/>
        <updated>2026-05-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Ampliación de max_new_tokens a 384 para enriquecer las respuestas y análisis del impacto de LoRA alpha (8 vs 16) en la empatía del bot.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-4dcde4cef4209e81d49b5f5306af009d.png" width="1484" height="888" class="img_ev3q"></p>
<p>El 13 de mayo, después de corregir los errores, reanudamos las pruebas de inferencia para los modelos del 2do fine-tuning.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="aumentar-la-longitud-del-token">Aumentar la Longitud del Token<a href="https://globaldevlog.com/es/blog/2026-05-13-maeumjigi-18#aumentar-la-longitud-del-token" class="hash-link" aria-label="Enlace directo al Aumentar la Longitud del Token" title="Enlace directo al Aumentar la Longitud del Token" translate="no">​</a></h3>
<p>Revisando los resultados de inferencia, sentí que las respuestas de <code>Llama33-70B_a8</code> seguían siendo extrañamente cortas.</p>
<blockquote>
<p>"Siento que max_seq_length y max_new_tokens son muy pequeños. Mirando la VRAM, ¿cuánto puedo aumentarlos?"</p>
</blockquote>
<p>Calculando la VRAM disponible con la IA, aumentamos audazmente <code>max_new_tokens</code> a 384. ¡El resultado fue un gran éxito!</p>
<p>Al simplemente aumentar la asignación de tokens, el modelo comenzó a generar oraciones de empatía mucho más profundas y cálidas. El modelo había estado limitando sus palabras porque estaba atrapado en un recuento de tokens limitado.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="análisis-comparativo-del-valor-alfa">Análisis Comparativo del Valor Alfa<a href="https://globaldevlog.com/es/blog/2026-05-13-maeumjigi-18#an%C3%A1lisis-comparativo-del-valor-alfa" class="hash-link" aria-label="Enlace directo al Análisis Comparativo del Valor Alfa" title="Enlace directo al Análisis Comparativo del Valor Alfa" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="Visualización de Gráficos" src="https://globaldevlog.com/es/assets/images/02_graph-feb5d1991f44dd7f378232f6b3515752.png" width="2053" height="1460" class="img_ev3q"></p>
<p>También se obtuvieron los resultados de la diferencia de rendimiento según el hiperparámetro de LoRA <code>alpha</code>. Generamos gráficos como <code>05_alpha_comparison_daily.png</code>. Con <code>rank=16</code> fijo, visualizamos claramente cómo diferían los patrones y la calidad final al dar <code>alpha=8</code> frente a <code>alpha=16</code>.</p>
<p>Los modelos con los parámetros correctos y suficiente longitud de token se estaban acercando al verdadero 'Maeumjigi' que planeamos.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="inference" term="inference"/>
        <category label="max_new_tokens" term="max_new_tokens"/>
        <category label="empathy" term="empathy"/>
        <category label="capstone" term="capstone"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #17] 2do Fine-Tuning y la Trampa de la Automatización]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-12-maeumjigi-17</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-12-maeumjigi-17"/>
        <updated>2026-05-12T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Ejecución de la 2ª ronda de fine-tuning con plantillas de chat limpias y ajuste de hiperparámetros LoRA para mejorar la convergencia.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-14a3c0d517e4c85b93ada4e973112325.png" width="2000" height="1457" class="img_ev3q"></p>
<p>¡El entrenamiento paralelo del 2do fine-tuning (<code>fine_tuning_2</code>), que comenzó para corregir el error de los hiperparámetros, finalmente terminó el 12 de mayo!</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="el-mejor-checkpoint-y-el-pipeline-de-inferencia">El Mejor Checkpoint y el Pipeline de Inferencia<a href="https://globaldevlog.com/es/blog/2026-05-12-maeumjigi-17#el-mejor-checkpoint-y-el-pipeline-de-inferencia" class="hash-link" aria-label="Enlace directo al El Mejor Checkpoint y el Pipeline de Inferencia" title="Enlace directo al El Mejor Checkpoint y el Pipeline de Inferencia" translate="no">​</a></h3>
<p>El fine-tuning de 3 modelos con 6 combinaciones de hiperparámetros se completó. Comparé el <code>eval_loss</code> para extraer los mejores checkpoints y los moví a las carpetas <code>adapter</code>.</p>
<blockquote>
<p>"Los modelos HCX-Text-1p5B generaron 12 salidas en 15 minutos. Uso de GPU es de 1.6GB..."</p>
</blockquote>
<p>Sin embargo, la velocidad de inferencia era desesperante. Hubo un cuello de botella porque el tamaño del lote se estableció en 1. Además, los problemas de almacenamiento del servidor nos obligaron a migrar la ruta del proyecto.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cayendo-en-la-trampa-del-hardcoding">Cayendo en la Trampa del Hardcoding<a href="https://globaldevlog.com/es/blog/2026-05-12-maeumjigi-17#cayendo-en-la-trampa-del-hardcoding" class="hash-link" aria-label="Enlace directo al Cayendo en la Trampa del Hardcoding" title="Enlace directo al Cayendo en la Trampa del Hardcoding" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="Error de Hardcoding" src="https://globaldevlog.com/es/assets/images/02_bug-900bd56611b3d6521891bcc956843259.png" width="2000" height="1457" class="img_ev3q"></p>
<p>Después de ejecutar laboriosamente todos los códigos de evaluación, descubrí un hecho horrible.</p>
<blockquote>
<p>"¿Por qué MODEL_ALIAS está codificado de forma rígida a 'Qwen35-9B_a16'?"</p>
</blockquote>
<p>Accidentalmente codifiqué de forma rígida <code>MODEL_ALIAS</code>. El script copiaba archivos diligentemente para probar el modelo HCX, pero dentro del código, ¡seguía cargando solo el modelo <code>Qwen35-9B</code> y repitiendo la misma inferencia una y otra vez! Mañana tendré que arreglar este error y volver a ejecutar las inferencias.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="best-performance" term="best-performance"/>
        <category label="checkpoint" term="checkpoint"/>
        <category label="hardcoding" term="hardcoding"/>
        <category label="capstone" term="capstone"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #16] Error Fatal, 2do Fine-Tuning y App React Native]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-08-maeumjigi-16</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-08-maeumjigi-16"/>
        <updated>2026-05-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Diagnóstico de errores de hardcoding en las plantillas de prompts y depuración urgente para asegurar la integridad de los datos.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-9eab7db0dac5c88d9a120a99e5e703d4.png" width="1874" height="1526" class="img_ev3q"></p>
<p>El 8 de mayo preparábamos la presentación de los resultados. Sin embargo, descubrí un error masivo.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="error-fatal-en-los-hiperparámetros-de-lora">Error Fatal en los Hiperparámetros de LoRA<a href="https://globaldevlog.com/es/blog/2026-05-08-maeumjigi-16#error-fatal-en-los-hiperpar%C3%A1metros-de-lora" class="hash-link" aria-label="Enlace directo al Error Fatal en los Hiperparámetros de LoRA" title="Enlace directo al Error Fatal en los Hiperparámetros de LoRA" translate="no">​</a></h3>
<blockquote>
<p>"Las respuestas del modelo son más cortas. Creo que es porque establecer r de LoRA a 8 y alfa a 16 redujo demasiado las características..."
"Espera, ¿era a/r? Pensé que era r/a...???"</p>
</blockquote>
<p>Comprendí mal la ecuación, configurándola de una manera que suprimió severamente o amplificó excesivamente las actualizaciones de peso. Con razón las respuestas eran anormalmente cortas.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2da-ronda-de-fine-tuning-fine_tuning_2">2da Ronda de Fine-Tuning (fine_tuning_2)<a href="https://globaldevlog.com/es/blog/2026-05-08-maeumjigi-16#2da-ronda-de-fine-tuning-fine_tuning_2" class="hash-link" aria-label="Enlace directo al 2da Ronda de Fine-Tuning (fine_tuning_2)" title="Enlace directo al 2da Ronda de Fine-Tuning (fine_tuning_2)" translate="no">​</a></h3>
<p>No podíamos simplemente avanzar. Inmediatamente creé una carpeta <code>fine_tuning_2</code> para una segunda ronda de fine-tuning.</p>
<blockquote>
<p>"Entrenar con rank=16, alpha=16, y en MIG-1 con rank=16, a=8."
"Extraiga las 2000 entradas más largas de Daily_train_dataset."</p>
</blockquote>
<p>Para evitar respuestas cortas, extrajimos solo los 2000 conjuntos de datos más largos y dividimos nuestros recursos de GPU para ejecutar entrenamiento en paralelo.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="desarrollo-frontend-app">Desarrollo Frontend (App)<a href="https://globaldevlog.com/es/blog/2026-05-08-maeumjigi-16#desarrollo-frontend-app" class="hash-link" aria-label="Enlace directo al Desarrollo Frontend (App)" title="Enlace directo al Desarrollo Frontend (App)" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="Desarrollo de App" src="https://globaldevlog.com/es/assets/images/02_app-9efe68797b061b7eda0d68995627a8cc.png" width="1476" height="1526" class="img_ev3q"></p>
<p>Mientras los modelos entrenaban, comencé a desarrollar la aplicación frontend.</p>
<blockquote>
<p>"Necesito mostrar un código QR para ejecutar maeum-app... pero cuando escribo npx go start, solo obtengo un error."</p>
</blockquote>
<p>Creé el proyecto usando React Native (Expo) y, después de algunos errores tipográficos, logré mostrar el código QR de Expo. Fue un día emocionante construyendo tanto el cerebro (IA) como la cara de la aplicación.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="LoRA" term="LoRA"/>
        <category label="hyperparameters" term="hyperparameters"/>
        <category label="ReactNative" term="ReactNative"/>
        <category label="app-development" term="app-development"/>
        <category label="frontend" term="frontend"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[[Registro de Desarrollo Maeumjigi #15] Visualización de Resultados de 5 Modelos y Configuración Local]]></title>
        <id>https://globaldevlog.com/es/blog/2026-05-07-maeumjigi-15</id>
        <link href="https://globaldevlog.com/es/blog/2026-05-07-maeumjigi-15"/>
        <updated>2026-05-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Análisis de perplejidad y métricas de rendimiento, construyendo un pipeline de visualización con matplotlib para comparar modelos.]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Imagen de Portada" src="https://globaldevlog.com/es/assets/images/01_cover-b5ad981f0a0602b8afaf1bdbc982094d.png" width="1181" height="731" class="img_ev3q"></p>
<p>El 7 de mayo sintetizamos los resultados de los 5 modelos que habíamos entrenado (Llama3.3-70B, DSR1-70B, HCX-Omni-8B, Qwen35-9B, HCX-Text-1.5B) y procedimos con la visualización a gran escala.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="configuración-local-para-la-comparación-de-modelos">Configuración Local para la Comparación de Modelos<a href="https://globaldevlog.com/es/blog/2026-05-07-maeumjigi-15#configuraci%C3%B3n-local-para-la-comparaci%C3%B3n-de-modelos" class="hash-link" aria-label="Enlace directo al Configuración Local para la Comparación de Modelos" title="Enlace directo al Configuración Local para la Comparación de Modelos" translate="no">​</a></h3>
<p>Para revisar cómodamente los resultados en mi computadora portátil, creé un nuevo cuaderno: <code>31_comparison_local.ipynb</code>.</p>
<blockquote>
<p>"¿No puede 30_comparison.ipynb ejecutarse también en mi computadora?"</p>
</blockquote>
<p>Al configurar el kernel local de Jupyter en VSCode e instalar las bibliotecas, enfrenté bloqueos del kernel y errores como <code>ModuleNotFoundError</code>. Sin embargo, los resolví paso a paso arreglando las rutas.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="informe-completo-y-gráficos">Informe Completo y Gráficos<a href="https://globaldevlog.com/es/blog/2026-05-07-maeumjigi-15#informe-completo-y-gr%C3%A1ficos" class="hash-link" aria-label="Enlace directo al Informe Completo y Gráficos" title="Enlace directo al Informe Completo y Gráficos" translate="no">​</a></h3>
<p>La tarea más importante fue visualizar el rendimiento de estos 5 modelos para compararlos de un vistazo. Junto con la IA, establecimos un plan y comenzamos a organizar los datos sistemáticamente.</p>
<blockquote>
<p>"¿Cuál es la diferencia entre la línea tenue y la línea gruesa? Visualice el training loss y el eval loss."</p>
</blockquote>
<p>Eliminé las líneas de tendencia innecesarias de los gráficos generados por la IA, extrayendo finalmente <code>03_training_loss_all.png</code> y <code>04_eval_loss_all.png</code> que reunieron perfectamente las curvas de pérdida de todos los modelos en un solo lugar.</p>
<p><img decoding="async" loading="lazy" alt="Visualización de Gráficos" src="https://globaldevlog.com/es/assets/images/02_graph-8f91ee1a78e9220a703c6884ad9a4f40.png" width="1785" height="735" class="img_ev3q"></p>
<p>Ahora, basándonos en estos gráficos, podemos decorar maravillosamente nuestros materiales de presentación de la próxima semana.</p>]]></content>
        <author>
            <name>Jihwan Park (jaybee)</name>
            <uri>https://github.com/jbjihwan</uri>
        </author>
        <category label="devlog" term="devlog"/>
        <category label="fine-tuning" term="fine-tuning"/>
        <category label="results-analysis" term="results-analysis"/>
        <category label="visualization" term="visualization"/>
        <category label="Jupyter" term="Jupyter"/>
        <category label="capstone" term="capstone"/>
        <category label="Inteligencia Artificial (AI)" term="Inteligencia Artificial (AI)"/>
    </entry>
</feed>