bowling-analysis-system
Version:
A comprehensive system for analyzing bowling techniques using video processing and metrics calculation
105 lines (91 loc) • 3.29 kB
JavaScript
/**
* @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
};