UNPKG

bowling-analysis-system

Version:

A comprehensive system for analyzing bowling techniques using video processing and metrics calculation

105 lines (91 loc) 3.29 kB
/** * @module bowling_analysis * @description Main entry point for bowling motion analysis */ const { processBowlingMetrics } = require('./pipeline'); const { defaultLogger } = require('../utils/logger'); const { performance } = require('perf_hooks'); const systemConfig = require('../config/system-config'); /** * Process keypoint data for bowling metrics * @param {Array} keypointData - Array of keypoint frames * @param {Object} options - Processing options * @returns {Promise<Object>} Processed metrics and analysis */ async function processFrames(keypointData, options = {}) { const startTime = performance.now(); const logger = options.logger || defaultLogger.child('bowling-analysis'); try { // Process through pipeline logger.debug('Processing bowling metrics from keypoint data'); const pipelineResult = await processBowlingMetrics(keypointData, { ...options, outputPath: options.outputPath || null, preserveAllFrames: options.preserveAllFrames !== false, debug: options.debug || false, biasPath: options.biasFilePath }); // Map moments data to events const events = pipelineResult?.events || {}; const momentData = mapEventsToMoments(events, pipelineResult?.metrics, keypointData); const result = { metrics: pipelineResult?.metrics || {}, events, moments: momentData, metadata: { framesProcessed: keypointData.length, timings: { total: performance.now() - startTime, ...pipelineResult?.metadata?.timings || {} } } }; logger.debug(`Bowling analysis completed in ${result.metadata.timings.total.toFixed(2)}ms`); return result; } catch (error) { logger.error(`Error processing frames: ${error.message}`); throw error; } } /** * Map events to moments data with corresponding frame indices * @param {Object} events - Detected events * @param {Object} metrics - Processed metrics * @param {Array} keypointData - Original keypoint data * @returns {Object} Mapped moments data */ function mapEventsToMoments(events, metrics, keypointData) { const moments = {}; // Get the standard event names for (const eventName in events) { const standardEventName = systemConfig.getStandardEventName(eventName); const eventData = events[eventName]; // Skip if invalid frame if (!eventData || !keypointData || eventData.frame >= keypointData.length) { continue; } // Get the keypoints for this frame const keypointsData = keypointData[eventData.frame]; // Create moment data moments[standardEventName] = { name: standardEventName, frame: eventData.frame, confidence: eventData.confidence, keypoints: keypointsData, metrics: {} }; // Add metrics at this frame if available if (metrics && metrics.pointMetrics) { for (const metricKey in metrics.pointMetrics) { const metricData = metrics.pointMetrics[metricKey]; if (Array.isArray(metricData) && eventData.frame < metricData.length) { moments[standardEventName].metrics[metricKey] = metricData[eventData.frame]; } } } } return moments; } module.exports = { processFrames };