I'm trying to make an app that can recognize face, eyes and the smile.
But everything is working good except the text on the box which is created when smiling. Because when I flipped the frame (frame that capture by 1cv2.VideoCapture(0)`), the text is also flipped.
How can I stop it? Any help please....
Here is my code,
import cv2
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_eye.xml")
smile_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_smile.xml")
cap = cv2.VideoCapture(0)
while True:
_, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
fsced = face_cascade.detectMultiScale(gray, 1.1, 4)
eyes = eye_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in fsced:
center_cordinates = x + w // 2, y + h // 2
radius = w // 2
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 3)
roi_gray = gray[y : y + h, x : x +w]
roi_colour = img[y : y + h, x : x +w]
smiles = smile_cascade.detectMultiScale(roi_gray, 1.8, 20)
for (sx, sy, sw, sh) in smiles:
cv2.rectangle(roi_colour, (sx, sy), ((sx + sw), (sy + sh)), (0, 0, 255), 2)
cv2.putText(roi_colour, "Smile", (sx, sy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
for (ex, ey, ew, eh) in eyes:
center_cordinates_eye = ex + ew // 2, ey + eh // 2
radius_eye = w // 10
cv2.circle(img, center_cordinates_eye, radius_eye, (5, 50, 10), thickness=2, lineType=8, shift=0)
img = cv2.flip(img, 1)
cv2.imshow('img', img)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyWindow('img')
In this code you can see the text "Smile". when I run the code, this text will flip.
I tried changing the text after the flipping, But nothing good.
Like this,
Text = "" # This Text = "" is at the start of the code
"""
Other code
"""
img = cv2.flip(img, 1)
Text = "Smile"
In the moment when you do:
cv2.putText(roi_colour, "Smile", (sx, sy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
You "melt" the text into the image, you cannot modify it per se after that.
Regarding:
I tried changing the text after the flipping, But nothing good. Like this,
What you did was you actually changed the value of the string "Text", you can print it below, it is indeed changed, but the np.array/openCV image is not.
You can however gather the coordinates for the text into a list let's say and then in a loop add the text after the flipping.
smiles_coordinates = []
for (sx, sy, sw, sh) in smiles:
cv2.rectangle(roi_colour, (sx, sy), ((sx + sw), (sy + sh)), (0, 0, 255), 2)
smiles_coordinates.append((sx,sy)) # Here the "sy" is probably fine, but figure out correct "sx" as a homework
And then after the flip
for (sx, sy) in smile_coordinates:
cv2.putText(roi_colour, "Smile", (sx, sy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
Related
I have this simple Python code that makes predictions on the emotions of the face (refer to here in case you need to run it), whether the person is happy, sad, etc. It uses cv2 and Keras. Now, I would like to visualize and place a meter on the frame based on the probability of each frame (prob value below which is a percentage). How can I do that?
Something like this. Don't worry about the colors for now.
cap = cv2.VideoCapture(1)
canvasImage = cv2.imread("fg2.png")
x0, x1 = 330, 1290
y0, y1 = 155, 700
prediction_history = []
LOOKBACK = 5 # how far you want to look back
counter = 0
while True:
# Find haar cascade to draw bounding box around face
ret, frame = cap.read()
frame=cv2.flip(frame,3)
if not ret:
break
facecasc = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = facecasc.detectMultiScale(gray,scaleFactor=1.3, minNeighbors=5)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)
roi_gray = gray[y:y + h, x:x + w]
cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)
prediction = model.predict(cropped_img)
maxindex = int(np.argmax(prediction))
text = emotion_dict[maxindex]
prob = round(prediction[0][3]*100, 2)
prediction_history.append(maxindex)
most_common_index = max(set(prediction_history[-LOOKBACK:][::-1]), key = prediction_history.count)
text = emotion_dict[most_common_index]
#if ("Sad" in text) or ("Angry" in text) or ("Disgusted" in text):
# text = "Sad"
if ("Happy" in text) or ("Sad" in text) :
cv2.putText(frame, text+": "+str(prob), (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
dim = (800,480)
frame_shrunk = cv2.resize(frame, (x1 - x0, y1 - y0))
canvasImage[y0:y1, x0:x1] = frame_shrunk
#cv2.imshow('Video', cv2.resize(frame,dim,interpolation = cv2.INTER_CUBIC))
cv2.imshow('Demo', canvasImage)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
There is no built in function in OpenCV for drawing meters, here is a helper function that you can use to draw a meter over an image:
def draw_indicator(img, percentage):
def percentage_to_color(p):
return 0, 255 * p, 255 - (255 * p)
# config
levels = 10
indicator_width = 80
indicator_height = 220
level_width = indicator_width - 20
level_height = int((indicator_height - 20) / levels - 5)
# draw
img_levels = int(percentage * levels)
cv2.rectangle(img, (10, img.shape[0] - (indicator_height + 10)), (10 + indicator_width, img.shape[0] - 10), (0, 0, 0), cv2.FILLED)
for i in range(img_levels):
level_y_b = int(img.shape[0] - (20 + i * (level_height + 5)))
cv2.rectangle(img, (20, level_y_b - level_height), (20 + level_width, level_y_b), percentage_to_color(i / levels), cv2.FILLED)
# test code
img = cv2.imread('a.jpg')
draw_indicator(img, 0.7)
cv2.imshow("test", img)
cv2.waitKey(10000)
I have a problem with correct eye detection in the program below. The problem is the detection of eyes in the wrong place. If anyone knows the answer please help
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 5)
roi_gray = gray[y:y + w, x:x + w]
roi_color = frame[y:y + h, x:x + w]
eyes = eye_cascade.detectMultiScale(roi_gray, 1.3, 5)
for (ex, ey, ew, eh) in eyes:
# center_coordinates = ex + ew // 2, ey + eh // 2
radius = eh // 2
cv2.circle(roi_color, (ex, ey), radius, (0, 0, 255), 5)
#cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 5)
cv2.imshow('frame', frame)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
When you draw a rectangle with cv2.rectangle you need top-left and bottom-right corners but when you draw a circle with cv2.circle you need the centre point. You are using cv2.circle with the same coordinates as with the initial rectangles, you need to transform them to the centre before. Add this and it should work
for (ex,ey,ew,eh) in eyes:
radius = eh//2
eye_x = int(ex+0.5*ew)
eye_y = int(ey+0.5*ey)
cv2.circle(roi_color, (eye_x, eye_y), radius, (0, 0, 255), 5)
Hi I am trying to make the eyes that is circled to be white. I know we cant delete the eyes so i wanted to mask it, but i couldnt figure out a way. Below is my code.
import cv2
import os
cascPathface = os.path.dirname(
cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml"
cascPatheyes = os.path.dirname(
cv2.__file__) + "/data/haarcascade_eye_tree_eyeglasses.xml"
faceCascade = cv2.CascadeClassifier(cascPathface)
eyeCascade = cv2.CascadeClassifier(cascPatheyes)
while True:
img = cv2.imread('man1.png')
newImg = cv2.resize(img, (600,600))
gray = cv2.cvtColor(newImg, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(60, 60),
flags=cv2.CASCADE_SCALE_IMAGE)
for (x,y,w,h) in faces:
cv2.rectangle(newImg, (x, y), (x + w, y + h),(0,255,0), 2)
faceROI = newImg[y:y+h,x:x+w]
eyes = eyeCascade.detectMultiScale(faceROI)
for (x2, y2, w2, h2) in eyes:
eye_center = (x + x2 + w2 // 2, y + y2 + h2 // 2)
radius = int(round((w2 + h2) * 0.25))
frame = cv2.circle(newImg, eye_center, radius, (255, 0, 0), 4)
# Display the resulting frame
cv2.imshow('Image', newImg)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
last = cv2.imwrite('faces_detected.png', faceROI)
cv2.destroyAllWindows()
This is the image where i want the eyes to be white:
In order to mask the eyes, change the thickness parameter in the cv2.circle method to -1. That will fill the circle with the specified color.
Change the code from frame = cv2.circle(newImg, eye_center, radius, (255, 0, 0), 4) to frame = cv2.circle(newImg, eye_center, radius, (255, 0, 0), -1).
Refer: https://www.geeksforgeeks.org/python-opencv-cv2-circle-method/
Kindly do upvote the solution, if you find it helpful.
enter image description hereI'm using dlib for my image-based face recognition application. How do I use cv2.putText to write names above the detected faces?
for ( k, face ) in enumerate( face_image ):
faceBlob = cv2.dnn.blobFromImage(face, 1.0 / 255,
(96, 96), (0, 0, 0), swapRB=True, crop=False)
embedder.setInput(faceBlob)
vec = embedder.forward()
# perform classification to recognize the face
preds = recognizer.predict_proba(vec)[0]
j = np.argmax(preds)
proba = preds[j]
name = le.classes_[j]
Try playing around with the values.
font = cv2.FONT_HERSHEY_SIMPLEX
org = (x, y)
fontScale = 1 #(try differnt values)
color = (0, 0, 0)
thickness = 2 #(try differnt values)
image = cv2.putText(img, "TEXT", org, font,
fontScale, color, thickness, cv2.LINE_AA)
Try using these
image = cv2.rectangle(webcamFrame, (x, y), (x + w, y + h), (36,255,12), 1)
cv2.putText(webcamFrame, 'PUT_YOUR_TEXT', (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)
roi_gray = grayImage[y:y+h, x:x+w]
roi_color = webcamFrame[y:y+h, x:x+w]
I want to run this code on my Raspberry Pi 3. I have used pip install imutils on the Pi but, when I run the code via the CLI, it returns "No module named imutils". I do not wish to use virtual environments. I have cv2 running correctly on the Pi and that works no problem, is there a fix for this imutils problem?
Updating, upgrading, removing imutils but it is needed.
import numpy as np
import cv2
import Person
import time
import imutils
import datetime
cap = cv2.VideoCapture('testVideo.mp4')
fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows=True) # Create the background substractor
kernelOp = np.ones((3, 3), np.uint8)
kernelOp1 = np.ones((7, 7), np.uint8)
kernelOp2 = np.ones((5, 5), np.uint8)
kernelCl = np.ones((11, 11), np.uint8)
kernelCl1 = np.ones((20, 20), np.uint8)
kernelCl2 = np.ones((25, 25), np.uint8)
# Variables
font = cv2.FONT_HERSHEY_SIMPLEX
persons = []
max_p_age = 5
pid = 1
areaTH = 5000
w_margin = 50
h_margin = 50
wmax = 500
import pdb;
pdb.set_trace() # debuginimo pradzia
# Atvaizdavimo kintamieji
cnt_up = 0
cnt_down = 0
line_down_color = (255, 0, 0)
line_up_color = (0, 0, 255)
pts_L1 = np.array([[0, 320], [480, 320]])
pts_L2 = np.array([[0, 400], [480, 400]])
counter = 0
while (cap.isOpened()):
ret, frame = cap.read() # read a frame
frame = imutils.resize(frame, width=min(640, frame.shape[1]))
fgmask = fgbg.apply(frame) # Use the substractor
try:
ret, imBin = cv2.threshold(fgmask, 200, 255, cv2.THRESH_BINARY)
mask0 = cv2.morphologyEx(imBin, cv2.MORPH_OPEN, kernelOp2)
mask = cv2.morphologyEx(mask0, cv2.MORPH_CLOSE, kernelCl2)
except:
# if there are no more frames to show...
print('EOF')
break
maskOriginal = mask
_, contours0, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
########if contour is too big cut in half
mask2_flag = 0
for cnt in contours0:
area = cv2.contourArea(cnt)
if area > areaTH:
M = cv2.moments(cnt)
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
x, y, w, h = cv2.boundingRect(cnt)
if w > wmax:
mask2 = cv2.line(mask, ((x + w / 2), 0), ((x + w / 2), 640), (0, 0, 0), 10)
mask2_flag = 1
if mask2_flag == 0:
mask2 = mask
cv2.imshow('Mask line', mask2)
cv2.imshow('mask to open', mask0)
cv2.imshow('Mask initialize', maskOriginal)
cv2.imshow('initial subtraction', imBin)
_, contours0, hierarchy = cv2.findContours(mask2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours0:
cv2.drawContours(frame, cnt, -1, (0, 255, 0), 3, 8)
area = cv2.contourArea(cnt)
for i in persons:
i.updateDingimas(i.getDingimas() + 1)
if i.getDingimas() > 25:
persons.remove(i)
if area > areaTH:
M = cv2.moments(cnt)
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
x, y, w, h = cv2.boundingRect(cnt)
print('x{} y{} w{} h{}'.format(x, y, w, h))
new = True
for i in persons:
if abs(x - i.getX()) <= w_margin and abs(y - i.getY()) <= h_margin:
new = False
i.updateCoords(cx, cy)
i.updateDingimas(0)
break
if new == True:
p = Person.MyPerson(pid, cx, cy, max_p_age)
persons.append(p)
pid += 1
cv2.circle(frame, (cx, cy), 5, (0, 0, 255), -1)
img = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.drawContours(frame, cnt, -1, (0, 255, 0), 3)
cv2.imshow('img', img)
#########################
# Trajectory rendering
#########################
for i in persons:
if len(i.getTracks()) >= 2:
pts = np.array(i.getTracks(), np.int32)
pts = pts.reshape((-1, 1, 2))
frame = cv2.polylines(frame, [pts], False, i.getRGB())
if i.getDir() == None:
i.kurEina(pts_L2[0, 1], pts_L1[0, 1])
if i.getDir() == 'up':
cnt_up += 1
print('Timestamp: {:%H:%M:%S} UP {}'.format(datetime.datetime.now(), cnt_up))
elif i.getDir() == 'down':
cnt_down += 1
print('Timestamp: {:%H:%M:%S} DOWN {}'.format(datetime.datetime.now(), cnt_down))
cv2.putText(frame, str(i.getId()), (i.getX(), i.getY()), font, 0.7, i.getRGB(), 1, cv2.LINE_AA)
#########################
# Rendering
#########################
str_in = 'In: ' + str(cnt_up)
str_out = 'Out: ' + str(cnt_down)
frame = cv2.polylines(frame, [pts_L1], False, line_down_color, thickness=4)
frame = cv2.polylines(frame, [pts_L2], False, line_up_color, thickness=4)
cv2.putText(frame, str_in, (10, 50), font, 1, (0, 0, 255), 2, cv2.LINE_AA)
cv2.putText(frame, str_out, (10, 100), font, 1, (255, 0, 0), 2, cv2.LINE_AA)
cv2.imshow('Frame', frame)
# Abort and exit with 'Q' or ESC
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release() # release video file
cv2.destroyAllWindows() # close all openCV windows
I want to run this code without "No module named imutils" error.
If you intend to use the module with Python 3, you need to install it with pip3 so that it is installed in the correct location.