Skip to content

Commit

Permalink
hand detection added
Browse files Browse the repository at this point in the history
  • Loading branch information
alvonx committed May 8, 2021
1 parent 685472b commit e193309
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 3 deletions.
77 changes: 76 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,79 @@
---

- Face Detection
- Face Mesh
- Face Mesh

## Install the package
```sh
pip install alvonCV
```

## Demo Code for Face Detection

```c
import alvonCV
import cv2
import time

cap = cv2.VideoCapture(0)
pTime = 0
# here you use the alvonCV package
faceDetectorObj = alvonCV.FaceDetector()

while True:
success, img = cap.read()
img, bboxs = faceDetectorObj.findFaces(img, draw=True)
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(img, f'FPS: {int(fps)}', (20, 70), cv2.FONT_HERSHEY_PLAIN, 3, (0, 255, 0), 2)
cv2.imshow("Image", img)
cv2.waitKey(1)
```

## Demo Code for Face Mesh

```c
import alvonCV
import cv2
import time

cap = cv2.VideoCapture(0)
pTime = 0
faceDetectorObj = alvonCV.FaceMeshDetector()

while True:
success, img = cap.read()
img = faceDetectorObj.findFaceMesh(img, draw=True)
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(img, f'FPS: {int(fps)}', (20, 70), cv2.FONT_HERSHEY_PLAIN, 3, (0, 255, 0), 2)
cv2.imshow("Image", img)
cv2.waitKey(1)

```

## Demo Code for Hand Detector

```c
import alvonCV
import cv2
import time

cap = cv2.VideoCapture(0)
detector = alvonCV.HandDetector(detectionCon=0.8, maxHands=1)
while True:
# Get image frame
success, img = cap.read()

# Find the hand and its landmarks
img = detector.findHands(img)
lmList, bbox = detector.findPosition(img)
fingersUp = detector.fingersUp()
print(fingersUp)

# Display
cv2.imshow("Image", img)
cv2.waitKey(1)
```
2 changes: 0 additions & 2 deletions alvonCV/FaceDetectionModule.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ def findFaces(self, img, draw=False):
int(bboxC.width * iw), int(bboxC.height * ih)
bboxs.append([id, bbox, detection.score])

right_eye = (detection.location_data.relative_keypoints[0].x * iw, detection.location_data.relative_keypoints[0].y*ih)
if draw:
self.fancyBBoxDraw(img, bbox)
cv2.circle(img, (int(right_eye[0]), int(right_eye[1])), 1, (0, 0, 255), 1)
cv2.putText(img, f'Score: {int(detection.score[0] * 100)}', (bbox[0], bbox[1] - 20),
cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 255), 2)

Expand Down
179 changes: 179 additions & 0 deletions alvonCV/HandTrackingModule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
"""
Hand Tracking Module
By: Computer Vision Zone
Website: https://www.computervision.zone/
"""

import cv2
import mediapipe as mp
import math


class HandDetector:
"""
Finds Hands using the mediapipe library. Exports the landmarks
in pixel format. Adds extra functionalities like finding how
many fingers are up or the distance between two fingers. Also
provides bounding box info of the hand found.
"""

def __init__(self, mode=False, maxHands=2, detectionCon=0.5, minTrackCon=0.5):
"""
:param mode: In static mode, detection is done on each image: slower
:param maxHands: Maximum number of hands to detect
:param detectionCon: Minimum Detection Confidence Threshold
:param minTrackCon: Minimum Tracking Confidence Threshold
"""
self.mode = mode
self.maxHands = maxHands
self.detectionCon = detectionCon
self.minTrackCon = minTrackCon

self.mpHands = mp.solutions.hands
self.hands = self.mpHands.Hands(self.mode, self.maxHands,
self.detectionCon, self.minTrackCon)
self.mpDraw = mp.solutions.drawing_utils
self.tipIds = [4, 8, 12, 16, 20]
self.fingers = []
self.lmList = []

def findHands(self, img, draw=True):
"""
Finds hands in a BGR image.
:param img: Image to find the hands in.
:param draw: Flag to draw the output on the image.
:return: Image with or without drawings
"""
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):
"""
Finds landmarks of a single hand and puts them in a list
in pixel format. Also finds the bounding box around the hand.
:param img: main image to find hand in
:param handNo: hand id if more than one hand detected
:param draw: Flag to draw the output on the image.
:return: list of landmarks in pixel format; bounding box
"""

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)
boxW, boxH = xmax - xmin, ymax - ymin
bbox = xmin, ymin, boxW, boxH

if draw:
cv2.rectangle(img, (bbox[0] - 20, bbox[1] - 20),
(bbox[0] + bbox[2] + 20, bbox[1] + bbox[3] + 20),
(0, 255, 0), 2)

return self.lmList, bbox

def fingersUp(self):
"""
Finds how many fingers are open and returns in a list.
Considers left and right hands separately
:return: List of which fingers are up
"""
self.fingers = []
if self.results.multi_hand_landmarks:
myHandType = self.handType()
# Thumb
if myHandType == "Right":
if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]:
self.fingers.append(1)
else:
self.fingers.append(0)
else:
if self.lmList[self.tipIds[0]][1] < self.lmList[self.tipIds[0] - 1][1]:
self.fingers.append(1)
else:
self.fingers.append(0)

# 4 Fingers
for id in range(1, 5):
if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:
self.fingers.append(1)
else:
self.fingers.append(0)
return self.fingers

def findDistance(self, p1, p2, img, draw=True):
"""
Find the distance between two landmarks based on their
index numbers.
:param p1: Point1 - Index of Landmark 1.
:param p2: Point2 - Index of Landmark 2.
:param img: Image to draw on.
:param draw: Flag to draw the output on the image.
:return: Distance between the points
Image with output drawn
Line information
"""

if self.results.multi_hand_landmarks:
x1, y1 = self.lmList[p1][1], self.lmList[p1][2]
x2, y2 = self.lmList[p2][1], self.lmList[p2][2]
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2

if draw:
cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)
cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED)
cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 3)
cv2.circle(img, (cx, cy), 15, (255, 0, 255), cv2.FILLED)

length = math.hypot(x2 - x1, y2 - y1)
return length, img, [x1, y1, x2, y2, cx, cy]

def handType(self):
"""
Checks if the hand is left or right
:return: "Right" or "Left"
"""
if self.results.multi_hand_landmarks:
if self.lmList[17][1] < self.lmList[5][1]:
return "Right"
else:
return "Left"

def main():
cap = cv2.VideoCapture(0)
detector = HandDetector(detectionCon=0.8, maxHands=1)
while True:
# Get image frame
success, img = cap.read()
# Find the hand and its landmarks
img = detector.findHands(img)
lmList, bbox = detector.findPosition(img)
fingersUp = detector.fingersUp()
print(fingersUp)

# Display
cv2.imshow("Image", img)
cv2.waitKey(1)


if __name__ == "__main__":
main()
6 changes: 6 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from setuptools import setup
from distutils.core import setup

with open('README.md') as f:
long_description = f.read()

setup(
name='alvonCV', # How you named your package folder (MyLib)
packages=['alvonCV'], # Chose the same as "name"
version='0.1', # Start with a small number and increase it with every change you make
license='MIT', # Chose a license from here: https://help.github.com/articles/licensing-a-repository
description='Computer Vision Helper Package', # Give a short description about your library
long_description=long_description,
long_description_content_type="text/markdown",
author='Deepak Singh', # Type in your name
author_email='deepaksinghgs30@gmail.com', # Type in your E-Mail
url='https://github.com/alvon-X/alvonCV', # Provide either the link to your github or to your website
Expand Down

0 comments on commit e193309

Please sign in to comment.