Fred808 commited on
Commit
05c007d
·
verified ·
1 Parent(s): 6e0f3de

Update cursor_tracker.py

Browse files
Files changed (1) hide show
  1. cursor_tracker.py +76 -4
cursor_tracker.py CHANGED
@@ -1,7 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
1
  from typing import List, Tuple
2
- from PIL import Image
3
- from io import BytesIO
4
- import requests
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  def track_cursor_from_images(
7
  images: List[Tuple[str, np.ndarray]],
@@ -10,7 +82,7 @@ def track_cursor_from_images(
10
  threshold=0.8,
11
  email_results=False
12
  ):
13
- """Detect cursor in a list of in-memory images (filename, image)."""
14
 
15
  cursor_templates_dir = Path(cursor_templates_dir).resolve()
16
  output_json_path = Path(output_json_path).resolve()
 
1
+ """
2
+ Cursor detection and action logging utilities.
3
+ """
4
+
5
+ import os
6
+ import json
7
+ import cv2
8
+ import numpy as np # ✅ FIXED MISSING IMPORT
9
+ from pathlib import Path
10
+ from email.message import EmailMessage
11
+ import smtplib
12
  from typing import List, Tuple
13
+
14
+ def to_rgb(img):
15
+ if img is None:
16
+ return None
17
+ if len(img.shape) == 2:
18
+ return cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
19
+ if img.shape[2] == 4:
20
+ return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
21
+ return img
22
+
23
+ def get_mask_from_alpha(template_img):
24
+ if template_img is not None and len(template_img.shape) == 3 and template_img.shape[2] == 4:
25
+ return (template_img[:, :, 3] > 0).astype(np.uint8) * 255
26
+ return None
27
+
28
+ def detect_cursor_in_frame_multi(frame, cursor_templates, threshold=0.8):
29
+ best_pos = None
30
+ best_conf = -1
31
+ best_template_name = None
32
+ frame_rgb = to_rgb(frame)
33
+ for template_name, cursor_template in cursor_templates.items():
34
+ template_rgb = to_rgb(cursor_template)
35
+ mask = get_mask_from_alpha(cursor_template)
36
+ if template_rgb is None or frame_rgb is None or template_rgb.shape[2] != frame_rgb.shape[2]:
37
+ print(f"[WARN] Skipping template {template_name} due to channel mismatch or load error.")
38
+ continue
39
+ try:
40
+ result = cv2.matchTemplate(frame_rgb, template_rgb, cv2.TM_CCOEFF_NORMED, mask=mask)
41
+ except Exception as e:
42
+ print(f"[WARN] matchTemplate failed for {template_name}: {e}")
43
+ continue
44
+ _, max_val, _, max_loc = cv2.minMaxLoc(result)
45
+ if max_val > best_conf:
46
+ best_conf = max_val
47
+ if max_val >= threshold:
48
+ cursor_w, cursor_h = template_rgb.shape[1], template_rgb.shape[0]
49
+ cursor_x = max_loc[0] + cursor_w // 2
50
+ cursor_y = max_loc[1] + cursor_h // 2
51
+ best_pos = (cursor_x, cursor_y)
52
+ best_template_name = template_name
53
+ if best_conf >= threshold:
54
+ return best_pos, best_conf, best_template_name
55
+ return None, best_conf, None
56
+
57
+ def ensure_dir(path):
58
+ os.makedirs(path, exist_ok=True)
59
+
60
+ def send_email_with_attachment(subject, body, to_email, from_email, app_password, attachment_path):
61
+ msg = EmailMessage()
62
+ msg['Subject'] = subject
63
+ msg['From'] = from_email
64
+ msg['To'] = to_email
65
+ msg.set_content(body)
66
+ with open(attachment_path, 'rb') as f:
67
+ file_data = f.read()
68
+ file_name = Path(attachment_path).name
69
+ msg.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name)
70
+ try:
71
+ with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
72
+ smtp.login(from_email, app_password)
73
+ smtp.send_message(msg)
74
+ print(f"[SUCCESS] Email sent to {to_email}")
75
+ except Exception as e:
76
+ print(f"[ERROR] Failed to send email: {e}")
77
 
78
  def track_cursor_from_images(
79
  images: List[Tuple[str, np.ndarray]],
 
82
  threshold=0.8,
83
  email_results=False
84
  ):
85
+ """Detect cursor in a list of in-memory images (filename, image ndarray)."""
86
 
87
  cursor_templates_dir = Path(cursor_templates_dir).resolve()
88
  output_json_path = Path(output_json_path).resolve()