Files
ozone-tech_owl_prime/src/components/CVInspectionOverlay.tsx
root 35138c824c feat: add CV inspection overlay with visual effects
- Add CVInspectionOverlay component (industrial camera monitor style)
- Add inspectionViewModel adapter for playback → inspection data
- Add camera rig with overhead frame and laser emitters
- Add inspection zone highlight on belt
- Add animated scan line during detection
- Add bounding box wireframe during measurement
- Add shape outline (circle/square) during classification
- Show dimensions pass/fail, roundness warning, confidence warning
- Show C-priority indicator for edge cases

Tested on https://arhipovdan.ru/ — all phases display correctly
2026-07-09 14:07:50 +02:00

135 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* CV Inspection Overlay — industrial camera monitor style panel.
* Shows detection, measurement, and classification data.
*/
import type { InspectionData } from '../domain/inspectionViewModel';
interface CVInspectionOverlayProps {
data: InspectionData;
}
const SHAPE_ICONS: Record<string, string> = {
box: '▭',
cylinder: '⬤',
round: '◯',
irregular: '◇',
unknown: '?',
};
export default function CVInspectionOverlay({ data }: CVInspectionOverlayProps) {
if (!data.visible) return null;
const {
phaseLabel,
itemTitle,
shape,
dimensions,
roundness,
confidence,
isLowConfidence,
category,
command,
warning,
dimensionsFail,
roundnessFail,
cPriority,
} = data;
const confidencePercent = Math.round(confidence * 100);
const roundnessPercent = Math.round(roundness * 100);
const categoryColors: Record<string, string> = {
B: '#22c55e',
C: '#f97316',
D: '#8b5cf6',
};
return (
<div className="cv-overlay">
<div className="cv-header">
<span className="cv-icon">📷</span>
<span className="cv-title">CV INSPECTION</span>
<span className={`cv-status ${data.phase}`}>{phaseLabel}</span>
</div>
<div className="cv-body">
<div className="cv-row cv-item-row">
<span className="cv-label">ITEM</span>
<span className="cv-value">{itemTitle}</span>
</div>
<div className="cv-divider" />
<div className="cv-row">
<span className="cv-label">SHAPE</span>
<span className="cv-value cv-shape">
<span className="shape-icon">{SHAPE_ICONS[shape]}</span>
{shape}
</span>
</div>
<div className="cv-row cv-dims-row">
<span className="cv-label">SIZE</span>
<span className={`cv-value cv-dims ${dimensionsFail ? 'fail' : 'pass'}`}>
{dimensions.width} × {dimensions.depth} × {dimensions.height} mm
</span>
</div>
<div className="cv-row">
<span className="cv-label">ROUNDNESS</span>
<span className={`cv-value ${roundnessFail ? 'fail' : 'pass'}`}>
K = {(roundness).toFixed(2)} ({roundnessPercent}%)
{roundnessFail && <span className="cv-flag"> ⚠ ≥0.7</span>}
</span>
</div>
<div className="cv-row">
<span className="cv-label">CONFIDENCE</span>
<span className={`cv-value ${isLowConfidence ? 'warning' : ''}`}>
{confidencePercent}%
{isLowConfidence && <span className="cv-flag"> ⚠ LOW</span>}
</span>
</div>
<div className="cv-divider" />
{category && (
<div className="cv-row cv-result-row">
<span className="cv-label">CLASS</span>
<span
className="cv-value cv-category"
style={{ color: categoryColors[category] }}
>
{category}
{cPriority && <span className="cv-priority"> (C priority)</span>}
</span>
</div>
)}
<div className="cv-row cv-command-row">
<span className="cv-label">CMD</span>
<span
className="cv-value cv-command"
style={{ color: category ? categoryColors[category] : '#64748b' }}
>
{command}
</span>
</div>
{warning && (
<div className="cv-warning">
<span className="warning-icon">⚠</span>
<span className="warning-text">{warning}</span>
</div>
)}
</div>
<div className="cv-footer">
<span className="cv-live">● LIVE</span>
<span className="cv-fps">60 FPS</span>
</div>
</div>
);
}