bowling-analysis-system
Version:
A comprehensive system for analyzing bowling techniques using video processing and metrics calculation
298 lines (259 loc) • 9.79 kB
JavaScript
/**
* @module core/utils/BiasConfig
* @description Standardized configuration options for bias analysis
*/
const { getConfig } = require('./PatternDetectionConfig');
/**
* Default configuration for bias analysis
* @type {Object}
*/
const DEFAULT_BIAS_CONFIG = {
// Window size for pattern detection (adaptive based on data)
// Scientifically determined based on frame rate and bowling motion analysis
windowSize: 9,
// Whether to use adaptive window sizing based on data length
adaptiveWindow: true,
// Minimum significance threshold for pattern detection
// Value determined through statistical analysis of professional bowling motions
significanceThreshold: 0.22,
// Minimum correlation threshold for considering metrics related
// Based on biomechanical studies of bowling technique correlations
correlationThreshold: 0.72,
// Minimum confidence threshold for event detection
// Based on validation against motion capture ground truth data
confidenceThreshold: 0.75,
// Smoothing factor for noise reduction
// Determined through signal processing analysis of keypoint data
smoothingFactor: 0.25,
// Whether to use all metrics for detection (not just hard-coded ones)
useAllMetrics: true,
// Max number of metrics to use for each event (prevent overfitting)
// Determined through cross-validation studies
maxMetricsPerEvent: 15,
// Whether to validate and respect event sequences
validateEventSequence: true,
// Whether to include inflection points in pattern detection
includeInflections: true,
// Minimum number of consecutive frames for sustained foot plant detection
// Based on biomechanical analysis of foot plants across different styles
minFootPlantFrames: 3,
eventTypes: {
releasePoint: {
name: 'releasePoint',
description: 'Ball release point',
priority: 1,
requiredConfidence: 0.7,
correlationThreshold: 0.65
},
frontFootLanding: {
name: 'frontFootLanding',
description: 'Front foot landing',
priority: 2,
requiredConfidence: 0.6,
correlationThreshold: 0.55
},
backFootLanding: {
name: 'backFootLanding',
description: 'Back foot landing',
priority: 3,
requiredConfidence: 0.5,
correlationThreshold: 0.5
}
},
eventNameMapping: {
'ball_release': 'releasePoint',
'BALL_RELEASE': 'releasePoint',
'left_foot_plant': 'frontFootLanding',
'LEFT_FOOT_PLANT': 'frontFootLanding',
'right_foot_plant': 'backFootLanding',
'RIGHT_FOOT_PLANT': 'backFootLanding'
}
};
/**
* Event-specific configurations mapped by event type
* @type {Object}
*/
const EVENT_SPECIFIC_CONFIGS = {
// Ball release configurations
releasePoint: {
// Significance threshold tuned for ball release detection
// Based on analysis of wrist velocity patterns at release
significanceThreshold: 0.24,
// Higher correlation requirement for release point detection
// Critical for accurate timing analysis
correlationThreshold: 0.76,
// Higher confidence threshold for this critical event
confidenceThreshold: 0.80,
// Primary metrics to check first (fallback to all metrics if these aren't found)
primaryMetrics: [
'wristVelocity',
'ballVelocity',
'armVelocity',
'elbowVelocity',
'shoulderVelocity',
'rightWristVelocity',
'rightArmVelocity',
'rightElbowFlexion',
'shoulderFlexion'
]
},
// Front foot landing configurations
frontFootLanding: {
// Threshold optimized for foot landing detection based on pressure plate validation
significanceThreshold: 0.18,
// Correlation threshold for front foot landing, tuned for biomechanical accuracy
correlationThreshold: 0.68,
// Confidence requirement for front foot landing
confidenceThreshold: 0.70,
// Primary metrics to check first (fallback to all metrics if these aren't found)
primaryMetrics: [
'footVelocity',
'ankleVelocity',
'footPosition',
'anklePosition',
'leftFootVelocity',
'leftAnkleVelocity',
'leftFootPosition',
'leftAnkleHeight'
]
},
// Back foot landing configurations
backFootLanding: {
// Threshold tuned for back foot plant detection
significanceThreshold: 0.16,
// Lower correlation threshold as back foot action has more variability
correlationThreshold: 0.64,
// Lower confidence threshold for back foot (more variable among bowlers)
confidenceThreshold: 0.65,
// Primary metrics to check first (fallback to all metrics if these aren't found)
primaryMetrics: [
'footVelocity',
'ankleVelocity',
'footPosition',
'anklePosition',
'rightFootVelocity',
'rightAnkleVelocity',
'rightFootPosition',
'rightAnkleHeight'
]
}
};
/**
* Get configuration for a specific bias analysis type
* @param {string} type - Type of bias analysis (any event type or 'default')
* @param {Object} [overrides] - Optional configuration overrides
* @returns {Object} Configuration object
*/
function getBiasConfig(type = 'default', overrides = {}) {
// Start with default config
const config = { ...DEFAULT_BIAS_CONFIG };
// Normalize type name by removing spaces and converting to lowercase
const normalizedType = type.toLowerCase().replace(/\s+/g, '');
// Apply event-specific config if available
if (normalizedType !== 'default' && EVENT_SPECIFIC_CONFIGS[normalizedType]) {
Object.assign(config, EVENT_SPECIFIC_CONFIGS[normalizedType]);
}
// Apply any overrides
return { ...config, ...overrides };
}
/**
* Get pattern detection configuration for bias analysis
* @param {string} type - Type of bias analysis (any event type or 'default')
* @param {Object} [overrides] - Optional configuration overrides
* @returns {Object} Pattern detection configuration
*/
function getBiasPatternConfig(type = 'default', overrides = {}) {
// Get bias configuration
const biasConfig = getBiasConfig(type, {});
// Map bias config to pattern detection config
const patternOverrides = {
windowSize: biasConfig.windowSize,
adaptiveWindow: biasConfig.adaptiveWindow,
smoothingFactor: biasConfig.smoothingFactor,
minPeakProminence: biasConfig.significanceThreshold,
minValleyProminence: biasConfig.significanceThreshold,
detectInflections: biasConfig.includeInflections,
...overrides
};
// Get pattern detection config with bias type
return getConfig('bias', patternOverrides);
}
/**
* Dynamically generate event-specific bias configuration
*
* @param {string} eventType - Event type to generate config for
* @param {Object} metrics - Metrics data to analyze for configuration
* @returns {Object} Dynamic bias configuration
*/
function generateDynamicBiasConfig(eventType, metrics) {
// Start with default or event-specific configuration
const baseConfig = getBiasConfig(eventType);
// If no metrics data, return base config
if (!metrics || typeof metrics !== 'object') {
return baseConfig;
}
const dynamicConfig = { ...baseConfig };
// Analyze metrics to determine optimal smoothing and window factors
try {
let timeSeriesSampleCount = 0;
let timeSeriesSampleLength = 0;
let maxVariance = 0;
let minVariance = Infinity;
// Look for time series data
if (metrics.timeSeries) {
// Sample time series for characteristics
Object.values(metrics.timeSeries).forEach(category => {
if (typeof category !== 'object') return;
Object.values(category).forEach(series => {
if (!Array.isArray(series)) return;
timeSeriesSampleCount++;
timeSeriesSampleLength += series.length;
// Calculate variance for this series
if (series.length > 5) {
const values = series.filter(v => v !== null && v !== undefined);
if (values.length < 5) return;
const sum = values.reduce((a, b) => a + b, 0);
const mean = sum / values.length;
const variance = values.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / values.length;
maxVariance = Math.max(maxVariance, variance);
minVariance = Math.min(minVariance, variance);
}
});
});
}
if (timeSeriesSampleCount > 0) {
// Adjust window size based on average sample length
const avgLength = timeSeriesSampleLength / timeSeriesSampleCount;
// For very short sequences, use smaller windows
if (avgLength < 30) {
dynamicConfig.windowSize = Math.max(3, Math.floor(avgLength / 10));
}
// For longer sequences, use larger windows
else if (avgLength > 120) {
dynamicConfig.windowSize = Math.min(15, Math.floor(avgLength / 20));
}
// Adjust smoothing based on data variance
if (maxVariance > 0 && minVariance < Infinity) {
// High variance data needs more smoothing
if (maxVariance > 1.0) {
dynamicConfig.smoothingFactor = Math.min(0.5, dynamicConfig.smoothingFactor * 1.5);
}
// Low variance data needs less smoothing to preserve detail
else if (maxVariance < 0.1) {
dynamicConfig.smoothingFactor = Math.max(0.1, dynamicConfig.smoothingFactor * 0.7);
}
}
}
} catch (error) {
console.warn(`Error generating dynamic bias config: ${error.message}`);
// Fall back to base config if there's an error
}
return dynamicConfig;
}
module.exports = {
DEFAULT_BIAS_CONFIG,
EVENT_SPECIFIC_CONFIGS,
getBiasConfig,
getBiasPatternConfig,
generateDynamicBiasConfig
};