batch24-28 1.2.3__tar.gz → 1.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {batch24_28-1.2.3/src/batch24_28.egg-info → batch24_28-1.2.4}/PKG-INFO +32 -3
  2. batch24_28-1.2.3/PKG-INFO → batch24_28-1.2.4/README.md +22 -9
  3. batch24_28-1.2.4/pyproject.toml +21 -0
  4. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/__init__.py +3 -2
  5. batch24_28-1.2.4/src/batch24_28/vision.py +187 -0
  6. batch24_28-1.2.3/README.md → batch24_28-1.2.4/src/batch24_28.egg-info/PKG-INFO +39 -1
  7. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28.egg-info/SOURCES.txt +1 -0
  8. batch24_28-1.2.4/src/batch24_28.egg-info/requires.txt +9 -0
  9. batch24_28-1.2.3/pyproject.toml +0 -10
  10. batch24_28-1.2.3/src/batch24_28.egg-info/requires.txt +0 -2
  11. {batch24_28-1.2.3 → batch24_28-1.2.4}/setup.cfg +0 -0
  12. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/art.py +0 -0
  13. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/calculator.py +0 -0
  14. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/chess_game.py +0 -0
  15. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/from .py +0 -0
  16. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/games.py +0 -0
  17. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/monitor.py +0 -0
  18. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/reporter.py +0 -0
  19. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/timers.py +0 -0
  20. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28/watcher.py +0 -0
  21. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28.egg-info/dependency_links.txt +0 -0
  22. {batch24_28-1.2.3 → batch24_28-1.2.4}/src/batch24_28.egg-info/top_level.txt +0 -0
@@ -1,11 +1,18 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batch24-28
3
- Version: 1.2.3
4
- Summary: A multi featured Python terminal
5
- Requires-Python: >=3.7
3
+ Version: 1.2.4
4
+ Summary: A multi featured Python terminal and vision toolkit
5
+ Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
7
7
  Requires-Dist: psutil
8
8
  Requires-Dist: watchdog
9
+ Requires-Dist: opencv-python
10
+ Requires-Dist: mediapipe==0.10.21
11
+ Requires-Dist: fer
12
+ Requires-Dist: tensorflow==2.17.0
13
+ Requires-Dist: protobuf==4.25.9
14
+ Requires-Dist: setuptools==81.0.0
15
+ Requires-Dist: python-chess
9
16
 
10
17
 
11
18
  # batch24-28
@@ -145,3 +152,25 @@ from batch24_28 import start_file_watcher
145
152
  # Watch the current directory
146
153
  start_file_watcher(path=".")
147
154
  ```
155
+
156
+ ---
157
+
158
+ ### 10. Computer Vision & Emotion Analysis Toolkit
159
+
160
+ An interactive computer vision pipeline powered by MediaPipe hand-tracking and deep learning emotion recognition. Includes virtual mid-air drawing (Air Canvas) and facial expression tracking via webcam, static images, or video files.
161
+
162
+ ```python
163
+ from batch24_28 import VisionAnalyzer
164
+
165
+ analyzer = VisionAnalyzer()
166
+
167
+ # Option A: Run live Air Canvas and Emotion detection via webcam
168
+ analyzer.run_air_canvas(run_draw=True, run_emotion=True)
169
+
170
+ # Option B: Analyze facial expression from a static image file
171
+ emotion, score, img = analyzer.analyze_image_file("path_to_image.jpg")
172
+ print(f"Detected: {emotion} ({int(score * 100)}%)")
173
+
174
+ # Option C: Stream and analyze a video file for expressions
175
+ analyzer.analyze_video_file("path_to_video.mp4")
176
+ ```
@@ -1,12 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: batch24-28
3
- Version: 1.2.3
4
- Summary: A multi featured Python terminal
5
- Requires-Python: >=3.7
6
- Description-Content-Type: text/markdown
7
- Requires-Dist: psutil
8
- Requires-Dist: watchdog
9
-
10
1
 
11
2
  # batch24-28
12
3
 
@@ -145,3 +136,25 @@ from batch24_28 import start_file_watcher
145
136
  # Watch the current directory
146
137
  start_file_watcher(path=".")
147
138
  ```
