1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| import numpy as np from typing import Tuple, List from enum import Enum
class GazeRegion(Enum): """Euro NCAP 注视区域枚举""" ROAD_FORWARD = "road_forward" DRIVER_SIDE_WINDOW = "driver_side_window" PASSENGER_SIDE_WINDOW = "passenger_side_window" DRIVER_SIDE_MIRROR = "driver_side_mirror" PASSENGER_SIDE_MIRROR = "passenger_side_mirror" REAR_MIRROR = "rear_mirror" INSTRUMENT_CLUSTER = "instrument_cluster" CENTER_STACK = "center_stack" GLOVEBOX = "glovebox" DRIVER_FOOTWELL = "driver_footwell" DRIVER_LAP = "driver_lap" PHONE_DASHBOARD = "phone_dashboard" PHONE_LAP = "phone_lap" PASSENGER_FACE = "passenger_face"
class GazeRegionClassifier: """ 注视区域分类器 基于头部姿态和眼动向量判定驾驶员注视区域 """ def __init__(self): self.camera_position = np.array([0.3, -0.1, 1.2]) self.region_bounds = { GazeRegion.ROAD_FORWARD: { 'yaw': (-30, 30), 'pitch': (-20, 10), 'valid': True }, GazeRegion.DRIVER_SIDE_WINDOW: { 'yaw': (-90, -45), 'pitch': (-10, 20), 'valid': True }, GazeRegion.PASSENGER_SIDE_WINDOW: { 'yaw': (45, 90), 'pitch': (-10, 20), 'valid': True }, GazeRegion.DRIVER_SIDE_MIRROR: { 'yaw': (-35, -25), 'pitch': (-15, -5), 'valid': True }, GazeRegion.PASSENGER_SIDE_MIRROR: { 'yaw': (55, 65), 'pitch': (-15, -5), 'valid': True }, GazeRegion.REAR_MIRROR: { 'yaw': (-15, 15), 'pitch': (-25, -15), 'valid': True }, GazeRegion.INSTRUMENT_CLUSTER: { 'yaw': (-25, -5), 'pitch': (-35, -20), 'valid': False }, GazeRegion.CENTER_STACK: { 'yaw': (-5, 35), 'pitch': (-40, -25), 'valid': False }, GazeRegion.GLOVEBOX: { 'yaw': (30, 50), 'pitch': (-50, -35), 'valid': False }, GazeRegion.DRIVER_FOOTWELL: { 'yaw': (-20, 0), 'pitch': (-70, -50), 'valid': False }, GazeRegion.DRIVER_LAP: { 'yaw': (-30, 10), 'pitch': (-50, -35), 'valid': False }, GazeRegion.PASSENGER_FACE: { 'yaw': (20, 50), 'pitch': (-10, 10), 'valid': False } } def classify(self, head_yaw: float, head_pitch: float, gaze_yaw_offset: float, gaze_pitch_offset: float) -> Tuple[GazeRegion, bool]: """ 分类注视区域 Args: head_yaw: 头部偏航角(度) head_pitch: 头部俯仰角(度) gaze_yaw_offset: 眼动相对头部的偏航偏移(度) gaze_pitch_offset: 眼动相对头部的俯仰偏移(度) Returns: region: 注视区域 is_valid: 是否为合法注视区域 """ total_yaw = head_yaw + gaze_yaw_offset total_pitch = head_pitch + gaze_pitch_offset for region, bounds in self.region_bounds.items(): yaw_min, yaw_max = bounds['yaw'] pitch_min, pitch_max = bounds['pitch'] if (yaw_min <= total_yaw <= yaw_max and pitch_min <= total_pitch <= pitch_max): return region, bounds['valid'] return GazeRegion.ROAD_FORWARD, True
|