-
Notifications
You must be signed in to change notification settings - Fork 120
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a8b2de7
commit 499ab84
Showing
4 changed files
with
259 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,64 @@ | ||
# Hand Controller: Control Cars 🚗 Using Hand Gestures in Games | ||
|
||
This project leverages Python and OpenCV to create a gesture-based hand controller for games. Using computer vision techniques, the program tracks the user's hand movements and translates them into real-time actions to control a car in any game. This unique and intuitive interface allows players to steer, accelerate, brake, and perform other functions without the need for physical controllers or keyboards. | ||
|
||
## Features | ||
|
||
- **Real-time Hand Tracking:** Uses OpenCV to detect hand gestures. | ||
- **Gesture-based Controls:** Move your hand to steer the car, accelerate, or change directions. | ||
- **Supports PC and Mobile Cameras:** Control the car using either your PC's webcam or your mobile device's camera. | ||
- **Cross-Game Compatibility:** Can be used to control vehicles in various driving games by mapping hand gestures to game actions. | ||
|
||
## How It Works | ||
|
||
This project captures the live feed from a camera (either from your PC or mobile) and detects specific hand gestures. These gestures are then translated into game commands (e.g., moving left, right, accelerating, or braking). The gesture detection works using basic image processing techniques, including contour detection and hand tracking algorithms. | ||
|
||
### Key Gestures: | ||
- **Open hand** – Move the car forward | ||
- **Closed fist** – Stop the car | ||
- **Move hand left** – Steer left | ||
- **Move hand right** – Steer right | ||
|
||
These gestures are customizable and can be adjusted based on user preferences or the specific game being played. | ||
|
||
## Installation | ||
|
||
To get started, clone the repository and install the required dependencies. | ||
|
||
```bash | ||
git clone https://github.com/your-username/hand-controller.git | ||
cd hand-controller | ||
pip install -r requirements.txt | ||
``` | ||
|
||
Make sure you have Python 3.x installed along with the required libraries in `requirements.txt`. | ||
|
||
### Requirements: | ||
|
||
- Python 3.x | ||
- OpenCV | ||
- NumPy | ||
|
||
## Usage | ||
|
||
You can use either your PC's camera or your mobile camera to control the car. | ||
|
||
### Using PC Camera: | ||
1. Run the following command to start the program with your PC webcam: | ||
```bash | ||
python main-pc-cam.py | ||
``` | ||
2. Put your hand in front of the camera, and the program will start detecting gestures. | ||
|
||
### Using Mobile Camera: | ||
1. Download the [IP Webcam](https://play.google.com/store/apps/details?id=com.pas.webcam) app on your mobile device. | ||
2. Launch the app and note the IP address shown on the screen. | ||
3. In the `main-mobile-cam.py` script, update the `url` variable with the IP address provided by the IP Webcam app. | ||
4. Run the following command to start the program using your mobile camera: | ||
```bash | ||
python main-mobile-cam.py | ||
``` | ||
5. Position your hand in front of the mobile camera to control the car. | ||
|
||
### Customizing Gesture Control: | ||
You can modify the gesture mappings in the main script files (`main-pc-cam.py` or `main-mobile-cam.py`) to assign specific hand gestures to different game actions. Feel free to experiment with different gestures to fit your playstyle. |
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,85 @@ | ||
import cv2 | ||
import mediapipe as mp | ||
|
||
from pynput.keyboard import Controller | ||
|
||
mp_hands = mp.solutions.hands.Hands() | ||
keyboard = Controller() | ||
|
||
url = 'http://<YOUR-IP>/video' | ||
cp = cv2.VideoCapture(url) | ||
x1, x2, y1, y2 =0, 0, 0, 0 | ||
|
||
while(True): | ||
|
||
_, image = cp.read() | ||
|
||
image_height, image_width, image_depth = image.shape | ||
image = cv2.flip(image, 1) | ||
rgb_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | ||
output_hands = mp_hands.process(rgb_img) | ||
all_hands = output_hands.multi_hand_landmarks | ||
|
||
if all_hands: | ||
hand = all_hands[0] | ||
one_hand_landmark = hand.landmark | ||
|
||
for id, lm in enumerate(one_hand_landmark): | ||
x = int(lm.x * image_width) | ||
y = int(lm.y * image_height) | ||
|
||
if id == 12: | ||
x1 = x | ||
y1 = y | ||
|
||
if id == 0: | ||
x2 = x | ||
y2 = y | ||
|
||
distX = 0 | ||
distX = x1 - x2 | ||
distY = 0 | ||
distY =y1 - y2 | ||
|
||
if distY > -140 and distY !=0: | ||
# press S | ||
keyboard.release('d') | ||
keyboard.release('a') | ||
keyboard.release('w') | ||
keyboard.press('s') | ||
print("S") | ||
|
||
if distY < -200 and distY != 0: | ||
keyboard.release('s') | ||
keyboard.release('d') | ||
keyboard.release('a') | ||
keyboard.press('w') | ||
print("W") | ||
|
||
if (distX < -100 and distX != 0): | ||
keyboard.release('s') | ||
keyboard.release('d') | ||
keyboard.press('w') | ||
keyboard.press('a') | ||
print('A') | ||
|
||
if (distX > 55 and distX != 0): | ||
keyboard.release('a') | ||
keyboard.release('s') | ||
keyboard.press('w') | ||
keyboard.press('d') | ||
print('D') | ||
|
||
else: | ||
print('none') | ||
keyboard.release('d') | ||
keyboard.release('a') | ||
keyboard.release('w') | ||
keyboard.release('s') | ||
|
||
# if image is not None: | ||
# cv2.imshow("Frame", image) | ||
q = cv2.waitKey(1) | ||
if q==ord("q"): | ||
break | ||
cv2.destroyAllWindows() |
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,84 @@ | ||
import cv2 | ||
import mediapipe as mp | ||
|
||
from pynput.keyboard import Controller | ||
|
||
mp_hands = mp.solutions.hands.Hands() | ||
keyboard = Controller() | ||
|
||
cp = cv2.VideoCapture(0) | ||
x1, x2, y1, y2 =0, 0, 0, 0 | ||
|
||
while(True): | ||
|
||
_, image = cp.read() | ||
|
||
image_height, image_width, image_depth = image.shape | ||
image = cv2.flip(image, 1) | ||
rgb_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | ||
output_hands = mp_hands.process(rgb_img) | ||
all_hands = output_hands.multi_hand_landmarks | ||
|
||
if all_hands: | ||
hand = all_hands[0] | ||
one_hand_landmark = hand.landmark | ||
|
||
for id, lm in enumerate(one_hand_landmark): | ||
x = int(lm.x * image_width) | ||
y = int(lm.y * image_height) | ||
|
||
if id == 12: | ||
x1 = x | ||
y1 = y | ||
|
||
if id == 0: | ||
x2 = x | ||
y2 = y | ||
|
||
distX = 0 | ||
distX = x1 - x2 | ||
distY = 0 | ||
distY =y1 - y2 | ||
|
||
if distY > -140 and distY !=0: | ||
# press S | ||
keyboard.release('d') | ||
keyboard.release('a') | ||
keyboard.release('w') | ||
keyboard.press('s') | ||
print("S") | ||
|
||
if distY < -200 and distY != 0: | ||
keyboard.release('s') | ||
keyboard.release('d') | ||
keyboard.release('a') | ||
keyboard.press('w') | ||
print("W") | ||
|
||
if (distX < -100 and distX != 0): | ||
keyboard.release('s') | ||
keyboard.release('d') | ||
keyboard.press('w') | ||
keyboard.press('a') | ||
print('A') | ||
|
||
if (distX > 55 and distX != 0): | ||
keyboard.release('a') | ||
keyboard.release('s') | ||
keyboard.press('w') | ||
keyboard.press('d') | ||
print('D') | ||
|
||
else: | ||
print('none') | ||
keyboard.release('d') | ||
keyboard.release('a') | ||
keyboard.release('w') | ||
keyboard.release('s') | ||
|
||
# if image is not None: | ||
# cv2.imshow("Frame", image) | ||
q = cv2.waitKey(1) | ||
if q==ord("q"): | ||
break | ||
cv2.destroyAllWindows() |
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,26 @@ | ||
absl-py==2.1.0 | ||
attrs==23.2.0 | ||
cffi==1.16.0 | ||
contourpy==1.2.1 | ||
cycler==0.12.1 | ||
flatbuffers==24.3.25 | ||
fonttools==4.51.0 | ||
jax==0.4.26 | ||
kiwisolver==1.4.5 | ||
matplotlib==3.8.4 | ||
mediapipe==0.10.11 | ||
ml-dtypes==0.4.0 | ||
numpy==1.26.4 | ||
opencv-contrib-python==4.9.0.80 | ||
opencv-python==4.9.0.80 | ||
opt-einsum==3.3.0 | ||
packaging==24.0 | ||
pillow==10.3.0 | ||
protobuf==3.20.3 | ||
pycparser==2.22 | ||
pynput==1.7.6 | ||
pyparsing==3.1.2 | ||
python-dateutil==2.9.0.post0 | ||
scipy==1.13.0 | ||
six==1.16.0 | ||
sounddevice==0.4.6 |