139
+
140
+ ---
141
+
142
+ ### 10. Computer Vision & Emotion Analysis Toolkit
143
+
144
+ An interactive computer vision pipeline powered by MediaPipe hand-tracking and deep learning emotion recognition. Includes virtual mid-air drawing (Air Canvas) and facial expression tracking via webcam, static images, or video files.
145
+
146
+ ```python
147
+ from batch24_28 import VisionAnalyzer
148
+
149
+ analyzer = VisionAnalyzer()
150
+
151
+ # Option A: Run live Air Canvas and Emotion detection via webcam
152
+ analyzer.run_air_canvas(run_draw=True, run_emotion=True)
153
+
154
+ # Option B: Analyze facial expression from a static image file
155
+ emotion, score, img = analyzer.analyze_image_file("path_to_image.jpg")
156
+ print(f"Detected: {emotion} ({int(score * 100)}%)")
157
+
158
+ # Option C: Stream and analyze a video file for expressions
159
+ analyzer.analyze_video_file("path_to_video.mp4")
160
+ ```
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "batch24-28"
7
+ version = "1.2.4"
8
+ description = "A multi featured Python terminal and vision toolkit"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ dependencies = [
12
+ "psutil",
13
+ "watchdog",
14
+ "opencv-python",
15
+ "mediapipe==0.10.21",
16
+ "fer",
17
+ "tensorflow==2.17.0",
18
+ "protobuf==4.25.9",
19
+ "setuptools==81.0.0",
20
+ "python-chess"
21
+ ]
@@ -1,4 +1,4 @@
1
- __version__ = "1.2.3"
1
+ __version__ = "1.2.4"
2
2
 
3
3
  from .timers import start_countdown, start_stopwatch, run_interactive_timer
4
4
  from .art import print_hello
@@ -7,4 +7,5 @@ from .games import RockPaperScissors
7
7
  from .chess_game import TerminalChess
8
8
  from .watcher import start_file_watcher
9
9
  from .monitor import monitor_performance
