{"id":29124296,"url":"https://github.com/pedronjorge/average-face","last_synced_at":"2026-04-30T08:34:38.782Z","repository":{"id":274219715,"uuid":"922267361","full_name":"PedroNJorge/average-face","owner":"PedroNJorge","description":"Generate an average face from a given set of images by detecting facial landmarks, aligning features, and blending the images using Delaunay Triangulation. Libraries used: Dlib, OpenCV, NumPy","archived":false,"fork":false,"pushed_at":"2025-06-28T12:35:36.000Z","size":72175,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-10T01:13:16.704Z","etag":null,"topics":["dlib","image-generation","jupyter-notebook","numpy","opencv","python3"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PedroNJorge.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-25T18:52:38.000Z","updated_at":"2025-06-28T12:35:39.000Z","dependencies_parsed_at":"2025-02-09T18:38:56.563Z","dependency_job_id":null,"html_url":"https://github.com/PedroNJorge/average-face","commit_stats":null,"previous_names":["pedronjorge/average-face-python"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/PedroNJorge/average-face","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroNJorge%2Faverage-face","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroNJorge%2Faverage-face/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroNJorge%2Faverage-face/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroNJorge%2Faverage-face/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PedroNJorge","download_url":"https://codeload.github.com/PedroNJorge/average-face/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroNJorge%2Faverage-face/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32381691,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T11:25:28.583Z","status":"ssl_error","status_checked_at":"2026-04-28T11:25:05.435Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dlib","image-generation","jupyter-notebook","numpy","opencv","python3"],"created_at":"2025-06-29T20:07:24.015Z","updated_at":"2026-04-28T12:38:48.910Z","avatar_url":"https://github.com/PedroNJorge.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Average Face Computation in Python\nThis project generates an average face from a given set of images by detecting facial landmarks, aligning features, and blending the images using Delaunay Triangulation.\n\n# **Import Libraries**\nThroughout this project we will use:\n\n* **OpenCV**\n* **Dlib**\n* **NumPy**\n* **Pillow** (will be used to help display images in Jupyter Notebook)\n\n\n# **Extract facial features**\u003cbr\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://pyimagesearch.com/wp-content/uploads/2017/04/facial_landmarks_68markup.jpg\" width=400 height=300\u003e\n\u003c/div\u003e\n\nWith the help of **dlib**, we will extract the facial features of each image, as demonstrated in the picture above. We will use **get_frontal_face_detector** to detect where the face is, and **shape_predictor_68_face_landmarks.dat** to extract the 68 landmarks of the face. Here is an example:\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/39629786-3a29-4d9d-b574-e2b8763571e4\"\u003e\n\u003c/div\u003e\n\n\n# **Normalize images**\nIn drawing, faces can be simplified using the “Rule of Thirds,” which divides the face into horizontal and vertical thirds to help position facial features accurately.\u003cbr\u003e\u003cbr\u003e\n\n**Rule of Thirds:** The face can be divided into three equal horizontal sections. The top third is from the hairline to the eyebrows, the middle third is from the eyebrows to the bottom of the nose, and the bottom third is from the bottom of the nose to the chin. This method helps ensure that facial features are proportionally placed.\u003cbr\u003e\n**Facial Features Placement:** Eyes are typically positioned halfway between the top of the head and the chin, which aligns with the horizontal third division. The nose line is found in the middle of the eye line and the bottom of the chin, and the mouth line is about one-third of the way down from the nose line to the chin.\u003cbr\u003e\u003cbr\u003e\n\nSince each image has a different size, we need to normalize them, warping each to a **600x600 image**. With the drawing rules stated earlier, let's define where certain facial features will warp to:\u003cbr\u003e\u003cbr\u003e\n\n* Left corner of the **left eye**: (180, 200)\n* Right corner of the **right eye**: (420, 200)\n* **Bottom lip**: (300, 400)\n\nNow that we know the starting and ending positions, we can use the similarity transform (rotation, translation and scale). To find this transformation, we will use `cv2.getAffineTransform`. With this matrix, we can warp the image with `cv2.warpAffine` and update the landmarks:\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://learnopencv.com/wp-content/ql-cache/quicklatex.com-b6e614b5448854f2c83abcb6e5786774_l3.png\"\u003e\n\u003c/div\u003e\n\nThe *first* and *second* columns **rotate and scale** the vector. You will need to add the *last* column, which represents the **translation**.\n\n\n# **Delaunay Triangulation**\nNow that the images are normalized, we need to align the rest of the remaining features. To do that, we will first calculate the **Delaunay Triangulation** of the final image:\u003cbr\u003e\n\n* Calculate the **landmarks** of the final image, by taking the **average** of the images' landmarks;\n* Create a **planar subdivision**, with `cv2.Subdiv2D`, that contains the landmarks of the final image;\n* Extract the **Delaunay triangles** with `cv2.getTriangleList` and the respective **indices of the landmarks** used to form each triangle.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/03b65f05-2b76-4805-a2c6-b09221ed9e4a\"\u003e\n\u003c/div\u003e\n\n\n# **Align images**\nWith the Delaunay Triangulation of the final image already computed, our next step is to warp the Delaunay Triangles of each input image so that their landmarks align with those of the final image. To warp, we will use `cv2.getAffineTransform` again. However, `cv2.warpAffine` applies transformations to the entire image, while we only need to warp the pixels within the triangle.\u003cbr\u003e\nTo solve that, we will create a mask for the triangle with the help of `cv2.fillConvexPoly` (this will generate a black image with the triangle painted in white).\n\n\n# **Generate Average Face**\nNow that we have everything set up, we can generate the average face by taking the **mean pixel intensity of all warped images**. Below is the final output generated by averaging the faces of **Elon Musk**, **Donald Trump**, and **Mark Zuckerberg**.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/038e2dfb-bafd-4c1a-b283-68838019a0af\"\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedronjorge%2Faverage-face","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpedronjorge%2Faverage-face","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedronjorge%2Faverage-face/lists"}