implement ML model conversion, deploy models, and fix card detection noise

This commit is contained in:
10x Developer 2026-05-09 21:37:21 +02:00
parent ff1561a704
commit a084777e64
12 changed files with 51 additions and 47 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -18,15 +18,6 @@ const App = () => {
); );
}; };
const App = () => {
return (
<GameStateProvider>
<AppContent />
</GameStateProvider>
);
};
const AppContent = () => { const AppContent = () => {
const { gameState } = useGameStateContext(); const { gameState } = useGameStateContext();

View file

@ -98,9 +98,8 @@ const Detection: React.FC<DetectionProps> = ({ videoRef, canvasRef, onCardsDetec
// Enhanced card region detection specialized for Jass cards // Enhanced card region detection specialized for Jass cards
const findCardRegions = (imageData: ImageData, width: number, height: number): {x: number, y: number, width: number, height: number}[] => { const findCardRegions = (imageData: ImageData, width: number, height: number): {x: number, y: number, width: number, height: number}[] => {
const regions = []; const regions = [];
const step = 12; // Adjusted step for better detection const step = 24; // Increased step to reduce noise and overlapping detections
// Look for card-colored regions: typically white/gray cards with identifiable suit symbols
for (let y = 0; y < height; y += step) { for (let y = 0; y < height; y += step) {
for (let x = 0; x < width; x += step) { for (let x = 0; x < width; x += step) {
const i = (y * width + x) * 4; const i = (y * width + x) * 4;
@ -109,17 +108,11 @@ const Detection: React.FC<DetectionProps> = ({ videoRef, canvasRef, onCardsDetec
const b = imageData.data[i + 2]; const b = imageData.data[i + 2];
const brightness = (r + g + b) / 3; const brightness = (r + g + b) / 3;
// Card background brightness range (light cards) if (brightness > 200 && brightness < 255) {
if (brightness > 180 && brightness < 250) {
const region = getCardRegionWithShapeAnalysis(imageData, width, height, x, y, step); const region = getCardRegionWithShapeAnalysis(imageData, width, height, x, y, step);
if (region && region.width > 30 && region.height > 40) { if (region && region.width > 60 && region.height > 80) {
// Check that this is a proper rectangular card area by testing aspect ratio const aspectRatio = region.width / region.height;
const widthDiff = region.width; if (aspectRatio > 0.6 && aspectRatio < 1.4) {
const heightDiff = region.height;
const aspectRatio = widthDiff / heightDiff;
// Typical playing card aspect ratio (roughly 0.7 to 1.3)
if (aspectRatio > 0.7 && aspectRatio < 1.3) {
regions.push(region); regions.push(region);
} }
} }
@ -127,7 +120,20 @@ const Detection: React.FC<DetectionProps> = ({ videoRef, canvasRef, onCardsDetec
} }
} }
return regions; // Remove overlapping regions to avoid "dozens of nonsense cards"
const uniqueRegions = [];
regions.sort((a, b) => (a.width * a.height) - (b.width * b.height));
for (const region of regions) {
const isOverlapping = uniqueRegions.some(u =>
Math.abs(u.x - region.x) < 30 && Math.abs(u.y - region.y) < 30
);
if (!isOverlapping) {
uniqueRegions.push(region);
}
}
return uniqueRegions;
}; };
// Improved card region extraction with shape analysis for more accurate detection // Improved card region extraction with shape analysis for more accurate detection

View file

@ -80,7 +80,12 @@ const ResultsScreen: React.FC = () => {
<div className="cards-grid"> <div className="cards-grid">
{gameState.detectedCards.map(card => ( {gameState.detectedCards.map(card => (
<div key={card.id} className="card-preview"> <div key={card.id} className="card-preview">
<div className="card-suit"></div> <div className="card-suit">
{card.suit === 'Schellen' && '🔔'}
{card.suit === 'Schilten' && '🛡️'}
{card.suit === 'Eicheln' && '🌰'}
{card.suit === 'Rosen' && '🌹'}
</div>
<div className="card-value">{card.value || '?'}pts</div> <div className="card-value">{card.value || '?'}pts</div>
</div> </div>
))} ))}

View file

@ -13,7 +13,7 @@ class CardModelService {
private readonly VALUE_MODEL_PATH = '/models/value_model/model.json'; private readonly VALUE_MODEL_PATH = '/models/value_model/model.json';
private readonly SUIT_LABELS = ['Schellen', 'Schilten', 'Eicheln', 'Rosen']; private readonly SUIT_LABELS = ['Schellen', 'Schilten', 'Eicheln', 'Rosen'];
private readonly VALUE_LABELS = ['6', '7', '8', '9', '10', '11', '12', '13']; private readonly VALUE_LABELS = ['6', '7', '8', '9', '10', '11', '12', '13', '14'];
async init(): Promise<void> { async init(): Promise<void> {
try { try {