You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gesture_rec/utils/annotate.py

116 lines
4.4 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# === Вот эта связка нужна для всех исполняемых скриптов внутри библиотеки, которая будет использоваться как сабмодуль ===
import sys
from pathlib import Path
ROOT = Path(__file__).parent.parent
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
# === перед вмеми импортами ===
import cv2
import os
import csv
import argparse
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()