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 128 129 130 131
| #include "mediapipe/calculators/ims/eye_aspect_ratio_calculator.h" #include "mediapipe/framework/port/logging.h"
namespace mediapipe {
using mediapipe::NormalizedLandmarkList; using mediapipe::NormalizedLandmark;
absl::Status EyeAspectRatioCalculator::GetContract(CalculatorContract* cc) { cc->Inputs().Tag("LANDMARKS").Set<NormalizedLandmarkList>(); cc->Outputs().Tag("EAR").Set<EyeAspectRatio>(); cc->Options<EyeAspectRatioOptions>(); return absl::OkStatus(); }
absl::Status EyeAspectRatioCalculator::Open(CalculatorContext* cc) { const auto& options = cc->Options<EyeAspectRatioOptions>(); left_iris_center_ = options.left_iris_center(); right_iris_center_ = options.right_iris_center(); normal_ear_threshold_ = options.normal_ear_threshold(); closed_ear_threshold_ = options.closed_ear_threshold(); LOG(INFO) << "EyeAspectRatioCalculator initialized"; return absl::OkStatus(); }
absl::Status EyeAspectRatioCalculator::Process(CalculatorContext* cc) { if (cc->Inputs().Tag("LANDMARKS").IsEmpty()) { return absl::OkStatus(); } const auto& landmarks = cc->Inputs().Tag("LANDMARKS").Get<NormalizedLandmarkList>(); if (landmarks.landmark_size() < 478) { LOG(WARNING) << "Insufficient landmarks for EAR calculation"; return absl::OkStatus(); } float left_ear = CalculateEAR( landmarks, {159, 145, 133, 153, 154, 145}, {33, 160, 158, 133, 153, 144} ); float right_ear = CalculateEAR( landmarks, {386, 374, 373, 380, 374, 380}, {263, 246, 161, 160, 159, 133} ); float avg_ear = (left_ear + right_ear) / 2.0f; float confidence = std::min({left_ear, right_ear, avg_ear}); EyeAspectRatio ear; ear.left_ear = left_ear; ear.right_ear = right_ear; ear.avg_ear = avg_ear; ear.confidence = confidence; ear.timestamp = cc->InputTimestamp().Value(); cc->Outputs().Tag("EAR").AddPacket( MakePacket<EyeAspectRatio>(ear).At(cc->InputTimestamp())); VLOG(1) << "EAR: left=" << left_ear << ", right=" << right_ear << ", avg=" << avg_ear; return absl::OkStatus(); }
float EyeAspectRatioCalculator::CalculateEAR( const NormalizedLandmarkList& landmarks, const std::vector<int>& upper_indices, const std::vector<int>& lower_indices) { float numerator = 0.0f; float denominator = 0.0f; for (size_t i = 0; i < upper_indices.size() - 1; ++i) { const auto& p1 = landmarks.landmark(upper_indices[i]); const auto& p2 = landmarks.landmark(upper_indices[i + 1]); numerator += std::sqrt( std::pow(p2.x() - p1.x(), 2) + std::pow(p2.y() - p1.y(), 2) ); } for (size_t i = 0; i < lower_indices.size() - 1; ++i) { const auto& p1 = landmarks.landmark(lower_indices[i]); const auto& p2 = landmarks.landmark(lower_indices[i + 1]); numerator += std::sqrt( std::pow(p2.x() - p1.x(), 2) + std::pow(p2.y() - p1.y(), 2) ); } for (size_t i = 0; i < upper_indices.size() - 1; ++i) { const auto& p1 = landmarks.landmark(upper_indices[i]); const auto& p2 = landmarks.landmark(lower_indices[i]); denominator += std::sqrt( std::pow(p2.x() - p1.x(), 2) + std::pow(p2.y() - p1.y(), 2) ); } if (denominator < 1e-6f) { return 0.0f; } return numerator / denominator; }
REGISTER_CALCULATOR(EyeAspectRatioCalculator);
}
|