Search code examples
pythonarrayspython-imaging-libraryface-recognition

Better way to use this 2D array in Python


I am working on a personal project to help me learn Python. I am working on drawing on an image using face_recognition library and PIL library. I am currently drawing "eyeliner" on a person's face by doing the following:

# x and y coordinates of top of left_eye
shape_left_eye = face_landmarks['left_eye']
l_i_x0 = shape_left_eye[0][0]
l_i_y0 = shape_left_eye[0][1]
l_i_x1 = shape_left_eye[1][0]
l_i_y1 = shape_left_eye[1][1]
l_i_x2 = shape_left_eye[2][0]
l_i_y2 = shape_left_eye[2][1]
l_i_x3 = shape_left_eye[3][0]
l_i_y3 = shape_left_eye[3][1]

# x and y coordinates of top of right_eye
shape_right_eye = face_landmarks['right_eye']
r_i_x0 = shape_right_eye[0][0]
r_i_y0 = shape_right_eye[0][1]
r_i_x1 = shape_right_eye[1][0]
r_i_y1 = shape_right_eye[1][1]
r_i_x2 = shape_right_eye[2][0]
r_i_y2 = shape_right_eye[2][1]
r_i_x3 = shape_right_eye[3][0]
r_i_y3 = shape_right_eye[3][1]

d.line([(l_i_x0,l_i_y0-5),(l_i_x1,l_i_y1-5),(l_i_x2,l_i_y2-5),(l_i_x3,l_i_y3-5)], fill=(0, 0, 0, 175), width=6)
d.line([(r_i_x0,r_i_y0-5),(r_i_x1,r_i_y1-5),(r_i_x2,r_i_y2-5),(r_i_x3,r_i_y3-5)], fill=(0, 0, 0, 175), width=6)

The above method works, but seems so inefficient and I am convinced their is a better way. This way is more efficient, but draws a "circle" around entire eye and I am just trying to place line above eye.

d.line(face_landmarks['left_eye'] + [face_landmarks['left_eye'][0]], fill=(0, 0, 0, 110), width=4) 

I also want a way to be able to adjust just the y-points without changing the x-points, which is why I am each point individually.

The d object is as follows:

d = PIL.ImageDraw.Draw(pil_image, 'RGBA')

and

pil_image = PIL.Image.fromarray(image)

Any suggestions on how I could clean this up would be appreciated.


Solution

  • Now I'll be honest I have no idea if this is more efficient, and it's definitely more complicated, but I gave it a shot:

    shape_left_eye = face_landmarks['left_eye']
    l = [
        shape_left_eye[i][j] if j != 1 else
        shape_left_eye[i][j] - 5 for i in
        range(4) for j in range(2)
    ]
    
    shape_right_eye = face_landmarks['right_eye']
    r = [
        shape_right_eye[i][j] if j != 1 else
        shape_right_eye[i][j] - 5 for i in
        range(4) for j in range(2)
    ]
    
    d.line([(l[0],l[1]),(l[2],l[3]),(l[4],l[5]),(l[6],l[7])], fill=(0, 0, 0, 175), width=6)
    d.line([(r[0],r[1]),(r[2],r[3]),(r[4],r[5]),(r[6],r[7])], fill=(0, 0, 0, 175), width=6)
    

    Is this helpful? More importantly does it work, as I can't test it without your setup.