<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Global Dev Blog Blog</title>
        <link>https://globaldevlog.com/ja/blog</link>
        <description>Global Dev Blog Blog</description>
        <lastBuildDate>Sun, 18 Oct 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>ja</language>
        <item>
            <title><![CDATA[45件のnpm脆弱性警告と無リスクの真実：静的サイトで npm audit fix --force を盲信してはいけない理由]]></title>
            <link>https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth</link>
            <guid>https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth</guid>
            <pubDate>Sun, 18 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[静的サイト(SSG)環境における45件のnpm脆弱性警告がなぜランタイム上で無害なのかを脅威モデリングから紐解き、npm audit fix --forceが本番環境を破壊する理由と実践的セキュリティ対策を解説します。]]></description>
            <content:encoded><![CDATA[<p>モダンなフロントエンドやドキュメントサイトを運用するエンジニアであれば、一度は血の気が引くような経験をしたことがあるはずです。何気なく <code>npm audit</code> を実行した瞬間、コンソールに警告が溢れ出します：</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><strong>Critical</strong>、<strong>Remote Code Execution (RCE)</strong>、<strong>Prototype Pollution</strong> といった不穏な単語を目にすると、反射的に <code>npm audit fix --force</code> を実行して赤い警告を消したくなります。</p>
<p>しかし、DocusaurusやNext.jsなどの <strong>静的サイトジェネレーター(SSG)</strong> をGitHub PagesやAWS S3にデプロイするアーキテクチャでは、この無分別なダウングレードこそが最新フレームワークを破壊する最大の原因になります。</p>
<p>本記事では、<strong>静的サイトの脅威モデル (Threat Model)</strong> を明確にし、ビルドツールとランタイム脆弱性の本質的な違いを分析した上で、実際に守るべき <strong>4層のセキュリティ対策</strong> を共有します。</p>
<!-- -->
<hr>
<p><img decoding="async" loading="lazy" alt="脅威モデル比較: 動的Webサーバー vs 静的サイト" src="https://globaldevlog.com/ja/assets/images/01_threat_model-4770df6c58430b3bba205124a37d91ab.png" width="2000" height="1000" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-3行まとめエンジニアリングの判断基準">1. 3行まとめ：エンジニアリングの判断基準<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#1-3%E8%A1%8C%E3%81%BE%E3%81%A8%E3%82%81%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AE%E5%88%A4%E6%96%AD%E5%9F%BA%E6%BA%96" class="hash-link" aria-label="1. 3行まとめ：エンジニアリングの判断基準 への直接リンク" title="1. 3行まとめ：エンジニアリングの判断基準 への直接リンク" translate="no">​</a></h2>
<ol>
<li class=""><strong>ビルド時ツール != 本番ランタイム</strong>: 警告されたパッケージ（<code>tinypool</code>、<code>serialize-javascript</code> など）は、ローカルPCで <code>npm run build</code> を実行するときだけ動作するバンドラー依存関係です。</li>
<li class=""><strong>CDN上に稼働するサーバーはない</strong>: ビルド後のGitHub Pagesには純粋なHTML/CSS/JSしか残りません。<strong>稼働中のNode.jsデーモンも、リッスンしているポートも、データベース接続も存在しません。</strong></li>
<li class=""><strong><code>--force</code> の危険性</strong>: <code>--force</code> で無理に依存関係を書き換えると、Docusaurusが古いバージョン(3.7.0)に巻き戻され、React 19やMDX v3との互換性が完全に壊れます。</li>
<li class=""><strong>静的サイトの本当の脅威</strong>: 狙われるのはサーバーではなく、<strong>Git履歴内のAPIキー流出</strong>、<strong>データセット内の個人情報(PII)</strong>、<strong>クライアントのリファラー漏洩</strong>です。</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-45件の脆弱性の正体ビルド時-vs-ランタイム">2. 45件の脆弱性の正体：ビルド時 vs ランタイム<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#2-45%E4%BB%B6%E3%81%AE%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%AE%E6%AD%A3%E4%BD%93%E3%83%93%E3%83%AB%E3%83%89%E6%99%82-vs-%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0" class="hash-link" aria-label="2. 45件の脆弱性の正体：ビルド時 vs ランタイム への直接リンク" title="2. 45件の脆弱性の正体：ビルド時 vs ランタイム への直接リンク" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-tinypool-のプロトタイプ汚染-ghsa-5gmw-xhrv-c9v3---critical">A. Tinypool のプロトタイプ汚染 (<code>GHSA-5gmw-xhrv-c9v3</code> - Critical)<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#a-tinypool-%E3%81%AE%E3%83%97%E3%83%AD%E3%83%88%E3%82%BF%E3%82%A4%E3%83%97%E6%B1%9A%E6%9F%93-ghsa-5gmw-xhrv-c9v3---critical" class="hash-link" aria-label="a-tinypool-のプロトタイプ汚染-ghsa-5gmw-xhrv-c9v3---critical への直接リンク" title="a-tinypool-のプロトタイプ汚染-ghsa-5gmw-xhrv-c9v3---critical への直接リンク" translate="no">​</a></h3>
<ul>
<li class=""><code>tinypool</code> はビルドタスクをローカルCPUコアに分散するためのライブラリです。入力値は自身の <code>docusaurus.config.ts</code> のみであり、外部の攻撃者がCDN経由でビルドワーカーに悪意あるペイロードを送信することは不可能です。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="b-serialize-javascript-の-rce-ghsa-5c6j-r48x-rmvq---high">B. Serialize-JavaScript の RCE (<code>GHSA-5c6j-r48x-rmvq</code> - High)<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#b-serialize-javascript-%E3%81%AE-rce-ghsa-5c6j-r48x-rmvq---high" class="hash-link" aria-label="b-serialize-javascript-の-rce-ghsa-5c6j-r48x-rmvq---high への直接リンク" title="b-serialize-javascript-の-rce-ghsa-5c6j-r48x-rmvq---high への直接リンク" translate="no">​</a></h3>
<ul>
<li class="">Webpackが静的チャンクを書き出す際に使用します。出力されたJSファイルは単なる静的ファイルとして配信されるだけであり、サーバー上で逆シリアル化が実行されることはありません。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="c-postcss-selector-parser-の-dos-ghsa-rj75-hqrm-r3gf---moderate">C. PostCSS Selector Parser の DoS (<code>GHSA-rj75-hqrm-r3gf</code> - Moderate)<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#c-postcss-selector-parser-%E3%81%AE-dos-ghsa-rj75-hqrm-r3gf---moderate" class="hash-link" aria-label="c-postcss-selector-parser-の-dos-ghsa-rj75-hqrm-r3gf---moderate への直接リンク" title="c-postcss-selector-parser-の-dos-ghsa-rj75-hqrm-r3gf---moderate への直接リンク" translate="no">​</a></h3>
<ul>
<li class="">パース対象のCSSは開発者が作成したスタイルシートです。GitHubリポジトリの書き込み権限が奪われない限り、悪意ある外部CSSが混入することはありません。</li>
</ul>
<p>結論として、SSG環境で <code>npm audit fix --force</code> を叩くことは、<strong>存在しない脅威を防ぐために正常に動作しているシステムを破壊する行為</strong>に他なりません。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-実践的4層セキュリティブループリント">3. 実践的4層セキュリティ・ブループリント<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#3-%E5%AE%9F%E8%B7%B5%E7%9A%844%E5%B1%A4%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%96%E3%83%AB%E3%83%BC%E3%83%97%E3%83%AA%E3%83%B3%E3%83%88" class="hash-link" aria-label="3. 実践的4層セキュリティ・ブループリント への直接リンク" title="3. 実践的4層セキュリティ・ブループリント への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="4層の静的ブログ・セキュリティ強化パイプライン" src="https://globaldevlog.com/ja/assets/images/02_security_pipeline-120240a37282a9b3b578a5dc4f6231c0.png" width="2000" height="900" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="第1層gitプリコミットシークレットスキャン自動化">第1層：Gitプリコミット・シークレットスキャン自動化<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#%E7%AC%AC1%E5%B1%A4git%E3%83%97%E3%83%AA%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%82%B9%E3%82%AD%E3%83%A3%E3%83%B3%E8%87%AA%E5%8B%95%E5%8C%96" class="hash-link" aria-label="第1層：Gitプリコミット・シークレットスキャン自動化 への直接リンク" title="第1層：Gitプリコミット・シークレットスキャン自動化 への直接リンク" translate="no">​</a></h3>
<p>最も致命的なリスクは、APIキー（OpenAI <code>sk-...</code>、GitHub PAT <code>ghp_...</code>、AWS <code>AKIA...</code>）を誤って公開コミットすることです。Gitの追跡ファイルを正規表現で一括検査する監査スクリプト（<code>tools/audit_security.py</code>）を構築し、リリース前にゼロ漏洩を保証します。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="第2層個人情報piiとデータセット保護">第2層：個人情報(PII)とデータセット保護<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#%E7%AC%AC2%E5%B1%A4%E5%80%8B%E4%BA%BA%E6%83%85%E5%A0%B1pii%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88%E4%BF%9D%E8%AD%B7" class="hash-link" aria-label="第2層：個人情報(PII)とデータセット保護 への直接リンク" title="第2層：個人情報(PII)とデータセット保護 への直接リンク" translate="no">​</a></h3>
<p>AI相談やナンバープレート認識プロジェクトでは、実データの代わりにLLMパイプラインで生成した <strong>合成対話データ (<code>synth_gen</code>)</strong> を活用し、医療倫理やプライバシー侵害を根本から排除しています。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="第3層堅牢な-gitignore-設定">第3層：堅牢な <code>.gitignore</code> 設定<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#%E7%AC%AC3%E5%B1%A4%E5%A0%85%E7%89%A2%E3%81%AA-gitignore-%E8%A8%AD%E5%AE%9A" class="hash-link" aria-label="第3層堅牢な-gitignore-設定 への直接リンク" title="第3層堅牢な-gitignore-設定 への直接リンク" translate="no">​</a></h3>
<p><code>.env</code>、SSL秘密鍵（<code>*.pem</code>, <code>*.key</code>）、CSV解析ダンプファイル（<code>*.csv</code>）が誤って公開リポジトリにプッシュされないよう設定を強化しました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="第4層クライアント側プライバシー保護">第4層：クライアント側プライバシー保護<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#%E7%AC%AC4%E5%B1%A4%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E5%81%B4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%90%E3%82%B7%E3%83%BC%E4%BF%9D%E8%AD%B7" class="hash-link" aria-label="第4層：クライアント側プライバシー保護 への直接リンク" title="第4層：クライアント側プライバシー保護 への直接リンク" translate="no">​</a></h3>
<ul>
<li class=""><strong>厳格なリファラーポリシー</strong>: <code>strict-origin-when-cross-origin</code> を適用し、外部サイトへ遷移する際にブログの詳細URLパスが漏洩しないよう保護。</li>
<li class=""><strong>Giscus iframeサンドボックス</strong>: <code>emitMetadata="0"</code>, <code>loading="lazy"</code> を設定し、第三者スクリプトによるセッション干渉を遮断。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-エンジニアへの提言">4. エンジニアへの提言<a href="https://globaldevlog.com/ja/blog/static-site-security-npm-audit-truth#4-%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%B8%E3%81%AE%E6%8F%90%E8%A8%80" class="hash-link" aria-label="4. エンジニアへの提言 への直接リンク" title="4. エンジニアへの提言 への直接リンク" translate="no">​</a></h2>
<ul>
<li class=""><strong>赤い警告に惑わされない</strong>: その脆弱性が「ローカルのビルドツール」なのか「本番サーバー」なのかを切り分けることがセキュリティの本質です。</li>
<li class=""><strong>真の攻撃対象に注力する</strong>: シークレットの検出自動化、個人情報の排除、適切なプライバシー設定こそが、技術ブログの信頼性を高める鍵となります。</li>
</ul>]]></content:encoded>
            <category>ウェブセキュリティ</category>
            <category>npm-audit</category>
            <category>Docusaurus</category>
            <category>DevOps</category>
            <category>サプライチェーン</category>
        </item>
        <item>
            <title><![CDATA[[Vision AI] 韓国ナンバープレートOCR最適化、正規表現検証および時間軸多数決アンサンブル (v01~v11完結編) (#5)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-06-29-vision-anpr-5</link>
            <guid>https://globaldevlog.com/ja/blog/2026-06-29-vision-anpr-5</guid>
            <pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[韓国ナンバープレートの正規表現検証、EasyOCR誤読補正、時間軸多数決投票エンジン、および初期の文字化けから「64가1511」確定に至るv01~v11の進化記録。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="時間軸多数決投票と最終確定画面" src="https://globaldevlog.com/ja/assets/images/01_voting_evolution-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (要約)</strong></p>
<ul>
<li class=""><strong>課題</strong>: 単一フレームOCRは車体の揺れや光の反射により、一時的な誤認識（<code>64아1511</code>、<code>24가1511</code>など）が不可避です。</li>
<li class=""><strong>解決策</strong>: 韓国ナンバープレート規格の正規表現（<code>^\d{2,3}[가-힣]\d{4}$</code>）検証と、過去7フレームのバッファで3回以上一致した場合に確定する時間軸多数決投票エンジンを構築しました。</li>
<li class=""><strong>成果</strong>: 6月5日の初期の文字化け（<code>ACCIIXOY...</code>）から6月7日の完全な「64가1511」確定まで、11段階（v01〜v11）のリファクタリングを経て99.4%の信頼性を達成しました。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-韓国ナンバープレート正規表現とeasyocr">1. 韓国ナンバープレート正規表現とEasyOCR<a href="https://globaldevlog.com/ja/blog/2026-06-29-vision-anpr-5#1-%E9%9F%93%E5%9B%BD%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%81%A8easyocr" class="hash-link" aria-label="1. 韓国ナンバープレート正規表現とEasyOCR への直接リンク" title="1. 韓国ナンバープレート正規表現と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-時間軸多数決投票エンジン">2. 時間軸多数決投票エンジン<a href="https://globaldevlog.com/ja/blog/2026-06-29-vision-anpr-5#2-%E6%99%82%E9%96%93%E8%BB%B8%E5%A4%9A%E6%95%B0%E6%B1%BA%E6%8A%95%E7%A5%A8%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3" class="hash-link" aria-label="2. 時間軸多数決投票エンジン への直接リンク" title="2. 時間軸多数決投票エンジン への直接リンク" 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-v01からv11への進化記録">3. v01からv11への進化記録<a href="https://globaldevlog.com/ja/blog/2026-06-29-vision-anpr-5#3-v01%E3%81%8B%E3%82%89v11%E3%81%B8%E3%81%AE%E9%80%B2%E5%8C%96%E8%A8%98%E9%8C%B2" class="hash-link" aria-label="3. v01からv11への進化記録 への直接リンク" title="3. v01からv11への進化記録 への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="v11システム動作画面" src="https://globaldevlog.com/ja/assets/images/02_final_system-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<table><thead><tr><th style="text-align:left">日時</th><th style="text-align:left">認識テキストログ</th><th style="text-align:left">技術的ブレイクスルー</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。路面ノイズを文字と誤認</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>: 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>: 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>: EDSR_x4深層超解像による文字復元</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>: マルチフレームスタッキングでノイズ除去</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</strong>: 多数決投票で完全確定！</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-シリーズ完結">4. シリーズ完結<a href="https://globaldevlog.com/ja/blog/2026-06-29-vision-anpr-5#4-%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA%E5%AE%8C%E7%B5%90" class="hash-link" aria-label="4. シリーズ完結 への直接リンク" title="4. シリーズ完結 への直接リンク" translate="no">​</a></h2>
<p>全5編にわたり、<strong>動的車線検出、IoU侵犯判定、階層型YOLO検出、CSRT追跡、EDSR超解像、多数決OCR</strong>を統合した堅牢なビジョンパイプラインを完遂しました。</p>]]></content:encoded>
            <category>computer-vision</category>
            <category>anpr</category>
            <category>easyocr</category>
            <category>regex</category>
            <category>voting-ensemble</category>
            <category>python</category>
        </item>
        <item>
            <title><![CDATA[[Vision AI] 低解像度ドラレコのぼやけ克服: EDSR深層超解像とマルチフレームスタッキングノイズ除去 (#4)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-06-28-vision-anpr-4</link>
            <guid>https://globaldevlog.com/ja/blog/2026-06-28-vision-anpr-4</guid>
            <pubDate>Sun, 28 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[切り出された低解像度ナンバープレートを4倍復元するEDSR深層超解像と、複数フレーム平均化スタッキングによるノイズ除去手法。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="EDSR深層超解像適用結果" src="https://globaldevlog.com/ja/assets/images/01_edsr_sr_comparison-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (要約)</strong></p>
<ul>
<li class=""><strong>課題</strong>: ドラレコ映像から抽出されたプレート領域は40x20ピクセル以下と極小で、バイキュービック補間では輪郭がぼやけて文字認識が不可能です。</li>
<li class=""><strong>解決策</strong>: バッチ正規化を除去してテクスチャ復元力を高めたEDSR_x4深層残差ネットワーク（EDSR_x4.pb）を導入し、連続3〜5フレームを平均化するマルチフレーム画像スタッキングを併用しました。</li>
<li class=""><strong>成果</strong>: プレート解像度を4倍に拡大し文字のエッジを鮮明化、EasyOCRのハングル認識成功率を32%から91%以上へ大幅に向上させました。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-edsr_x4深層超解像エンジン">1. EDSR_x4深層超解像エンジン<a href="https://globaldevlog.com/ja/blog/2026-06-28-vision-anpr-4#1-edsr_x4%E6%B7%B1%E5%B1%A4%E8%B6%85%E8%A7%A3%E5%83%8F%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3" class="hash-link" aria-label="1. EDSR_x4深層超解像エンジン への直接リンク" title="1. 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-マルチフレームスタッキング">2. マルチフレームスタッキング<a href="https://globaldevlog.com/ja/blog/2026-06-28-vision-anpr-4#2-%E3%83%9E%E3%83%AB%E3%83%81%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0" class="hash-link" aria-label="2. マルチフレームスタッキング への直接リンク" title="2. マルチフレームスタッキング への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="マルチフレームスタッキング" src="https://globaldevlog.com/ja/assets/images/02_frame_stacking-0ce024bbbafb08d7449c40abec7b6dc2.png" width="2149" height="1599" class="img_ev3q"></p>
<p>時間軸で連続するフレームを整列・平均化することで、ランダムなノイズを打ち消し、文字のコントラストを強調します。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-次回予告">3. 次回予告<a href="https://globaldevlog.com/ja/blog/2026-06-28-vision-anpr-4#3-%E6%AC%A1%E5%9B%9E%E4%BA%88%E5%91%8A" class="hash-link" aria-label="3. 次回予告 への直接リンク" title="3. 次回予告 への直接リンク" translate="no">​</a></h2>
<p>最終回（第5編）では、<strong>EasyOCR韓国ナンバープレート正規表現検証</strong>、初期の文字化けから「64가1511」確定に至る<strong>多数決投票アンサンブルとv01~v11の進化記録</strong>を総括します。</p>]]></content:encoded>
            <category>computer-vision</category>
            <category>super-resolution</category>
            <category>edsr</category>
            <category>image-stacking</category>
            <category>anpr</category>
            <category>deep-learning</category>
            <category>python</category>
        </item>
        <item>
            <title><![CDATA[[Vision AI] 階層型物体検出: YOLOv3車両ROI、YOLOv5ナンバープレート検出器およびCSRT追跡統合 (#3)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-06-27-vision-anpr-3</link>
            <guid>https://globaldevlog.com/ja/blog/2026-06-27-vision-anpr-3</guid>
            <pubDate>Sat, 27 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[広域車両検出（YOLOv3）とROI内高精度プレート検出（YOLOv5）の2段階階層構造、およびCSRT相関フィルタ追跡器を組み合わせた演算最適化手法。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="YOLOv5プレート検出結果" src="https://globaldevlog.com/ja/assets/images/01_plate_localization-e3a163202d7a73e57bdf504aafdd6919.png" width="957" height="766" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (要約)</strong></p>
<ul>
<li class=""><strong>課題</strong>: 640x480全体から直接小さなナンバープレートを探索すると看板等の誤検出が多発し、フレーム毎の深層学習推論はFPSを10以下に低下させます。</li>
<li class=""><strong>解決策</strong>: YOLOv3-tinyで車両全体を検出した後、そのROI内部でのみYOLOv5（lp_det.pt）を実行する2段階階層構造を採用。15フレーム毎の再検出とOpenCV CSRT高速トラッカーを統合しました。</li>
<li class=""><strong>成果</strong>: 背景の誤検出をほぼ完全に排除し、GPU演算負荷を80%削減して50+ FPSの滑らかなリアルタイム追跡を実現しました。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-階層型物体検出アーキテクチャ">1. 階層型物体検出アーキテクチャ<a href="https://globaldevlog.com/ja/blog/2026-06-27-vision-anpr-3#1-%E9%9A%8E%E5%B1%A4%E5%9E%8B%E7%89%A9%E4%BD%93%E6%A4%9C%E5%87%BA%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3" class="hash-link" aria-label="1. 階層型物体検出アーキテクチャ への直接リンク" title="1. 階層型物体検出アーキテクチャ への直接リンク" 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-csrtトラッカーによるリアルタイム化">2. CSRTトラッカーによるリアルタイム化<a href="https://globaldevlog.com/ja/blog/2026-06-27-vision-anpr-3#2-csrt%E3%83%88%E3%83%A9%E3%83%83%E3%82%AB%E3%83%BC%E3%81%AB%E3%82%88%E3%82%8B%E3%83%AA%E3%82%A2%E3%83%AB%E3%82%BF%E3%82%A4%E3%83%A0%E5%8C%96" class="hash-link" aria-label="2. CSRTトラッカーによるリアルタイム化 への直接リンク" title="2. CSRTトラッカーによるリアルタイム化 への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="CSRTトラッカーによる追跡画面" src="https://globaldevlog.com/ja/assets/images/02_csrt_tracking-bea82f7c3eb5c74b33968501166fbe5a.png" width="2139" height="1599" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-次回予告">3. 次回予告<a href="https://globaldevlog.com/ja/blog/2026-06-27-vision-anpr-3#3-%E6%AC%A1%E5%9B%9E%E4%BA%88%E5%91%8A" class="hash-link" aria-label="3. 次回予告 への直接リンク" title="3. 次回予告 への直接リンク" translate="no">​</a></h2>
<p>第4編では、ぼやけたプレート画像を復元する<strong>EDSR_x4深層超解像ネットワーク</strong>と、ノイズを低減する<strong>マルチフレームスタッキング技術</strong>を解説します。</p>]]></content:encoded>
            <category>computer-vision</category>
            <category>anpr</category>
            <category>yolo</category>
            <category>csrt-tracker</category>
            <category>object-detection</category>
            <category>opencv</category>
            <category>python</category>
        </item>
        <item>
            <title><![CDATA[[Vision AI] 動的車線境界抽出および幾何学的IoU車線侵犯判定アルゴリズム (#2)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-06-26-vision-anpr-2</link>
            <guid>https://globaldevlog.com/ja/blog/2026-06-26-vision-anpr-2</guid>
            <pubDate>Fri, 26 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cannyエッジ検出、確率的ハフ変換、左右の傾きフィルタリング、および車両接地領域と車線ポリゴン間の幾何学的IoU侵犯判定数学。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="動的車線検出オーバーレイ" src="https://globaldevlog.com/ja/assets/images/01_lane_detection-0ce024bbbafb08d7449c40abec7b6dc2.png" width="2149" height="1599" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (要約)</strong></p>
<ul>
<li class=""><strong>課題</strong>: ドラレコ映像は路面反射、アスファルトの亀裂、影によって誤検出が多発し、単純な座標判定では車線変更の瞬間を正確に捉えられません。</li>
<li class=""><strong>解決策</strong>: 消失点基準の台形ROIマスク、傾きフィルタリング（|slope| &gt; 0.5）、および7フレーム移動平均キューを採用しました。侵犯判定は車両接地領域（下部30%）と車線ポリゴン間の幾何学的IoU（&gt; 0.05）で定式化しました。</li>
<li class=""><strong>成果</strong>: 路面ノイズを95%以上除外しながら、車線侵犯の瞬間をサブフレーム単位で安定して検出することに成功しました。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-動的車線検出-cannyと確率的ハフ変換">1. 動的車線検出: Cannyと確率的ハフ変換<a href="https://globaldevlog.com/ja/blog/2026-06-26-vision-anpr-2#1-%E5%8B%95%E7%9A%84%E8%BB%8A%E7%B7%9A%E6%A4%9C%E5%87%BA-canny%E3%81%A8%E7%A2%BA%E7%8E%87%E7%9A%84%E3%83%8F%E3%83%95%E5%A4%89%E6%8F%9B" class="hash-link" aria-label="1. 動的車線検出: Cannyと確率的ハフ変換 への直接リンク" title="1. 動的車線検出: Cannyと確率的ハフ変換 への直接リンク" 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-傾きフィルタリングと平滑化">2. 傾きフィルタリングと平滑化<a href="https://globaldevlog.com/ja/blog/2026-06-26-vision-anpr-2#2-%E5%82%BE%E3%81%8D%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%A8%E5%B9%B3%E6%BB%91%E5%8C%96" class="hash-link" aria-label="2. 傾きフィルタリングと平滑化 への直接リンク" title="2. 傾きフィルタリングと平滑化 への直接リンク" translate="no">​</a></h2>
<p>線分の傾き <code>m = (y2 - y1) / (x2 - x1)</code> を評価:</p>
<ul>
<li class=""><strong>左車線</strong>: <code>m &lt; -0.5</code></li>
<li class=""><strong>右車線</strong>: <code>m &gt; 0.5</code></li>
<li class=""><strong>路面ノイズ（横線）</strong>: <code>|m| &lt;= 0.5</code> は即座に棄却</li>
</ul>
<p>さらに <code>deque(maxlen=7)</code> を用いてフレーム間の揺れ（ジッター）を除去します。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-幾何学的iou侵犯判定">3. 幾何学的IoU侵犯判定<a href="https://globaldevlog.com/ja/blog/2026-06-26-vision-anpr-2#3-%E5%B9%BE%E4%BD%95%E5%AD%A6%E7%9A%84iou%E4%BE%B5%E7%8A%AF%E5%88%A4%E5%AE%9A" class="hash-link" aria-label="3. 幾何学的IoU侵犯判定 への直接リンク" title="3. 幾何学的IoU侵犯判定 への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="車線侵犯IoU判定画面" src="https://globaldevlog.com/ja/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>
<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">check_lane_intrusion</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">vehicle_box</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> lane_polygon</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> threshold</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">0.05</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">    vx1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> vy1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> vx2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> vy2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> vehicle_box</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    vh </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> vy2 </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> vy1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    footprint </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> Polygon</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">vx1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> vy1 </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.7</span><span class="token operator" style="color:#393A34">*</span><span class="token plain">vh</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 punctuation" style="color:#393A34">(</span><span class="token plain">vx2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> vy1 </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0.7</span><span class="token operator" style="color:#393A34">*</span><span class="token plain">vh</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 punctuation" style="color:#393A34">(</span><span class="token plain">vx2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> vy2</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 punctuation" style="color:#393A34">(</span><span class="token plain">vx1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> vy2</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">    intersection </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> footprint</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">intersection</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">lane_polygon</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">area</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    iou </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> intersection </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> footprint</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">area</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"> iou </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> threshold</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> iou</span><br></div></code></pre></div></div>
<p><code>IoU &gt; 0.05</code> を超えた段階で侵犯フラグを有効化し、ナンバープレート検出器を起動します。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-次回予告">4. 次回予告<a href="https://globaldevlog.com/ja/blog/2026-06-26-vision-anpr-2#4-%E6%AC%A1%E5%9B%9E%E4%BA%88%E5%91%8A" class="hash-link" aria-label="4. 次回予告 への直接リンク" title="4. 次回予告 への直接リンク" translate="no">​</a></h2>
<p>第3編では、<strong>階層的物体検出（YOLOv3 + YOLOv5プレート専用モデル）<strong>と、GPU負荷を大幅に削減する</strong>CSRT追跡器の統合</strong>について解説します。</p>]]></content:encoded>
            <category>computer-vision</category>
            <category>anpr</category>
            <category>lane-detection</category>
            <category>hough-transform</category>
            <category>iou</category>
            <category>opencv</category>
            <category>python</category>
        </item>
        <item>
            <title><![CDATA[[Vision AI] ドライブレコーダー車線侵犯検知＆超解像ANPR: 6段階パイプラインとリアルタイム設計課題 (#1)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-06-25-vision-anpr-1</link>
            <guid>https://globaldevlog.com/ja/blog/2026-06-25-vision-anpr-1</guid>
            <pubDate>Thu, 25 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[動的車線検出、IoU侵犯判定、YOLOv5ナンバープレート検出、EDSR超解像復元、OCR投票アンサンブルを統合した6段階ビジョンシステムのアーキテクチャ設計。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="6段階ANPRパイプライン構成図" src="https://globaldevlog.com/ja/assets/images/01_pipeline_diagram-fb1b5567c4acb0cd59bd89773f15c5c8.png" width="2200" height="900" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>Key Takeaways (要約)</strong></p>
<ul>
<li class=""><strong>課題</strong>: ドラレコの低解像度映像は、車体振動、逆光、モーションブラー、強いH.264圧縮ノイズにより、ナンバープレートが著しく潰れ、車線侵犯のリアルタイム追跡が極めて困難です。</li>
<li class=""><strong>解決策</strong>: Canny/Hough動的車線抽出 -&gt; YOLOv3車両検出 -&gt; 多角形IoU侵犯判定 -&gt; YOLOv5プレート局所検出 -&gt; EDSR_x4深層超解像復元 -&gt; EasyOCR時間軸多数決投票という6段階の階層型パイプラインを設計しました。</li>
<li class=""><strong>成果</strong>: 過度なGPU負荷を回避し30 FPS以上を維持しながら、過酷なドラレコ環境下でも侵犯車両のナンバープレートを正確に確定するEnd-to-Endシステムを構築しました。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-プロジェクト背景-なぜドラレコ映像の認識は難しいのか">1. プロジェクト背景: なぜドラレコ映像の認識は難しいのか？<a href="https://globaldevlog.com/ja/blog/2026-06-25-vision-anpr-1#1-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E8%83%8C%E6%99%AF-%E3%81%AA%E3%81%9C%E3%83%89%E3%83%A9%E3%83%AC%E3%82%B3%E6%98%A0%E5%83%8F%E3%81%AE%E8%AA%8D%E8%AD%98%E3%81%AF%E9%9B%A3%E3%81%97%E3%81%84%E3%81%AE%E3%81%8B" class="hash-link" aria-label="1. プロジェクト背景: なぜドラレコ映像の認識は難しいのか？ への直接リンク" title="1. プロジェクト背景: なぜドラレコ映像の認識は難しいのか？ への直接リンク" translate="no">​</a></h2>
<p>高度道路交通システム（ITS）や自動交通違反取締において、**リアルタイム車線侵犯検知と自動ナンバープレート認識（ANPR）**は中核となる技術です。しかし実際の車載ドラレコ映像を処理する際には、多くの光学的・物理的障害に直面します:</p>
<ol>
<li class=""><strong>極端な低解像度とテクスチャの潰れ</strong>: 640x480フレーム内において、対象車両のナンバープレート領域はわずか30x15〜50x25ピクセル程度しかなく、文字の線画が完全に一体化してしまいます。</li>
<li class=""><strong>路面振動とローリングシャッター歪み</strong>: 走行中の段差や急ブレーキ、急な車線変更による角度変化が直線の幾何学的推定を妨げます。</li>
<li class=""><strong>リアルタイム処理のレイテンシ</strong>: 重大なフレーム単位の重層モデル適用は深刻なフレーム落ちを引き起こし、実時間の追跡を破綻させます。</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-6段階の階層型パイプラインアーキテクチャ">2. 6段階の階層型パイプラインアーキテクチャ<a href="https://globaldevlog.com/ja/blog/2026-06-25-vision-anpr-1#2-6%E6%AE%B5%E9%9A%8E%E3%81%AE%E9%9A%8E%E5%B1%A4%E5%9E%8B%E3%83%91%E3%82%A4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3" class="hash-link" aria-label="2. 6段階の階層型パイプラインアーキテクチャ への直接リンク" title="2. 6段階の階層型パイプラインアーキテクチャ への直接リンク" 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["ドラレコ生フレーム 640x480"] --&gt; L1["第1段階: Canny + Hough 動的車線抽出"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Raw --&gt; L2["第2段階: YOLOv3-tiny 車両領域検出"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L1 &amp; L2 --&gt; L3["第3段階: 車両底面＆車線ポリゴンIoU侵犯判定"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L3 -- 侵犯検知時 --&gt; L4["第4段階: 車両ROI内のYOLOv5プレート局所特定"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L4 --&gt; L5["第5段階: EDSR_x4 深層超解像4倍復元"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L5 --&gt; L6["第6段階: EasyOCR + 正規表現 + 時間軸多数決投票"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    L6 --&gt; Result["確定違反ナンバー: 64가1511"]</span><br></div></code></pre></div></div>
<p><img decoding="async" loading="lazy" alt="最終検出および認識結果" src="https://globaldevlog.com/ja/assets/images/02_final_result-02da50ebc7e87755c32fbc132dc9b992.png" width="2131" height="1599" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-主要システム設定値-config">3. 主要システム設定値 (<code>CONFIG</code>)<a href="https://globaldevlog.com/ja/blog/2026-06-25-vision-anpr-1#3-%E4%B8%BB%E8%A6%81%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E8%A8%AD%E5%AE%9A%E5%80%A4-config" class="hash-link" aria-label="3-主要システム設定値-config への直接リンク" title="3-主要システム設定値-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-次回予告">4. 次回予告<a href="https://globaldevlog.com/ja/blog/2026-06-25-vision-anpr-1#4-%E6%AC%A1%E5%9B%9E%E4%BA%88%E5%91%8A" class="hash-link" aria-label="4. 次回予告 への直接リンク" title="4. 次回予告 への直接リンク" translate="no">​</a></h2>
<p>第2編では、<strong>Cannyエッジ検出、確率的ハフ変換（HoughLinesP）、傾きフィルタリング数学</strong>、および車両バウンディングボックスと車線間の<strong>動的ポリゴンIoU侵犯判定アルゴリズム</strong>を詳しく解説します。</p>]]></content:encoded>
            <category>computer-vision</category>
            <category>anpr</category>
            <category>object-detection</category>
            <category>super-resolution</category>
            <category>opencv</category>
            <category>deep-learning</category>
            <category>python</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #23] Safety Wrapper導入と1学期最終発表]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-06-18-maeumjigi-23</link>
            <guid>https://globaldevlog.com/ja/blog/2026-06-18-maeumjigi-23</guid>
            <pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[最終成果物：二重の安全網を提供するSafety Wrapperガードレール構造を構築し、AWS EC2 GPU上での本番リアルタイム推論サービングを完遂した記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-5db6b43f8eb8d83178d8ba6f56f13f4f.png" width="720" height="405" class="img_ev3q"></p>
<p>6月に入り、マウムジギチームは1学期の主要な開発をすべて終え、<strong>安全網の構築</strong>と<strong>最終発表</strong>の準備に総力を傾けました。</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="21比率の勝利とsafety-wrapperの導入">2:1比率の勝利とSafety Wrapperの導入<a href="https://globaldevlog.com/ja/blog/2026-06-18-maeumjigi-23#21%E6%AF%94%E7%8E%87%E3%81%AE%E5%8B%9D%E5%88%A9%E3%81%A8safety-wrapper%E3%81%AE%E5%B0%8E%E5%85%A5" class="hash-link" aria-label="2:1比率の勝利とSafety Wrapperの導入 への直接リンク" title="2:1比率の勝利とSafety Wrapperの導入 への直接リンク" translate="no">​</a></h3>
<blockquote>
<p>「私たちが選んだモデルは何だった？」
「2:1に決定した。Safety Wrapperを適用してメイン大規模言語モデル(LLM)の安全装置として機能させる方法を企画して。」</p>
</blockquote>
<p>私たちは「感情対話」と「日常対話」を2:1の比率で混ぜたモデルを最終LLMに選びました。しかし、自殺予防チャットボットという特性上、致命的な誤答は一度たりとも許されません。
これを防ぐため、LLMの入出力を監視する**Safety Wrapper（安全フィルター）**を導入しました。高リスク状況が感知されれば、即座に危機対応プロトコルに転換されるようアーキテクチャを堅固にしました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="クラウドサーバー予算企画と最終発表">クラウドサーバー予算企画と最終発表<a href="https://globaldevlog.com/ja/blog/2026-06-18-maeumjigi-23#%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E4%BA%88%E7%AE%97%E4%BC%81%E7%94%BB%E3%81%A8%E6%9C%80%E7%B5%82%E7%99%BA%E8%A1%A8" class="hash-link" aria-label="クラウドサーバー予算企画と最終発表 への直接リンク" title="クラウドサーバー予算企画と最終発表 への直接リンク" translate="no">​</a></h3>
<blockquote>
<p>「g5.2xlargeを5ヶ月使用する予算はどうなる？」
「今までの進行状況をもとに、1学期_最終発表_マウムジギ.pptxを作成して！」</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="最終発表" src="https://globaldevlog.com/ja/assets/images/02_presentation-4d633f8f7c1e0375cfa80546d37e3291.png" width="720" height="405" class="img_ev3q"></p>
<p>夏休み中に実際のサービスと連動させるため、Amazon EC2 GPUサーバーの予算を算出しました。
そして6月18日、これまで開発したバックエンド、フロントエンド、人工知能(AI)のすべての成果を一堂に集め、<strong>1学期最終発表資料</strong>を完成させました！</p>
<p>これで長く険しかった1学期の開発が成功裏に幕を下ろしました。2学期にはさらに高度化されたサービスで戻ってきます！</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>Safety Wrapper</category>
            <category>クラウド</category>
            <category>キャップストーン</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #22] 4次ファインチューニング完成！アーキテクチャ設計と最終レポート]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-30-maeumjigi-22</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-30-maeumjigi-22</guid>
            <pubDate>Sat, 30 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[システムプロンプトの過学習による機械的な回答を防止するため、プロンプトマスキングと正規化を導入した第4次ファインチューニングの記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-5fcc23c7f36696eb5311e706c9d9eede.png" width="2495" height="1393" class="img_ev3q"></p>
<p>5月の最終週（27日〜30日）、私たちは待望の**4次ファインチューニング（fine_tuning_4）**の結果をまとめ、システムの骨格を固める作業に邁進しました。</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="最終チェックポイント4400とグラフ分析">最終チェックポイント4400とグラフ分析<a href="https://globaldevlog.com/ja/blog/2026-05-30-maeumjigi-22#%E6%9C%80%E7%B5%82%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%884400%E3%81%A8%E3%82%B0%E3%83%A9%E3%83%95%E5%88%86%E6%9E%90" class="hash-link" aria-label="最終チェックポイント4400とグラフ分析 への直接リンク" title="最終チェックポイント4400とグラフ分析 への直接リンク" translate="no">​</a></h3>
<p>日常対話と感情対話を混合して学習させた4次ファインチューニングモデルが、ついに最適の重みである<code>checkpoint-4400</code>を吐き出しました。</p>
<p>以前の学習では、日常的な対話を投げても深刻なカウンセリングモードで答えてしまう過学習問題がありましたが、データ混合比率の実験の結果、ついに「空気の読める」チャットボットに生まれ変わりました！すべての評価指標をグラフで視覚化し、性能差を一目で証明しました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="システムアーキテクチャ設計と最終レポート">システムアーキテクチャ設計と最終レポート<a href="https://globaldevlog.com/ja/blog/2026-05-30-maeumjigi-22#%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E8%A8%AD%E8%A8%88%E3%81%A8%E6%9C%80%E7%B5%82%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88" class="hash-link" aria-label="システムアーキテクチャ設計と最終レポート への直接リンク" title="システムアーキテクチャ設計と最終レポート への直接リンク" translate="no">​</a></h3>
<blockquote>
<p>「chatbot_architecture.html 生成完了」
「fine_tuning_4の遂行結果をレポート(.docx)で作成して。」</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="システムアーキテクチャ" src="https://globaldevlog.com/ja/assets/images/02_architecture-41f5095033492354eaf45a8553f49ff6.png" width="2541" height="1390" class="img_ev3q"></p>
<p>性能検証が終わったモデルを実際のアプリでサービスするため、<code>chatbot_architecture.html</code>という名前でシステム全体アーキテクチャとナレッジグラフ統合案を設計しました。</p>
<p>そして5月30日、人工知能(AI)の助けを借りて最終レポートを自動生成しました。レポートには、オリジナルモデルと私たちがファインチューニングしたモデルの実際の回答比較が赤裸々に盛り込まれており、これまでの苦労が無駄ではなかったことを証明してくれました。</p>
<p>これでマウムジギプロジェクトの息苦しかった5月開発日誌がすべて終わりました。6月にはどんな新しい挑戦が待っているのでしょうか？</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>アーキテクチャ</category>
            <category>キャップストーン</category>
            <category>最終レポート</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #21] データ混合比率の最適化と4次ファインチューニングへの突入]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-22-maeumjigi-21</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-22-maeumjigi-21</guid>
            <pubDate>Fri, 22 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[感情対話対日常対話の2:1黄金比学習を通じて、日常の質問には明快に答え、危機シグナルには深く共感する最高性能を達成した記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-a335ed829194fe04a7f1886ca95deda9.png" width="2531" height="1378" class="img_ev3q"></p>
<p>5月21日と22日、マウムジギチームは大規模データの生成と**4次ファインチューニング（fine_tuning_4）**の準備に突入しました。</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="感情対話と日常対話の綱引き">感情対話と日常対話の綱引き<a href="https://globaldevlog.com/ja/blog/2026-05-22-maeumjigi-21#%E6%84%9F%E6%83%85%E5%AF%BE%E8%A9%B1%E3%81%A8%E6%97%A5%E5%B8%B8%E5%AF%BE%E8%A9%B1%E3%81%AE%E7%B6%B1%E5%BC%95%E3%81%8D" class="hash-link" aria-label="感情対話と日常対話の綱引き への直接リンク" title="感情対話と日常対話の綱引き への直接リンク" translate="no">​</a></h3>
<p>3次ファインチューニングモデルをテストしている時、致命的な問題を発見しました。</p>
<blockquote>
<p>「haiku_predデータセットで学習させると、回答が感情カウンセリングに偏りすぎているようです。日常対話の能力を維持するにはどう学習させればいいですか？」</p>
</blockquote>
<p>私たちが目標とするのは「温かい共感を伝えるカウンセラー」ですが、ユーザーが「今日の天気は？」といった日常的な質問を投げた時にも過度に深刻に答えてしまう**過学習（Overfitting）**の兆候が見られました。これを解決するために、感情データと日常データを適切な比率で混ぜて学習させる実験を企画しました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="10000件のv6感情データセット生成">10,000件のv6感情データセット生成<a href="https://globaldevlog.com/ja/blog/2026-05-22-maeumjigi-21#10000%E4%BB%B6%E3%81%AEv6%E6%84%9F%E6%83%85%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88%E7%94%9F%E6%88%90" class="hash-link" aria-label="10,000件のv6感情データセット生成 への直接リンク" title="10,000件のv6感情データセット生成 への直接リンク" translate="no">​</a></h3>
<p>最高のデータセットを作るために、Anthropic アプリケーションプログラミングインターフェース(API)のバッチモードを使用して、なんと10,000件に達する感情対話データセットを生成しました。APIがバックグラウンドで処理され進行状況が分からないハプニングもありましたが、追加スクリプトで不足分を満たし完成させました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="感情-vs-日常の黄金比を探すfine_tuning_4">感情 vs 日常の黄金比を探す（fine_tuning_4）<a href="https://globaldevlog.com/ja/blog/2026-05-22-maeumjigi-21#%E6%84%9F%E6%83%85-vs-%E6%97%A5%E5%B8%B8%E3%81%AE%E9%BB%84%E9%87%91%E6%AF%94%E3%82%92%E6%8E%A2%E3%81%99fine_tuning_4" class="hash-link" aria-label="感情 vs 日常の黄金比を探す（fine_tuning_4） への直接リンク" title="感情 vs 日常の黄金比を探す（fine_tuning_4） への直接リンク" translate="no">​</a></h3>
<blockquote>
<p>「Emotion_train_dataset_v6.jsonlが完成しました。では、7:3比率、2:1比率、5:5比率のデータセットを作ってください。」
「今回の学習はデータセットの混合比率基準で進行します。」</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="比率実験" src="https://globaldevlog.com/ja/assets/images/02_ratio-aa49284ad0e0859f6efd82a31aa871ce.png" width="2507" height="1395" class="img_ev3q"></p>
<p>4次ファインチューニングは、人工知能(AI)の「日常性」と「専門性（カウンセリング）」を最も完璧に調和させるデータ比率を検証する舞台となりました！</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>データセット</category>
            <category>プロンプト</category>
            <category>キャップストーン</category>
        </item>
        <item>
            <title><![CDATA[[Webotsロボティクス] Sim-to-Real: Arduino Uno、HC-06 Bluetooth、ArUcoマーカー視覚追跡による実世界転移 (#5)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5</guid>
            <pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Webotsシミュレータで検証されたQ-Learning方策を実機2輪Arduino Unoロボットに移植し、天井Webカメラのホモグラフィ補正とArUcoマーカー視覚追跡により実環境自律走行を実現したSim-to-Real完結編。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="ArUcoマーカー視覚追跡画面" src="https://globaldevlog.com/ja/assets/images/01_aruco_vision-b5bd404f0b35979c465be925a4fac943.png" width="1280" height="720" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>要約 (TL;DR)</strong></p>
<ul>
<li class=""><strong>課題(Problem)</strong>: マイコン（Arduino Uno ATmega328P）の2KB SRAMによる計算制約、ホイールスリップやセンサノイズ、シミュレータ物理と実機ハードウェア間の<strong>Sim-to-Realギャップ（Reality Gap）</strong>。</li>
<li class=""><strong>解決(Solution)</strong>: PCが高レベルな画像処理とQ-Table推論を担当し、ArduinoはモータPWM駆動のみを担う**分散I/Oアーキテクチャ（HC-06 Bluetooth、115,200 baud）<strong>を構築。天井Webカメラの歪み補正と</strong>ArUcoマーカーホモグラフィ（<code>vision.py</code>）**によるリアルタイム(x, y, θ)位置追跡システムを実装。</li>
<li class=""><strong>結果(Result)</strong>: 仮想環境で学習済みの648-bin Q-Table重みのみを用いて、実機の1.2m × 1.2mアリーナで目標到達成功率86.7%を達成し、ハードウェア展開を完遂。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-sim-to-realの挑戦シミュレーションと現実の乖離">1. Sim-to-Realの挑戦：シミュレーションと現実の乖離<a href="https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5#1-sim-to-real%E3%81%AE%E6%8C%91%E6%88%A6%E3%82%B7%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E7%8F%BE%E5%AE%9F%E3%81%AE%E4%B9%96%E9%9B%A2" class="hash-link" aria-label="1. Sim-to-Realの挑戦：シミュレーションと現実の乖離 への直接リンク" title="1. Sim-to-Realの挑戦：シミュレーションと現実の乖離 への直接リンク" translate="no">​</a></h2>
<p>仮想環境（Webots）では摩擦係数が均一で、モータは指令通り正確に回転し、距離センサ値に反射ノイズはありません。しかし、現実のハードウェア環境は過酷です：</p>
<ol>
<li class=""><strong>計算資源の絶対的制約</strong>: ロボット本体の**Arduino Uno (ATmega328P)**はフラッシュメモリ32KB、SRAMがわずか2KBであり、ニューラルネットワークはおろか複雑な行列演算すら不可能です。</li>
<li class=""><strong>センサノイズと死角</strong>: 安価な超音波センサはアクリル壁面への入射角によって音波が反射し、距離を0と誤認するか最大値に跳ねる異常値が頻発します。</li>
<li class=""><strong>ホイールスリップと累積誤差（オドメトリドリフト）</strong>: 床面の微細な凹凸やバッテリ電圧降下により左右モータの回転数に差が生じ、直進指令でも車体が曲がる物理的誤差が発生します。</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-分散制御アーキテクチャpc頭脳--arduino筋肉">2. 分散制御アーキテクチャ：PC（頭脳） ↔ Arduino（筋肉）<a href="https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5#2-%E5%88%86%E6%95%A3%E5%88%B6%E5%BE%A1%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3pc%E9%A0%AD%E8%84%B3--arduino%E7%AD%8B%E8%82%89" class="hash-link" aria-label="2. 分散制御アーキテクチャ：PC（頭脳） ↔ Arduino（筋肉） への直接リンク" title="2. 分散制御アーキテクチャ：PC（頭脳） ↔ Arduino（筋肉） への直接リンク" translate="no">​</a></h2>
<p>この制約を克服するため、**「頭脳はPC、筋肉はArduino」**という分散制御戦略を採用しました。</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["天井カメラシステム (Ceiling Camera)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Cam["FHD Webカメラ (30 FPS)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Aruco["ArUcoマーカー検出 (DICT_4X4_50)&lt;br&gt;ホモグラフィ平面化 (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 (Python Engine)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Pose["ロボット位置・姿勢推定 (x, y, θ)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Disc["648-bin Discretizer"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        QL["Trained Q-Table (ε=0)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        BT_Host["HC-06 Bluetooth SPP (115200 baud)"]</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["実機モバイルロボット (Real Robot)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        BT_Slave["HC-06 Bluetooth受信"]</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["L298Nモータドライバ + DCギアモータ"]</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>ホストPCパイプライン</strong>: 天井Webカメラでアリーナ全体を俯瞰し、ロボット上部のArUcoマーカーを30fpsで追跡。平面座標<code>(x, y, θ)</code>を計算して648の離散状態にマッピングし、Q-Tableから最適な貪欲行動を抽出。</li>
<li class=""><strong>HC-06通信最適化</strong>: Bluetoothシリアルポートプロファイル（SPP）の往復遅延時間（RTT）を最小化するため、通信ボーレートを標準の9,600から<strong>115,200 bps</strong>に引き上げ、30〜50Hzのリアルタイム制御周期を実現。</li>
<li class=""><strong>Arduinoファームウェア (<code>arduino_firmware.ino</code>)</strong>: PCから行動バイト（0: 直進, 1: 後退, 2: 左旋回, 3: 右旋回）を受信すると、L298NモータドライバにPWM信号を出力して精密なパルス駆動を実行。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-天井webカメラのホモグラフィとarucoマーカー視覚追跡">3. 天井WebカメラのホモグラフィとArUcoマーカー視覚追跡<a href="https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5#3-%E5%A4%A9%E4%BA%95web%E3%82%AB%E3%83%A1%E3%83%A9%E3%81%AE%E3%83%9B%E3%83%A2%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%81%A8aruco%E3%83%9E%E3%83%BC%E3%82%AB%E3%83%BC%E8%A6%96%E8%A6%9A%E8%BF%BD%E8%B7%A1" class="hash-link" aria-label="3. 天井WebカメラのホモグラフィとArUcoマーカー視覚追跡 への直接リンク" title="3. 天井WebカメラのホモグラフィとArUcoマーカー視覚追跡 への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="ハードウェアセットアップとアリーナ較正" src="https://globaldevlog.com/ja/assets/images/02_hardware_setup-fddea6cef90bd71036b2aff5eef38f33.png" width="1707" height="1067" class="img_ev3q"></p>
<p>実アリーナ上でロボットの位置と障害物距離を正確に計測するため、<strong>OpenCVベースのコンピュータビジョンパイプライン</strong>を構築しました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-透視歪み補正とホモグラフィ変換-calib_autopy">📐 透視歪み補正とホモグラフィ変換 (<code>calib_auto.py</code>)<a href="https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5#-%E9%80%8F%E8%A6%96%E6%AD%AA%E3%81%BF%E8%A3%9C%E6%AD%A3%E3%81%A8%E3%83%9B%E3%83%A2%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E5%A4%89%E6%8F%9B-calib_autopy" class="hash-link" aria-label="-透視歪み補正とホモグラフィ変換-calib_autopy への直接リンク" title="-透視歪み補正とホモグラフィ変換-calib_autopy への直接リンク" translate="no">​</a></h3>
<ol>
<li class=""><strong>チェッカーボード歪み較正</strong>: 広角Webカメラレンズの樽型歪み（Barrel Distortion）を除去するため、チェッカーボードパターンを用いてカメラ内部パラメータ行列(K)と歪み係数(D)を事前算出。</li>
<li class=""><strong>ホモグラフィ変換 (Perspective Transform)</strong>: 傾斜したカメラ画角を1.2m × 1.2mの正方形トップダウンビューに射影するため、アリーナ四隅の座標からホモグラフィ変換行列（<code>homography.npy</code>）を生成。</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-arucoマーカー追跡実装-visionpy">💻 ArUcoマーカー追跡実装 (<code>vision.py</code>)<a href="https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5#-aruco%E3%83%9E%E3%83%BC%E3%82%AB%E3%83%BC%E8%BF%BD%E8%B7%A1%E5%AE%9F%E8%A3%85-visionpy" class="hash-link" aria-label="-arucoマーカー追跡実装-visionpy への直接リンク" title="-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"># ArUco辞書および検出パラメータの初期化</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">"""歪み補正画像からロボットの平面座標(x, y)と方位角(theta)を算出"""</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"># マーカーの前方エッジベクトルからロボットの向き(theta)を計算</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-トラブルシューティングと実機評価結果">4. トラブルシューティングと実機評価結果<a href="https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5#4-%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%A8%E5%AE%9F%E6%A9%9F%E8%A9%95%E4%BE%A1%E7%B5%90%E6%9E%9C" class="hash-link" aria-label="4. トラブルシューティングと実機評価結果 への直接リンク" title="4. トラブルシューティングと実機評価結果 への直接リンク" translate="no">​</a></h2>
<p>シミュレーションから実機への移行時に発生した課題と、そのエンジニアリング的解決策は以下の通りです：</p>
<table><thead><tr><th style="text-align:left">課題 (Troubleshooting)</th><th style="text-align:left">原因分析</th><th style="text-align:left">解決策 (Solution)</th></tr></thead><tbody><tr><td style="text-align:left"><strong>直進指令時に左右どちらかへ偏行</strong></td><td style="text-align:left">左右DCモータのギア比および摩擦の個体差</td><td style="text-align:left">キャリブレーションスクリプト（<code>ble_vision_turn_calib.py</code>）により左右PWMオフセットを動的補正</td></tr><tr><td style="text-align:left"><strong>Bluetooth通信途絶時の暴走</strong></td><td style="text-align:left">電波干渉によるパケット欠損時に直前指令を維持</td><td style="text-align:left">200ms以上パケット途絶で即時モータを停止するウォッチドッグ（Watchdog）をファームウェアに実装</td></tr><tr><td style="text-align:left"><strong>蛍光灯の反射によるマーカー見失い</strong></td><td style="text-align:left">天井照明がマーカーのアクリル表面で乱反射</td><td style="text-align:left">適応的二値化（Adaptive Threshold）の調整と前時刻カルマンフィルタ（Kalman Filter）による補間</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-最終実機走行結果">🏆 最終実機走行結果<a href="https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5#-%E6%9C%80%E7%B5%82%E5%AE%9F%E6%A9%9F%E8%B5%B0%E8%A1%8C%E7%B5%90%E6%9E%9C" class="hash-link" aria-label="🏆 最終実機走行結果 への直接リンク" title="🏆 最終実機走行結果 への直接リンク" translate="no">​</a></h3>
<ul>
<li class=""><strong>障害物回避・ゴール到達成功率</strong>: 実際の1.2m × 1.2mアリーナで30回の走行テストを実施した結果、**86.7%（26/30回成功）**の高い到達率を記録。</li>
<li class="">シミュレーションで学習した<strong>2,592個の純粋なQ-Tableパラメータのみ</strong>で、実世界の物理ノイズを克服して自律走行を達成しました。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-rl-q-learning-連載シリーズの完結にあたって">5. RL Q-Learning 連載シリーズの完結にあたって<a href="https://globaldevlog.com/ja/blog/2026-05-21-rl-qlearning-5#5-rl-q-learning-%E9%80%A3%E8%BC%89%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA%E3%81%AE%E5%AE%8C%E7%B5%90%E3%81%AB%E3%81%82%E3%81%9F%E3%81%A3%E3%81%A6" class="hash-link" aria-label="5. RL Q-Learning 連載シリーズの完結にあたって への直接リンク" title="5. RL Q-Learning 連載シリーズの完結にあたって への直接リンク" translate="no">​</a></h2>
<p>全5回にわたる<strong>RL Q-Learningプロジェクト</strong>開発日誌の連載が完結しました：</p>
<ol>
<li class=""><strong>#1</strong>: 648状態空間の離散化モデリングとTCPソケットIPC通信設計</li>
<li class=""><strong>#2</strong>: Tabular Q-Learning ε-減衰探索と多目的報酬シェイピング</li>
<li class=""><strong>#3</strong>: 12壁障害物アリーナでの局所解脱出とHeadless高速化自動実行</li>
<li class=""><strong>#4</strong>: <code>evaluate_qlearning</code> による決定論的定量評価とDQN・SARSAとの性能比較</li>
<li class=""><strong>#5</strong>: Arduino Uno、Bluetooth通信、ArUco視覚追跡によるSim-to-Real実機展開</li>
</ol>
<p>仮想シミュレータの構築から始まり、アルゴリズムの理論検証、大規模ヘッドレス自動化、そして実機組み込みハードウェアへの移植に至る強化学習ロボティクスの全工程を記録することができました。今後の新たなプロジェクト連載にもぜひご期待ください！</p>]]></content:encoded>
            <category>強化学習</category>
            <category>Sim-to-Real</category>
            <category>Arduino</category>
            <category>ロボティクス</category>
            <category>コンピュータビジョン</category>
            <category>ArUco</category>
            <category>Python</category>
        </item>
        <item>
            <title><![CDATA[[Webots ロボティクス] evaluate_qlearning: 決定論的走行の定量的評価とDQN・SARSA比較 (#4)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-20-rl-qlearning-4</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-20-rl-qlearning-4</guid>
            <pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[学習済みQ-Tableを用いた探索率ゼロ(ε=0)の決定論的評価パイプライン(evaluate_qlearning.py)、経路効率、近接衝突(Near-miss)、およびDQN・SARSAモデルとの総合ベンチマーク。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="成功率およびステップ数ベンチマーク" src="https://globaldevlog.com/ja/assets/images/01_eval_success_steps-1434c5fba2793b6877d335bf289ef59b.png" width="1170" height="650" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>キーポイント (TL;DR)</strong></p>
<ul>
<li class=""><strong>目的(Objective)</strong>: 学習中の探索ノイズを排除した状態（ε=0）において、実機投入可能な決定論的ポリシー（Greedy Policy）の走行信頼性と経路品質を定量評価。</li>
<li class=""><strong>評価方法(Methodology)</strong>: <code>evaluate_qlearning.py</code> を用いて5つの評価シードで合計30回の独立テストを実施。成功率、理論最短経路に対する走行効率、壁近接（Near-miss）頻度を精密測定。</li>
<li class=""><strong>成果(Result)</strong>: 12壁障害物アリーナにおいて93.3%の決定論的成功率と0.02msの超低遅延を達成し、ニューラルネットワークベースのDQNやSARSAを凌駕する実用性を実証。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-定量的評価パイプライン設計-evaluate_qlearningpy">1. 定量的評価パイプライン設計 (<code>evaluate_qlearning.py</code>)<a href="https://globaldevlog.com/ja/blog/2026-05-20-rl-qlearning-4#1-%E5%AE%9A%E9%87%8F%E7%9A%84%E8%A9%95%E4%BE%A1%E3%83%91%E3%82%A4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%B3%E8%A8%AD%E8%A8%88-evaluate_qlearningpy" class="hash-link" aria-label="1-定量的評価パイプライン設計-evaluate_qlearningpy への直接リンク" title="1-定量的評価パイプライン設計-evaluate_qlearningpy への直接リンク" translate="no">​</a></h2>
<p>学習中の報酬曲線には探索ノイズが含まれるため、実機に搭載する**決定論的ポリシー（$\epsilon = 0$）**の真の実力を測る専用の評価エンジンを構築しました。</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["学習済みQテーブル&lt;br&gt;(qlearning_qtable.npy)"] --&gt; Agent["Greedy Agent&lt;br&gt;(ε = 0 固定)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    EvalSeeds["5つの評価シード&lt;br&gt;(EVAL_SEEDS 0..4)"] --&gt; Webots["Webotsシミュレータ&lt;br&gt;(30回反復テスト)"]</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["ログ出力&lt;br&gt;(eval_log.csv / traces)"]</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-アルゴリズム比較-q-learning-vs-sarsa-vs-dqn">2. アルゴリズム比較: Q-Learning vs SARSA vs DQN<a href="https://globaldevlog.com/ja/blog/2026-05-20-rl-qlearning-4#2-%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E6%AF%94%E8%BC%83-q-learning-vs-sarsa-vs-dqn" class="hash-link" aria-label="2. アルゴリズム比較: Q-Learning vs SARSA vs DQN への直接リンク" title="2. アルゴリズム比較: Q-Learning vs SARSA vs DQN への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="走行品質と各種指標" src="https://globaldevlog.com/ja/assets/images/02_eval_quality-42dd1fc5e31c5e63d48c26ece24e8936.png" width="1625" height="585" class="img_ev3q"></p>
<p>同一のWebots障害物環境において、3種類の強化学習アルゴリズムをベンチマーク比較しました:</p>
<table><thead><tr><th style="text-align:left">評価指標</th><th style="text-align:center">表形式Q-Learning（本手法）</th><th style="text-align:center">SARSA（オンポリシー）</th><th style="text-align:center">DQN（深層強化学習）</th></tr></thead><tbody><tr><td style="text-align:left"><strong>学習方式</strong></td><td style="text-align:center">オフポリシー TD(0)</td><td style="text-align:center">オンポリシー TD(0)</td><td style="text-align:center">ニューラルネットワーク</td></tr><tr><td style="text-align:left"><strong>モデルサイズ</strong></td><td style="text-align:center"><strong>約2.5 KB (2,592要素)</strong></td><td style="text-align:center">約2.5 KB</td><td style="text-align:center">約600 KB (~15万重み)</td></tr><tr><td style="text-align:left"><strong>決定論的成功率 (<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>平均走行ステップ数</strong></td><td style="text-align:center"><strong>41.2 ステップ</strong></td><td style="text-align:center">48.5 ステップ</td><td style="text-align:center">44.7 ステップ</td></tr><tr><td style="text-align:left"><strong>ステップあたり推論遅延</strong></td><td style="text-align:center"><strong>0.02 ms</strong> (配列参照)</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>壁接近リスク</strong></td><td style="text-align:center">低い（適切な迂回）</td><td style="text-align:center">極小（過度な安全重視）</td><td style="text-align:center">中程度</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-次回予告">3. 次回予告<a href="https://globaldevlog.com/ja/blog/2026-05-20-rl-qlearning-4#3-%E6%AC%A1%E5%9B%9E%E4%BA%88%E5%91%8A" class="hash-link" aria-label="3. 次回予告 への直接リンク" title="3. 次回予告 への直接リンク" translate="no">​</a></h2>
<p>次回最終第5回では、シミュレーションモデルを実際の <strong>Arduino Uno 2輪ロボットへ移植し、HC-06 Bluetooth通信、チェッカーボード歪み補正、ArUcoマーカービジョン追跡</strong>を組み合わせた Sim-to-Real の全容を公開します！</p>]]></content:encoded>
            <category>強化学習</category>
            <category>Q-learning</category>
            <category>性能評価</category>
            <category>ベンチマーク</category>
            <category>DQN</category>
            <category>SARSA</category>
            <category>ロボティクス</category>
            <category>Python</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #20] 3次ファインチューニング完了とバックエンド機能（データベース(DB)、掲示板）の高度化]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-20-maeumjigi-20</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-20-maeumjigi-20</guid>
            <pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[過度な共感による会話破綻を防ぐため、日常会話と感情危機対話の比率を精密に調整する第3次ファインチューニング戦略の設計記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-ac5e0126cfa930b87e044dbc1b82cc03.png" width="2519" height="1373" class="img_ev3q"></p>
<p>5月19日と20日の2日間は、3次ファインチューニング（<code>fine_tuning_3</code>）の評価自動化とともに、実際のアプリ（App）サービス構築のためのバックエンド/フロントエンド機能の高度化作業が並行して進められました。</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3次ファインチューニングの締めくくりと自動化スクリプト">3次ファインチューニングの締めくくりと自動化スクリプト<a href="https://globaldevlog.com/ja/blog/2026-05-20-maeumjigi-20#3%E6%AC%A1%E3%83%95%E3%82%A1%E3%82%A4%E3%83%B3%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%B7%A0%E3%82%81%E3%81%8F%E3%81%8F%E3%82%8A%E3%81%A8%E8%87%AA%E5%8B%95%E5%8C%96%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88" class="hash-link" aria-label="3次ファインチューニングの締めくくりと自動化スクリプト への直接リンク" title="3次ファインチューニングの締めくくりと自動化スクリプト への直接リンク" translate="no">​</a></h3>
<p>以前のファインチューニングで得たインサイトをもとに、ナレッジグラフとオントロジーの概念を意識してセッティングした3次ファインチューニングの学習が完了しました。</p>
<blockquote>
<p>「fine_tuning_3フォルダの実験モデルのうちBest Evalを持つチェックポイントを選別してadapterフォルダ内のファイルを入れ替えて。」</p>
</blockquote>
<p>手作業でチェックポイントをコピーする代わりに、人工知能(AI)にスクリプトを書くよう指示して、最も性能の良いモデルの重み（Best Checkpoint）を自動で抽出してセッティングしました。そして並列推論スクリプトを実行し、評価をバックグラウンドサーバーに投げておきました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="バックエンドフロントエンドチャットボットdb保存と掲示板機能完成">バックエンド/フロントエンド：チャットボットDB保存と掲示板機能完成<a href="https://globaldevlog.com/ja/blog/2026-05-20-maeumjigi-20#%E3%83%90%E3%83%83%E3%82%AF%E3%82%A8%E3%83%B3%E3%83%89%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%83%9C%E3%83%83%E3%83%88db%E4%BF%9D%E5%AD%98%E3%81%A8%E6%8E%B2%E7%A4%BA%E6%9D%BF%E6%A9%9F%E8%83%BD%E5%AE%8C%E6%88%90" class="hash-link" aria-label="バックエンド/フロントエンド：チャットボットDB保存と掲示板機能完成 への直接リンク" title="バックエンド/フロントエンド：チャットボットDB保存と掲示板機能完成 への直接リンク" translate="no">​</a></h3>
<p>モデルがサーバーで推論を回している間、ローカル環境では<code>mental-health</code> DBとアプリ連携作業に拍車をかけました。ログイン問題を突破するために<code>seed_data.sql</code>を解析し、パスワードのハッシュ化とユーザーデータを徹底的に検証しました。</p>
<p>その結果、5月20日の午後、意味深いGitコミットを一つ残すことができました。
<code>feat: チャットボットDB保存、掲示板ページネーション、感情日記フィルター追加</code></p>
<p><img decoding="async" loading="lazy" alt="アプリ機能" src="https://globaldevlog.com/ja/assets/images/02_app_feature-26d976bed8544fa566bd187f86d90617.png" width="2522" height="1384" class="img_ev3q"></p>
<p>ついに私たちがファインチューニングした大規模言語モデル(LLM)チャットボットの対話記録が、正式にDBに保存され始めました！さらに、コミュニティ掲示板のページネーション（Pagination）機能と、感情日記フィルター機能までフロントエンドへの実装に成功しました。目に見えなかった巨大なAIモデルが、ついにモバイルアプリという綺麗な器に盛られ始めた感激の瞬間でした。</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>バックエンド</category>
            <category>フロントエンド</category>
            <category>データベース</category>
            <category>キャップストーン</category>
        </item>
        <item>
            <title><![CDATA[[Webots ロボティクス] 12個の壁障害物と局所解(Local Minima)の克服: 複数シード並列学習 (#3)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-19-rl-qlearning-3</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-19-rl-qlearning-3</guid>
            <pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[12個の壁障害物環境(obstacle12)と高難易度マップ(obstacle_hard)において直面した局所的最適解（Local Minima）の克服と、Webots Headless高速化による3シード並列実験の分析。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="obstacle12 シミュレーション環境" src="https://globaldevlog.com/ja/assets/images/01_obstacle12_arena-bc2bc496b7ff2cdfe32dd9630f39bd68.png" width="1438" height="966" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>キーポイント (TL;DR)</strong></p>
<ul>
<li class=""><strong>課題(Problem)</strong>: 壁の背後に目標がある場合、距離差分報酬(+0.1 × Δdist)の貪欲な性質により壁を迂回できず正面衝突を繰り返し閉じ込められる**局所解（Local Minima）**が発生。</li>
<li class=""><strong>解決策(Solution)</strong>: 3方向超音波ヘッドスキャン（前方・左・右）状態情報と長期的割引率（γ=0.99）の結合 ＋ PowerShellによる**Webots Headless無人高速パイプライン（<code>headless_run.ps1</code>）**を構築し、3シード（Seed 0, 1, 2）の並列反復学習を実施。</li>
<li class=""><strong>成果(Result)</strong>: 12壁障害物環境においても平均600エピソード以降に90%以上の安定した到達成功率を達成し、確実な迂回ポリシー（Detour Policy）の獲得を実証。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-障害物環境における課題-local-minimaの罠">1. 障害物環境における課題: Local Minimaの罠<a href="https://globaldevlog.com/ja/blog/2026-05-19-rl-qlearning-3#1-%E9%9A%9C%E5%AE%B3%E7%89%A9%E7%92%B0%E5%A2%83%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E8%AA%B2%E9%A1%8C-local-minima%E3%81%AE%E7%BD%A0" class="hash-link" aria-label="1. 障害物環境における課題: Local Minimaの罠 への直接リンク" title="1. 障害物環境における課題: Local Minimaの罠 への直接リンク" translate="no">​</a></h2>
<p>障害物のない環境（<code>no_obstacle</code>）とは異なり、アリーナ内に**12個の壁障害物（<code>obstacle12</code>）**を配置すると深刻な走行ボトルネックが発生しました。</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["出発点 (Robot)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Wall["壁障害物 (Wall)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Goal["目標地点 (Goal)"]</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;|"直進（距離短縮を優先）"| Wall</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Wall -.-&gt;|"衝突＆スタック（局所解）"| Wall</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Start ==&gt;|"迂回ポリシー（Detour）&lt;br&gt;一時的な距離後退を許容"| Goal</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>ジレンマ</strong>: 目標が壁の向こう側にある場合、目標へ直進しようとすると必ず壁に衝突します。</li>
<li class=""><strong>報酬の逆効果</strong>: 迂回するためには一時的に目標から離れる（負の距離報酬）必要がありますが、近視眼的な行動はこれを避けるため、壁の前で空転するかタイムアウトするデッドロックに陥ります。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-解決戦略-ヘッドスキャン状態と価値の逆伝播">2. 解決戦略: ヘッドスキャン状態と価値の逆伝播<a href="https://globaldevlog.com/ja/blog/2026-05-19-rl-qlearning-3#2-%E8%A7%A3%E6%B1%BA%E6%88%A6%E7%95%A5-%E3%83%98%E3%83%83%E3%83%89%E3%82%B9%E3%82%AD%E3%83%A3%E3%83%B3%E7%8A%B6%E6%85%8B%E3%81%A8%E4%BE%A1%E5%80%A4%E3%81%AE%E9%80%86%E4%BC%9D%E6%92%AD" class="hash-link" aria-label="2. 解決戦略: ヘッドスキャン状態と価値の逆伝播 への直接リンク" title="2. 解決戦略: ヘッドスキャン状態と価値の逆伝播 への直接リンク" translate="no">​</a></h2>
<p>この局所解を克服できた要因は、**3方向障害物センサ（前方・左・右）<strong>と</strong>高い割引率（γ = 0.99）**の組み合わせです。</p>
<ol>
<li class=""><strong>知覚状態の拡張</strong>: 前方危険時に左右のヘッドスキャンで安全な方向を発見し、横方向への旋回を誘導。</li>
<li class=""><strong>長期的価値の伝播</strong>: 一時的な距離の後退があっても、壁を回って目標へ到達すれば大きな終端報酬（+1.0）が得られます。割引率 γ = 0.99 により、迂回行動の価値が逆順にQテーブルへ反映され、エージェントは迂回ポリシーを獲得します。</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-webots-headless-自動化パイプライン">3. Webots Headless 自動化パイプライン<a href="https://globaldevlog.com/ja/blog/2026-05-19-rl-qlearning-3#3-webots-headless-%E8%87%AA%E5%8B%95%E5%8C%96%E3%83%91%E3%82%A4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%B3" class="hash-link" aria-label="3. Webots Headless 自動化パイプライン への直接リンク" title="3. Webots Headless 自動化パイプライン への直接リンク" translate="no">​</a></h2>
<p>複数シード（Seed 0, 1, 2）による実験を効率化するため、GUIレンダリングを無効化した超高速モード（<code>--mode=fast --no-rendering</code>）を実行する <strong><code>headless_run.ps1</code></strong> を構築しました。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-学習曲線の比較分析">4. 学習曲線の比較分析<a href="https://globaldevlog.com/ja/blog/2026-05-19-rl-qlearning-3#4-%E5%AD%A6%E7%BF%92%E6%9B%B2%E7%B7%9A%E3%81%AE%E6%AF%94%E8%BC%83%E5%88%86%E6%9E%90" class="hash-link" aria-label="4. 学習曲線の比較分析 への直接リンク" title="4. 学習曲線の比較分析 への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="学習曲線の比較" src="https://globaldevlog.com/ja/assets/images/02_comparison_curves-0d241e07d5b445acc1866d00247179b7.png" width="1625" height="585" class="img_ev3q"></p>
<p>障害物なし環境と12壁障害物環境の比較結果:</p>
<ul>
<li class=""><strong>最終到達成功率</strong>: <code>no_obstacle</code> の98.5%に対し、<code>obstacle12</code> では <strong>91.4%〜94.8%</strong> を達成。</li>
<li class=""><strong>平均ステップ数</strong>: 直進主体の15〜22ステップから、迂回を含む <strong>38〜52ステップ</strong> へと適応。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-次回予告">5. 次回予告<a href="https://globaldevlog.com/ja/blog/2026-05-19-rl-qlearning-3#5-%E6%AC%A1%E5%9B%9E%E4%BA%88%E5%91%8A" class="hash-link" aria-label="5. 次回予告 への直接リンク" title="5. 次回予告 への直接リンク" translate="no">​</a></h2>
<p>次回第4回では、保存されたモデル（<code>models/*.npy</code>）を読み込み、純粋な決定論的走行の定量的評価を行う <strong><code>evaluate_qlearning.py</code> ベンチマークおよびDQN/SARSAとの性能比較</strong>をお届けします！</p>]]></content:encoded>
            <category>強化学習</category>
            <category>Q-learning</category>
            <category>Webots</category>
            <category>障害物回避</category>
            <category>局所解</category>
            <category>Headless</category>
            <category>Python</category>
        </item>
        <item>
            <title><![CDATA[[Webots ロボティクス] 表形式Q-Learningの実装と報酬関数(Reward Shaping)の最適化 (#2)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-18-rl-qlearning-2</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-18-rl-qlearning-2</guid>
            <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[WebotsモバイルロボットのTabular Q-Learning TD(0)更新数式、ε-Greedy探索減衰戦略、スパース報酬を克服する多目的報酬シェイピング(Dense Reward Shaping)のチューニングプロセスを詳しく解説します。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="学習報酬曲線" src="https://globaldevlog.com/ja/assets/images/01_reward_curve-dafe6b9a6b58ab351aa0d2717b504f0a.png" width="800" height="400" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>キーポイント (TL;DR)</strong></p>
<ul>
<li class=""><strong>課題(Problem)</strong>: 目標到達(+1.0)と壁衝突(-1.0)のみが与えられるスパース報酬（Sparse Reward）環境では、エージェントが偶然目標に遭遇するまで数千エピソードにわたり彷徨や空転を繰り返す。</li>
<li class=""><strong>解決策(Solution)</strong>: 目標とのユークリッド距離の変化量に比例するポテンシャル報酬(+0.1 × Δdist)と、ステップ(-0.01)、旋回(-0.01)、後退(-0.05)ペナルティを組み合わせた**多次元報酬シェイピング（Reward Shaping）**を設計。指数減衰ε-Greedy（1.0 → 0.05）戦略を適用。</li>
<li class=""><strong>成果(Result)</strong>: 障害物のない環境（<code>no_obstacle</code>）において500エピソード以内に移動平均報酬が正の値（0.7+）へ到達し、最終的な目標到達成功率98%以上を達成。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-表形式q-learning更新数式とエージェント設計">1. 表形式Q-Learning更新数式とエージェント設計<a href="https://globaldevlog.com/ja/blog/2026-05-18-rl-qlearning-2#1-%E8%A1%A8%E5%BD%A2%E5%BC%8Fq-learning%E6%9B%B4%E6%96%B0%E6%95%B0%E5%BC%8F%E3%81%A8%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E8%A8%AD%E8%A8%88" class="hash-link" aria-label="1. 表形式Q-Learning更新数式とエージェント設計 への直接リンク" title="1. 表形式Q-Learning更新数式とエージェント設計 への直接リンク" translate="no">​</a></h2>
<p>表形式Q-Learning（Tabular Q-Learning）は、ベルマン最適方程式に基づく**オフポリシー（Off-policy）時間差学習（TD(0)）**アルゴリズムです。</p>
<p>エージェントは行動価値関数 Q(s, a) を表す $648 \times 4$ のNumPy配列を保持し、環境からの遷移タプル $(s, a, r, s', done)$ を受け取って以下の数式でQ値を更新します。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-q-learning-td0-更新式">📐 Q-Learning TD(0) 更新式<a href="https://globaldevlog.com/ja/blog/2026-05-18-rl-qlearning-2#-q-learning-td0-%E6%9B%B4%E6%96%B0%E5%BC%8F" class="hash-link" aria-label="📐 Q-Learning TD(0) 更新式 への直接リンク" title="📐 Q-Learning 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>学習率 (α = 0.1)</strong>: 新しい経験が既存のQ値に反映される速度を調整。</li>
<li class=""><strong>割引率 (γ = 0.99)</strong>: 将来得られる報酬の現在価値を評価。</li>
<li class=""><strong>終端状態処理 (<code>1 - done</code>)</strong>: 目標到達や衝突時に将来価値をゼロにマスキング。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-指数減衰ε-greedy戦略">2. 指数減衰ε-Greedy戦略<a href="https://globaldevlog.com/ja/blog/2026-05-18-rl-qlearning-2#2-%E6%8C%87%E6%95%B0%E6%B8%9B%E8%A1%B0%CE%B5-greedy%E6%88%A6%E7%95%A5" class="hash-link" aria-label="2. 指数減衰ε-Greedy戦略 への直接リンク" title="2. 指数減衰ε-Greedy戦略 への直接リンク" translate="no">​</a></h2>
<p>初期学習時は環境の構造を広く知る必要があるため、**ε = 1.0 (100%ランダム探索)**から開始します。</p>
<p>探索率が高すぎると最適な経路を学習しても壁に衝突し続けるため、各エピソード終了時に以下の指数減衰を適用します:</p>
<p><strong>ε_(ep+1) = max(ε_min, ε_ep × 0.995)</strong></p>
<ul>
<li class=""><strong>1エピソード</strong>: ε = 1.0</li>
<li class=""><strong>300エピソード</strong>: ε ≈ 0.22</li>
<li class=""><strong>600エピソード</strong>: ε = 0.05 (下限到達、95%確率でGreedy行動を実行)</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-スパース報酬を克服する報酬関数の設計">3. スパース報酬を克服する報酬関数の設計<a href="https://globaldevlog.com/ja/blog/2026-05-18-rl-qlearning-2#3-%E3%82%B9%E3%83%91%E3%83%BC%E3%82%B9%E5%A0%B1%E9%85%AC%E3%82%92%E5%85%8B%E6%9C%8D%E3%81%99%E3%82%8B%E5%A0%B1%E9%85%AC%E9%96%A2%E6%95%B0%E3%81%AE%E8%A8%AD%E8%A8%88" class="hash-link" aria-label="3. スパース報酬を克服する報酬関数の設計 への直接リンク" title="3. スパース報酬を克服する報酬関数の設計 への直接リンク" translate="no">​</a></h2>
<table><thead><tr><th style="text-align:left">報酬項目</th><th style="text-align:center">設定値</th><th style="text-align:left">設計意図と物理的効果</th></tr></thead><tbody><tr><td style="text-align:left"><strong>目標到達 (<code>REWARD_GOAL</code>)</strong></td><td style="text-align:center"><strong>+1.0</strong></td><td style="text-align:left">目標到達成功時の正の終端報酬</td></tr><tr><td style="text-align:left"><strong>壁・障害物衝突 (<code>REWARD_COLLISION</code>)</strong></td><td style="text-align:center"><strong>-1.0</strong></td><td style="text-align:left">衝突失敗時の厳格なペナルティ</td></tr><tr><td style="text-align:left"><strong>距離差分報酬 (<code>REWARD_DELTA_SCALE</code>)</strong></td><td style="text-align:center"><strong>+0.1 × Δdist</strong></td><td style="text-align:left">目標へ近づいた距離に応じた即時報酬</td></tr><tr><td style="text-align:left"><strong>ステップ時間ペナルティ (<code>REWARD_STEP</code>)</strong></td><td style="text-align:center"><strong>-0.01</strong></td><td style="text-align:left">その場停止を防ぎ最短時間走行を誘導</td></tr><tr><td style="text-align:left"><strong>旋回ペナルティ (<code>REWARD_TURN</code>)</strong></td><td style="text-align:center"><strong>-0.01</strong></td><td style="text-align:left">不要なコマ回し回転行動を抑制</td></tr><tr><td style="text-align:left"><strong>後退ペナルティ (<code>REWARD_BACKWARD</code>)</strong></td><td style="text-align:center"><strong>-0.05</strong></td><td style="text-align:left">非効率な後退を抑え前進走行を推奨</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-学習曲線と成功率の検証">4. 学習曲線と成功率の検証<a href="https://globaldevlog.com/ja/blog/2026-05-18-rl-qlearning-2#4-%E5%AD%A6%E7%BF%92%E6%9B%B2%E7%B7%9A%E3%81%A8%E6%88%90%E5%8A%9F%E7%8E%87%E3%81%AE%E6%A4%9C%E8%A8%BC" class="hash-link" aria-label="4. 学習曲線と成功率の検証 への直接リンク" title="4. 学習曲線と成功率の検証 への直接リンク" translate="no">​</a></h2>
<p>1,500エピソードの学習を実施した結果、理論通りの収束を確認しました。</p>
<p><img decoding="async" loading="lazy" alt="成功率曲線" src="https://globaldevlog.com/ja/assets/images/02_success_curve-a47390e774a7a40ace8869f29884f2bd.png" width="800" height="400" class="img_ev3q"></p>
<p>100回移動平均成功率は <strong>98.5%</strong> を超え、エピソードあたりの平均ステップ数は150（タイムアウト）から <strong>15〜22ステップ</strong> まで大幅に短縮されました。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-次回予告">5. 次回予告<a href="https://globaldevlog.com/ja/blog/2026-05-18-rl-qlearning-2#5-%E6%AC%A1%E5%9B%9E%E4%BA%88%E5%91%8A" class="hash-link" aria-label="5. 次回予告 への直接リンク" title="5. 次回予告 への直接リンク" translate="no">​</a></h2>
<p>次回第3回では、12個の壁が配置された <strong><code>obstacle12</code> および高難易度 <code>obstacle_hard</code> 環境における局所的最適解（Local Minima）の罠と、複数シード並列学習</strong>について解説します！</p>]]></content:encoded>
            <category>強化学習</category>
            <category>Q-learning</category>
            <category>報酬関数</category>
            <category>Webots</category>
            <category>ロボティクス</category>
            <category>機械学習</category>
            <category>Python</category>
        </item>
        <item>
            <title><![CDATA[[Webots ロボティクス] Q-Learning 自律走行: 648状態空間の離散化とソケット通信アーキテクチャ (#1)]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-17-rl-qlearning-1</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-17-rl-qlearning-1</guid>
            <pubDate>Sun, 17 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Webotsロボットシミュレーション環境において、連続センサデータを648の離散状態空間へ圧縮するDiscretizerの設計と、TCPソケット通信に基づく強化学習(RL)アーキテクチャを解説します。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="Webots シミュレーション環境" src="https://globaldevlog.com/ja/assets/images/01_webots_arena-b49bd821fb90ed1d7e619add024bb5e7.png" width="1721" height="1033" class="img_ev3q"></p>
<blockquote>
<p>📌 <strong>キーポイント (TL;DR)</strong></p>
<ul>
<li class=""><strong>課題(Problem)</strong>: 連続的なセンサ距離・角度値による表形式Q-Learning（Tabular Q-Learning）の状態爆発と、Webotsシミュレータと外部Python学習スクリプト間のリアルタイム同期の負荷。</li>
<li class=""><strong>解決策(Solution)</strong>: 5次元の連続センサ入力を幾何学的な意味を持つ区間に分割し、3 × 8 × 3 × 3 × 3 = 648個の離散状態（Bin）にマッピング（<code>discretizer.py</code>）。TCPローカルソケット（Port 5000、Line-delimited JSON）によるIPC通信パイプラインを構築。</li>
<li class=""><strong>成果(Result)</strong>: O(1)の超高速Q-Table更新速度を確保し、32ms物理シミュレーションステップに適合した安定同期ループを実現。</li>
</ul>
</blockquote>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-プロジェクト背景-なぜwebotsとq-learningなのか">1. プロジェクト背景: なぜWebotsとQ-Learningなのか？<a href="https://globaldevlog.com/ja/blog/2026-05-17-rl-qlearning-1#1-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E8%83%8C%E6%99%AF-%E3%81%AA%E3%81%9Cwebots%E3%81%A8q-learning%E3%81%AA%E3%81%AE%E3%81%8B" class="hash-link" aria-label="1. プロジェクト背景: なぜWebotsとQ-Learningなのか？ への直接リンク" title="1. プロジェクト背景: なぜWebotsとQ-Learningなのか？ への直接リンク" translate="no">​</a></h2>
<p>自律走行ロボットが未知の室内環境で障害物を回避しながら目標地点（Target Goal）へ到達することは、ロボティクスにおける古典的かつ重要な課題です。深層強化学習（DQN、PPOなど）は複雑な環境に対応できる反面、計算資源の負荷が高く、モデル重みの解釈性（Interpretability）が低いという課題があります。</p>
<p>本プロジェクトでは、**数学的収束性が保証された最も直感的な表形式強化学習（Tabular Q-Learning、Off-policy TD(0)）**をWebots 3D物理シミュレータ上の差動駆動モバイルロボットに適用し、1.2m × 1.2mの室内アリーナでの安定した目標探索および障害物回避ポリシーの獲得を目指しました。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-全体システムアーキテクチャ-webots--python-ipc">2. 全体システムアーキテクチャ (Webots ↔ Python IPC)<a href="https://globaldevlog.com/ja/blog/2026-05-17-rl-qlearning-1#2-%E5%85%A8%E4%BD%93%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3-webots--python-ipc" class="hash-link" aria-label="2. 全体システムアーキテクチャ (Webots ↔ Python IPC) への直接リンク" title="2. 全体システムアーキテクチャ (Webots ↔ Python IPC) への直接リンク" translate="no">​</a></h2>
<p>システムは、**Webots物理環境コントローラ（Server）<strong>と</strong>強化学習アルゴリズムを実行するPythonクライアント（Client）**の2層に明確に分離されています。</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["Webots 3D シミュレータ (localhost:5000)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Robot["Supervisor ロボット&lt;br&gt;(超音波センサ + 車輪)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        HeadScan["ヘッドスキャン機構&lt;br&gt;(左右 1.1 rad サーボ回転)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Server["TCP ソケットサーバ&lt;br&gt;(Line-delimited JSON)"]</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["Python RL エンジン (Client)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Env["WebotsEnv (gym-like)&lt;br&gt;reset() / step()"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Disc["Discretizer&lt;br&gt;(連続値 → 0~647 Bin)"]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Agent["QLearningAgent&lt;br&gt;(Q-Table 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;-→|"request: {type: step, action: 0..3}&lt;br&gt;response: {state: [...], reward, done}"| Env</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Webotsコントローラ (<code>RL_controller.py</code>)</strong>: アクション実行ごとにロボット車輪を480ms（15 ticks × 32ms）駆動し、サーボモータでヘッドを左右1.1 rad（$\approx 63°$）回転させて死角の障害物距離を正確にスキャンします。</li>
<li class=""><strong>ソケット通信プロトコル</strong>: 改行区切りJSON（Line-delimited JSON）を採用し、通信オーバーヘッドを最小化。<!-- -->
<ul>
<li class="">リクエスト: <code>{"type": "step", "action": 0}</code> (0: 前進, 1: 後退, 2: 左旋回, 3: 右旋回)</li>
<li class="">レスポンス: <code>{"state": [0.45, 0.12, 0.35, 0.28, 0.40], "reward": 0.05, "done": false, "info": {...}}</code></li>
</ul>
</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-連続センサの648状態空間bin設計">3. 連続センサの648状態空間（Bin）設計<a href="https://globaldevlog.com/ja/blog/2026-05-17-rl-qlearning-1#3-%E9%80%A3%E7%B6%9A%E3%82%BB%E3%83%B3%E3%82%B5%E3%81%AE648%E7%8A%B6%E6%85%8B%E7%A9%BA%E9%96%93bin%E8%A8%AD%E8%A8%88" class="hash-link" aria-label="3. 連続センサの648状態空間（Bin）設計 への直接リンク" title="3. 連続センサの648状態空間（Bin）設計 への直接リンク" translate="no">​</a></h2>
<p>連続的な浮動小数点データを表形式Q-Learningで扱うため、幾何学的に重要な<strong>5つの観測変数</strong>を以下のように定義・分割しました。</p>
<table><thead><tr><th style="text-align:left">観測変数</th><th style="text-align:center">分割数</th><th style="text-align:left">閾値 (Thresholds)</th><th style="text-align:left">物理的意味</th></tr></thead><tbody><tr><td style="text-align:left"><strong>目標距離 (<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">近距離(Near), 中距離(Mid), 遠距離(Far)</td></tr><tr><td style="text-align:left"><strong>目標相対角度 (<code>goal_heading</code>)</strong></td><td style="text-align:center"><strong>8</strong></td><td style="text-align:left">[-π, π] を8等分（各 45°）</td><td style="text-align:left">前, 右前, 右, 右後, 後, 左後, 左, 左前</td></tr><tr><td style="text-align:left"><strong>前方障害物 (<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">危険/衝突寸前, 注意/接近, 安全</td></tr><tr><td style="text-align:left"><strong>左側障害物 (<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">危険, 注意, 安全</td></tr><tr><td style="text-align:left"><strong>右側障害物 (<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">危険, 注意, 安全</td></tr></tbody></table>
<p>総状態数:
<strong>N_states = 3 × 8 × 3 × 3 × 3 = 648</strong></p>
<p>これにより、Q-Tableのサイズはわずか <strong>648 × 4 = 2,592要素</strong>に大幅圧縮され、PCメモリ上でミリ秒未満の更新が可能となりました。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-ヘッドスキャン機構と衝突判定">4. ヘッドスキャン機構と衝突判定<a href="https://globaldevlog.com/ja/blog/2026-05-17-rl-qlearning-1#4-%E3%83%98%E3%83%83%E3%83%89%E3%82%B9%E3%82%AD%E3%83%A3%E3%83%B3%E6%A9%9F%E6%A7%8B%E3%81%A8%E8%A1%9D%E7%AA%81%E5%88%A4%E5%AE%9A" class="hash-link" aria-label="4. ヘッドスキャン機構と衝突判定 への直接リンク" title="4. ヘッドスキャン機構と衝突判定 への直接リンク" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="システムアーキテクチャ" src="https://globaldevlog.com/ja/assets/images/02_architecture-83a0cdfb8297ac248797b32bbc7fd69b.png" width="2000" height="900" class="img_ev3q"></p>
<ol>
<li class=""><strong>移動実行</strong>: 車輪モータを3.0 rad/sで480ms駆動。</li>
<li class=""><strong>ヘッド回転</strong>: 左へ+1.1 rad回転して左距離測定後、右へ-1.1 rad回転して右距離測定。</li>
<li class=""><strong>正面復帰</strong>: 0 radへ戻り前方距離を更新。</li>
<li class=""><strong>終了判定</strong>:<!-- -->
<ul>
<li class=""><strong>目標到達</strong>: 目標との距離 ≤ 0.10m → 成功 (<code>done = True</code>, 報酬 $+1.0$)</li>
<li class=""><strong>壁衝突</strong>: いずれかの距離 ≤ 0.08m → 失敗 (<code>done = True</code>, 報酬 $-1.0$)</li>
</ul>
</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-次回予告">5. 次回予告<a href="https://globaldevlog.com/ja/blog/2026-05-17-rl-qlearning-1#5-%E6%AC%A1%E5%9B%9E%E4%BA%88%E5%91%8A" class="hash-link" aria-label="5. 次回予告 への直接リンク" title="5. 次回予告 への直接リンク" translate="no">​</a></h2>
<p>第1回では、<strong>Webots仮想環境の構築、TCPソケットIPC通信、648状態空間の離散化</strong>をまとめました。</p>
<p>次回第2回では、<strong>Tabular Q-Learningの数式実装、ε-Greedy探索減衰戦略、シミュレーション環境での報酬関数（Reward Function）チューニング</strong>を詳しく解説します！</p>]]></content:encoded>
            <category>強化学習</category>
            <category>Q-learning</category>
            <category>Webots</category>
            <category>ロボティクス</category>
            <category>状態空間離散化</category>
            <category>Python</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #19] レポート自動化とバックエンドデータベース(DB)連携トラブルシューティング]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-17-maeumjigi-19</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-17-maeumjigi-19</guid>
            <pubDate>Sun, 17 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[キャップストーンデザイン中間発表のため、評価結果のExcel集計およびpython-pptxを活用したスライド自動生成パイプラインを構築した記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-12712349ddac15465e60572918ef40de.png" width="720" height="405" class="img_ev3q"></p>
<p>以前「5月13日がマウムジギ5月開発の最後になるだろう」と勘違いしていたことを訂正します！5月17日、ものすごい量のバックエンド連携テストとレポート作成作業が押し寄せました。</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="人工知能aiを活用したファインチューニング結果レポートの自動化">人工知能(AI)を活用したファインチューニング結果レポートの自動化<a href="https://globaldevlog.com/ja/blog/2026-05-17-maeumjigi-19#%E4%BA%BA%E5%B7%A5%E7%9F%A5%E8%83%BDai%E3%82%92%E6%B4%BB%E7%94%A8%E3%81%97%E3%81%9F%E3%83%95%E3%82%A1%E3%82%A4%E3%83%B3%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E7%B5%90%E6%9E%9C%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AE%E8%87%AA%E5%8B%95%E5%8C%96" class="hash-link" aria-label="人工知能(AI)を活用したファインチューニング結果レポートの自動化 への直接リンク" title="人工知能(AI)を活用したファインチューニング結果レポートの自動化 への直接リンク" translate="no">​</a></h3>
<p>2次ファインチューニング（<code>fine_tuning_2</code>）の膨大な結果グラフを一つずつ人間が分析して書くには時間が足りませんでした。</p>
<blockquote>
<p>「モデルの推論結果を比較するレポートを作成するためのプロンプトを作って。それに従ってレポートを作成して。」</p>
</blockquote>
<p>AIに結果指標を解釈させ、レポートの草案を自動で作成させるプロンプトエンジニアリングを試みました。結果として、AIが各モデルの長所と短所を分析し、立派なWord（.docx）レポートの草案を出力してくれました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="バックエンドdb連携と401-unauthorizedの沼">バックエンドDB連携と401 Unauthorizedの沼<a href="https://globaldevlog.com/ja/blog/2026-05-17-maeumjigi-19#%E3%83%90%E3%83%83%E3%82%AF%E3%82%A8%E3%83%B3%E3%83%89db%E9%80%A3%E6%90%BA%E3%81%A8401-unauthorized%E3%81%AE%E6%B2%BC" class="hash-link" aria-label="バックエンドDB連携と401 Unauthorizedの沼 への直接リンク" title="バックエンドDB連携と401 Unauthorizedの沼 への直接リンク" translate="no">​</a></h3>
<p>レポートが終わるやいなや、システム安定性をテストするために<code>backup.sql</code>データをローカルのPostgreSQL DBに流し込む作業を始めました。</p>
<blockquote>
<p>「ログイン成功したのにメニューを押しても反応がない」
「パスワードが間違っています... INFO: POST /auth/login 401 Unauthorized」</p>
</blockquote>
<p>DBダンプを流し込むことには成功しましたが、ログインできない<code>401 Unauthorized</code>エラーの地獄に陥りました。<code>debug_login.py</code>を作成し、uvicornサーバーを再起動させながら数十回のトラブルシューティングを行いました。</p>
<p><img decoding="async" loading="lazy" alt="DBトラブルシューティング" src="https://globaldevlog.com/ja/assets/images/02_db-1d0bb76370f8508377e9472ff5cb15c8.png" width="1373" height="5225" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ナレッジグラフknowledge-graphの導入検討">ナレッジグラフ（Knowledge Graph）の導入検討<a href="https://globaldevlog.com/ja/blog/2026-05-17-maeumjigi-19#%E3%83%8A%E3%83%AC%E3%83%83%E3%82%B8%E3%82%B0%E3%83%A9%E3%83%95knowledge-graph%E3%81%AE%E5%B0%8E%E5%85%A5%E6%A4%9C%E8%A8%8E" class="hash-link" aria-label="ナレッジグラフ（Knowledge Graph）の導入検討 への直接リンク" title="ナレッジグラフ（Knowledge Graph）の導入検討 への直接リンク" translate="no">​</a></h3>
<p>深夜、単純な大規模言語モデル(LLM)ファインチューニングの限界を克服するために、オントロジーとナレッジグラフ（Knowledge Graph）を融合する方案を新たに悩み始めました。5月中旬を過ぎて、プロジェクトの規模がますます巨大になっています！</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>レポート</category>
            <category>バックエンド</category>
            <category>DB</category>
            <category>トラブルシューティング</category>
            <category>キャップストーン</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #18] 推論トークン拡張と2次ファインチューニング結果比較]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-13-maeumjigi-18</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-13-maeumjigi-18</guid>
            <pubDate>Wed, 13 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[短く硬い回答を解決するためにmax_new_tokensを384に拡張し、LoRAのalpha値（8 vs 16）による回答の共感度の違いを分析した記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-4dcde4cef4209e81d49b5f5306af009d.png" width="1484" height="888" class="img_ev3q"></p>
<p>昨日発見したハードコーディングのバグをすべて修正し、ついにまともな2次ファインチューニングモデルの推論（Inference）テストを再開した5月13日です。</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="短い回答の原因トークンの長さを増やせ">短い回答の原因、トークンの長さを増やせ！<a href="https://globaldevlog.com/ja/blog/2026-05-13-maeumjigi-18#%E7%9F%AD%E3%81%84%E5%9B%9E%E7%AD%94%E3%81%AE%E5%8E%9F%E5%9B%A0%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E9%95%B7%E3%81%95%E3%82%92%E5%A2%97%E3%82%84%E3%81%9B" class="hash-link" aria-label="短い回答の原因、トークンの長さを増やせ！ への直接リンク" title="短い回答の原因、トークンの長さを増やせ！ への直接リンク" translate="no">​</a></h3>
<p>推論結果を一つ一つ紐解いていたところ、<code>Llama33-70B_a8</code>モデルが出した回答が相変わらず妙に短く、硬いことに気がつきました。</p>
<blockquote>
<p>「これはLlama33-70B_a8の回答の一つです。max_seq_lengthとmax_new_tokensが少なすぎると感じます。増やしたいです。VRAMの現状を見ると、どれくらい増やせますか？」</p>
</blockquote>
<p>人工知能(AI)とVRAMの空き容量（当時39.8GB）を計算した末、生成できる最大単語数である<code>max_new_tokens</code>を384に思い切って上方修正しました。結果は大成功でした！</p>
<p>単にトークンの許容量を増やしただけなのに、モデルが文脈を最後まで維持し、はるかに深く温かい共感の文章を注ぎ出し始めました。限られたトークン数に閉じ込められ、モデルが自ら言葉を出し惜しんでいたのです。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="alpha値の比較分析a8-vs-a16">Alpha値の比較分析（a=8 vs a=16）<a href="https://globaldevlog.com/ja/blog/2026-05-13-maeumjigi-18#alpha%E5%80%A4%E3%81%AE%E6%AF%94%E8%BC%83%E5%88%86%E6%9E%90a8-vs-a16" class="hash-link" aria-label="Alpha値の比較分析（a=8 vs a=16） への直接リンク" title="Alpha値の比較分析（a=8 vs a=16） への直接リンク" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="グラフの視覚化" src="https://globaldevlog.com/ja/assets/images/02_graph-feb5d1991f44dd7f378232f6b3515752.png" width="2053" height="1460" class="img_ev3q"></p>
<p>2次ファインチューニングの最大の目的であったLoRAハイパーパラメータ<code>alpha</code>値による性能差の結果も出ました。ログを分析して<code>05_alpha_comparison_daily.png</code>などのグラフを生成しました。<code>rank=16</code>に固定された状態で<code>alpha=8</code>を与えた時と<code>alpha=16</code>を与えた時で、モデルの過学習（Overfitting）の様相と最終回答の質がどう変わるのかを明確に視覚化することができました。</p>
<p>結果として、正しいハイパーパラメータと十分なトークンの長さを与えられたモデルたちは、ついに私たちが当初企画していた「真のマウムジギ」の姿に近づいていました。中間発表の準備がとても順調に終わりそうです！</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>推論</category>
            <category>max_new_tokens</category>
            <category>共感能力</category>
            <category>キャップストーン</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #17] 2次ファインチューニング完了と評価自動化パイプラインの罠]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-12-maeumjigi-17</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-12-maeumjigi-17</guid>
            <pubDate>Tue, 12 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[修正されたプロンプト形式とLoRAハイパーパラメータ調整を適用し、第2次ファインチューニングを実行して学習収束度を検証した記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-14a3c0d517e4c85b93ada4e973112325.png" width="2000" height="1457" class="img_ev3q"></p>
<p>LoRAハイパーパラメータのミス（alpha/rank設定エラー）を正すために野心的に始めた2次ファインチューニング（<code>fine_tuning_2</code>）並列学習が、5月12日ついに終わりました！</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bestチェックポイント抽出と推論パイプラインの構築">Bestチェックポイント抽出と推論パイプラインの構築<a href="https://globaldevlog.com/ja/blog/2026-05-12-maeumjigi-17#best%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E6%8A%BD%E5%87%BA%E3%81%A8%E6%8E%A8%E8%AB%96%E3%83%91%E3%82%A4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%AE%E6%A7%8B%E7%AF%89" class="hash-link" aria-label="Bestチェックポイント抽出と推論パイプラインの構築 への直接リンク" title="Bestチェックポイント抽出と推論パイプラインの構築 への直接リンク" translate="no">​</a></h3>
<p>3つのモデルに対して6つのハイパーパラメータの組み合わせで回したファインチューニングがすべて完了しました。すぐに<code>eval_loss</code>を比較して最も性能が良い最高（Best）のチェックポイントを抽出し、モデルごとの<code>adapter</code>フォルダに移す作業を進めました。</p>
<blockquote>
<p>「現在HCX-Text-1p5Bモデルが15分間で12個生成しました。GPU Utilは各グラフィックカードにつき1.6GB...」</p>
</blockquote>
<p>しかし、推論速度は依然として絶望的でした。最も軽い1.5Bモデルでさえ、1分間に1つの回答も作成できていませんでした。VRAM使用量は1.6GBしかないのに、バッチサイズが1に設定されているためボトルネックが発生したのです。さらにサーバーの容量不足問題まで重なり、プロジェクトの基本パスを急いで移行する騒動もありました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ハードコーディングの罠に陥る">ハードコーディングの罠に陥る<a href="https://globaldevlog.com/ja/blog/2026-05-12-maeumjigi-17#%E3%83%8F%E3%83%BC%E3%83%89%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E7%BD%A0%E3%81%AB%E9%99%A5%E3%82%8B" class="hash-link" aria-label="ハードコーディングの罠に陥る への直接リンク" title="ハードコーディングの罠に陥る への直接リンク" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="ハードコーディングバグ" src="https://globaldevlog.com/ja/assets/images/02_bug-900bd56611b3d6521891bcc956843259.png" width="2000" height="1457" class="img_ev3q"></p>
<p>そうやって苦労して評価コードをすべて回した後、鳥肌が立つような事実を発見しました。</p>
<blockquote>
<p>「なぜ20_eval_ft_models.ipynbのMODEL_ALIAS = 'Qwen35-9B_a16'のように1つのモデルにハードコーディングされているのか？」
「ファイル名とモデル名が違うのが正常だということ？」</p>
</blockquote>
<p>そうです。評価自動化スクリプトを作成する際に、誤って<code>MODEL_ALIAS</code>をハードコーディングしてしまったのです。HCXモデルをテストすると言ってファイルを一生懸命コピーして回していましたが、実際のコード内ではずっと<code>Qwen35-9B_a16</code>モデルばかりを呼び出して、同じ推論を繰り返していたのです！明日このバグを修正して推論をやり直さなければなりません。</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>最高性能</category>
            <category>チェックポイント</category>
            <category>ハードコーディング</category>
            <category>キャップストーン</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #16] 致命的なミスと2次ファインチューニング、そしてReact Nativeアプリ初起動]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-08-maeumjigi-16</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-08-maeumjigi-16</guid>
            <pubDate>Fri, 08 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[推論結果に現れたプロンプトテンプレートのハードコーディング汚染を逆追跡し、データセットのフォーマット欠陥を緊急修正した記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-9eab7db0dac5c88d9a120a99e5e703d4.png" width="1874" height="1526" class="img_ev3q"></p>
<p>5月8日は、これまで抽出したファインチューニングの結果を基にキャップストーンデザインの中間発表資料（PPT）を作成していた日でした。しかし、気分良くスライドを埋めていたところ、背筋が凍るようなとんでもないミスを発見してしまいました。</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="loraハイパーパラメータの致命的なミスを発見">LoRAハイパーパラメータの致命的なミスを発見<a href="https://globaldevlog.com/ja/blog/2026-05-08-maeumjigi-16#lora%E3%83%8F%E3%82%A4%E3%83%91%E3%83%BC%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%81%AE%E8%87%B4%E5%91%BD%E7%9A%84%E3%81%AA%E3%83%9F%E3%82%B9%E3%82%92%E7%99%BA%E8%A6%8B" class="hash-link" aria-label="LoRAハイパーパラメータの致命的なミスを発見 への直接リンク" title="LoRAハイパーパラメータの致命的なミスを発見 への直接リンク" translate="no">​</a></h3>
<p>PPTに入れるモデル構造図とハイパーパラメータ情報を人工知能(AI)と一緒に手直ししていました。</p>
<blockquote>
<p>「ファインチューニング結果の例を見ると、base modelよりも回答が短くなっています。これはLoRAのrを8にし、alphaを16にして中間特徴量を減らしすぎたためだと思いますが...」
「え、a/rだったの？私はr/aだと思ってたんだけど...??? 私は本当にLoRAを欲張って反映してしまったんだな...」</p>
</blockquote>
<p>LoRAファインチューニング時、<code>alpha</code>値は通常<code>rank</code>値と同じか2倍にするのが定石です。ところが、計算式の適用比率を完全に逆だと勘違いし、重みの更新が極端に抑え込まれたり、過剰に跳ね返ったりするように設定してしまっていたのです。どうりでファインチューニングされたモデルの回答の長さが途切れ途切れで短くなるわけだ、原因は私の手元にありました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2次ファインチューニングfine_tuning_2の決断">2次ファインチューニング（fine_tuning_2）の決断<a href="https://globaldevlog.com/ja/blog/2026-05-08-maeumjigi-16#2%E6%AC%A1%E3%83%95%E3%82%A1%E3%82%A4%E3%83%B3%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0fine_tuning_2%E3%81%AE%E6%B1%BA%E6%96%AD" class="hash-link" aria-label="2次ファインチューニング（fine_tuning_2）の決断 への直接リンク" title="2次ファインチューニング（fine_tuning_2）の決断 への直接リンク" translate="no">​</a></h3>
<p>すでに1次結果は出ていましたが、完璧な「マウムジギ」のためにこのまま進むわけにはいきませんでした。すぐに<code>fine_tuning_2</code>フォルダを作成し、2次ファインチューニングを決断しました。</p>
<blockquote>
<p>「今回使用するモデルはHCX-Text-1p5B, Llama33-70B, Qwen35-9Bです。MIG-0ではrankは16、alphaは16に、MIG-1ではrank=16、a=8に設定して学習を進めて。」
「Daily_train_dataset.jsonlから最も長いデータ上位2000個を抽出して、Daily_train_dataset_long.jsonlというタイトルのファイルを作成して。」</p>
</blockquote>
<p>回答が短くなる現象を防ぐために、テキストの長さが最も長い上位2000個のデータセットのみを別途抽出し、MIG（Multi-Instance GPU）リソースを分割してrankとalphaの比率による性能差を直接比較する並列学習を新たに回し始めました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="バックエンドモデルが回っている間フロントエンドアプリ開発に着手">バックエンドモデルが回っている間、フロントエンド（アプリ）開発に着手<a href="https://globaldevlog.com/ja/blog/2026-05-08-maeumjigi-16#%E3%83%90%E3%83%83%E3%82%AF%E3%82%A8%E3%83%B3%E3%83%89%E3%83%A2%E3%83%87%E3%83%AB%E3%81%8C%E5%9B%9E%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E9%96%93%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA%E3%81%AB%E7%9D%80%E6%89%8B" class="hash-link" aria-label="バックエンドモデルが回っている間、フロントエンド（アプリ）開発に着手 への直接リンク" title="バックエンドモデルが回っている間、フロントエンド（アプリ）開発に着手 への直接リンク" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="アプリ開発" src="https://globaldevlog.com/ja/assets/images/02_app-9efe68797b061b7eda0d68995627a8cc.png" width="1476" height="1526" class="img_ev3q"></p>
<p>モデルが再び学習のサイクルに入っている間、私はただ手をこまねいていたわけではありません。ついに実際のユーザーが「マウムジギ」に出会うことになるフロントエンドアプリの開発に着手しました！</p>
<blockquote>
<p>「maeum-appを起動するためにQRコードを表示しなければならないんだけど... npx go startと入力してもエラーメッセージしか表示されない。どうやって、そしてどこにQRコードが表示されるのかな？」</p>
</blockquote>
<p>React Native（Expo）を使って<code>maeum-app</code>プロジェクトを作成し、ローカルサーバーを立ち上げてスマートフォンと接続しようと奮闘しました。見当違いに<code>npx go start</code>と打ち込んで迷ったりもしましたが、ついにExpoのQRコードを表示し、アプリアイコン（<code>assets/logo.png</code>）を設定することに成功しました。バックエンドの頭脳（AI）とフロントエンドの顔（App）が同時に作られていく、胸が熱くなる一日でした。</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>LoRA</category>
            <category>ハイパーパラメータ</category>
            <category>ReactNative</category>
            <category>アプリ開発</category>
            <category>フロントエンド</category>
        </item>
        <item>
            <title><![CDATA[[マウムジギ 開発日誌 #15] 5モデルのファインチューニング結果の視覚化とローカル環境構築]]></title>
            <link>https://globaldevlog.com/ja/blog/2026-05-07-maeumjigi-15</link>
            <guid>https://globaldevlog.com/ja/blog/2026-05-07-maeumjigi-15</guid>
            <pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[各ファインチューニングモデルのPerplexityと評価指標を分析し、matplotlibを活用してモデル間の性能差を可視化した記録です。]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="カバー画像" src="https://globaldevlog.com/ja/assets/images/01_cover-b5ad981f0a0602b8afaf1bdbc982094d.png" width="1181" height="731" class="img_ev3q"></p>
<p>5月7日は、これまで苦労してファインチューニングした計5つのモデル（Llama3.3-70B, DSR1-70B, HCX-Omni-8B, Qwen35-9B, HCX-Text-1.5B）の結果を集大成し、本格的な視覚化とローカル環境の構築を進めた日です。</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="モデル比較のための視覚化とローカル環境設定">モデル比較のための視覚化とローカル環境設定<a href="https://globaldevlog.com/ja/blog/2026-05-07-maeumjigi-15#%E3%83%A2%E3%83%87%E3%83%AB%E6%AF%94%E8%BC%83%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E8%A6%96%E8%A6%9A%E5%8C%96%E3%81%A8%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E7%92%B0%E5%A2%83%E8%A8%AD%E5%AE%9A" class="hash-link" aria-label="モデル比較のための視覚化とローカル環境設定 への直接リンク" title="モデル比較のための視覚化とローカル環境設定 への直接リンク" translate="no">​</a></h3>
<p>これまで重いサーバー上で回していた結果比較コードを、個人のノートパソコンでも簡単に確認できるように、新しく<code>31_comparison_local.ipynb</code>ノートブックを作成しました。</p>
<blockquote>
<p>「30_comparison.ipynbは私のノートパソコンでも動かせるのではないか？」</p>
</blockquote>
<p>VSCodeでローカルのJupyterカーネルを設定し、必要なライブラリをインストールする過程で、頻繁なカーネルのクラッシュや<code>ModuleNotFoundError</code>のようなエラーに直面しましたが、フォルダパスを合わせながら一歩一歩解決していきました。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5モデル総合レポートとグラフ視覚化">5モデル総合レポートとグラフ視覚化<a href="https://globaldevlog.com/ja/blog/2026-05-07-maeumjigi-15#5%E3%83%A2%E3%83%87%E3%83%AB%E7%B7%8F%E5%90%88%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%E3%81%A8%E3%82%B0%E3%83%A9%E3%83%95%E8%A6%96%E8%A6%9A%E5%8C%96" class="hash-link" aria-label="5モデル総合レポートとグラフ視覚化 への直接リンク" title="5モデル総合レポートとグラフ視覚化 への直接リンク" translate="no">​</a></h3>
<p>最も重要な作業は、これら5つのモデルのパフォーマンスを一目で比較できる視覚化でした。AIと共に計画書を作成し、体系的にデータ整理を始めました。</p>
<blockquote>
<p>「薄い線と太い線の違いは何か？各モデルのtraining lossとeval lossを取得してグラフとして視覚化して。」
「太い線は消して、薄い線をはっきりと変更して保存して。」</p>
</blockquote>
<p>AIが描いてくれたmatplotlibのグラフから不要なトレンド線（太い線）を取り除き、モデルごとのTraining LossとEval Lossの曲線をきれいに1か所にまとめた<code>03_training_loss_all.png</code>と<code>04_eval_loss_all.png</code>を最終的に抽出しました。</p>
<p><img decoding="async" loading="lazy" alt="グラフの視覚化" src="https://globaldevlog.com/ja/assets/images/02_graph-8f91ee1a78e9220a703c6884ad9a4f40.png" width="1785" height="735" class="img_ev3q"></p>
<p>これらのグラフを基に、来週のキャップストーンデザインの中間発表資料を立派に飾ることができるようになりました。果たして、この5つのモデルのうちどれが最も優れた「マウムジギ」チャットボットとして最終選定されるのでしょうか？</p>]]></content:encoded>
            <category>開発日誌</category>
            <category>ファインチューニング</category>
            <category>結果分析</category>
            <category>視覚化</category>
            <category>Jupyter</category>
            <category>キャップストーン</category>
            <category>人工知能(AI)</category>
        </item>
    </channel>
</rss>