Ahilan Kumaresan commited on
Commit
5807ca9
·
1 Parent(s): 9997313

added functions from the presentation file into the functions.py script, make presentation notebook more cleaner

Browse files
Files changed (2) hide show
  1. ModularedPresentation.ipynb +0 -0
  2. functions.py +141 -0
ModularedPresentation.ipynb CHANGED
The diff for this file is too large to render. See raw diff
 
functions.py CHANGED
@@ -595,3 +595,144 @@ def capture_potential(tune, A_MIN, A_MAX, mode='wait'):
595
  cv2.destroyAllWindows()
596
  return captured_V
597
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
595
  cv2.destroyAllWindows()
596
  return captured_V
597
 
598
+ # Create a notebook-friendly version of the function
599
+ def capture_potential_notebook(tune, A_MIN, A_MAX, mode='wait'):
600
+ import time
601
+ from IPython.display import display, Image, clear_output
602
+
603
+
604
+ # Copy relevant constants from the file for local scope
605
+ THUMB_TIP_ID = 4
606
+ INDEX_TIP_ID = 8
607
+ REQUIRED_STABLE_FRAMES = 45
608
+ MOVEMENT_THRESHOLD = 0.015
609
+ PLOT_CEILING_A = 10.0
610
+ EPS = 1e-9
611
+
612
+ D_MIN = 0.001
613
+ D_MAX = 0.2
614
+ D_RANGE = D_MAX - D_MIN
615
+ A_RANGE = A_MAX - A_MIN
616
+ SLOPE = -A_RANGE / D_RANGE
617
+ INTERCEPT = A_MAX - SLOPE * D_MIN
618
+ # End of copied constants
619
+
620
+ cap = cv2.VideoCapture(0)
621
+ captured_V = None
622
+
623
+ if not cap.isOpened():
624
+ print("Error: Could not open video stream. Check permissions or camera index.")
625
+ return None
626
+
627
+ stability_counter = 0
628
+ prev_landmarks = []
629
+
630
+ start_time = time.time()
631
+ MAX_RUN_TIME_SECONDS = 30
632
+
633
+ print("Controls: HOLD STILL to capture, or wait for the time limit to exit.")
634
+
635
+ while True:
636
+ ret, frame = cap.read()
637
+ if not ret:
638
+ break
639
+
640
+ frame = cv2.flip(frame, 1)
641
+ h, w, _ = frame.shape
642
+ rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
643
+ res = hands.process(rgb)
644
+
645
+ pot_profile = None
646
+ mode_msg = "No Hands"
647
+ params_to_display = []
648
+ current_landmarks_flat = []
649
+
650
+ # --- LANDMARK AND POTENTIAL LOGIC (Skipped for brevity, assume this is correct) ---
651
+ if res.multi_hand_landmarks:
652
+ for hand_lms in res.multi_hand_landmarks:
653
+ for lm in hand_lms.landmark:
654
+ current_landmarks_flat.extend([lm.x, lm.y])
655
+ for lm in res.multi_hand_landmarks:
656
+ drawer.draw_landmarks(frame, lm, mp_hands.HAND_CONNECTIONS)
657
+
658
+ # TWO HANDS (Square Well)
659
+ if len(res.multi_hand_landmarks) >= 2:
660
+ mode_msg = "Mode: Square Well (Auto-Centered)"
661
+ x_coords = [lm.landmark[INDEX_TIP_ID].x * w for lm in res.multi_hand_landmarks]
662
+ x_coords.sort()
663
+ xL_hand, xR_hand = int(x_coords[0]), int(x_coords[1])
664
+ cv2.line(frame, (xL_hand, 0), (xL_hand, h), (0, 255, 255), 2)
665
+ cv2.line(frame, (xR_hand, 0), (xR_hand, h), (0, 255, 255), 2)
666
+ well_width = xR_hand - xL_hand
667
+ center_screen = w / 2
668
+ centered_L = center_screen - (well_width / 2)
669
+ centered_R = center_screen + (well_width / 2)
670
+ params_to_display.append(f"Width: {well_width:4.0f} px")
671
+ params_to_display.append(f"Status: Centered")
672
+ x_space = np.linspace(0, w, 400)
673
+ pot_profile = np.ones_like(x_space)
674
+ pot_profile[(x_space > centered_L) & (x_space < centered_R)] = 0
675
+ # ONE HAND (QHO)
676
+ elif len(res.multi_hand_landmarks) == 1:
677
+ mode_msg = "Mode: Pinch QHO"
678
+ lm = res.multi_hand_landmarks[0]
679
+ thumb = lm.landmark[THUMB_TIP_ID]
680
+ index = lm.landmark[INDEX_TIP_ID]
681
+ dx = index.x - thumb.x
682
+ dy = index.y - thumb.y
683
+ pinch_distance = math.sqrt(dx**2 + dy**2)
684
+ A = SLOPE * pinch_distance + INTERCEPT
685
+ A = max(A_MIN, min(A_MAX, A))
686
+ x_space = np.linspace(-1, 1, 400)
687
+ pot_profile = A * (x_space**2)
688
+ pot_profile = pot_profile / (PLOT_CEILING_A + EPS)
689
+ pot_profile = np.clip(pot_profile, 0.0, 1.0)
690
+ params_to_display.append(f"Pinch Dist: {pinch_distance:.4f}")
691
+ params_to_display.append(f"A (curv): {A:.4f}")
692
+ display_pts = np.column_stack(((x_space + 1)/2 * w, (1 - pot_profile) * h)).astype(np.int32)
693
+ cv2.polylines(frame, [display_pts], False, (0, 0, 255), 2)
694
+ # --- END LANDMARK AND POTENTIAL LOGIC ---
695
+
696
+ # STABILITY CHECK
697
+ if mode != 'wait':
698
+ if current_landmarks_flat and prev_landmarks and len(current_landmarks_flat) == len(prev_landmarks):
699
+ movement = np.mean(np.abs(np.array(current_landmarks_flat) - np.array(prev_landmarks)))
700
+ stability_counter = stability_counter + 1 if movement < MOVEMENT_THRESHOLD else 0
701
+ else:
702
+ stability_counter = 0
703
+
704
+ prev_landmarks = current_landmarks_flat
705
+
706
+ if stability_counter > 0:
707
+ progress = stability_counter / REQUIRED_STABLE_FRAMES
708
+ bar_width = int(w * progress)
709
+ color = (0, 255*progress, 255*(1-progress))
710
+ cv2.rectangle(frame, (0, 0), (bar_width, 20), color, -1)
711
+ cv2.putText(frame, "HOLDING...", (10, 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
712
+
713
+ # Finished
714
+ if stability_counter >= REQUIRED_STABLE_FRAMES and pot_profile is not None:
715
+ captured_V = pot_profile
716
+ cap.release()
717
+ # --- LINE REMOVED HERE (was cv2.destroyAllWindows()) ---
718
+ print("Stable capture triggered and video stream closed.")
719
+ return captured_V
720
+
721
+ # UI OVERLAY
722
+ cv2.putText(frame, mode_msg, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
723
+ display_params(frame, params_to_display)
724
+
725
+ # NOTEBOOK DISPLAY
726
+ clear_output(wait=True)
727
+ _, buffer = cv2.imencode('.jpeg', frame)
728
+ display(Image(data=buffer.tobytes()))
729
+
730
+ time.sleep(0.01)
731
+
732
+ if time.time() - start_time > MAX_RUN_TIME_SECONDS:
733
+ print(f"Time limit of {MAX_RUN_TIME_SECONDS} seconds reached.")
734
+ break
735
+
736
+ # -----------------------------------------------------------------
737
+ cap.release()
738
+ return captured_V