ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

检信ALLEMOTION VibrationAI 2.4.0 12维度情绪识别开源源代码

检信ALLEMOTION VibrationAI 2.4.0 12维度情绪识别开源源代码 检信ALLEMOTION VibrationAI 技术的核心是通过摄像头非接触式捕捉面部肌肉微振动频率、振幅、能量结合多模态AI模型在60秒内客观输出12维心理情绪指标如压力、攻击性。它的核心应用场景是大规模早期心理筛查可无缝集成到教育、医疗、安保、军工等领域的现有系统中为岗前测评、学生建档、社区预警等提供量化数据支撑有效补传统量表主观性强、效率低的短板 项目核心12维度技术开源如下如果需要帮助 请连携我们QQ 515164561QQ.COM12-Dimensional Emotion Quantification Fusion Engine.Implements PRD 4.6-4.9 | V2.4.0: Full log1p scaling on all 12 dimensions.All formulas match PRD. No hard-coded weights or thresholds in functions.import mathfrom typing import Dict, List, Optional, TupleDIMENSION_NAMES: List[str] [aggression, suspicion, stress, tension,inhibition, neuroticism, depression, self_regulation,energy, balance, confidence, happiness,]DEFAULT_WEIGHTS: Dict[str, float] {aggression: 0.12, suspicion: 0.11, stress: 0.10,tension: 0.10, inhibition: 0.09, neuroticism: 0.09,depression: 0.08, self_regulation: 0.07, energy: 0.06,balance: 0.06, confidence: 0.07, happiness: 0.05,}# V1.2.2: 人口学参数 — 年龄分组生理基线AGE_GROUP_PROFILES {child: {tag: 少年(8-17), hr_baseline: 85, hrv_baseline: 45},young: {tag: 青年(18-35), hr_baseline: 70, hrv_baseline: 35},middle: {tag: 中年(36-55), hr_baseline: 72, hrv_baseline: 30},senior: {tag: 老年(56), hr_baseline: 75, hrv_baseline: 25},}# V1.2.2: 人口学参数 — 性别生理基线GENDER_PROFILES {male: {hr_baseline: 70, hrv_baseline: 32, depression_bias: -5},female: {hr_baseline: 76, hrv_baseline: 38, depression_bias: 5},}def _clamp(value: float, low: float 0.0, high: float 100.0) - float:Clamp *value* to inclusive [*low*, *high*].return max(low, min(high, value))def _round2(value: float) - float:Round to two decimal places.return round(value, 2)# ---------------------------------------------------------------------------# PRD 4.6 -- Weighted Base Score# ---------------------------------------------------------------------------def calculate_base_score(emotion_vector: Dict[str, float],weights: Optional[Dict[str, float]] None,age_group: Optional[str] None,gender: Optional[str] None,) - float:S_base sum(w_i * x_i) over 12 dimensions, clamped [0, 100].V1.2.2: age_group and gender params accepted for future population-basedbaseline correction; currently forward-compatible placeholders.w weights if weights is not None else DEFAULT_WEIGHTStotal sum(w.get(d, 0.0) * emotion_vector.get(d, 0.0) for d in DIMENSION_NAMES)return _round2(_clamp(total))# ---------------------------------------------------------------------------# PRD 4.7 -- Global Variance Penalty# ---------------------------------------------------------------------------def calculate_global_variance(emotion_vector: Dict[str, float]) - float:Population variance sigma^2 (1/N) * sum((x_i - mu)^2) across 12 dims.vals [emotion_vector.get(d, 0.0) for d in DIMENSION_NAMES]n len(vals)if n 0:return 0.0mu sum(vals) / nreturn _round2(sum((v - mu) ** 2 for v in vals) / n)def calculate_penalty_coefficient(global_variance: float,lambda_param: float 0.8,) - float:K_std 1 - lambda * var_norm, clamped [0, 1].Normalises *global_variance* by dividing by 10000.0 (the maximumtheoretical variance for 12 dimensions bounded [0, 100]) so that thepenalty operates in a well-conditioned [0, 1] range.V1.2.1.1 fix: previously raw variance (0-2500) caused penalty tozero out at sigma^2 1.25, collapsing nearly all real data.var_norm global_variance / 10000.0return _round2(_clamp(1.0 - lambda_param * var_norm, 0.0, 1.0))# ---------------------------------------------------------------------------# PRD 4.8 -- Extreme-Value Correction# ---------------------------------------------------------------------------def check_extreme_dimensions(emotion_vector: Dict[str, float],high_threshold: float 80.0,low_threshold: float 15.0,) - dict:Return dict of dimensions exceeding high_thr or below low_thr with metadata.high_dims {d: v for d, v in emotion_vector.items() if v high_threshold}low_dims {d: v for d, v in emotion_vector.items() if v low_threshold}all_vals list(emotion_vector.values()) if emotion_vector else [0.0]return {high_dims: high_dims,low_dims: low_dims,has_high_risk: len(high_dims) 0,has_low_anomaly: len(low_dims) 0,high_count: len(high_dims),low_count: len(low_dims),max_value: _round2(max(all_vals)),min_value: _round2(min(all_vals)),extreme_count: len(high_dims) len(low_dims),}def calculate_extreme_correction(extreme_info: dict) - float:eta correction factor: high-risk0.85, mild anomaly0.92, normal1.00.if extreme_info.get(has_high_risk, False):return 0.85if extreme_info.get(has_low_anomaly, False):return 0.92return 1.0# ---------------------------------------------------------------------------# PRD 4.9 -- Final Comprehensive Score Risk Level# ---------------------------------------------------------------------------def calculate_final_score(base_score: float,penalty_coeff: float,extreme_correction: float,age_group: Optional[str] None,gender: Optional[str] None,) - float:S_all clamp(S_base * K_std * eta, 0, 100), rounded to 2 decimals.V1.2.2: age_group and gender params accepted for future population-basedcorrection; currently forward-compatible placeholders.return _round2(_clamp(base_score * penalty_coeff * extreme_correction))def determine_risk_level(final_score: float) - Tuple[str, str]:(risk_level, description). 85:良好 | 65:一般 | 40:欠佳 | 40:提醒.if final_score 85.0:return (良好, 情绪稳定、身心平和、状态良好)if final_score 65.0:return (一般, 情绪基本稳定、轻微波动、无风险)if final_score 40.0:return (欠佳, 情绪不稳定、负面情绪偏高、需关注)return (提醒, 情绪波动剧烈、存在高危心理风险)# # Single-Dimension Quantification Functions (12 dimensions)# Each: 3 params, 30 lines, clamp(expr, 0, 100)# Normal ranges specified per dimension as defined in PRD.# def quantify_aggression(high_freq_energy: float,jaw_motion: float,pulse_spike: float,) - float:Aggression via 8-15 Hz HF peak * jaw micro-motion * pulse spike. Normal:20-50.V1.2.2: Applied log1p scaling for robust range mapping.raw high_freq_energy * jaw_motion * pulse_spikeif raw 0.0:return 10.0scaled math.log1p(raw) * 13.0return _round2(_clamp(scaled, 10.0, 100.0))def quantify_stress(fullband_baseline: float,temporal_stability: float,) - float:Stress via full-band baseline * 1/stability. Normal:20-40.V1.2.2: Applied log1p scaling for robust range mapping.if temporal_stability 0.0:temporal_stability 1e-6raw fullband_baseline * (1.0 / temporal_stability)if raw 0.0:return 10.0scaled math.log1p(raw) * 8.0return _round2(_clamp(scaled, 10.0, 100.0))def quantify_tension(eye_high_freq_density: float,short_term_fluctuation: float,) - float:Tension via periocular HF density * short-term fluctuation. Normal:20-40.V1.2.2: Applied log1p scaling for robust range mapping.raw eye_high_freq_density * short_term_fluctuationif raw 0.0:return 10.0scaled math.log1p(raw) * 9.0return _round2(_clamp(scaled, 10.0, 100.0))def quantify_confidence(low_freq_ordered_ratio: float,stability_coeff: float,) - float:Confidence via LF ordered ratio * stability. Normal:40-100.V1.2.2: Applied log1p scaling for robust range mapping.M7: multiplier 22-28 to increase dynamic range, floor 25-20to restore frame-to-frame variance lost when S2 stability fixesnarrowed input range.raw low_freq_ordered_ratio * stability_coeffif raw 0.0:return 20.0 # M7: floor 25-20scaled math.log1p(raw) * 28.0 # M7: 22-28, amplify small differencesreturn _round2(_clamp(scaled, 20.0, 100.0)) # M7: floor 25-20def quantify_balance(phase_consistency: float,temporal_dispersion_inverse: float,) - float:Balance via phase consistency * temporal dispersion inverse. Normal:50-100.V1.2.2: Applied log1p scaling for robust range mapping.raw phase_consistency * temporal_dispersion_inverseif raw 0.0:return 20.0scaled math.log1p(raw) * 20.0return _round2(_clamp(scaled, 20.0, 100.0))def quantify_suspicion(muscle_stiffness: float,intermittent_spike: float,) - float:Suspicion via muscle stiffness * intermittent spike. Normal:20-50.V1.2.2: Applied log1p scaling for robust range mapping.raw muscle_stiffness * intermittent_spikeif raw 0.0:return 10.0scaled math.log1p(raw) * 12.0return _round2(_clamp(scaled, 10.0, 100.0))def quantify_energy(fullband_total_energy: float) - float:Energy via total vibration energy integral. Normal:10-50.Applies log1p-based scaling to map raw fullband energy into the expected10-50 normal range. Low inputs (5) remain near floor; mid-range inputs(10-60) map into 15-40; very high inputs asymptote toward ~50-75.if fullband_total_energy 0.0:return 10.0 # floor at normal minimum# log1p scaling: gentle compression to keep typical values in 10-50scaled math.log1p(fullband_total_energy) * 13.0return _round2(_clamp(scaled, 5.0, 75.0))def quantify_self_regulation(peak_decay_rate: float,recovery_speed: float,) - float:Self-regulation via peak decay rate * recovery speed. Normal:50-100.V1.2.2: Applied log1p scaling for robust range mapping.raw peak_decay_rate * recovery_speedif raw 0.0:return 25.0scaled math.log1p(raw) * 23.0return _round2(_clamp(scaled, 25.0, 100.0))def quantify_depression(low_freq_lethargy_ratio: float) - float:Depression via 0.1-3 Hz LF lethargic energy ratio. Normal:15-50.V1.2.2: Applied log1p scaling for robust range mapping.if low_freq_lethargy_ratio 0.0:return 10.0scaled math.log1p(low_freq_lethargy_ratio) * 10.0return _round2(_clamp(scaled, 10.0, 100.0))def quantify_neuroticism(high_freq_fluctuation: float,instability_coeff: float,) - float:Neuroticism via HF fluctuation * instability. Normal:10-60.V1.2.2: Applied log1p-based scaling to map the raw product intothe expected normal range, consistent with quantify_energy.Previously the theoretical maximum was 9.5 (9.5*1.0), far belowthe documented normal range bottom of 15. This was an omission bug-- only energy had log1p scaling applied in V1.2.1.raw high_freq_fluctuation * instability_coeffif raw 0.0:return 10.0scaled math.log1p(raw) * 20.0return _round2(_clamp(scaled, 10.0, 100.0))def quantify_inhibition(external_low_amp: float,internal_high_energy: float,) - float:Inhibition via external low-amp * internal high-energy. Normal:10-40.V1.2.2: Applied log1p scaling to constrain the product into thenarrow normal range. Previously the product range was 0.04-90.25with no scaling, causing both underflow (15) and overflow (25).The log1p*5.5 compression maps [0.04, 90.25] - [10.0, 24.8],covering the normal range 10-40 centrally.raw external_low_amp * internal_high_energyif raw 0.0:return 5.0 # M8: floor 10-5, match widened clampscaled math.log1p(raw) * 12.0 # M8: 5.5-12.0, widen inhibition dynamic rangereturn _round2(_clamp(scaled, 5.0, 60.0)) # M8: clamp [10,100]-[5,60]def quantify_happiness(low_freq_relax_ratio: float,pulse_stability: float,) - float:Happiness via LF relaxed ratio * pulse stability. Normal:30-80.V1.2.2: Applied log1p scaling for robust range mapping.raw low_freq_relax_ratio * pulse_stabilityif raw 0.0:return 15.0scaled math.log1p(raw) * 16.0return _round2(_clamp(scaled, 15.0, 100.0))# # Full 12-Dimension Vector Computation# }def compute_full_emotion_vector(features: dict,age_group: Optional[str] None,gender: Optional[str] None) - Dict[str, float]:Compute all 12 emotion dimensions from a signal-feature dictionary.Args:features: Dict of raw signal features keyed by feature name.Missing features default to 0.0.age_group: Optional age group key (child,young,middle,senior)for population-based baseline correction. Default None.gender: Optional gender key (male,female) for gender-basedphysiological bias correction. Default None.Returns:12-dim dict {dim_name: float} with values clamped [0, 100].result: Dict[str, float] {}for dim_name, (quantifier_fn, param_keys) in _FEATURE_MAP.items():args [features.get(k, 0.0) for k in param_keys]result[dim_name] quantifier_fn(*args)# V1.2.2: 性别偏差校正 - 抑郁评分受生理基线差异影响if gender is not None and gender in GENDER_PROFILES:profile GENDER_PROFILES[gender]bias profile.get(depression_bias, 0)if depression in result:result[depression] _round2(_clamp(result[depression] bias, 10.0, 100.0))return result# # Temporal Statistics# def _compute_per_dim_stats(sequence: List[Dict[str, float]],dim_names: List[str],) - Tuple[dict, List[float]]:Return per-dimension {mean, variance, max, min} and list of variances.n len(sequence)per_dim {}variances []for dim in dim_names:vals [frame.get(dim, 0.0) for frame in sequence]mu sum(vals) / nvar sum((v - mu) ** 2 for v in vals) / nper_dim[dim] {mean: _round2(mu),variance: _round2(var),max: _round2(max(vals)),min: _round2(min(vals)),}variances.append(var)return per_dim, variancesdef _derive_global_metrics(dim_variances: List[float]) - Tuple[float, float, float]:From per-dim variances: (global_variance, stability_coeff, combined_fluctuation).if not dim_variances:return 0.0, 0.0, 0.0mean_var sum(dim_variances) / len(dim_variances)sqrt_mv math.sqrt(mean_var)stability 1.0 / (1.0 sqrt_mv)return _round2(mean_var), _round2(stability), _round2(sqrt_mv)def compute_temporal_statistics(emotion_sequence: List[Dict[str, float]],) - dict:Compute per-dimension mean/variance/max/min, global variance, stability,and combined fluctuation over a time-series of 12-dim emotion vectors.Returns dict with keys: frame_count, per_dimension, global_variance,stability_coefficient, combined_fluctuation.if not emotion_sequence:return {frame_count: 0,per_dimension: {},global_variance: 0.0,stability_coefficient: 0.0,combined_fluctuation: 0.0,}per_dim, variances _compute_per_dim_stats(emotion_sequence, DIMENSION_NAMES)global_var, stability, fluctuation _derive_global_metrics(variances)return {frame_count: len(emotion_sequence),per_dimension: per_dim,global_variance: global_var,stability_coefficient: stability,combined_fluctuation: fluctuation,}
返回列表