10
- from .reporter import generate_system_report
10
+ from .reporter import generate_system_report
11
+ from .vision import VisionAnalyzer
@@ -0,0 +1,187 @@
1
+ import cv2
2
+ import math
3
+ import time
4
+ import os
5
+
6
+ class VisionAnalyzer:
7
+ def __init__(self):
8
+ self.colors = {
9
+ "BLUE": (255, 0, 0),
10
+ "GREEN": (0, 255, 0),
11
+ "RED": (0, 0, 255),
12
+ "YELLOW": (0, 255, 255)
13
+ }
14
+
15
+ def analyze_image_file(self, img_path):
16
+ """Analyzes facial emotion from a static image file."""
17
+ from fer.fer import FER
18
+ if not os.path.exists(img_path):
19
+ raise FileNotFoundError(f"Image not found at: {img_path}")
20
+
21
+ detector = FER(mtcnn=False)
22
+ img = cv2.imread(img_path)
23
+ dominant_emotion, score = detector.top_emotion(img)
24
+
25
+ if dominant_emotion is None:
26
+ dominant_emotion = "Neutral"
27
+ score = 0.0
28
+
29
+ return dominant_emotion, score, img
30
+
31
+ def analyze_video_file(self, vid_path):
32
+ """Streams and analyzes facial emotion from a video file."""
33
+ from fer.fer import FER
34
+ if not os.path.exists(vid_path):
35
+ raise FileNotFoundError(f"Video not found at: {vid_path}")
36
+
37
+ detector = FER(mtcnn=False)
38
+ cap = cv2.VideoCapture(vid_path)
39
+
40
+ while cap.isOpened():
41
+ success, frame = cap.read()
42
+ if not success:
43
+ break
44
+
45
+ dominant_emotion, score = detector.top_emotion(frame)
46
+ if dominant_emotion is None:
47
+ dominant_emotion = "Neutral"
48
+ score = 0.0
49
+
50
+ expression_text = f"Emotion: {dominant_emotion.capitalize()} ({int(score * 100)}%)"
51
+ cv2.putText(frame, expression_text, (30, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)
52
+
53
+ cv2.imshow('Video Emotion Analysis', frame)
54
+ if cv2.waitKey(25) & 0xFF == ord('q'):
55
+ break
56
+
57
+ cap.release()
58
+ cv2.destroyAllWindows()
59
+
60
+ def run_air_canvas(self, run_draw=True, run_emotion=True):
61
+ """Runs the live webcam pipeline for Air Canvas and/or Emotion Detection."""
62
+ from fer.fer import FER
63
+ import mediapipe as mp
64
+
65
+ emotion_detector = FER(mtcnn=False) if run_emotion else None
66
+ mp_hands = mp.solutions.hands if run_draw else None
67
+ mp_drawing = mp.solutions.drawing_utils if run_draw else None
68
+
69
+ strokes = []
70
+ current_stroke = []
71
+ cap = cv2.VideoCapture(0)
72
+
73
+ PINCH_THRESHOLD = 42
74
+ ERASER_RADIUS = 35
75
+ is_drawing = False
76
+ tool_mode = "DRAW"
77
+ current_color_name = "GREEN"
78
+ current_color = self.colors[current_color_name]
79
+
80
+ save_message_timer = 0
81
+ prev_ix, prev_iy = 0, 0
82
+ smoothing_factor = 0.5
83
+
84
+ hands_obj = mp_hands.Hands(min_detection_confidence=0.75, min_tracking_confidence=0.75) if run_draw else None
85
+
86
+ try:
87
+ while cap.isOpened():
88
+ success, frame = cap.read()
89
+ if not success:
90
+ continue
91
+
92
+ frame = cv2.flip(frame, 1)
93
+ h, w, _ = frame.shape
94
+ rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
95
+
96
+ expression_text = ""
97
+ expression_color = (200, 200, 200)
98
+
99
+ if run_emotion and emotion_detector:
100
+ dominant_emotion, score = emotion_detector.top_emotion(frame)
101
+ if dominant_emotion is None:
102
+ dominant_emotion = "Neutral"
103
+ score = 0.0
104
+ expression_text = f"Emotion: {dominant_emotion.capitalize()} ({int(score * 100)}%)"
105
+ expression_color = (0, 255, 255) if dominant_emotion == "happy" else (200, 200, 200)
106
+
107
+ if run_draw:
108
+ box_width, box_height, box_y = 90, 40, 15
109
+ palette_x = 50
110
+
111
+ for name, col in self.colors.items():
112
+ thickness = 3 if current_color_name == name and tool_mode == "DRAW" else 1
113
+ cv2.rectangle(frame, (palette_x, box_y), (palette_x + box_width, box_y + box_height), col, -1)
114
+ cv2.rectangle(frame, (palette_x, box_y), (palette_x + box_width, box_y + box_height), (255, 255, 255), thickness)
115
+ cv2.putText(frame, name, (palette_x + 10, box_y + 26), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (255, 255, 255), 1)
116
+ palette_x += 105
117
+
118
+ mode_text = f"MODE: DRAW | Color: {current_color_name} ('e' to Erase)" if tool_mode == "DRAW" else "MODE: ERASER ('e' to Draw)"
119
+ mode_color = current_color if tool_mode == "DRAW" else (0, 165, 255)
120
+
121
+ hand_results = hands_obj.process(rgb_frame)
122
+ if hand_results.multi_hand_landmarks:
123
+ for hand_landmarks in hand_results.multi_hand_landmarks:
124
+ mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
125
+ thumb_tip = hand_landmarks.landmark[4]
126
+ index_tip = hand_landmarks.landmark[8]
127
+
128
+ raw_ix, raw_iy = int(index_tip.x * w), int(index_tip.y * h)
129
+ tx, ty = int(thumb_tip.x * w), int(thumb_tip.y * h)
130
+
131
+ ix = int(prev_ix * smoothing_factor + raw_ix * (1 - smoothing_factor))
132
+ iy = int(prev_iy * smoothing_factor + raw_iy * (1 - smoothing_factor))
133
+ prev_ix, prev_iy = ix, iy
134
+
135
+ distance = math.hypot(ix - tx, iy - ty)
136
+
137
+ if iy < box_y + box_height + 10:
138
+ p_x = 50
139
+ for name in self.colors.keys():
140
+ if p_x <= ix <= p_x + box_width:
141
+ current_color_name = name
142
+ current_color = self.colors[name]
143
+ tool_mode = "DRAW"
144
+ p_x += 105
145
+ else:
146
+ if tool_mode == "DRAW":
147
+ if distance < PINCH_THRESHOLD:
148
+ cv2.circle(frame, (ix, iy), 10, current_color, -1)
149
+ if not is_drawing:
150
+ is_drawing = True
151
+ current_stroke = []
152
+ strokes.append((current_stroke, current_color))
153
+ current_stroke.append((ix, iy))
154
+ else:
155
+ cv2.circle(frame, (ix, iy), 8, (0, 0, 255), -1)
156
+ is_drawing = False
157
+ elif tool_mode == "ERASER":
158
+ cv2.circle(frame, (ix, iy), ERASER_RADIUS, (0, 165, 255), 2)
159
+ if distance < PINCH_THRESHOLD:
160
+ cv2.circle(frame, (ix, iy), ERASER_RADIUS, (0, 165, 255), -1)
161
+ for stroke_pts, _ in strokes:
162
+ stroke_pts[:] = [pt for pt in stroke_pts if math.hypot(pt[0] - ix, pt[1] - iy) > ERASER_RADIUS]
163
+ strokes = [s for s in strokes if len(s[0]) > 0]
164
+ else:
165
+ is_drawing = False
166
+
167
+ for stroke_pts, col in strokes:
168
+ for i in range(1, len(stroke_pts)):
169
+ cv2.line(frame, stroke_pts[i - 1], stroke_pts[i], col, 4)
170
+
171
+ if run_emotion:
172
+ cv2.putText(frame, expression_text, (w - 380, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.6, expression_color, 2)
173
+
174
+ cv2.imshow('Batch24-28 Vision Pipeline', frame)
175
+
176
+ key = cv2.waitKey(1) & 0xFF
177
+ if key == ord('q'):
178
+ break
179
+ elif key == ord('c') and run_draw:
180
+ strokes.clear()
181
+ elif key == ord('e') and run_draw:
182
+ tool_mode = "ERASER" if tool_mode == "DRAW" else "DRAW"
183
+ finally:
184
+ if hands_obj:
185
+ hands_obj.close()
186
+ cap.release()
187
+ cv2.destroyAllWindows()
@@ -1,3 +1,19 @@
1
+ Metadata-Version: 2.4
2
+ Name: batch24-28
3
+ Version: 1.2.4
4
+ Summary: A multi featured Python terminal and vision toolkit
5
+ Requires-Python: >=3.12
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: psutil
8
+ Requires-Dist: watchdog
9
+ Requires-Dist: opencv-python
10
+ Requires-Dist: mediapipe==0.10.21
11
+ Requires-Dist: fer
12
+ Requires-Dist: tensorflow==2.17.0
13
+ Requires-Dist: protobuf==4.25.9
14
+ Requires-Dist: setuptools==81.0.0
15
+ Requires-Dist: python-chess
16
+
1
17
 
2
18
  # batch24-28
3
19
 
@@ -135,4 +151,26 @@ from batch24_28 import start_file_watcher
135
151
 
136
152
  # Watch the current directory
137
153
  start_file_watcher(path=".")
138
- ```
154
+ ```
155
+
156
+ ---
157
+
158
+ ### 10. Computer Vision & Emotion Analysis Toolkit
159
+
160
+ An interactive computer vision pipeline powered by MediaPipe hand-tracking and deep learning emotion recognition. Includes virtual mid-air drawing (Air Canvas) and facial expression tracking via webcam, static images, or video files.
161
+
162
+ ```python
163
+ from batch24_28 import VisionAnalyzer
164
+
165
+ analyzer = VisionAnalyzer()
166
+
167
+ # Option A: Run live Air Canvas and Emotion detection via webcam
168
+ analyzer.run_air_canvas(run_draw=True, run_emotion=True)
169
+
170
+ # Option B: Analyze facial expression from a static image file
171
+ emotion, score, img = analyzer.analyze_image_file("path_to_image.jpg")
172
+ print(f"Detected: {emotion} ({int(score * 100)}%)")
173
+
174
+ # Option C: Stream and analyze a video file for expressions
175
+ analyzer.analyze_video_file("path_to_video.mp4")
176
+ ```
@@ -9,6 +9,7 @@ src/batch24_28/games.py
9
9
  src/batch24_28/monitor.py
10
10
  src/batch24_28/reporter.py
11
11
  src/batch24_28/timers.py
12
+ src/batch24_28/vision.py
12
13
  src/batch24_28/watcher.py
13
14
  src/batch24_28.egg-info/PKG-INFO
14
15
  src/batch24_28.egg-info/SOURCES.txt
@@ -0,0 +1,9 @@
1
+ psutil
2
+ watchdog
3
+ opencv-python
4
+ mediapipe==0.10.21
5
+ fer
6
+ tensorflow==2.17.0
7
+ protobuf==4.25.9
8
+ setuptools==81.0.0
9
+ python-chess
@@ -1,10 +0,0 @@
1
- [project]
2
- name = "batch24-28"
3
- version = "1.2.3"
4
- description = "A multi featured Python terminal"
5
- readme = "README.md"
6
- requires-python = ">=3.7"
7
- dependencies = [
8
- "psutil",
9
- "watchdog",
10
- ]
@@ -1,2 +0,0 @@
1
- psutil
2
- watchdog
File without changes