diff --git a/README.md b/README.md index 4a81b74..9405fad 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,79 @@ --- - Face Detection -- Face Mesh \ No newline at end of file +- 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) +``` \ No newline at end of file diff --git a/alvonCV/FaceDetectionModule.py b/alvonCV/FaceDetectionModule.py index ef1e56f..8c33443 100644 --- a/alvonCV/FaceDetectionModule.py +++ b/alvonCV/FaceDetectionModule.py @@ -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) diff --git a/alvonCV/HandTrackingModule.py b/alvonCV/HandTrackingModule.py new file mode 100644 index 0000000..6136787 --- /dev/null +++ b/alvonCV/HandTrackingModule.py @@ -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() diff --git a/setup.py b/setup.py index d46a561..3cb2590 100644 --- a/setup.py +++ b/setup.py @@ -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