Skip to content

Commit

Permalink
Merge pull request #1 from 18ljones/faces
Browse files Browse the repository at this point in the history
Faces
  • Loading branch information
nfaltermeier authored Nov 13, 2022
2 parents 90456a9 + 954066b commit 3b19406
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 17 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,5 @@ $RECYCLE.BIN/
# End of https://www.toptal.com/developers/gitignore/api/windows,python

!/src/lib/
autogen_buildtime.py
*.png
6 changes: 6 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
opencv-python
numpy
pillow
pycord
python-dotenv
discord
2 changes: 2 additions & 0 deletions src/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from datetime import datetime, timezone
import donut
import soup
import faces
import roll
import config
import asyncio
Expand Down Expand Up @@ -47,6 +48,7 @@ async def on_message(message):
await donut.on_message(message, config, client)
await soup.on_message(message, client, config)
await excuse.on_message(message)
await faces.on_message(message, client, config)
if await roll.on_message(message):
return

Expand Down
9 changes: 9 additions & 0 deletions src/config.py.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ excuses = [
("grocery shopping", 2)
] # An array of string messages or tuples containing a string message and a weight. Non-tuples have a weight on 1.
# Weights can be a decimal, 0 < w < infinity

# Face configs
face_picture = 'lib/face.png'

face_dims = [
[43, 208, 430, 430],
[245, 125, 82, 82],
[98, 131, 87, 87]
]
31 changes: 31 additions & 0 deletions src/faces.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import lib.faces_util as faces_util
import os
import discord

BYTES_IN_MEGABYTE = 1048576

allowable_attachment_types = ['image/png', 'image/jpeg']

async def on_message(message, client, conf):
if message.content.startswith("$face"):
if len(message.attachments) > 0:
for attachment in message.attachments:
# check if attachment is a picture and is smaller than 8mb
if attachment.content_type in allowable_attachment_types and attachment.size < (8 * BYTES_IN_MEGABYTE):
if attachment.proxy_url != '404':
try:
await attachment.save('attachment_picture.png', use_cached=True)
found, path = faces_util.get_face_replace('attachment_picture.png')
if found:
await message.channel.send(file=discord.File(path))
else:
await message.channel.send('No face found :(')
if os.path.exists('face_detected.png'):
os.remove('face_detected.png')
except discord.HTTPException as error:
logging.exception(f'{datetime.now(timezone.utc)} Face on_message')
await message.channel.send('Could not download attachment :(')
except discord.NotFound as error:
logging.exception(f'{datetime.now(timezone.utc)} Face on_message')
await message.channel.send('Attachment not found :(')

50 changes: 33 additions & 17 deletions src/lib/faces.py → src/lib/faces_util.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import cv2
import numpy as np
import math
import aiohttp
import os
import config as conf
from PIL import Image

face_cascade = cv2.CascadeClassifier('opencv/face_detector.xml')
eye_cascade = cv2.CascadeClassifier('opencv/eye_detector.xml')
smile_cascade = cv2.CascadeClassifier('opencv/smile_detector.xml')
face_cascade = cv2.CascadeClassifier('lib/opencv/face_detector.xml')
eye_cascade = cv2.CascadeClassifier('lib/opencv/eye_detector.xml')
smile_cascade = cv2.CascadeClassifier('lib/opencv/smile_detector.xml')

def load_image_rgba(path):
og_image = Image.open(path)
Expand Down Expand Up @@ -74,20 +77,33 @@ def replace_faces(gray, frame, replacement, replacement_dims):

return found, frame

img = load_image_rgba('student_small.png')
# img = load_image_rgba('group.png')
student = np.array(img)

face = load_image_rgba('face.png')
face_dims = [
[43, 208, 430, 430],
[245, 125, 82, 82],
[98, 131, 87, 87]
]
gray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY)
found,img = replace_faces(gray, img, face, face_dims)
cv2.imwrite("face_detected.png", img)
print('Successfully saved')
def get_face_replace(replacing_image):
face_replace = load_image_rgba(conf.face_picture)
attachment_pic = load_image_rgba(replacing_image)
gray = cv2.cvtColor(attachment_pic, cv2.COLOR_RGBA2GRAY)
found,img = replace_faces(gray, attachment_pic, face_replace, conf.face_dims)

if found:
cv2.imwrite('face_detected.png', img)
return True, 'face_detected.png'

return False, None

if __name__ == '__main__':
img = load_image_rgba('student_small.png')
# img = load_image_rgba('group.png')
student = np.array(img)

face = load_image_rgba('face.png')
face_dims = [
[43, 208, 430, 430],
[245, 125, 82, 82],
[98, 131, 87, 87]
]
gray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY)
found,img = replace_faces(gray, img, face, face_dims)
cv2.imwrite("face_detected.png", img)
print('Successfully saved')

# A video with faces applied for testing purposes
# video_capture = cv2.VideoCapture(0)
Expand Down

0 comments on commit 3b19406

Please sign in to comment.