Initial commit

This commit is contained in:
moscovskayaliza
2026-03-20 17:01:27 +03:00
commit 14fb06a903
19 changed files with 1071 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
import cv2
import os
import csv
import sys
from pathlib import Path
import argparse
sys.path.append(str(Path(__file__).parent.parent))
from skeleton.mediapipe_detector import MediaPipeDetector
from ml_gestures.feature_extractor import normalize_landmarks
def main():
parser = argparse.ArgumentParser(description='Разметка изображений для обучения')
parser.add_argument('--folder', required=True, help='Папка с изображениями')
parser.add_argument('--classes', default='dome,cross,none',
help='Список классов через запятую')
parser.add_argument('--output', default='gesture_data.csv',
help='Имя выходного CSV-файла')
parser.add_argument('--max_display_size', default='800,600',
help='Максимальный размер для отображения (ширина,высота)')
args = parser.parse_args()
classes = [c.strip() for c in args.classes.split(',')]
key_to_class = {str(i+1): cls for i, cls in enumerate(classes)}
print("Классы:", classes)
detector = MediaPipeDetector()
max_width, max_height = map(int, args.max_display_size.split(','))
image_extensions = ('.jpg', '.jpeg', '.png', '.bmp')
image_files = [f for f in os.listdir(args.folder) if f.lower().endswith(image_extensions)]
image_files.sort()
print(f"Найдено {len(image_files)} изображений.")
csv_file = args.output
file_exists = os.path.isfile(csv_file)
if not file_exists:
with open(csv_file, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['class'] + [f'f{i}' for i in range(99)])
for idx, filename in enumerate(image_files):
filepath = os.path.join(args.folder, filename)
print(f"\n[{idx+1}/{len(image_files)}] {filename}")
image = cv2.imread(filepath)
if image is None:
print("Не удалось загрузить")
continue
result = detector.detect(image)
if result['success']:
landmarks = result['landmarks']
features = normalize_landmarks(landmarks)
vis_image = detector.draw_landmarks(image.copy(), result['pose_landmarks'])
else:
vis_image = image.copy()
landmarks = None
# Масштабирование для отображения
h, w = vis_image.shape[:2]
scale = min(max_width / w, max_height / h, 1.0)
if scale < 1.0:
new_w = int(w * scale)
new_h = int(h * scale)
display = cv2.resize(vis_image, (new_w, new_h))
else:
display = vis_image.copy()
# Панель с инструкцией
dh, dw = display.shape[:2]
overlay = display.copy()
cv2.rectangle(overlay, (0, dh-80), (dw, dh), (50,50,50), -1)
cv2.addWeighted(overlay, 0.6, display, 0.4, 0, display)
y = dh - 60
for i, cls in enumerate(classes):
cv2.putText(display, f"{i+1}:{cls}", (10 + i*120, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,255), 2)
cv2.putText(display, "n:skip q:quit", (10, y+30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,0), 2)
cv2.imshow('Annotation', display)
key = cv2.waitKey(0) & 0xFF
cv2.destroyAllWindows()
if key == ord('q'):
break
elif key == ord('n'):
continue
else:
key_char = chr(key) if key < 256 else None
if key_char in key_to_class:
selected = key_to_class[key_char]
with open(csv_file, 'a', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow([selected] + features.tolist())
print(f"Сохранено: {selected}")
else:
print("Неверная клавиша")
print("Готово.")
if __name__ == '__main__':
main()
+79
View File
@@ -0,0 +1,79 @@
import cv2
import os
import sys
import time
from pathlib import Path
def capture_photo(output_dir='captured', camera_id=0, mirror=True):
"""
Простой инструмент для захвата фото с камеры.
При нажатии 's' запускается отсчёт 3 секунды, затем делается снимок.
При нажатии 'q' выход.
"""
# Создаём папку, если её нет
Path(output_dir).mkdir(parents=True, exist_ok=True)
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
print("Не удалось открыть камеру")
sys.exit(1)
print("Нажмите 's' для захвата фото (отсчёт 3 секунды)")
print("Нажмите 'q' для выхода")
capture_count = 0
countdown = 0
countdown_start = 0
while True:
ret, frame = cap.read()
if not ret:
break
if mirror:
frame = cv2.flip(frame, 1)
display = frame.copy()
# Отображение отсчёта, если активен
if countdown > 0:
elapsed = time.time() - countdown_start
remaining = max(0, 3 - elapsed)
if remaining > 0:
cv2.putText(display, f"Capturing in {int(remaining)}", (display.shape[1]//2-100, display.shape[0]//2),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
else:
# Сохраняем фото
timestamp = time.strftime("%Y%m%d_%H%M%S")
filename = f"photo_{timestamp}.jpg"
filepath = os.path.join(output_dir, filename)
cv2.imwrite(filepath, frame)
print(f"Сохранено: {filepath}")
capture_count += 1
countdown = 0
else:
# Подсказка
cv2.putText(display, "Press 's' to capture, 'q' to quit", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,0), 2)
cv2.imshow('Capture', display)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('s') and countdown == 0:
countdown = 1
countdown_start = time.time()
cap.release()
cv2.destroyAllWindows()
print(f"Завершено. Сохранено {capture_count} фото.")
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--dir', default='captured', help='Папка для сохранения')
parser.add_argument('--camera', type=int, default=0, help='ID камеры')
parser.add_argument('--no-mirror', action='store_true', help='Отключить зеркалирование')
args = parser.parse_args()
capture_photo(output_dir=args.dir, camera_id=args.camera, mirror=not args.no_mirror)