├── Hand Gesture Calculator ├── requirements.txt ├── readme.md └── Calculator.py ├── Gesture Volume Control ├── requirements.txt ├── GestureVolumeControl.py ├── readme.md └── HandTrackingModule.py ├── Hand Gestures with AI ├── requirements.txt ├── readme.md └── MathWithGestures.py ├── LICENSE └── README.md /Hand Gesture Calculator/requirements.txt: -------------------------------------------------------------------------------- 1 | opencv-python 2 | mediapipe 3 | numpy 4 | -------------------------------------------------------------------------------- /Gesture Volume Control/requirements.txt: -------------------------------------------------------------------------------- 1 | opencv-python 2 | mediapipe 3 | numpy 4 | pycaw 5 | comtypes 6 | -------------------------------------------------------------------------------- /Hand Gestures with AI/requirements.txt: -------------------------------------------------------------------------------- 1 | opencv-python 2 | pillow 3 | cvzone 4 | mediapipe 5 | numpy 6 | google-generativeai 7 | streamlit 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Jaya Bharath Reddy Iska 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Computer Vision Projects 2 | 3 | This repository showcases a collection of computer vision projects, demonstrating various techniques and applications. 4 | 5 | ## Projects 6 | 7 | 1. **Hand Gesture Calculator:** 8 | * A touchless calculator that allows users to input numbers and operators using finger counting and hand gestures. 9 | * Uses OpenCV and MediaPipe for real-time hand tracking and finger detection. 10 | * Includes eye blink detection to store the total number inputed by hands. 11 | * See the `hand_calculator/` directory for detailed information. 12 | 13 | ## About 14 | 15 | This repository aims to provide examples of practical computer vision applications. Each project is contained within its own directory, including its own README with specific instructions and details. 16 | 17 | ## Contributing 18 | 19 | Contributions are welcome! If you have a computer vision project you'd like to add, please follow these guidelines: 20 | 21 | 1. Create a new directory for your project. 22 | 2. Include a `README.md` file within your project directory, describing the project, its features, installation, and usage. 23 | 3. Ensure your project includes a `requirements.txt` file listing all necessary dependencies. 24 | 4. Submit a pull request with your project. 25 | 26 | ## Author 27 | 28 | Jaya Bharath Reddy Iska 29 | 30 | ## License 31 | 32 | [MIT License](LICENSE) 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ## 📞 Contact Me 44 | - GitHub: [Jay](https://github.com/bharathreddy18) 45 | - LinkedIn: [Jaya Bharath Reddy](https://linkedin.com/in/jaya-bharath-reddy-iska-7a3844210) 46 | - Mail: bharathreddy.iska@gmail.com 47 | -------------------------------------------------------------------------------- /Gesture Volume Control/GestureVolumeControl.py: -------------------------------------------------------------------------------- 1 | from HandTrackingModule import HandDetector 2 | import cv2 3 | import time 4 | import numpy as np 5 | import math 6 | from ctypes import cast, POINTER 7 | from comtypes import CLSCTX_ALL 8 | from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume, IPropertyStore 9 | 10 | cap = cv2.VideoCapture(0) 11 | cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) 12 | cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) 13 | # cap.set(cv2.CAP_PROP_FPS, 20) 14 | pTime = 0 15 | 16 | detector = HandDetector() 17 | 18 | devices = AudioUtilities.GetSpeakers() 19 | interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None) 20 | volume = cast(interface, POINTER(IAudioEndpointVolume)) 21 | vol_range = volume.GetVolumeRange() 22 | # print(vol_range) 23 | min_vol, max_vol = vol_range[0], vol_range[1] 24 | print(f"Volume range: {min_vol} to {max_vol}") 25 | volBar = 400 26 | volPer = 0 27 | while True: 28 | ret, img = cap.read() 29 | if not ret: 30 | break 31 | img = detector.findHands(img) 32 | lmList = detector.findPositions(img, draw=False) 33 | if len(lmList) != 0: 34 | # print(lmList[4], lmList[8]) 35 | 36 | x1, y1 = lmList[4][1], lmList[4][2] 37 | x2, y2 = lmList[8][1], lmList[8][2] 38 | cx, cy = (x1+x2)//2, (y1+y2)//2 39 | 40 | cv2.circle(img, (x1,y1), 10, (255,0,255), -1) 41 | cv2.circle(img, (x2,y2), 10, (255, 0, 255), -1) 42 | cv2.line(img, (x1,y1), (x2,y2), (255,0,255), 2) 43 | cv2.circle(img, (cx, cy), 10, (255, 0, 255), -1) 44 | 45 | length = math.hypot(x2-x1, y2-y1) 46 | # Apply log scaling to hand distance 47 | log_length = np.log10(length + 1) # Adding 1 to avoid log(0) 48 | 49 | # Adjusting input range to match hand distance 50 | vol = np.interp(log_length, [np.log10(30+1), np.log10(250+1)], [min_vol, max_vol]) 51 | volBar = np.interp(length, [30, 250], [400, 150]) 52 | # volPer = np.interp(length, [30, 250], [0, 100]) 53 | print(length, vol) 54 | 55 | volume.SetMasterVolumeLevel(vol, None) 56 | 57 | if length < 30: 58 | cv2.circle(img, (cx,cy), 10, (0,255,0), -1) 59 | 60 | cv2.rectangle(img, (50,150), (85, 400), (0,255,0), 2) 61 | cv2.rectangle(img, (50, int(volBar)), (85,400), (0,255,0), -1) 62 | # cv2.putText(img, f'{int(volPer)}%', (55, 140), cv2.FONT_HERSHEY_PLAIN, 1, (255, 0, 0), 2) 63 | 64 | cTime = time.time() 65 | fps = 1/(cTime-pTime) 66 | pTime = cTime 67 | cv2.putText(img, str(int(fps)), (30,40), cv2.FONT_HERSHEY_PLAIN, 1, (255,0,255), 1) 68 | 69 | cv2.imshow('image', img) 70 | if cv2.waitKey(1) & 0xFF == ord('q'): 71 | break 72 | 73 | cap.release() 74 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Hand Gesture Calculator/readme.md: -------------------------------------------------------------------------------- 1 | # Hand Gesture Calculator 2 | 3 | This project implements a hand gesture-based calculator using OpenCV and MediaPipe. It allows users to input numbers and operators using finger counting and hand gestures, providing a touchless and interactive calculation experience. 4 | 5 | ## Features 6 | 7 | - **Finger-based Digit Input:** Input digits by raising the corresponding number of fingers. 8 | - **Gesture-based Operator Selection:** Select mathematical operators (+, -, \*, /) with hand movements. 9 | - **Real-time Calculation Display:** See the calculation results instantly on the screen. 10 | - **Touchless Interaction:** Perform calculations without touching a physical keypad. 11 | 12 | ## Technologies Used 13 | 14 | - **OpenCV:** For capturing and displaying the live video feed. 15 | - **MediaPipe Hands:** For accurate and real-time hand tracking and finger counting. 16 | - **Python:** The backbone of the application's logic. 17 | 18 | ## Prerequisites 19 | 20 | - Python 3.6+ 21 | - OpenCV (`pip install opencv-python`) 22 | - MediaPipe (`pip install mediapipe`) 23 | - NumPy (`pip install numpy`) 24 | 25 | ## Installation 26 | 27 | 1. Clone the repository: 28 | 29 | ```bash 30 | git clone https://github.com/bharathreddy18/Computer-Vision-Projects.git 31 | cd Hand Gesture Calculator 32 | ``` 33 | 34 | 2. Install the required libraries: 35 | 36 | ```bash 37 | pip install -r requirements.txt 38 | ``` 39 | 40 | ## Usage 41 | 42 | 1. Run the Python script: 43 | 44 | ```bash 45 | python hand_calculator.py 46 | ``` 47 | 48 | 2. **Digit Input:** Raise the corresponding number of fingers within the designated input boxes. 49 | 3. **Operator Selection:** Point your index finger to the desired operator button. 50 | 4. **Confirmation:** Show your palm with your right hand to confirm the input. 51 | 5. **Evaluation:** Make fists with both hands to evaluate the expression. 52 | 6. **Reset:** Press 'r' to reset the calculator. 53 | 7. **Quit:** Press 'q' to quit. 54 | 55 | ## Code Structure 56 | 57 | - `hand_calculator.py`: Contains the main `HandCalculator` class and the application's logic. 58 | 59 | ## Contributing 60 | 61 | Contributions are welcome! Please feel free to submit pull requests or open issues to suggest improvements or report bugs. 62 | 63 | ## Author 64 | 65 | Jaya Bharath Reddy Iska 66 | 67 | ## Hashtags 68 | 69 | \#TouchlessTechnology \#HandTracking \#Codinglife \#MediaPipe \#Python \#OpenCV \#ComputerVision \#GestureControl \#ArtificialIntelligence \#AI \#MachineLearning \#ML \#DeepLearning \#NeuralNetworks \#Tech \#Technology \#Code \#Programmer \#Programming \#PythonProjects \#SoftwareDeveloper \#SoftwareEngineer \#Development \#Engineering \#RealTimeTracking \#InteractiveTech \#Innovation \#TechForGood \#DataScience \#ComputerScience \#LinkedIn \#AICommunity \#FutureofLearning 70 | -------------------------------------------------------------------------------- /Hand Gestures with AI/readme.md: -------------------------------------------------------------------------------- 1 | # Gesture-Based Math Solver & Shape Recognition using AI 🤖🖐️ 2 | 3 | ## 🎯 Project Overview 4 | This project enables users to **solve math problems** and **recognize shapes** using only **hand gestures**! By leveraging **computer vision and AI**, it provides a seamless, hands-free interaction experience. 5 | 6 | ## 🔥 Features 7 | ✅ **Hand Gesture-Based Math Solver** – Draw numbers & equations in the air, and AI will solve them instantly! 8 | ✅ **Shape Recognition** – Sketch a shape using gestures, and AI will recognize and classify it. 9 | ✅ **Real-Time Processing** – Instant AI-powered results with no delay. 10 | ✅ **Canvas Reset** – Easily clear the screen and start fresh. 11 | 12 | ## 📌 Real-World Applications 13 | 🔹 **Education** 📚 – Interactive math learning tool for students. 14 | 🔹 **Accessibility** ♿ – Helps individuals with disabilities interact hands-free. 15 | 🔹 **Smart Classrooms** 🏫 – Enhances digital learning. 16 | 🔹 **AR/VR Interactions** 🎮 – Gesture-based controls in gaming & immersive tech. 17 | 🔹 **Creative Design** 🎨 – Artists can sketch and get AI-powered interpretations. 18 | 🔹 **Industrial Use** 🏭 – Engineers & professionals can interact with AI-driven systems hands-free. 19 | 🔹 **Human-Computer Interaction** 💻 – A step toward natural AI interfaces. 20 | 21 | ## 🛠 Tech Stack 22 | - **Python** 🐍 23 | - **OpenCV & Mediapipe** – Real-time hand tracking 📷 24 | - **Google Gemini AI** – AI-powered content generation 🤖 25 | - **Streamlit** – Interactive UI ⚡ 26 | - **Deep Learning** – For shape recognition & equation solving 🧠 27 | 28 | ## 🚀 Installation & Setup 29 | 1. Clone the repository: 30 | ```bash 31 | git clone https://github.com/bharathreddy18/Computer-Vision-Projects.git 32 | cd "Hand Gestures with AI" 33 | ``` 34 | 2. Install dependencies: 35 | ```bash 36 | pip install -r requirements.txt 37 | ``` 38 | 3. Run the application: 39 | ```bash 40 | streamlit run MathWithGestures.py 41 | ``` 42 | 43 | ## 📌 How It Works 44 | 1. **Show a specific hand gesture** to start drawing on the virtual canvas. 45 | 2. **Draw numbers or shapes in the air**, and AI will process the input. 46 | 3. **AI generates an output**, solving math problems or recognizing the drawn shape. 47 | 4. **Use a five-finger gesture** to reset the canvas and answer. 48 | 49 | ## 📢 Contributing 50 | Want to improve this project? Feel free to fork, submit PRs, or suggest new features! 51 | 52 | ## 🔗 Connect with Me 53 | [LinkedIn](https://www.linkedin.com/in/jaya-bharath-reddy-iska-7a3844210/) | [GitHub](https://github.com/bharathreddy18/) 54 | 55 | ## 🏷️ Hashtags 56 | #AI #MachineLearning #ComputerVision #GestureRecognition #DeepLearning #Python #Technology #HandTracking #AIAutomation #TechForGood #DataScience #GestureBasedInteraction #AIInnovation #HumanComputerInteraction #SmartEducation #FutureTech #Robotics #MathAI #ShapeRecognition #DigitalTransformation 57 | 58 | -------------------------------------------------------------------------------- /Gesture Volume Control/readme.md: -------------------------------------------------------------------------------- 1 | # 🎵 Gesture-Based Volume Control 2 | 3 | This project allows users to **control system volume using hand gestures**. By detecting the distance between the **thumb and index finger**, the system dynamically adjusts the volume. It uses **OpenCV, MediaPipe, and Pycaw** for real-time hand tracking and audio control. 4 | 5 | ## 🚀 Features 6 | 7 | - ✋ **Real-time Hand Tracking** using MediaPipe 8 | - 🔊 **Volume Control** based on hand distance 9 | - 📊 **Logarithmic Scaling** for smoother control 10 | - 🎚️ **Visual Volume Bar** for feedback 11 | - 🎥 **Works with Any Webcam** 12 | - 🖥️ **Windows Audio System Integration** 13 | 14 | --- 15 | 16 | ## 📌 How It Works 17 | 18 | 1. **Hand Detection**: Uses MediaPipe to detect the hand and identify key landmarks. 19 | 2. **Distance Measurement**: Calculates the distance between **thumb (landmark 4)** and **index finger (landmark 8)**. 20 | 3. **Volume Mapping**: Converts the measured distance to a volume level using Pycaw. 21 | 4. **Display Feedback**: A **volume bar** visually represents the current volume level. 22 | 23 | --- 24 | 25 | ## 🛠️ Installation 26 | 27 | ### 1️⃣ Clone the Repository 28 | 29 | ```bash 30 | git clone https://github.com/bharathreddy18/Computer-Vision-Projects.git 31 | cd "Gesture Volume Control" 32 | ``` 33 | 34 | ### 2️⃣ Install Dependencies 35 | 36 | Ensure you have **Python 3.8+** installed, then run: 37 | 38 | ```bash 39 | pip install -r requirements.txt 40 | ``` 41 | 42 | --- 43 | 44 | ## 📄 Requirements (`requirements.txt`) 45 | 46 | ``` 47 | opencv-python 48 | mediapipe 49 | numpy 50 | pycaw 51 | comtypes 52 | ``` 53 | 54 | --- 55 | 56 | ## ▶️ Usage 57 | 58 | 1️⃣ **Run the script** 59 | 60 | ```bash 61 | python GestureVolumeControl.py 62 | ``` 63 | 64 | 2️⃣ **Control volume** by moving your **thumb and index finger** closer or farther apart. 65 | 3️⃣ **Press `q` to exit** the program. 66 | 67 | --- 68 | 69 | ## 🚗 Use in Cars 70 | 71 | Gesture-based volume control is now integrated into **modern car infotainment systems**. Instead of using physical buttons or touchscreens, drivers can **adjust volume with simple hand gestures**, improving **safety and convenience** while driving. 72 | 73 | - **🚘 BMW Gesture Control**: Featured in **BMW iDrive**, allowing volume adjustments with a circular hand motion. 74 | - **🔊 Mercedes MBUX**: Uses **gesture recognition cameras** to detect driver commands. 75 | - **🎵 Tesla**: Exploring gesture-based UI for infotainment controls. 76 | 77 | This project demonstrates a **basic version** of this concept using a webcam! 78 | 79 | --- 80 | 81 | ## 📌 To-Do / Improvements 82 | 83 | - ✅ Improve hand tracking accuracy 84 | - ✅ Implement gesture-based **play/pause** control 85 | - 🔲 Integrate with **custom audio applications** 86 | - 🔲 Add **voice feedback** for volume changes 87 | 88 | --- 89 | 90 | ## 📜 License 91 | 92 | This project is **open-source** under the **MIT License**. 93 | 94 | --- 95 | 96 | ## 🏷️ Hashtags 97 | 98 | `#ComputerVision #OpenCV #HandTracking #AI #MachineLearning #GestureControl #Python #DeepLearning #Automation #Innovation #HCI #Mediapipe #Pycaw #GestureRecognition` 99 | 100 | -------------------------------------------------------------------------------- /Gesture Volume Control/HandTrackingModule.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import mediapipe as mp 3 | import time 4 | 5 | 6 | class HandDetector: 7 | def __init__(self, 8 | mode=False, 9 | maxHands=2, 10 | detectionConf=0.5, 11 | trackConf=0.5): 12 | 13 | self.hand_params = { 14 | "static_image_mode":mode, 15 | "max_num_hands":maxHands, 16 | "min_detection_confidence": detectionConf, 17 | "min_tracking_confidence": trackConf 18 | } 19 | 20 | self.mpHands = mp.solutions.hands 21 | self.hands = self.mpHands.Hands(**self.hand_params) 22 | self.mpDraw = mp.solutions.drawing_utils 23 | 24 | self.tipIds = [4, 8, 12, 16, 20] 25 | 26 | def findHands(self, img, draw=True): 27 | imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 28 | self.results = self.hands.process(imgRGB) 29 | 30 | if self.results.multi_hand_landmarks: 31 | for handLms in self.results.multi_hand_landmarks: 32 | if draw: 33 | self.mpDraw.draw_landmarks(img, 34 | handLms, 35 | self.mpHands.HAND_CONNECTIONS, 36 | self.mpDraw.DrawingSpec((0,0,255), 2, 3), 37 | self.mpDraw.DrawingSpec((0,255,0), 2)) 38 | return img 39 | 40 | def findPositions(self, img, handNo=0, draw=True): 41 | self.lmList = [] 42 | 43 | if self.results.multi_hand_landmarks: 44 | myHand = self.results.multi_hand_landmarks[handNo] 45 | for id, lm in enumerate(myHand.landmark): 46 | h, w, c = img.shape 47 | cx, cy = int(lm.x * w), int(lm.y * h) 48 | self.lmList.append([id, cx, cy]) 49 | if draw: 50 | cv2.circle(img, (cx, cy), 10, (255,0,255), -1) 51 | return self.lmList 52 | 53 | def fingersUp(self): 54 | fingers = [] 55 | 56 | # if self.lmList[17][1] < self.lmList[2][1]: 57 | # Right Thumb - This is for the cv2.flip(img, 1) image 58 | if self.lmList[self.tipIds[0]][1] < self.lmList[self.tipIds[0] - 1][1]: 59 | fingers.append(1) 60 | else: 61 | fingers.append(0) 62 | # else: 63 | # Left Thumb 64 | # if self.lmList[tipIds[0]][1] < self.lmList[tipIds[0] - 1][1]: 65 | # fingers.append(1) 66 | # else: 67 | # fingers.append(0) 68 | 69 | # Four Fingers Right 70 | for i in range(1, len(self.tipIds)): 71 | if self.lmList[self.tipIds[i]][2] < self.lmList[self.tipIds[i] - 2][2]: 72 | fingers.append(1) 73 | else: 74 | fingers.append(0) 75 | return fingers 76 | 77 | def main(): 78 | cap = cv2.VideoCapture(0) 79 | detector = HandDetector() 80 | pTime = 0 81 | cTime = 0 82 | 83 | while True: 84 | success, img = cap.read() 85 | if not success: 86 | print('Failed to capture image') 87 | break 88 | 89 | img = detector.findHands(img) 90 | lmList = detector.findPositions(img) 91 | print(lmList) 92 | 93 | cTime = time.time() 94 | fps = 1 / (cTime - pTime) 95 | pTime = cTime 96 | 97 | cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 255), 3) 98 | 99 | cv2.imshow('Image', img) 100 | 101 | if cv2.waitKey(1) & 0xFF == ord('q'): 102 | break 103 | 104 | cap.release() 105 | cv2.destroyAllWindows() 106 | 107 | if __name__ == '__main__': 108 | main() 109 | 110 | 111 | -------------------------------------------------------------------------------- /Hand Gestures with AI/MathWithGestures.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import cvzone 3 | from cvzone.HandTrackingModule import HandDetector 4 | import cv2 5 | import google.generativeai as genai 6 | import numpy as np 7 | import streamlit as st 8 | 9 | 10 | class GestureMathAI: 11 | def __init__(self, api_key, prompt): 12 | self.prompt = prompt 13 | self.canvas = None 14 | self.previous_position = None 15 | self.output_text = "" 16 | 17 | genai.configure(api_key=api_key) 18 | self.model = genai.GenerativeModel('gemini-1.5-flash') 19 | 20 | self.detector = HandDetector(staticMode=False, 21 | maxHands=1, 22 | modelComplexity=1, 23 | detectionCon=0.7, 24 | minTrackCon=0.5) 25 | 26 | self.cap = cv2.VideoCapture(0) 27 | self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) 28 | self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) 29 | 30 | def get_hands_info(self, frame): 31 | hands, _ = self.detector.findHands(frame, draw=False, flipType=True) 32 | if hands: 33 | return self.detector.fingersUp(hands[0]), hands[0]["lmList"] 34 | return None 35 | 36 | def draw_on_canvas(self, hand_info): 37 | fingers, landmarks = hand_info 38 | current_position = None 39 | 40 | if fingers == [0, 1, 0, 0, 0]: 41 | current_position = landmarks[8][:2] 42 | if self.previous_position is None: 43 | self.previous_position = current_position 44 | cv2.line(self.canvas, tuple(current_position), tuple(self.previous_position), (255, 0, 255), 10) 45 | 46 | elif fingers == [1, 1, 1, 1, 1]: 47 | self.canvas = np.zeros_like(self.canvas) 48 | self.output_text = "" 49 | 50 | self.previous_position = current_position 51 | 52 | def send_to_ai(self, hand_info): 53 | fingers, _ = hand_info 54 | if fingers == [1, 1, 1, 1, 0]: 55 | try: 56 | pil_image = Image.fromarray(self.canvas) 57 | response = self.model.generate_content([self.prompt, pil_image]) 58 | return response.text 59 | except Exception as e: 60 | return f'Error: {str(e)}' 61 | 62 | elif fingers == [1, 1, 1, 1, 1]: 63 | return None 64 | 65 | return self.output_text 66 | 67 | def run(self): 68 | st.set_page_config(layout='wide') 69 | st.image('POV.png') 70 | col1, col2 = st.columns([2, 1]) 71 | 72 | with col1: 73 | run_app = st.checkbox('Run', value=True) 74 | frame_window = st.image([]) 75 | 76 | with col2: 77 | st.title("Answer") 78 | output_display = st.subheader("") 79 | 80 | try: 81 | while run_app: 82 | ret, frame = self.cap.read() 83 | if not ret: 84 | break 85 | frame = cv2.flip(frame, 1) 86 | if self.canvas is None: 87 | self.canvas = np.zeros_like(frame) 88 | 89 | hand_info = self.get_hands_info(frame) 90 | if hand_info: 91 | self.draw_on_canvas(hand_info) 92 | self.output_text = self.send_to_ai(hand_info) 93 | 94 | blended_image = cv2.addWeighted(frame, 0.7, self.canvas, 0.3, 0) 95 | frame_window.image(blended_image, channels="BGR") 96 | 97 | if self.output_text is None: 98 | output_display.text("") 99 | else: 100 | output_display.text(self.output_text) 101 | except Exception as e: 102 | st.error(f"Error: {str(e)}") 103 | finally: 104 | self.cap.release() 105 | cv2.destroyAllWindows() 106 | 107 | 108 | if __name__ == "__main__": 109 | ai_instance = GestureMathAI(api_key="YOUR API KEY", prompt="Guess the shape") 110 | ai_instance.run() 111 | -------------------------------------------------------------------------------- /Hand Gesture Calculator/Calculator.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import mediapipe as mp 4 | import time 5 | 6 | 7 | class HandCalculator: 8 | def __init__(self): 9 | # Video Capture 10 | self.cap = cv2.VideoCapture(0) 11 | self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) 12 | self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) 13 | 14 | # Hands 15 | self.mp_hands = mp.solutions.hands 16 | self.hands = self.mp_hands.Hands(max_num_hands=2, min_detection_confidence=0.85, min_tracking_confidence=0.5) 17 | self.mp_draw = mp.solutions.drawing_utils 18 | 19 | # Face Mesh 20 | # self.mp_face_mesh = mp.solutions.face_mesh 21 | # self.face_mesh = self.mp_face_mesh.FaceMesh(min_detection_confidence=0.5, min_tracking_confidence=0.5) 22 | # self.left_eye_indices = [386, 387, 388, 389, 390, 398, 362, 363, 263, 249, 390, 373] 23 | # self.right_eye_indices = [159, 145, 133, 153, 157, 158, 33, 7, 163, 144, 160, 154] 24 | # self.blink_threshold = 0.05 25 | 26 | self.expression = "" 27 | self.result = None 28 | self.last_confirm_time = 0 29 | self.current_display = None 30 | self.awaiting_confirmation = False 31 | 32 | self.box1 = (50, 200, 400, 600) 33 | self.box2 = (450, 200, 800, 600) 34 | self.box3 = (850, 200, 1250, 600) 35 | 36 | self.operator_positions = { 37 | "R": (50, 20, 150, 70), 38 | "+": (300, 50, 400, 100), 39 | "-": (450, 50, 550, 100), 40 | "*": (600, 50, 700, 100), 41 | "/": (750, 50, 850, 100), 42 | } 43 | 44 | def draw_ui(self, img): 45 | """Draws the input boxes and operator buttons.""" 46 | cv2.rectangle(img, (self.box1[0], self.box1[1]), (self.box1[2], self.box1[3]), (255, 0, 0), 2) 47 | cv2.rectangle(img, (self.box2[0], self.box2[1]), (self.box2[2], self.box2[3]), (255, 0, 0), 2) 48 | cv2.rectangle(img, (self.box3[0], self.box3[1]), (self.box3[2], self.box3[3]), (0, 255, 0), 2) 49 | cv2.putText(img, "Input 1", (self.box1[0], self.box1[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2) 50 | cv2.putText(img, "Input 2", (self.box2[0], self.box2[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2) 51 | cv2.putText(img, "Confirm (Fist)", (self.box3[0], self.box3[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) 52 | 53 | for op, (x1, y1, x2, y2) in self.operator_positions.items(): 54 | if op == 'R': 55 | cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), -1) 56 | cv2.putText(img, op, (x1 + 30, y1 + 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2) 57 | else: 58 | cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 255), -1) 59 | cv2.putText(img, op, (x1 + 30, y1 + 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2) 60 | 61 | def count_fingers(self, lm_list, box, left: bool): 62 | """Counts fingers in a given box and returns a digit.""" 63 | if not lm_list: 64 | return None 65 | 66 | wrist_x, wrist_y = lm_list[0][1], lm_list[0][2] 67 | if not (box[0] <= wrist_x <= box[2] and box[1] <= wrist_y <= box[3]): 68 | return None 69 | 70 | finger_tips = [4, 8, 12, 16, 20] 71 | finger_pips = [3, 6, 10, 14, 18] 72 | count = 0 73 | 74 | if left: 75 | if lm_list[finger_tips[0]][1] > lm_list[finger_pips[0]][1]: 76 | count += 1 77 | if not left: 78 | if lm_list[finger_tips[0]][1] < lm_list[finger_pips[0]][1]: 79 | count += 1 80 | 81 | for tip, pip in zip(finger_tips[1:], finger_pips[1:]): 82 | if lm_list[tip][2] < lm_list[pip][2]: 83 | count += 1 84 | 85 | return min(count, 9) 86 | 87 | def detect_operator_selection(self, lm_list): 88 | """Detects if the index finger is pointing at an operator button.""" 89 | if not lm_list: 90 | return None 91 | 92 | index_x, index_y = lm_list[8][1], lm_list[8][2] 93 | for op, (x1, y1, x2, y2) in self.operator_positions.items(): 94 | if x1 <= index_x <= x2 and y1 <= index_y <= y2: 95 | return op 96 | return None 97 | 98 | def evaluate_expression(self): 99 | """Evaluates the current expression and updates result.""" 100 | try: 101 | self.result = eval(self.expression, {"__builtins__": {}}, {}) 102 | except Exception: 103 | self.result = "Error" 104 | 105 | # def is_blinking(self, landmarks, eye_indices): 106 | # y_coords = [landmarks.landmark[i].y for i in eye_indices] 107 | # y_max = max(y_coords) 108 | # y_min = min(y_coords) 109 | # eye_height = y_max - y_min 110 | # return eye_height < self.blink_threshold 111 | 112 | def run(self): 113 | """Main loop of the calculator.""" 114 | while True: 115 | ret, img = self.cap.read() 116 | if not ret: 117 | print("Failed to grab frame") 118 | break 119 | img = cv2.flip(img, 1) 120 | img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 121 | 122 | results_hand = self.hands.process(img_rgb) 123 | # results_face = self.face_mesh.process(img_rgb) 124 | 125 | self.draw_ui(img) 126 | current_time = time.time() 127 | 128 | detected_digit = None 129 | total_digit = 0 130 | detected_operator = None 131 | confirm = False 132 | both_fists = 0 133 | # blinked = False 134 | 135 | if results_hand.multi_hand_landmarks: 136 | hands_list = [] 137 | for hand_landmarks in results_hand.multi_hand_landmarks: 138 | lm_list = [[id, int(lm.x * 1280), int(lm.y * 720)] for id, lm in enumerate(hand_landmarks.landmark)] 139 | hands_list.append((lm_list[0][1], lm_list)) # Store wrist X-coordinate with landmarks 140 | 141 | hands_list.sort() # Sort hands by wrist X-coordinate (leftmost first) 142 | 143 | for idx, (_, lm_list) in enumerate(hands_list): 144 | self.mp_draw.draw_landmarks(img, hand_landmarks, self.mp_hands.HAND_CONNECTIONS) 145 | 146 | # To input digits 147 | if idx == 0: # Left hand (smallest X value) 148 | detected_digit = self.count_fingers(lm_list, self.box1, left=True) 149 | if detected_digit is not None: 150 | total_digit = detected_digit 151 | self.current_display = str(total_digit) 152 | if detected_digit == 0: 153 | both_fists += 1 154 | 155 | selected_operator = self.detect_operator_selection(lm_list) 156 | if selected_operator: 157 | self.current_display = selected_operator 158 | if selected_operator == 'R': 159 | self.expression = "" 160 | self.result = None 161 | self.current_display = None 162 | 163 | elif idx == 1: # Right hand (largest X value) 164 | detected_digit = self.count_fingers(lm_list, self.box2, left=False) 165 | if detected_digit is not None: 166 | total_digit += detected_digit 167 | self.current_display = str(total_digit) 168 | # if results_face.multi_face_landmarks: 169 | # for landmarks in results_face.multi_face_landmarks: 170 | # left_blink = self.is_blinking(landmarks, self.left_eye_indices) 171 | # right_blink = self.is_blinking(landmarks, self.right_eye_indices) 172 | # if total_digit: 173 | # if left_blink and right_blink: 174 | # blinked = True 175 | # if blinked: 176 | # self.expression += str(total_digit) 177 | # blinked = False 178 | elif total_digit is None: 179 | total_digit = 0 180 | 181 | # To confirm expression 182 | for _, lm_list in hands_list: 183 | confirm_count = self.count_fingers(lm_list, self.box3, left=False) 184 | if confirm_count == 5: 185 | confirm = True 186 | elif confirm_count == 0: 187 | both_fists += 1 188 | 189 | if confirm and self.current_display is not None and not self.awaiting_confirmation: 190 | self.expression += self.current_display 191 | self.awaiting_confirmation = True 192 | self.last_confirm_time = current_time 193 | self.current_display = None 194 | 195 | if not confirm and self.awaiting_confirmation: 196 | self.awaiting_confirmation = False 197 | 198 | if both_fists >= 2 and (current_time - self.last_confirm_time > 2): 199 | self.evaluate_expression() 200 | self.last_confirm_time = current_time 201 | 202 | display_text = f"Expression: {self.expression}" if not self.result else f"{self.expression} = {self.result}" 203 | cv2.putText(img, display_text, (50, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3) 204 | 205 | if self.current_display: 206 | cv2.putText(img, f"Current: {self.current_display}", (900, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, 207 | (0, 0, 255), 3) 208 | 209 | cv2.imshow('Hand Calculator', img) 210 | key = cv2.waitKey(1) 211 | if key & 0xFF == ord('q'): 212 | break 213 | elif key & 0xFF == ord('r'): 214 | self.expression = "" 215 | self.result = None 216 | self.current_display = None 217 | 218 | self.cap.release() 219 | cv2.destroyAllWindows() 220 | 221 | 222 | if __name__ == "__main__": 223 | HandCalculator().run() 224 | --------------------------------------------------------------------------------