mirror of
https://github.com/AmanIbrash-brsh/emotional_damage.git
synced 2026-11-09 10:15:09 +00:00
вариант 6 эмоций
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
|
After Width: | Height: | Size: 470 KiB |
@@ -0,0 +1,228 @@
|
||||
import cv2
|
||||
import mediapipe as mp
|
||||
from mediapipe.tasks import python
|
||||
from mediapipe.tasks.python import vision
|
||||
import numpy as np
|
||||
import time
|
||||
import math
|
||||
|
||||
def overlay_image_alpha(img, img_overlay, x, y, alpha_mask):
|
||||
"""Наложение изображения img_overlay на img с учетом альфа-канала."""
|
||||
y1, y2 = max(0, y), min(img.shape[0], y + img_overlay.shape[0])
|
||||
x1, x2 = max(0, x), min(img.shape[1], x + img_overlay.shape[1])
|
||||
|
||||
y1o, y2o = max(0, -y), min(img_overlay.shape[0], img.shape[0] - y)
|
||||
x1o, x2o = max(0, -x), min(img_overlay.shape[1], img.shape[1] - x)
|
||||
|
||||
if y1 >= y2 or x1 >= x2 or y1o >= y2o or x1o >= x2o:
|
||||
return
|
||||
|
||||
alpha = alpha_mask[y1o:y2o, x1o:x2o]
|
||||
alpha_inv = 1.0 - alpha
|
||||
|
||||
for c in range(3):
|
||||
img[y1:y2, x1:x2, c] = (alpha * img_overlay[y1o:y2o, x1o:x2o, c] +
|
||||
alpha_inv * img[y1:y2, x1:x2, c])
|
||||
|
||||
def check_gestures(pose_landmarks, gesture_result):
|
||||
"""Проверяет позы пользователя и возвращает 'timeout', 'pointing', 'shocked', 'cinema', 'fist', 'bye' или None."""
|
||||
|
||||
is_fist = False
|
||||
is_open_palm = False
|
||||
|
||||
# 1. Жесты кисти
|
||||
if gesture_result and gesture_result.gestures:
|
||||
for hand_gestures in gesture_result.gestures:
|
||||
for gesture in hand_gestures:
|
||||
if gesture.category_name == 'Pointing_Up' and gesture.score > 0.5:
|
||||
return 'pointing'
|
||||
if gesture.category_name == 'Closed_Fist' and gesture.score > 0.5:
|
||||
is_fist = True
|
||||
if gesture.category_name == 'Open_Palm' and gesture.score > 0.5:
|
||||
is_open_palm = True
|
||||
|
||||
# 2. Поза тела
|
||||
if pose_landmarks:
|
||||
landmarks = pose_landmarks[0]
|
||||
nose = landmarks[0]
|
||||
left_ear = landmarks[7]
|
||||
right_ear = landmarks[8]
|
||||
mouth_l = landmarks[9]
|
||||
mouth_r = landmarks[10]
|
||||
left_wrist = landmarks[15]
|
||||
right_wrist = landmarks[16]
|
||||
|
||||
mouth_x = (mouth_l.x + mouth_r.x) / 2.0
|
||||
mouth_y = (mouth_l.y + mouth_r.y) / 2.0
|
||||
|
||||
# Мем "Кулак ко рту"
|
||||
if is_fist:
|
||||
dist_l_mouth = math.hypot(left_wrist.x - mouth_x, left_wrist.y - mouth_y) if left_wrist.visibility > 0.15 else 999
|
||||
dist_r_mouth = math.hypot(right_wrist.x - mouth_x, right_wrist.y - mouth_y) if right_wrist.visibility > 0.15 else 999
|
||||
if dist_l_mouth < 0.25 or dist_r_mouth < 0.25:
|
||||
return 'fist'
|
||||
|
||||
if left_wrist.visibility > 0.15 and right_wrist.visibility > 0.15:
|
||||
# Мем "Absolute Cinema" (обе руки высоко подняты)
|
||||
if left_wrist.y < nose.y and right_wrist.y < nose.y:
|
||||
return 'cinema'
|
||||
|
||||
# Мем с Шаком
|
||||
dist_wrists = math.hypot(left_wrist.x - right_wrist.x, left_wrist.y - right_wrist.y)
|
||||
if dist_wrists < 0.15 and left_wrist.y > nose.y and right_wrist.y > nose.y:
|
||||
return 'timeout'
|
||||
|
||||
# Мем "Шок"
|
||||
dist_l = math.hypot(left_wrist.x - left_ear.x, left_wrist.y - left_ear.y)
|
||||
dist_r = math.hypot(right_wrist.x - right_ear.x, right_wrist.y - right_ear.y)
|
||||
if dist_l < 0.25 and dist_r < 0.25:
|
||||
return 'shocked'
|
||||
|
||||
# Мем "Пока" (одна открытая ладонь на уровне лица)
|
||||
# Проверяем после Cinema, чтобы не перебивало двумя руками
|
||||
if is_open_palm:
|
||||
# Если хотя бы одно запястье находится примерно на уровне носа (по вертикали)
|
||||
if (left_wrist.visibility > 0.15 and abs(left_wrist.y - nose.y) < 0.25) or \
|
||||
(right_wrist.visibility > 0.15 and abs(right_wrist.y - nose.y) < 0.25):
|
||||
return 'bye'
|
||||
|
||||
return None
|
||||
|
||||
def load_mask(path):
|
||||
img = cv2.imread(path, cv2.IMREAD_UNCHANGED)
|
||||
if img is None:
|
||||
return None
|
||||
if img.shape[2] == 3:
|
||||
b, g, r = cv2.split(img)
|
||||
alpha = np.ones(b.shape, dtype=b.dtype) * 255
|
||||
img = cv2.merge((b, g, r, alpha))
|
||||
return img
|
||||
|
||||
def main():
|
||||
# Загружаем маски
|
||||
mask_timeout = load_mask('timeout.png')
|
||||
mask_pointing = load_mask('pointing.png')
|
||||
mask_cinema = load_mask('scorsese.png')
|
||||
mask_shocked = load_mask('shocked.png')
|
||||
mask_fist = load_mask('fist.png')
|
||||
mask_jarvis = load_mask('jarvis.png')
|
||||
mask_bye = load_mask('bye.png')
|
||||
|
||||
if mask_timeout is None or mask_pointing is None or mask_cinema is None or mask_shocked is None or mask_fist is None or mask_jarvis is None or mask_bye is None:
|
||||
print("Ошибка: Не удалось загрузить одну из картинок.")
|
||||
return
|
||||
|
||||
# Инициализация моделей Tasks API
|
||||
base_options_face = python.BaseOptions(model_asset_path='face_detector.tflite')
|
||||
options_face = vision.FaceDetectorOptions(base_options=base_options_face,
|
||||
running_mode=vision.RunningMode.VIDEO)
|
||||
face_detector = vision.FaceDetector.create_from_options(options_face)
|
||||
|
||||
base_options_pose = python.BaseOptions(model_asset_path='pose_landmarker.task')
|
||||
options_pose = vision.PoseLandmarkerOptions(base_options=base_options_pose,
|
||||
running_mode=vision.RunningMode.VIDEO,
|
||||
output_segmentation_masks=False)
|
||||
pose_landmarker = vision.PoseLandmarker.create_from_options(options_pose)
|
||||
|
||||
base_options_gesture = python.BaseOptions(model_asset_path='gesture_recognizer.task')
|
||||
options_gesture = vision.GestureRecognizerOptions(base_options=base_options_gesture,
|
||||
running_mode=vision.RunningMode.VIDEO,
|
||||
num_hands=2)
|
||||
gesture_recognizer = vision.GestureRecognizer.create_from_options(options_gesture)
|
||||
|
||||
cap = cv2.VideoCapture(0)
|
||||
if not cap.isOpened():
|
||||
print("Ошибка: Не удалось открыть камеру")
|
||||
return
|
||||
|
||||
print("Камера запущена!")
|
||||
print("Управление размером: клавиша '=' (или '+') - увеличить, '-' - уменьшить.")
|
||||
|
||||
scale_factor = 2.5 # Базовый размер
|
||||
|
||||
while cap.isOpened():
|
||||
success, image = cap.read()
|
||||
if not success:
|
||||
continue
|
||||
|
||||
image = cv2.flip(image, 1)
|
||||
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
||||
|
||||
mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image_rgb)
|
||||
timestamp_ms = int(time.time() * 1000)
|
||||
|
||||
# Обрабатываем кадр
|
||||
face_result = face_detector.detect_for_video(mp_image, timestamp_ms)
|
||||
pose_result = pose_landmarker.detect_for_video(mp_image, timestamp_ms)
|
||||
gesture_result = gesture_recognizer.recognize_for_video(mp_image, timestamp_ms)
|
||||
|
||||
pose_lms = pose_result.pose_landmarks if (pose_result and hasattr(pose_result, 'pose_landmarks')) else None
|
||||
|
||||
detected_gesture = check_gestures(pose_lms, gesture_result)
|
||||
|
||||
if face_result and hasattr(face_result, 'detections') and face_result.detections:
|
||||
detection = face_result.detections[0]
|
||||
bbox = detection.bounding_box
|
||||
|
||||
ih, iw, _ = image.shape
|
||||
x = int(bbox.origin_x)
|
||||
y = int(bbox.origin_y)
|
||||
w = int(bbox.width)
|
||||
h = int(bbox.height)
|
||||
|
||||
if w > iw * 0.25:
|
||||
detected_gesture = 'jarvis'
|
||||
|
||||
if detected_gesture:
|
||||
if detected_gesture == 'timeout':
|
||||
current_mask = mask_timeout
|
||||
elif detected_gesture == 'pointing':
|
||||
current_mask = mask_pointing
|
||||
elif detected_gesture == 'shocked':
|
||||
current_mask = mask_shocked
|
||||
elif detected_gesture == 'fist':
|
||||
current_mask = mask_fist
|
||||
elif detected_gesture == 'jarvis':
|
||||
current_mask = mask_jarvis
|
||||
elif detected_gesture == 'bye':
|
||||
current_mask = mask_bye
|
||||
else:
|
||||
current_mask = mask_cinema
|
||||
|
||||
mask_w = int(w * scale_factor)
|
||||
mask_h = int((mask_w / current_mask.shape[1]) * current_mask.shape[0])
|
||||
|
||||
mask_x = x - int((mask_w - w) / 2)
|
||||
mask_y = y - int((mask_h - h) / 1.5)
|
||||
|
||||
if mask_w > 0 and mask_h > 0:
|
||||
resized_mask = cv2.resize(current_mask, (mask_w, mask_h))
|
||||
alpha_mask = resized_mask[:, :, 3] / 255.0
|
||||
|
||||
overlay_image_alpha(image, resized_mask[:, :, :3], mask_x, mask_y, alpha_mask)
|
||||
|
||||
cv2.putText(image, f"Size: {scale_factor:.1f}x (+/- to change)", (10, 20),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 200, 200), 1, cv2.LINE_AA)
|
||||
|
||||
# Вывод на экран
|
||||
cv2.imshow('Meme Detector', image)
|
||||
|
||||
key = cv2.waitKey(5) & 0xFF
|
||||
if key == ord('q'):
|
||||
break
|
||||
elif key == ord('=') or key == ord('+'):
|
||||
scale_factor += 0.1
|
||||
elif key == ord('-'):
|
||||
scale_factor -= 0.1
|
||||
|
||||
scale_factor = max(0.5, min(scale_factor, 10.0))
|
||||
|
||||
cap.release()
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
face_detector.close()
|
||||
pose_landmarker.close()
|
||||
gesture_recognizer.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 310 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 344 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 636 KiB |
+20
@@ -0,0 +1,20 @@
|
||||
import cv2
|
||||
import mediapipe as mp
|
||||
from mediapipe.tasks import python
|
||||
from mediapipe.tasks.python import vision
|
||||
|
||||
print("Imports successful")
|
||||
|
||||
# Face Detector
|
||||
base_options_face = python.BaseOptions(model_asset_path='face_detector.tflite')
|
||||
options_face = vision.FaceDetectorOptions(base_options=base_options_face)
|
||||
detector = vision.FaceDetector.create_from_options(options_face)
|
||||
print("Face detector created")
|
||||
|
||||
# Pose Landmarker
|
||||
base_options_pose = python.BaseOptions(model_asset_path='pose_landmarker.task')
|
||||
options_pose = vision.PoseLandmarkerOptions(
|
||||
base_options=base_options_pose,
|
||||
output_segmentation_masks=False)
|
||||
landmarker = vision.PoseLandmarker.create_from_options(options_pose)
|
||||
print("Pose landmarker created")
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 867 KiB |
Reference in New Issue
Block a user