Files
mediaproc/docs/architecture/03-detection-pipeline.svg
2026-05-03 03:19:19 -03:00

177 lines
12 KiB
XML

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 14.1.2 (0)
-->
<!-- Title: detection_pipeline Pages: 1 -->
<svg width="410pt" height="901pt"
viewBox="0.00 0.00 410.00 901.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 897.24)">
<title>detection_pipeline</title>
<polygon fill="#0a0e17" stroke="none" points="-4,4 -4,-897.24 406.25,-897.24 406.25,4 -4,4"/>
<text xml:space="preserve" text-anchor="middle" x="201.12" y="-874.04" font-family="Helvetica,sans-Serif" font-size="16.00" fill="#0066ff">Detection Pipeline (core/detect/graph/nodes.py)</text>
<!-- extract_frames -->
<g id="node1" class="node">
<title>extract_frames</title>
<polygon fill="#121829" stroke="#1e2a4a" points="349.19,-865.74 194.44,-865.74 194.44,-829.74 349.19,-829.74 349.19,-865.74"/>
<text xml:space="preserve" text-anchor="middle" x="271.82" y="-850.79" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">extract_frames</text>
<text xml:space="preserve" text-anchor="middle" x="271.82" y="-837.29" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">(ffmpeg, fps from profile)</text>
</g>
<!-- filter_scenes -->
<g id="node2" class="node">
<title>filter_scenes</title>
<polygon fill="#121829" stroke="#1e2a4a" points="336.82,-792.74 206.82,-792.74 206.82,-756.74 336.82,-756.74 336.82,-792.74"/>
<text xml:space="preserve" text-anchor="middle" x="271.82" y="-777.79" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">filter_scenes</text>
<text xml:space="preserve" text-anchor="middle" x="271.82" y="-764.29" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">(scene&#45;change filter)</text>
</g>
<!-- extract_frames&#45;&gt;filter_scenes -->
<g id="edge1" class="edge">
<title>extract_frames&#45;&gt;filter_scenes</title>
<path fill="none" stroke="#4a5568" d="M271.82,-829.55C271.82,-821.97 271.82,-812.84 271.82,-804.28"/>
<polygon fill="#4a5568" stroke="#4a5568" points="275.32,-804.28 271.82,-794.28 268.32,-804.28 275.32,-804.28"/>
</g>
<!-- field_seg -->
<g id="node3" class="node">
<title>field_seg</title>
<polygon fill="#0d1a33" stroke="#1e2a4a" points="292.44,-719.74 139.19,-719.74 139.19,-683.74 292.44,-683.74 292.44,-719.74"/>
<text xml:space="preserve" text-anchor="middle" x="215.82" y="-704.79" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#0066ff">field_segmentation</text>
<text xml:space="preserve" text-anchor="middle" x="215.82" y="-691.29" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#0066ff">(HSV mask · GPU/WASM)</text>
</g>
<!-- filter_scenes&#45;&gt;field_seg -->
<g id="edge2" class="edge">
<title>filter_scenes&#45;&gt;field_seg</title>
<path fill="none" stroke="#4a5568" d="M258.26,-756.55C251.66,-748.18 243.58,-737.94 236.25,-728.64"/>
<polygon fill="#4a5568" stroke="#4a5568" points="239.13,-726.64 230.18,-720.96 233.63,-730.98 239.13,-726.64"/>
</g>
<!-- detect_objects -->
<g id="node5" class="node">
<title>detect_objects</title>
<polygon fill="#1a3a1a" stroke="#1e2a4a" points="312.94,-553.24 216.69,-553.24 216.69,-517.24 312.94,-517.24 312.94,-553.24"/>
<text xml:space="preserve" text-anchor="middle" x="264.82" y="-538.29" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#00c853">detect_objects</text>
<text xml:space="preserve" text-anchor="middle" x="264.82" y="-524.79" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#00c853">(YOLO · GPU)</text>
</g>
<!-- filter_scenes&#45;&gt;detect_objects -->
<g id="edge3" class="edge">
<title>filter_scenes&#45;&gt;detect_objects</title>
<path fill="none" stroke="#4a5568" d="M284,-756.64C290.55,-746.44 298.05,-732.94 301.82,-719.74 316.35,-668.74 313.7,-652.93 305.82,-600.49 303.79,-587.04 303.57,-583.05 296.82,-571.24 295.07,-568.19 293.02,-565.19 290.82,-562.3"/>
<polygon fill="#4a5568" stroke="#4a5568" points="293.53,-560.09 284.4,-554.71 288.18,-564.61 293.53,-560.09"/>
</g>
<!-- detect_edges -->
<g id="node4" class="node">
<title>detect_edges</title>
<polygon fill="#0d1a33" stroke="#1e2a4a" points="296.82,-636.49 112.82,-636.49 112.82,-600.49 296.82,-600.49 296.82,-636.49"/>
<text xml:space="preserve" text-anchor="middle" x="204.82" y="-621.54" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#0066ff">detect_edges</text>
<text xml:space="preserve" text-anchor="middle" x="204.82" y="-608.04" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#0066ff">(Canny + Hough · GPU/WASM)</text>
</g>
<!-- field_seg&#45;&gt;detect_edges -->
<g id="edge4" class="edge">
<title>field_seg&#45;&gt;detect_edges</title>
<path fill="none" stroke="#4a5568" d="M213.48,-683.51C212.09,-673.24 210.29,-659.94 208.69,-648.13"/>
<polygon fill="#4a5568" stroke="#4a5568" points="212.2,-647.92 207.39,-638.48 205.26,-648.86 212.2,-647.92"/>
<text xml:space="preserve" text-anchor="middle" x="225.22" y="-657.19" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8892a8">masks</text>
</g>
<!-- detect_edges&#45;&gt;detect_objects -->
<g id="edge5" class="edge">
<title>detect_edges&#45;&gt;detect_objects</title>
<path fill="none" stroke="#4a5568" stroke-dasharray="5,2" d="M217.54,-600.26C225.6,-589.35 236.18,-575.02 245.29,-562.68"/>
<polygon fill="#4a5568" stroke="#4a5568" points="247.88,-565.07 251,-554.94 242.25,-560.91 247.88,-565.07"/>
<text xml:space="preserve" text-anchor="middle" x="265.41" y="-573.94" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8892a8">region hints</text>
</g>
<!-- preprocess -->
<g id="node6" class="node">
<title>preprocess</title>
<polygon fill="#121829" stroke="#1e2a4a" points="344.07,-469.99 185.57,-469.99 185.57,-433.99 344.07,-433.99 344.07,-469.99"/>
<text xml:space="preserve" text-anchor="middle" x="264.82" y="-455.04" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">preprocess</text>
<text xml:space="preserve" text-anchor="middle" x="264.82" y="-441.54" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">(crop · contrast · deskew)</text>
</g>
<!-- detect_objects&#45;&gt;preprocess -->
<g id="edge6" class="edge">
<title>detect_objects&#45;&gt;preprocess</title>
<path fill="none" stroke="#4a5568" d="M264.82,-517.01C264.82,-506.74 264.82,-493.44 264.82,-481.63"/>
<polygon fill="#4a5568" stroke="#4a5568" points="268.32,-481.99 264.82,-471.99 261.32,-481.99 268.32,-481.99"/>
<text xml:space="preserve" text-anchor="middle" x="277.94" y="-490.69" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8892a8">boxes</text>
</g>
<!-- run_ocr -->
<g id="node7" class="node">
<title>run_ocr</title>
<polygon fill="#1a3a1a" stroke="#1e2a4a" points="306.57,-396.99 223.07,-396.99 223.07,-360.99 306.57,-360.99 306.57,-396.99"/>
<text xml:space="preserve" text-anchor="middle" x="264.82" y="-382.04" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#00c853">run_ocr</text>
<text xml:space="preserve" text-anchor="middle" x="264.82" y="-368.54" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#00c853">(OCR · GPU)</text>
</g>
<!-- preprocess&#45;&gt;run_ocr -->
<g id="edge7" class="edge">
<title>preprocess&#45;&gt;run_ocr</title>
<path fill="none" stroke="#4a5568" d="M264.82,-433.8C264.82,-426.22 264.82,-417.09 264.82,-408.53"/>
<polygon fill="#4a5568" stroke="#4a5568" points="268.32,-408.53 264.82,-398.53 261.32,-408.53 268.32,-408.53"/>
</g>
<!-- match_brands -->
<g id="node8" class="node">
<title>match_brands</title>
<polygon fill="#121829" stroke="#1e2a4a" points="333.19,-313.74 196.44,-313.74 196.44,-277.74 333.19,-277.74 333.19,-313.74"/>
<text xml:space="preserve" text-anchor="middle" x="264.82" y="-298.79" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">match_brands</text>
<text xml:space="preserve" text-anchor="middle" x="264.82" y="-285.29" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">(rapidfuzz vs session)</text>
</g>
<!-- run_ocr&#45;&gt;match_brands -->
<g id="edge8" class="edge">
<title>run_ocr&#45;&gt;match_brands</title>
<path fill="none" stroke="#4a5568" d="M264.82,-360.76C264.82,-350.49 264.82,-337.19 264.82,-325.38"/>
<polygon fill="#4a5568" stroke="#4a5568" points="268.32,-325.74 264.82,-315.74 261.32,-325.74 268.32,-325.74"/>
<text xml:space="preserve" text-anchor="middle" x="300.07" y="-334.44" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8892a8">text candidates</text>
</g>
<!-- escalate_vlm -->
<g id="node9" class="node">
<title>escalate_vlm</title>
<polygon fill="#1a3a1a" stroke="#1e2a4a" points="278.82,-230.49 166.82,-230.49 166.82,-194.49 278.82,-194.49 278.82,-230.49"/>
<text xml:space="preserve" text-anchor="middle" x="222.82" y="-215.54" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#00c853">escalate_vlm</text>
<text xml:space="preserve" text-anchor="middle" x="222.82" y="-202.04" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#00c853">(local VLM · GPU)</text>
</g>
<!-- match_brands&#45;&gt;escalate_vlm -->
<g id="edge9" class="edge">
<title>match_brands&#45;&gt;escalate_vlm</title>
<path fill="none" stroke="#4a5568" d="M253.63,-277.56C250.16,-271.97 246.44,-265.67 243.32,-259.74 240.25,-253.91 237.22,-247.53 234.47,-241.41"/>
<polygon fill="#4a5568" stroke="#4a5568" points="237.69,-240.03 230.48,-232.27 231.27,-242.83 237.69,-240.03"/>
<text xml:space="preserve" text-anchor="middle" x="268.07" y="-251.19" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8892a8">unresolved</text>
</g>
<!-- compile_report -->
<g id="node11" class="node">
<title>compile_report</title>
<polygon fill="#0d1a33" stroke="#1e2a4a" points="343.19,-36 194.44,-36 194.44,0 343.19,0 343.19,-36"/>
<text xml:space="preserve" text-anchor="middle" x="268.82" y="-21.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#0066ff">compile_report</text>
<text xml:space="preserve" text-anchor="middle" x="268.82" y="-7.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#0066ff">(timeline + brand stats)</text>
</g>
<!-- match_brands&#45;&gt;compile_report -->
<g id="edge11" class="edge">
<title>match_brands&#45;&gt;compile_report</title>
<path fill="none" stroke="#4a5568" d="M282.53,-277.29C286.71,-272.08 290.6,-266.06 292.82,-259.74 294.47,-255.02 292.91,-253.49 292.82,-248.49 291.26,-162.01 306.72,-137.93 285.82,-54 285.21,-51.55 284.41,-49.07 283.5,-46.62"/>
<polygon fill="#4a5568" stroke="#4a5568" points="286.79,-45.4 279.57,-37.65 280.38,-48.21 286.79,-45.4"/>
</g>
<!-- escalate_cloud -->
<g id="node10" class="node">
<title>escalate_cloud</title>
<polygon fill="#243056" stroke="#1e2a4a" points="240.57,-94.74 240.57,-125.5 185.65,-147.24 107.98,-147.24 53.06,-125.5 53.06,-94.74 107.98,-73 185.65,-73 240.57,-94.74"/>
<text xml:space="preserve" text-anchor="middle" x="146.82" y="-119.92" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">escalate_cloud</text>
<text xml:space="preserve" text-anchor="middle" x="146.82" y="-106.42" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">(Anthropic · Gemini</text>
<text xml:space="preserve" text-anchor="middle" x="146.82" y="-92.92" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">OpenAI · Groq)</text>
</g>
<!-- escalate_vlm&#45;&gt;escalate_cloud -->
<g id="edge10" class="edge">
<title>escalate_vlm&#45;&gt;escalate_cloud</title>
<path fill="none" stroke="#4a5568" d="M203.52,-194.11C198.01,-188.71 192.18,-182.58 187.32,-176.49 182.39,-170.32 177.58,-163.51 173.1,-156.69"/>
<polygon fill="#4a5568" stroke="#4a5568" points="176.34,-155.27 168.01,-148.72 170.44,-159.03 176.34,-155.27"/>
<text xml:space="preserve" text-anchor="middle" x="221.07" y="-167.94" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8892a8">still unresolved</text>
</g>
<!-- escalate_vlm&#45;&gt;compile_report -->
<g id="edge12" class="edge">
<title>escalate_vlm&#45;&gt;compile_report</title>
<path fill="none" stroke="#4a5568" d="M242.63,-194.26C247.42,-189.05 251.96,-182.97 254.82,-176.49 273.25,-134.61 273.61,-80.49 271.62,-47.83"/>
<polygon fill="#4a5568" stroke="#4a5568" points="275.12,-47.66 270.89,-37.94 268.14,-48.18 275.12,-47.66"/>
</g>
<!-- escalate_cloud&#45;&gt;compile_report -->
<g id="edge13" class="edge">
<title>escalate_cloud&#45;&gt;compile_report</title>
<path fill="none" stroke="#4a5568" d="M192.59,-75.31C207.2,-64.51 223.06,-52.8 236.51,-42.86"/>
<polygon fill="#4a5568" stroke="#4a5568" points="238.21,-45.96 244.17,-37.2 234.05,-40.33 238.21,-45.96"/>
</g>
</g>
</svg>