Skip to content

Commit 94202c6

Browse files
committed
Air Canvas (Python)
This is a Python mini project through which we can write on our screen by waving our hands.
1 parent 15b1194 commit 94202c6

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

Air_Canvas/README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Hand Gesture Controlled Paint Application 🎨
2+
3+
![Python](https://img.shields.io/badge/Python-3776AB?style=for-the-badge&logo=python&logoColor=white)
4+
![OpenCV](https://img.shields.io/badge/OpenCV-27338e?style=for-the-badge&logo=OpenCV&logoColor=white)
5+
![Mediapipe](https://img.shields.io/badge/Mediapipe-00c853?style=for-the-badge&logo=Mediapipe&logoColor=white)
6+
7+
A hand gesture controlled paint application using Python, OpenCV, and Mediapipe. This project allows users to draw on a virtual canvas using hand gestures, making use of hand landmarks for color selection and drawing.
8+
9+
## Features ✨
10+
- Draw with different colors using hand gestures.
11+
- Clear the canvas with a hand gesture.
12+
- Switch colors by moving the thumb close to the index finger.
13+
14+
## Demo 🖼️
15+
![Demo Image](result.png)
16+
17+
## Installation 🛠️
18+
1. Clone the repository:
19+
```bash
20+
git clone https://github.com/harshaparida/Hand_cv_sketch.git
21+
cd Hand_cv_sketch
22+
```
23+
24+
2. Create and activate a virtual environment (optional but recommended):
25+
```bash
26+
python -m venv venv
27+
source venv/bin/activate # On Windows use `venv\Scripts\activate`
28+
```
29+
30+
3. Install the required dependencies:
31+
```bash
32+
pip install -r requirements.txt
33+
```
34+
35+
## Usage 🚀
36+
1. Run the application:
37+
```bash
38+
python main.py
39+
```
40+
41+
2. Use your index finger to draw on the screen.
42+
3. Use the buttons on the top of the canvas to change colors or clear the screen.
43+
44+
## Libraries Used 📚
45+
- [OpenCV](https://opencv.org/) - Open Source Computer Vision Library
46+
- [Mediapipe](https://mediapipe.dev/) - Cross-platform ML solutions for live and streaming media
47+
- [NumPy](https://numpy.org/) - The fundamental package for scientific computing with Python
48+
49+
## Acknowledgments 🙏
50+
- Thanks to the developers of [OpenCV](https://opencv.org/) and [Mediapipe](https://mediapipe.dev/) for providing the tools necessary to build this project.
51+
52+
53+
---
54+
55+
Made with ❤️ by [Harsha](https://github.com/harshaparida)

Air_Canvas/main.py

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import cv2
2+
import numpy as np
3+
import mediapipe as mp
4+
from collections import deque
5+
6+
bpoints = [deque(maxlen=1024)]
7+
gpoints = [deque(maxlen=1024)]
8+
rpoints = [deque(maxlen=1024)]
9+
ypoints = [deque(maxlen=1024)]
10+
11+
blue_index = 0
12+
green_index = 0
13+
red_index = 0
14+
yellow_index = 0
15+
16+
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 255, 255)]
17+
colorIndex = 0
18+
19+
paintWindow = np.zeros((471,636,3)) + 255
20+
paintWindow = cv2.rectangle(paintWindow, (40,1), (140,65), (0,0,0), 2)
21+
paintWindow = cv2.rectangle(paintWindow, (160,1), (255,65), (255,0,0), 2)
22+
paintWindow = cv2.rectangle(paintWindow, (275,1), (370,65), (0,255,0), 2)
23+
paintWindow = cv2.rectangle(paintWindow, (390,1), (485,65), (0,0,255), 2)
24+
paintWindow = cv2.rectangle(paintWindow, (505,1), (600,65), (0,255,255), 2)
25+
26+
paintWindow = cv2.rectangle(paintWindow, (40, 1), (140, 65), (255, 255, 255), -1) # Clear (white)
27+
paintWindow = cv2.rectangle(paintWindow, (160, 1), (255, 65), (255, 0, 0), -1) # Blue
28+
paintWindow = cv2.rectangle(paintWindow, (275, 1), (370, 65), (0, 255, 0), -1) # Green
29+
paintWindow = cv2.rectangle(paintWindow, (390, 1), (485, 65), (0, 0, 255), -1) # Red
30+
paintWindow = cv2.rectangle(paintWindow, (505, 1), (600, 65), (0, 255, 255), -1) # Yellow
31+
32+
cv2.putText(paintWindow, "CLEAR", (49, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2, cv2.LINE_AA)
33+
cv2.putText(paintWindow, "BLUE", (185, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
34+
cv2.putText(paintWindow, "GREEN", (298, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
35+
cv2.putText(paintWindow, "RED", (420, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
36+
cv2.putText(paintWindow, "YELLOW", (520, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (150, 150, 150), 2, cv2.LINE_AA)
37+
cv2.namedWindow('Paint', cv2.WINDOW_AUTOSIZE)
38+
39+
# Initialize Mediapipe for hand detection
40+
mpHands = mp.solutions.hands
41+
hands = mpHands.Hands(max_num_hands=1, min_detection_confidence=0.7)
42+
mpDraw = mp.solutions.drawing_utils
43+
44+
cap = cv2.VideoCapture(0)
45+
ret = True
46+
47+
while ret:
48+
49+
ret, frame = cap.read()
50+
51+
# Flip the frame vertically
52+
frame = cv2.flip(frame, 1)
53+
54+
framergb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
55+
cv2.putText(paintWindow, "CLEAR", (49,33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0), 2, cv2.LINE_AA)
56+
cv2.putText(paintWindow, "BLUE", (185,33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2, cv2.LINE_AA)
57+
cv2.putText(paintWindow, "GREEN", (298,33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2, cv2.LINE_AA)
58+
cv2.putText(paintWindow, "RED", (420,33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2, cv2.LINE_AA)
59+
cv2.putText(paintWindow, "YELLOW", (520,33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (150,150,150), 2, cv2.LINE_AA)
60+
61+
# Get hand landmark prediction
62+
result = hands.process(framergb)
63+
64+
# Post-process the result
65+
if result.multi_hand_landmarks:
66+
landmarks = []
67+
for handslms in result.multi_hand_landmarks:
68+
for lm in handslms.landmark:
69+
lmx = int(lm.x * 640)
70+
lmy = int(lm.y * 480)
71+
landmarks.append([lmx, lmy])
72+
73+
# Drawing landmarks on frames
74+
mpDraw.draw_landmarks(frame, handslms, mpHands.HAND_CONNECTIONS)
75+
76+
# Extracting hand landmarks for finger and thumb
77+
fore_finger = (landmarks[8][0],landmarks[8][1])
78+
center = fore_finger
79+
thumb = (landmarks[4][0],landmarks[4][1])
80+
81+
# Detecting thumb movement to switch colors
82+
if (thumb[1]-center[1]<30):
83+
bpoints.append(deque(maxlen=512))
84+
blue_index += 1
85+
gpoints.append(deque(maxlen=512))
86+
green_index += 1
87+
rpoints.append(deque(maxlen=512))
88+
red_index += 1
89+
ypoints.append(deque(maxlen=512))
90+
yellow_index += 1
91+
92+
elif center[1] <= 65:
93+
if 40 <= center[0] <= 140: # Clear Button
94+
bpoints = [deque(maxlen=512)]
95+
gpoints = [deque(maxlen=512)]
96+
rpoints = [deque(maxlen=512)]
97+
ypoints = [deque(maxlen=512)]
98+
99+
blue_index = 0
100+
green_index = 0
101+
red_index = 0
102+
yellow_index = 0
103+
104+
paintWindow[67:,:,:] = 255
105+
elif 160 <= center[0] <= 255:
106+
colorIndex = 0 # Blue
107+
elif 275 <= center[0] <= 370:
108+
colorIndex = 1 # Green
109+
elif 390 <= center[0] <= 485:
110+
colorIndex = 2 # Red
111+
elif 505 <= center[0] <= 600:
112+
colorIndex = 3 # Yellow
113+
else :
114+
if colorIndex == 0:
115+
bpoints[blue_index].appendleft(center)
116+
elif colorIndex == 1:
117+
gpoints[green_index].appendleft(center)
118+
elif colorIndex == 2:
119+
rpoints[red_index].appendleft(center)
120+
elif colorIndex == 3:
121+
ypoints[yellow_index].appendleft(center)
122+
123+
124+
else:
125+
bpoints.append(deque(maxlen=512))
126+
blue_index += 1
127+
gpoints.append(deque(maxlen=512))
128+
green_index += 1
129+
rpoints.append(deque(maxlen=512))
130+
red_index += 1
131+
ypoints.append(deque(maxlen=512))
132+
yellow_index += 1
133+
134+
points = [bpoints, gpoints, rpoints, ypoints]
135+
136+
for i in range(len(points)):
137+
for j in range(len(points[i])):
138+
for k in range(1, len(points[i][j])):
139+
if points[i][j][k - 1] is None or points[i][j][k] is None:
140+
continue
141+
cv2.line(frame, points[i][j][k - 1], points[i][j][k], colors[i], 2)
142+
cv2.line(paintWindow, points[i][j][k - 1], points[i][j][k], colors[i], 2)
143+
144+
cv2.imshow("Output", frame)
145+
cv2.imshow("Paint", paintWindow)
146+
147+
if cv2.waitKey(1) == ord('q'):
148+
break
149+
150+
cap.release()
151+
cv2.destroyAllWindows()
152+

Air_Canvas/requirements.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Run this command to install
2+
# pip install -r requirements.txt
3+
4+
5+
opencv-python
6+
mediapipe
7+
numpy
8+

Air_Canvas/result.png

879 KB
Loading

0 commit comments

Comments
 (0)