Last active
September 1, 2021 07:03
-
-
Save Asadullah-Dal17/fd71c31bac74ee84e6a31af50fa62961 to your computer and use it in GitHub Desktop.
Mediapipe landmarks detection for each individual part, like an face-oval, eyes, lips, and Eyebrows
This file contains hidden or 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
| ''' | |
| Author: Asadullah Dal | |
| Youtube Channel: https://www.youtube.com/c/aiphile | |
| ''' | |
| import cv2 as cv | |
| import numpy as np | |
| import mediapipe as mp | |
| import utils | |
| import time | |
| # Landmarks indices for different parts of face, mediapipe. | |
| # face bounder indices | |
| FACE_OVAL=[ 10, 338, 297, 332, 284, 251, 389, 356, 454, 323, 361, 288, 397, 365, 379, 378, 400, 377, 152, 148, 176, 149, 150, 136, 172, 58, 132, 93, 234, 127, 162, 21, 54, 103,67, 109] | |
| # lips indices for Landmarks | |
| LIPS=[ 61, 146, 91, 181, 181, 84, 17, 314, 405, 321, 375, 61, 185, 40, 39, 37,0 ,267 ,269 ,270 ,409, 78, 95 ,88 ,178 ,87, 14, 317, 402, 318, 324, 78, 191, 80, 81, 82, 13, 312, 311, 310, 415 ] | |
| # Left eyes indices | |
| LEFT_EYE =[ 362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385,384, 398 ] | |
| LEFT_EYEBROW =[ 336, 296, 334, 293, 300, 276, 283, 282, 295, 285 ] | |
| # right eyes indices | |
| RIGHT_EYE=[ 33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161 , 246 ] | |
| RIGHT_EYEBROW=[ 70, 63, 105, 66, 107, 55, 65, 52, 53, 46 ] | |
| # Variables | |
| # Frame per seconds | |
| frame_counter =0 | |
| # Setting up mediapipe | |
| map_face_mesh= mp.solutions.face_mesh | |
| # Different function | |
| def faceLandmarksDetector(img, result, draw=False): | |
| # image width and height | |
| img_height, img_width = img.shape[:2] | |
| # getting all the landmark normalized cordinate(x,y) in the image | |
| # multiplying these coordinate with width and height we get image coordinates | |
| mesh_cord_point = [ (int(p.x*img_width) , int(p.y*img_height)) for p in results.multi_face_landmarks[0].landmark] | |
| if draw : | |
| [cv.circle(img, point_cord, 2, utils.GREEN, -1) for point_cord in mesh_cord_point] | |
| # print() | |
| return mesh_cord_point | |
| # setting up camera | |
| cap = cv.VideoCapture(0) | |
| # configring mediapipe for face mesh detection | |
| with map_face_mesh.FaceMesh( min_detection_confidence=0.5, min_tracking_confidence=0.5 ) as face_mesh: | |
| # string video/webcame feed here | |
| # initial time set here | |
| starting_time =time.time() | |
| while True: | |
| ret, frame = cap.read() | |
| frame_counter +=1 | |
| # converting color space from BGR to RGB | |
| rgb_frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB) | |
| # getting the frame width | |
| height, width = frame.shape[:2] | |
| # getting the landmarks | |
| results = face_mesh.process(rgb_frame) | |
| # checking if landmarks are detected or not | |
| if results.multi_face_landmarks: | |
| # calling faceLandmarksDetector function and getting coordinate of each point in face mesh | |
| mesh_cords =faceLandmarksDetector(img=frame, result=results) | |
| frame = utils.fillPolyTrans(img=frame,points=[mesh_cords[p] for p in FACE_OVAL],color=utils.BLACK, opacity=0.4) | |
| # draw lips landmarks portion | |
| frame = utils.fillPolyTrans(img=frame,points=[mesh_cords[p] for p in LIPS],color=utils.WHITE, opacity=0.4) | |
| frame = utils.fillPolyTrans(img=frame,points=[mesh_cords[p] for p in LEFT_EYE],color=utils.YELLOW, opacity=0.4) | |
| frame = utils.fillPolyTrans(img=frame,points=[mesh_cords[p] for p in LEFT_EYEBROW],color=utils.GREEN, opacity=0.4) | |
| frame = utils.fillPolyTrans(img=frame,points=[mesh_cords[p] for p in RIGHT_EYE],color=utils.YELLOW, opacity=0.4) | |
| frame = utils.fillPolyTrans(img=frame,points=[mesh_cords[p] for p in RIGHT_EYEBROW],color=utils.GREEN, opacity=0.4) | |
| # calculating the end time of total frames | |
| end_time = time.time()- starting_time | |
| # calculating the frames per seconds | |
| fps = frame_counter/end_time | |
| cv.imshow('frame',frame) | |
| key = cv.waitKey(1) | |
| if key==ord('q'): | |
| break | |
| cv.destroyAllWindows() | |
| cap.release() |
This file contains hidden or 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
| ''' | |
| Author: Asadullah Dal | |
| Youtube Channel: https://www.youtube.com/c/aiphile | |
| ''' | |
| import cv2 as cv | |
| import numpy as np | |
| # colors | |
| # values =(blue, green, red) opencv accepts BGR values not RGB | |
| BLACK = (0,0,0) | |
| WHITE = (255,255,255) | |
| BLUE = (255,0,0) | |
| RED = (0,0,255) | |
| CYAN = (255,255,0) | |
| YELLOW =(0,255,255) | |
| MAGENTA = (255,0,255) | |
| GRAY = (128,128,128) | |
| GREEN = (0,255,0) | |
| PURPLE = (128,0,128) | |
| ORANGE = (0,165,255) | |
| PINK = (147,20,255) | |
| points_list =[(200, 300), (150, 150), (400, 200)] | |
| def drawColor(img, colors): | |
| x, y = 0,10 | |
| w, h = 20, 30 | |
| for color in colors: | |
| x += w+5 | |
| # y += 10 | |
| cv.rectangle(img, (x-6, y-5 ), (x+w+5, y+h+5), (10, 50, 10), -1) | |
| cv.rectangle(img, (x, y ), (x+w, y+h), color, -1) | |
| def textWithBackground(img, text, font, fontScale, textPos, textThickness=1,textColor=(0,255,0), bgColor=(0,0,0), pad_x=3, pad_y=3, bgOpacity=0.5): | |
| """ | |
| Draws text with background, with control transparency | |
| @param img:(mat) which you want to draw text | |
| @param text: (string) text you want draw | |
| @param font: fonts face, like FONT_HERSHEY_COMPLEX, FONT_HERSHEY_PLAIN etc. | |
| @param fontScale: (double) the size of text, how big it should be. | |
| @param textPos: tuple(x,y) position where you want to draw text | |
| @param textThickness:(int) fonts weight, how bold it should be | |
| @param textPos: tuple(x,y) position where you want to draw text | |
| @param textThickness:(int) fonts weight, how bold it should be. | |
| @param textColor: tuple(BGR), values -->0 to 255 each | |
| @param bgColor: tuple(BGR), values -->0 to 255 each | |
| @param pad_x: int(pixels) padding of in x direction | |
| @param pad_y: int(pixels) 1 to 1.0 (), controls transparency of text background | |
| @return: img(mat) with draw with background | |
| """ | |
| (t_w, t_h), _= cv.getTextSize(text, font, fontScale, textThickness) # getting the text size | |
| x, y = textPos | |
| overlay = img.copy() # coping the image | |
| cv.rectangle(overlay, (x-pad_x, y+ pad_y), (x+t_w+pad_x, y-t_h-pad_y), bgColor,-1) # draw rectangle | |
| new_img = cv.addWeighted(overlay, bgOpacity, img, 1 - bgOpacity, 0) # overlaying the rectangle on the image. | |
| cv.putText(new_img,text, textPos,font, fontScale, textColor,textThickness ) # draw in text | |
| img = new_img | |
| return img | |
| def textBlurBackground(img, text, font, fontScale, textPos, textThickness=1,textColor=(0,255,0),kneral=(33,33) , pad_x=3, pad_y=3): | |
| """ | |
| Draw text with background blured, control the blur value, with kernal(odd, odd) | |
| @param img:(mat) which you want to draw text | |
| @param text: (string) text you want draw | |
| @param font: fonts face, like FONT_HERSHEY_COMPLEX, FONT_HERSHEY_PLAIN etc. | |
| @param fontScale: (double) the size of text, how big it should be. | |
| @param textPos: tuple(x,y) position where you want to draw text | |
| @param textThickness:(int) fonts weight, how bold it should be. | |
| @param textColor: tuple(BGR), values -->0 to 255 each | |
| @param kneral: tuple(3,3) int as odd number: higher the value, more blurry background would be | |
| @param pad_x: int(pixels) padding of in x direction | |
| @param pad_y: int(pixels) padding of in y direction | |
| @return: img mat, with text drawn, with background blured | |
| call the function: | |
| img =textBlurBackground(img, 'Blured Background Text', cv2.FONT_HERSHEY_COMPLEX, 0.9, (20, 60),2, (0,255, 0), (49,49), 13, 13 ) | |
| """ | |
| (t_w, t_h), _= cv.getTextSize(text, font, fontScale, textThickness) # getting the text size | |
| x, y = textPos | |
| blur_roi = img[y-pad_y-t_h: y+pad_y, x-pad_x:x+t_w+pad_x] # croping Text Background | |
| img[y-pad_y-t_h: y+pad_y, x-pad_x:x+t_w+pad_x]=cv.blur(blur_roi, kneral) # merging the blured background to img | |
| cv.putText(img,text, textPos,font, fontScale, textColor,textThickness ) | |
| # cv.imshow('blur roi', blur_roi) | |
| # cv.imshow('blured', img) | |
| return img | |
| def fillPolyTrans(img, points, color, opacity): | |
| """ | |
| @param img: (mat) input image, where shape is drawn. | |
| @param points: list [tuples(int, int) these are the points custom shape,FillPoly | |
| @param color: (tuples (int, int, int) | |
| @param opacity: it is transparency of image. | |
| @return: img(mat) image with rectangle draw. | |
| """ | |
| list_to_np_array = np.array(points, dtype=np.int32) | |
| overlay = img.copy() # coping the image | |
| cv.fillPoly(overlay,[list_to_np_array], color ) | |
| new_img = cv.addWeighted(overlay, opacity, img, 1 - opacity, 0) | |
| # print(points_list) | |
| img = new_img | |
| return img | |
| def rectTrans(img, pt1, pt2, color, thickness, opacity): | |
| """ | |
| @param img: (mat) input image, where shape is drawn. | |
| @param pt1: tuple(int,int) it specifies the starting point(x,y) os rectangle | |
| @param pt2: tuple(int,int) it nothing but width and height of rectangle | |
| @param color: (tuples (int, int, int), it tuples of BGR values | |
| @param thickness: it thickness of board line rectangle, if (-1) passed then rectangle will be fulled with color. | |
| @param opacity: it is transparency of image. | |
| @return: | |
| """ | |
| overlay = img.copy() | |
| cv.rectangle(overlay, pt1, pt2, color, thickness) | |
| new_img = cv.addWeighted(overlay, opacity, img, 1 - opacity, 0) # overlaying the rectangle on the image. | |
| img = new_img | |
| return img | |
| def main(): | |
| cap = cv.VideoCapture('Girl.mp4') | |
| counter =0 | |
| while True: | |
| success, img = cap.read() | |
| # img = np.zeros((1000,1000, 3), dtype=np.uint8) | |
| img=rectTrans(img, pt1=(30, 320), pt2=(160, 260), color=(0,255,255),thickness=-1, opacity=0.6) | |
| img =fillPolyTrans(img=img, points=points_list, color=(0,255,0), opacity=.5) | |
| drawColor(img, [BLACK,WHITE ,BLUE,RED,CYAN,YELLOW,MAGENTA,GRAY ,GREEN,PURPLE,ORANGE,PINK]) | |
| textBlurBackground(img, 'Blured Background Text', cv.FONT_HERSHEY_COMPLEX, 0.8, (60, 140),2, YELLOW, (71,71), 13, 13) | |
| img=textWithBackground(img, 'Colored Background Texts', cv.FONT_HERSHEY_SIMPLEX, 0.8, (60,80), textThickness=2, bgColor=GREEN, textColor=BLACK, bgOpacity=0.7, pad_x=6, pad_y=6) | |
| imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) | |
| # cv.imwrite('color_image.png', img) | |
| counter +=1 | |
| cv.imshow('img', img) | |
| cv.imwrite(f'image/image_{counter}.png', img) | |
| if cv.waitKey(1) ==ord('q'): | |
| break | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment