Загрузка данных


import cv2
import numpy as np
import mediapipe as mp
from mediapipe.python.solutions import hands as mp_hands

# Инициализация MediaPipe Hands
hands = mp_hands.Hands(
    static_image_mode=False,
    max_num_hands=2,
    min_detection_confidence=0.7,
    min_tracking_confidence=0.7
)

# Загрузка изображения (мема/картинки)
overlay_img = cv2.imread('meme.png', cv2.IMREAD_UNCHANGED)

if overlay_img is None:
    raise FileNotFoundError("Файл meme.png не найден в текущей папке!")

# Проверка и добавление альфа-канала (прозрачности) при необходимости
if overlay_img.shape[2] == 3:
    b, g, r = cv2.split(overlay_img)
    alpha = np.ones(b.shape, dtype=b.dtype) * 255
    overlay_img = cv2.merge((b, g, r, alpha))

h_overlay, w_overlay = overlay_img.shape[:2]
src_pts = np.float32([
    [0, 0],
    [w_overlay, 0],
    [w_overlay, h_overlay],
    [0, h_overlay]
])

# Встроенная вебкамера в Linux (V4L2)
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)

def overlay_transparent(background, overlay_warped):
    # 0.7 — прозрачность маски (как в оригинале)
    alpha_mask = (overlay_warped[:, :, 3] / 255.0) * 0.7 
    alpha_mask = alpha_mask[:, :, np.newaxis]
    
    overlay_colors = overlay_warped[:, :, :3]
    background_colors = background[:, :, :3]
    
    return (overlay_colors * alpha_mask + background_colors * (1.0 - alpha_mask)).astype(np.uint8)

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        print("Не удалось получить кадр с веб-камеры.")
        break

    frame = cv2.flip(frame, 1)  # Зеркалирование
    h_frame, w_frame, _ = frame.shape
    
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    hands_results = hands.process(rgb_frame)

    if hands_results.multi_hand_landmarks and len(hands_results.multi_hand_landmarks) == 2:
        landmarks_list = []
        
        # Сбор координат кончиков указательных и больших пальцев
        for hand_landmarks in hands_results.multi_hand_landmarks:
            index_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]
            thumb_tip = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP]
            
            landmarks_list.append((int(index_tip.x * w_frame), int(index_tip.y * h_frame)))
            landmarks_list.append((int(thumb_tip.x * w_frame), int(thumb_tip.y * h_frame)))

        # Сортировка по X (разделение на левую и правую руку в кадре)
        landmarks_list.sort(key=lambda pt: pt[0])
        
        left_pair = sorted(landmarks_list[:2], key=lambda pt: pt[1])
        right_pair = sorted(landmarks_list[2:], key=lambda pt: pt[1])

        dst_pts = np.float32([
            left_pair[0],    # Top-Left
            right_pair[0],   # Top-Right
            right_pair[1],   # Bottom-Right
            left_pair[1]     # Bottom-Left
        ])

        # Трансформация перспективы
        matrix = cv2.getPerspectiveTransform(src_pts, dst_pts)
        warped_overlay = cv2.warpPerspective(overlay_img, matrix, (w_frame, h_frame))

        # Наложение
        frame = overlay_transparent(frame, warped_overlay)

        # Отрисовка фиолетовой контурной рамки
        pts = dst_pts.astype(np.int32).reshape((-1, 1, 2))
        cv2.polylines(frame, [pts], isClosed=True, color=(255, 0, 180), thickness=3)

    cv2.imshow("TikTok Filter", frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()