-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #267 from Rohit131313/aivirtualpainter
Added a new project Aivirtualpainter
- Loading branch information
Showing
14 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import cv2 | ||
import mediapipe as mp | ||
import math | ||
|
||
class handDetector(): | ||
def __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5): | ||
self.mode = mode | ||
self.maxHands = maxHands | ||
self.detectionCon = detectionCon | ||
self.trackCon = trackCon | ||
|
||
self.mpHands = mp.solutions.hands | ||
self.hands = self.mpHands.Hands( | ||
static_image_mode=self.mode, | ||
max_num_hands=self.maxHands, | ||
min_detection_confidence=self.detectionCon, | ||
min_tracking_confidence=self.trackCon | ||
) | ||
self.mpDraw = mp.solutions.drawing_utils | ||
self.tipIds = [4, 8, 12, 16, 20] | ||
|
||
def findHands(self, img, draw=True): | ||
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) | ||
self.results = self.hands.process(imgRGB) | ||
|
||
if self.results.multi_hand_landmarks: | ||
for handLms in self.results.multi_hand_landmarks: | ||
if draw: | ||
self.mpDraw.draw_landmarks(img, handLms, | ||
self.mpHands.HAND_CONNECTIONS) | ||
|
||
return img | ||
|
||
def findPosition(self, img, handNo=0, draw=True): | ||
xList = [] | ||
yList = [] | ||
bbox = [] | ||
self.lmList = [] | ||
if self.results.multi_hand_landmarks: | ||
myHand = self.results.multi_hand_landmarks[handNo] | ||
for id, lm in enumerate(myHand.landmark): | ||
h, w, c = img.shape | ||
cx, cy = int(lm.x * w), int(lm.y * h) | ||
xList.append(cx) | ||
yList.append(cy) | ||
self.lmList.append([id, cx, cy]) | ||
if draw: | ||
cv2.circle(img, (cx, cy), 5, (255, 0, 255), cv2.FILLED) | ||
|
||
xmin, xmax = min(xList), max(xList) | ||
ymin, ymax = min(yList), max(yList) | ||
bbox = xmin, ymin, xmax, ymax | ||
|
||
if draw: | ||
cv2.rectangle(img, (xmin - 20, ymin - 20), (xmax + 20, ymax + 20), | ||
(0, 255, 0), 2) | ||
|
||
return self.lmList, bbox | ||
|
||
def fingersUp(self): | ||
fingers = [] | ||
# Thumb | ||
if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]: | ||
fingers.append(1) | ||
else: | ||
fingers.append(0) | ||
|
||
# Fingers | ||
for id in range(1, 5): | ||
if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]: | ||
fingers.append(1) | ||
else: | ||
fingers.append(0) | ||
|
||
return fingers | ||
|
||
def findDistance(self, p1, p2, img, draw=True,r=15, t=3): | ||
x1, y1 = self.lmList[p1][1:] | ||
x2, y2 = self.lmList[p2][1:] | ||
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2 | ||
|
||
if draw: | ||
cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t) | ||
cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED) | ||
cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED) | ||
cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED) | ||
length = math.hypot(x2 - x1, y2 - y1) | ||
|
||
return length, img, [x1, y1, x2, y2, cx, cy] |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# AI Virtual Painter Project | ||
|
||
## AIM | ||
Create a real-time interactive AI tool that uses hand gestures to allow users to paint or draw virtually using their camera feed. | ||
|
||
## DESCRIPTION | ||
The **AI Virtual Painter** project utilizes computer vision techniques to detect hand gestures and track finger movements in real-time, transforming these gestures into painting or drawing actions on the screen. This project leverages libraries like OpenCV and MediaPipe for hand detection and tracking, allowing users to interact with the system through gestures. | ||
|
||
### Why is this project necessary? | ||
This project showcases the innovative application of AI in enhancing user interaction without physical touch, particularly useful in creating virtual experiences. It’s beneficial for artists, educators, and anyone looking for creative ways to engage with digital tools. | ||
|
||
### How is it beneficial and used? | ||
The virtual painter can be used for: | ||
- Teaching and creative drawing experiences. | ||
- Gesture-controlled applications. | ||
- Fun and interactive painting applications. | ||
|
||
### How did you start approaching this project? | ||
I began by researching hand detection techniques and gesture-based controls using OpenCV and MediaPipe. After building a basic hand-tracking system, I incrementally added drawing capabilities, color selection, and an eraser feature. | ||
|
||
## EXPLANATION | ||
|
||
### DETAILS OF THE DIFFERENT FEATURES | ||
1. **Hand Detection and Tracking**: Using MediaPipe to detect and track hand landmarks. | ||
2. **Drawing**: Raising the index finger allows the user to draw on the screen. | ||
3. **Color Selection**: Both index and middle fingers raised allows color selection from the virtual palette. | ||
4. **Eraser**: Switches to eraser mode based on the gesture selection. | ||
|
||
### WHAT I HAVE DONE | ||
1. Implemented real-time camera feed capture. | ||
2. Integrated hand detection using MediaPipe. | ||
3. Added virtual painting and erasing capabilities. | ||
4. Created gesture-based interaction for selecting different colors and tools. | ||
5. Implemented a virtual header to house drawing tools. | ||
6. Enhanced the system for smooth tracking and minimal lag. | ||
|
||
### Controls for the AI Virtual Painter | ||
|
||
#### 1. Header Interaction | ||
- Use your right hand with both the **index and middle fingers** raised to hover over the header. | ||
- This gesture allows you to select between different tools and colors: **pink, blue, green**, or the **eraser**. | ||
|
||
#### 2. Drawing and Erasing | ||
- Raise only your **index finger** to draw or erase on the screen. | ||
- The action (drawing or erasing) depends on your current selection from the header. | ||
|
||
#### 3. Gesture Control | ||
- Ensure that your hand gestures are clear and visible to guarantee smooth interaction. | ||
- This will help in achieving precise drawing and erasing operations. | ||
|
||
### LIBRARIES NEEDED | ||
- OpenCV | ||
- MediaPipe | ||
- NumPy | ||
|
||
### SCREENSHOTS | ||
1. **Project structure**: | ||
![Project Structure](Images/treediagram.png) | ||
2. **Visualization of hand tracking and painting actions**: | ||
![Hand Tracking](Images/Project.png) | ||
|
||
### MODELS USED AND THEIR ACCURACIES | ||
This project does not involve traditional ML models but instead focuses on real-time computer vision for gesture detection. | ||
|
||
|
||
## CONCLUSION | ||
|
||
### WHAT YOU HAVE LEARNED | ||
- Real-time hand detection and tracking using MediaPipe. | ||
- Gesture-based interaction for virtual environments. | ||
- Building interactive applications with minimal lag using computer vision. | ||
|
||
### USE CASES OF THIS MODEL | ||
1. **Virtual Art Studio**: Artists can create digital art using hand gestures without any physical tools. | ||
2. **Interactive Teaching Tool**: Teachers can engage students by drawing and explaining concepts interactively. | ||
|
||
### HOW TO INTEGRATE THIS MODEL IN REAL WORLD | ||
1. **Prepare the data pipeline**: Ensure a high-quality camera feed is available for smooth hand-tracking. | ||
2. **Deploy the model**: Use tools like Flask or Streamlit to deploy the AI Virtual Painter as a web application. | ||
3. **Monitor and maintain**: Keep the hand detection models updated for improved accuracy in future versions. | ||
|
||
### FEATURES PLANNED BUT NOT IMPLEMENTED | ||
- **Save Drawings Feature**: The ability to save drawings created on the virtual canvas. | ||
- **Multi-user Interaction**: Supporting multiple users in real-time. | ||
|
||
*Rohit Motwani* | ||
|
||
[![LinkedIn](https://img.shields.io/badge/linkedin-%230077B5.svg?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/rohit-motwani1313/) | ||
|
||
#### Happy Coding 🧑💻 | ||
### Show some ❤️ by 🌟 this repository! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import cv2 | ||
import numpy as np | ||
import os | ||
import HandTrackingModule as htm | ||
|
||
####################### | ||
brushThickness = 25 | ||
eraserThickness = 40 | ||
######################## | ||
|
||
folderPath = "Header Files" | ||
myList = os.listdir(folderPath) | ||
overlayList = [] | ||
for imPath in myList: | ||
image = cv2.imread(f'{folderPath}/{imPath}') | ||
overlayList.append(image) | ||
|
||
header = overlayList[0] | ||
drawColor = (255, 0, 255) | ||
|
||
cap = cv2.VideoCapture(0) | ||
cap.set(3, 1280) | ||
cap.set(4, 720) | ||
|
||
detector = htm.handDetector(detectionCon=0.65, maxHands=1) | ||
xp, yp = 0, 0 | ||
imgCanvas = np.zeros((720, 1280, 3), np.uint8) | ||
|
||
eraser = False | ||
while True: | ||
# 1. Import image | ||
success, img = cap.read() | ||
img = cv2.flip(img, 1) | ||
|
||
# 2. Find Hand Landmarks | ||
img = detector.findHands(img) | ||
lmList, bbox = detector.findPosition(img, draw=False) | ||
if len(lmList) != 0: | ||
# tip of index and middle fingers | ||
x1, y1 = lmList[8][1:] | ||
x2, y2 = lmList[12][1:] | ||
|
||
# 3. Check which fingers are up | ||
fingers = detector.fingersUp() | ||
|
||
# 4. If Selection Mode – Two fingers are up | ||
if fingers[1] and fingers[2]: | ||
# Checking for the click | ||
if y1 < 125: | ||
if 250 < x1 < 450: | ||
eraser = False | ||
header = overlayList[0] | ||
drawColor = (255, 0, 255) | ||
elif 550 < x1 < 750: | ||
eraser = False | ||
header = overlayList[1] | ||
drawColor = (250, 0, 0) | ||
elif 800 < x1 < 950: | ||
eraser = False | ||
header = overlayList[2] | ||
drawColor = (0, 255, 0) | ||
elif 1050 < x1 < 1200: | ||
eraser = True | ||
header = overlayList[3] | ||
drawColor = (0, 0, 0) | ||
cv2.rectangle(img, (x1, y1 - 25), (x2, y2 + 25), drawColor, cv2.FILLED) | ||
xp, yp = 0, 0 | ||
|
||
# 5. If Drawing Mode – Index finger is up | ||
if fingers[1] and not fingers[2]: | ||
cv2.circle(img, (x1, y1), 15, drawColor, cv2.FILLED) | ||
if xp == 0 and yp == 0: | ||
xp, yp = x1, y1 | ||
|
||
if eraser: | ||
cv2.line(imgCanvas, (xp, yp), (x1, y1), drawColor, eraserThickness) | ||
else: | ||
cv2.line(imgCanvas, (xp, yp), (x1, y1), drawColor, brushThickness) | ||
|
||
|
||
xp, yp = x1, y1 | ||
|
||
# # Modify canvas | ||
imgGray = cv2.cvtColor(imgCanvas, cv2.COLOR_BGR2GRAY) | ||
_, imgInv = cv2.threshold(imgGray, 50, 255, cv2.THRESH_BINARY_INV) | ||
imgInv = cv2.cvtColor(imgInv, cv2.COLOR_GRAY2BGR) | ||
img = cv2.bitwise_and(img, imgInv) | ||
img = cv2.bitwise_or(img, imgCanvas) | ||
|
||
height, width, channel = header.shape | ||
# Setting the header image | ||
img[0:height, 0:1280] = header | ||
|
||
cv2.imshow("Image", img) | ||
|
||
if cv2.waitKey(1) & 0xFF == ord('q'): | ||
break | ||
|
||
cv2.destroyAllWindows() | ||
cap.release() |
Binary file added
BIN
+5.26 KB
Data_Science/AI Virtual Painter/__pycache__/HandTrackingModule.cpython-312.pyc
Binary file not shown.
Binary file added
BIN
+2.79 KB
Data_Science/AI Virtual Painter/__pycache__/HandTrackingModule.cpython-39.pyc
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
matplotlib==3.9.2 | ||
mediapipe==0.10.14 | ||
numpy==1.26.4 | ||
opencv-contrib-python==4.10.0.84 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters