i have a project where i'm trying to imitate the filtering system for snapchat. supposedly, after clicking on the filter buttons on the side of the window, the webcam would show whatever the filter is. however, the window just ends up freezing. if i try to implement the filters separately, they do actually work. but when i try to implement it here, the window freezes.
here's the code: (Functions detect(), get_cam_frame(), show_frame() and phone_filter() are not mine. I just retrieved them from the internet)
# Import Libraries
import numpy as np
import Tkinter as tk
import tkMessageBox
import cv2
import sys
from PIL import Image, ImageTk
from video import create_capture
# Initialize Window
root = tk.Tk()
root.wm_title("Filter App")
root.config(background="#000000")
canvas = tk.Canvas(root, width=600, height=700)
canvas.pack()
canvas.grid(row=0, column=0, padx=5, pady=20)
lmain = tk.Label(canvas)
lmain.grid(row=0, column=0, padx=85, pady=119)
cap = cv2.VideoCapture(0)
def detect(img, cascade):
rects = cascade.detectMultiScale(img, scaleFactor=1.3, minNeighbors=4, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE)
if len(rects) == 0:
return []
rects[:, 2:] += rects[:, :2]
return rects
def get_cam_frame(cam):
ret, img = cam.read()
# smaller frame size - things run a lot smoother than a full screen img
img = cv2.resize(img, (800, 470))
return img
def show_frame():
_, frame = cap.read()
frame = cv2.flip(frame, 1)
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img)
lmain.imgtk = imgtk
lmain.configure(image=imgtk)
lmain.after(10, show_frame)
sliderFrame = tk.Frame(root, width=500, height=50)
sliderFrame.grid(row = 500, column=0, padx=10, pady=2)
show_frame()
def phone_filter(img):
show_frame()
print img
if img == "dog":
filter_img = cv2.imread("img/face/dogfilter.png", cv2.IMREAD_COLOR)
elif img == "dalmatian":
filter_img = cv2.imread("img/face/dalmatianfilter.png", cv2.IMREAD_COLOR)
elif img == "anime":
filter_img = cv2.imread("img/face/animefilter.png", cv2.IMREAD_COLOR)
elif img == "catears":
filter_img = cv2.imread("img/face/catearsfilter.png", cv2.IMREAD_COLOR)
elif img == "mustache":
filter_img = cv2.imread("img/face/mustachefilter.png", cv2.IMREAD_COLOR)
elif img == "pig":
filter_img = cv2.imread("img/face/pigfilter.png", cv2.IMREAD_COLOR)
elif img == "shaider":
filter_img = cv2.imread("img/face/shaiderfilter.png", cv2.IMREAD_COLOR)
elif img == "none":
filter_img = cv2.imread("img/Empty.png", cv2.IMREAD_COLOR)
else:
filter_img = cv2.imread("img/Empty.png", cv2.IMREAD_COLOR)
haar_classifier = "data/haarcascade_frontalface_default.xml"
# use the haar classifier for now, it seems to work a little bit better
cascade = cv2.CascadeClassifier(haar_classifier)
print cascade
while True:
print "."
cam = cv2.VideoCapture(0)
print cam
bw = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bw = cv2.equalizeHist(bw)
rects = detect(bw, cascade)
final = img.copy()
# for x1, y1, x2, y2 in rects:
# cv2.rectangle(img, (x1, y1), (x2, y2), (0,255,0), 2)
if len(rects) >= 1:
allFaces = rects
#rect = (ax1, ay1, ax2, ay2)
for index, (ax1, ay1, ax2, ay2) in enumerate(allFaces):
deltaY = abs(ay2) - abs(ay1)
stretchFactor = 0.2
stretchAmount = int(stretchFactor * deltaY)
ay2 = ay2 + stretchAmount
ay1 = ay1 - stretchAmount
height, width, _ = img.shape
if ax1 > stretchAmount and ax2 < width - stretchAmount and ay1 > stretchAmount and ay2 < height - stretchAmount:
face = img[ay1:ay2, ax1:ax2]
filter_scale = []
if index % 2 == 0:
#dog_scale = cv2.resize(dog_img, (ax2 - ax1, ay2 - ay1))
filter_scale = cv2.resize(filter_img, (ax2 - ax1, ay2 - ay1))
else:
filter_scale = cv2.resize(filter_img, (ax2 - ax1, ay2 - ay1))
# my_scaled = np.where(dog_scale == 0, face, dog_scale)
my_scaled = np.where(filter_scale == 0, face, filter_scale)
# faceB = cv2.resize(
# img[by1:by2, bx1:bx2].copy(), (ax2 - ax1, ay2 - ay1))
final[ay1:ay2, ax1:ax2] = my_scaled
#final[by1:by2, bx1:bx2] = faceA
cv2.imshow(final)
def dogOp():
phone_filter("dog")
# tkMessageBox.showinfo("Face Filter", "Dog Filter")
def dalmatianOp():
phone_filter("dalmatian")
# tkMessageBox.showinfo("Face Filter", "Dalmatian Filter")
def animeOp():
phone_filter("anime")
# tkMessageBox.showinfo("Face Filter", "Anime Filter")
def catearsOp():
phone_filter("catears")
# tkMessageBox.showinfo("Face Filter", "Cat Ears Filter")
def mustacheOp():
phone_filter("mustache")
# tkMessageBox.showinfo("Face Filter", "Mustache Filter")
def pigOp():
phone_filter("pig")
# tkMessageBox.showinfo("Face Filter", "Pig Filter")
def shaiderOp():
phone_filter("shaider")
# tkMessageBox.showinfo("Face Filter", "Shaider Pulis Pangkalawakan")
initializing background
image = Image.open('img/phone_bg.png')
image = image.resize((820, 700), Image.ANTIALIAS)
tk_img = ImageTk.PhotoImage(image)
canvas.create_image(400, 360, image=tk_img)
initializing face filters
dogfilter = Image.open("img/face/dogfilter.png")
dogfilter = dogfilter.resize((50, 50), Image.ANTIALIAS)
dog = ImageTk.PhotoImage(dogfilter)
dalmatianfilter = Image.open("img/face/dalmatianfilter.png")
dalmatianfilter = dalmatianfilter.resize((50, 50), Image.ANTIALIAS)
dalmatian = ImageTk.PhotoImage(dalmatianfilter)
animefilter = Image.open("img/face/animefilter.png")
animefilter = animefilter.resize((50, 50), Image.ANTIALIAS)
anime = ImageTk.PhotoImage(animefilter)
catearsfilter = Image.open("img/face/catearsfilter.png")
catearsfilter = catearsfilter.resize((50, 50), Image.ANTIALIAS)
catears = ImageTk.PhotoImage(catearsfilter)
mustachefilter = Image.open("img/face/mustachefilter.png")
mustachefilter = mustachefilter.resize((50, 50), Image.ANTIALIAS)
mustache = ImageTk.PhotoImage(mustachefilter)
pigfilter = Image.open("img/face/pigfilter.png")
pigfilter = pigfilter.resize((50, 50), Image.ANTIALIAS)
pig = ImageTk.PhotoImage(pigfilter)
shaiderfilter = Image.open("img/face/shaiderfilter.png")
shaiderfilter = shaiderfilter.resize((50, 50), Image.ANTIALIAS)
shaider = ImageTk.PhotoImage(shaiderfilter)
face filter buttons
dogbtn = tk.Button(root, width=30, height=30, image = dog, command=dogOp)
dogbtn_window = canvas.create_window(100,150, anchor='nw', window=dogbtn)
dalmatianbtn = tk.Button(root, width=30, height=30, image = dalmatian, command=dalmatianOp)
dalmatianbtn_window = canvas.create_window(100,190, anchor='nw', window=dalmatianbtn)
animebtn = tk.Button(root, width=30, height=30, image = anime, command=animeOp)
animebtn_window = canvas.create_window(100,230, anchor='nw', window=animebtn)
catearsbtn = tk.Button(root, width=30, height=30, image = catears, command=catearsOp)
catearsbtn_window = canvas.create_window(100,270, anchor='nw', window=catearsbtn)
mustachebtn = tk.Button(root, width=30, height=30, image = mustache, command=mustacheOp)
mustachebtn_window = canvas.create_window(100,310, anchor='nw', window=mustachebtn)
pigbtn = tk.Button(root, width=30, height=30, image = pig, command=pigOp)
pigbtn_window = canvas.create_window(100,350, anchor='nw', window=pigbtn)
shaiderbtn = tk.Button(root, width=30, height=30, image = shaider, command=shaiderOp)
shaiderbtn_window = canvas.create_window(100,390, anchor='nw', window=shaiderbtn)
quit_button = tk.Button(root, text = "X", command = root.quit, anchor = 'w',
width = 2, bg="red")
quit_button_window = canvas.create_window(680,120, anchor='nw', window=quit_button)
root.mainloop()
The camerafeed freezes whenever you press a button because your phone_filter()
function never ends. Indeed, it contains a while True
loop.
Moreover, in this very function, you try to re-open VideoCapture(0)
, which is cleary wrong given the fact that you have already opened it in your initialization step (cap = cv2.VideoCapture(0)
). Use cap
variable instead.
Two lines bellow, with bw = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
, you try to convert img
which is your input string!
Anyways, I don't think your code structure is right according to what you are trying to achieve. You should do something in this taste:
Inside a while True
loop:
The functions bound to the buttons should only change a variable (that you could call selected_filter
). Then, in the while True
loop, you'd read this variable to draw the right filter.