-
Notifications
You must be signed in to change notification settings - Fork 1
/
emoji_webcam.py
223 lines (183 loc) · 6.5 KB
/
emoji_webcam.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# -*- coding: utf-8 -*-
"""
Author: Maximilian Schrapel
Copyright: Copyright 2020, Webcam Augmentator
License: MIT
Version: 1.0.0
Email: maximilian.schrapel@gmail.com
This simple script allows you to add emojis to webcam streams independently from the video chat program.
Add the output window to a virtual camera via OBS Studio https://obsproject.com/ to use the software with any operating system and video chat.
Follow the steps of my tutorial to set up your webcam.
The emojis were taken from https://openmoji.org/
Press q to quit the program
Press 0 to 9 or - to add emoji
Press w to stop overlaying emojis
Press + to increase the size of the shown emoji
Press - to decrease the size of the shown emoji
This code can help to show emotions with masks in video chats.
I have used parts of my code to teach my students how prototyping and AR can support wearing masks.
"""
import numpy as np
import cv2
import math
"""Configuration"""
VIDEO_SOURCE = 0 # Number of webcam to use
REZISE_PX = 240 # Size of the emoji in pixels
SCALE = 4 # Initial scale of the emoji
"""returns center of marker"""
def getCenter(prev_res):
xm=0
ym=0
for i in range(0,4):
ym+=prev_res[0][i][0]
xm+=prev_res[0][i][1]
xm=int(xm/4)
ym=int(ym/4)
center = (xm,ym)
return center
"""returns size of marker"""
def getSize(res):
size=0
for i in range (0,4):
size=max(size,math.sqrt((res[0][i][1]-res[0][(i+1)%4][1])**2
+ (res[0][i][0]-res[0][(i+1)%4][0])**2))
return size
"""returns image with overlayed emoji"""
def emojiOverlay(src , overlay , pos=(0,0),scale = 1):
overlay = cv2.resize(overlay,(0,0),fx=scale,fy=scale)
ax=0
ay=0
"""go through image and add emoji"""
for px in range(pos[0]-int(overlay.shape[0]/2),pos[0]+int(overlay.shape[0]/2)):
for py in range(pos[1]-int(overlay.shape[1]/2),pos[1]+int(overlay.shape[1]/2)):
if overlay[ax,ay].any()>0:
if px>=0 and px<src.shape[0] and py>=0 and py <src.shape[1]:
src[px,py]=overlay[ax,ay]
ay+=1
ax+=1
ay=0
return src
"""find green marker to make motion smooth """
def isMarker(img , marker):
minx=maxx=marker[0][0][1]
miny=maxy=marker[0][0][0]
for i in range (1,4):
minx=min(minx,marker[0][i][1])
maxx=max(maxx,marker[0][i][1])
miny=min(miny,marker[0][i][0])
maxy=max(maxy,marker[0][i][0])
n=(maxx-minx)*(maxy-miny)
count=0
for x in range (int(minx),int(maxx)):
for y in range (int(miny),int(maxy)):
if img[x,y] > 0:
count+=1
greenshare=count/n
return greenshare > 0.2
"""Opens webcam (set number according to your machine!)"""
cap = cv2.VideoCapture(VIDEO_SOURCE)
# stores the index of the actual selected emoji
imgindex = -1
"""Load emojis"""
img_emojilove=cv2.imread("Emojis/1F60D_color.png")
img_emojitogune=cv2.imread("Emojis/1F61B_color.png")
img_emojiteeth=cv2.imread("Emojis/1F62C_color.png")
img_emojicry=cv2.imread("Emojis/1F62D_color.png")
img_emojicrazy=cv2.imread("Emojis/1F92A_color.png")
img_emojimoulth=cv2.imread("Emojis/1F444_color.png")
img_emojihappy=cv2.imread("Emojis/1F600_color.png")
img_emojikiss=cv2.imread("Emojis/1F618_color.png")
img_emojiangry=cv2.imread("Emojis/1F620_color.png")
img_emojilol=cv2.imread("Emojis/1F923_color.png")
img_emojihot=cv2.imread("Emojis/1F975_color.png")
"""add emojis to dict"""
emojis= { i : [] for i in range(0,11) }
emojis[0]=img_emojilove
emojis[1]=img_emojitogune
emojis[2]=img_emojiteeth
emojis[3]=img_emojicry
emojis[4]=img_emojicrazy
emojis[5]=img_emojimoulth
emojis[6]=img_emojihappy
emojis[7]=img_emojikiss
emojis[8]=img_emojiangry
emojis[9]=img_emojilol
emojis[10]=img_emojihot
"""Resize emojis to (REZISE_PX x REZISE_PX) px"""
for e in range(0,len(emojis)):
emojis[e] = cv2.resize(emojis[e],(int(REZISE_PX),int(REZISE_PX)))
# stores the previous corners of the marker
prev_res=[]
"""Aruco markers"""
try:
dictionary = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
parameters = cv2.aruco.DetectorParameters_create()
except:
print("Please install module opencv-contrib-python via pip!")
exit()
imgemoji= np.zeros([REZISE_PX,REZISE_PX,3])
"""starting loop ☺ """
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# detect markers
res = cv2.aruco.detectMarkers(frame,dictionary)
if imgindex == -1:
img_emoji= np.zeros([80,80,3])
else:
for i in range(0,11):
if imgindex==i:
img_emoji=emojis[i]
break
"""overlay emoji"""
if len(res[0]) > 0 and imgindex != -1:
for marker in res[0]:
size_x = marker[0][0]
# For debugging: show markers
#cv2.aruco.drawDetectedMarkers(frame,res[0],res[1])
# store result temporarly
prev_res=res
# find center position
center=getCenter(prev_res[0][0])
# add emoji to image
scale=(getSize(prev_res[0][0])/REZISE_PX) * SCALE
frame=emojiOverlay(frame , img_emoji , pos=center,scale=scale)
# make emoji motion smooth in case of errors in detecting markers
elif prev_res!=[]:
if len(res[2]) > 0:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, (35, 25, 25), (90, 255,255))
for marker in res[2]:
if isMarker(mask,marker):
# find center position
center=getCenter(marker)
scale=(getSize(marker)/REZISE_PX) * SCALE
frame=emojiOverlay(frame , img_emoji , pos=center,scale=scale)
break
cv2.imshow('Webcam',frame)
"""press q to stop webcam recording"""
"""press w to delete emoji overlay"""
"""press + to increae size of the emoji"""
"""press - to decreae size of the emoji"""
k = cv2.waitKey(1) % 256
if k == ord('q'):
break
elif k == ord('+'):
SCALE+=0.5
elif k == ord('-'):
SCALE-=0.5
if SCALE<=0:
SCALE=0.5
else:
if k == ord('w'):
imgindex = -1
"""press 0 to 9 or ß or - to add overlayed emoji"""
for i in range(0,10):
if k == ord(str(i)):
imgindex=i
break;
if k == ord('ß') or k == ord('_'): # german and english keyboard layout
imgindex = 10
"""When stopping webcam recording, release the capture"""
cap.release()
cv2.destroyAllWindows()