-
-
Save smeschke/e59a9f5a40f0b0ed73305d34695d916b to your computer and use it in GitHub Desktop.
import cv2 | |
import numpy as np | |
fourcc = cv2.VideoWriter_fourcc(*'XVID') | |
out = cv2.VideoWriter('/home/sm/Desktop/nodcontrol.avi',fourcc, 20.0, (640,480)) | |
#dinstance function | |
def distance(x,y): | |
import math | |
return math.sqrt((x[0]-y[0])**2+(x[1]-y[1])**2) | |
#capture source video | |
cap = cv2.VideoCapture(0) | |
#params for ShiTomasi corner detection | |
feature_params = dict( maxCorners = 100, | |
qualityLevel = 0.3, | |
minDistance = 7, | |
blockSize = 7 ) | |
# Parameters for lucas kanade optical flow | |
lk_params = dict( winSize = (15,15), | |
maxLevel = 2, | |
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) | |
#path to face cascde | |
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml') | |
#function to get coordinates | |
def get_coords(p1): | |
try: return int(p1[0][0][0]), int(p1[0][0][1]) | |
except: return int(p1[0][0]), int(p1[0][1]) | |
#define font and text color | |
font = cv2.FONT_HERSHEY_SIMPLEX | |
#define movement threshodls | |
max_head_movement = 20 | |
movement_threshold = 50 | |
gesture_threshold = 175 | |
#find the face in the image | |
face_found = False | |
frame_num = 0 | |
while not face_found: | |
# Take first frame and find corners in it | |
frame_num += 1 | |
ret, frame = cap.read() | |
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) | |
faces = face_cascade.detectMultiScale(frame_gray, 1.3, 5) | |
for (x,y,w,h) in faces: | |
cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) | |
face_found = True | |
cv2.imshow('image',frame) | |
out.write(frame) | |
cv2.waitKey(1) | |
face_center = x+w/2, y+h/3 | |
p0 = np.array([[face_center]], np.float32) | |
gesture = False | |
x_movement = 0 | |
y_movement = 0 | |
gesture_show = 60 #number of frames a gesture is shown | |
while True: | |
ret,frame = cap.read() | |
old_gray = frame_gray.copy() | |
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) | |
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params) | |
cv2.circle(frame, get_coords(p1), 4, (0,0,255), -1) | |
cv2.circle(frame, get_coords(p0), 4, (255,0,0)) | |
#get the xy coordinates for points p0 and p1 | |
a,b = get_coords(p0), get_coords(p1) | |
x_movement += abs(a[0]-b[0]) | |
y_movement += abs(a[1]-b[1]) | |
text = 'x_movement: ' + str(x_movement) | |
if not gesture: cv2.putText(frame,text,(50,50), font, 0.8,(0,0,255),2) | |
text = 'y_movement: ' + str(y_movement) | |
if not gesture: cv2.putText(frame,text,(50,100), font, 0.8,(0,0,255),2) | |
if x_movement > gesture_threshold: | |
gesture = 'No' | |
if y_movement > gesture_threshold: | |
gesture = 'Yes' | |
if gesture and gesture_show > 0: | |
cv2.putText(frame,'Gesture Detected: ' + gesture,(50,50), font, 1.2,(0,0,255),3) | |
gesture_show -=1 | |
if gesture_show == 0: | |
gesture = False | |
x_movement = 0 | |
y_movement = 0 | |
gesture_show = 60 #number of frames a gesture is shown | |
#print distance(get_coords(p0), get_coords(p1)) | |
p0 = p1 | |
cv2.imshow('image',frame) | |
out.write(frame) | |
cv2.waitKey(1) | |
cv2.destroyAllWindows() | |
cap.release() | |
You need to plug a webcam into your computer. If you don't want to use a webcam, you can change the path in line 13 to a video that is saved on your hard drive.
Excuse me, but i have a problem with code line 57th.
The output is " name 'x' is not defined". But sometime, it's still run oke.
Hope you answer. Thank you!
Excuse me, but i have a problem with code line 57th.
The output is " name 'x' is not defined". But sometime, it's still run oke.
Hope you answer. Thank you!
I have updated the code, it should work now. Before it looked for a face for 30 frames. If a face was not found in the first 30 frames, the code would crash. I changed the code, so that now it looks for a face until a face is found.
Once a face is found, the center of the face is found, and the tracker is initialized. Then the nod detection can begin.
Excuse me, but i have a problem with code line 57th.
The output is " name 'x' is not defined". But sometime, it's still run oke.
Hope you answer. Thank you!I have updated the code, it should work now. Before it looked for a face for 30 frames. If a face was not found in the first 30 frames, the code would crash. I changed the code, so that now it looks for a face until a face is found.
Once a face is found, the center of the face is found, and the tracker is initialized. Then the nod detection can begin.
Thank you so much for your help !
Dear @smeschke,
How to use your program with video input instead webcam?
Dear @smeschke,
How to use your program with video input instead webcam?
Instead of
cap = cv2.VideoCapture(0)
Just use
cap = cv2.VideoCapture("path/to/folder/video.mp4")
You'll also need to download the xml file:
haarcascade_frontalface_alt.xml
You can download it and move it into current directory
Hi @smeschke, thanks for sharing this gist! Can you comment on the accuracy of this on different possibilities of the nod gesture (like from a stress test)? Also what is the minimum system configuration to run this code? Thanks!
Hello Geeks,
Please anyone help me out in resolving this issue
[ERROR:[email protected]] global cap.cpp:597 cv::VideoWriter::open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.7.0) D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): /home/sm/Desktop/nodcontrol.avi in function 'cv::icvExtractPattern'
[ERROR:[email protected]] global persistence.cpp:505 cv::FileStorage::Impl::open Can't open file: 'haarcascade_frontalface_alt.xml' in read mode
Traceback (most recent call last):
File "D:\HMI\PythonBased\HeadNodding\NoddingDetection.py", line 50, in <module>
faces = face_cascade.detectMultiScale(frame_gray, 1.3, 5)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cv2.error: OpenCV(4.7.0) D:\a\opencv-python\opencv-python\opencv\modules\objdetect\src\cascadedetect.cpp:1689: error: (-215:Assertion failed) !empty() in function 'cv::CascadeClassifier::detectMultiScale'
I am getting error
[ERROR:0] global /io/opencv/modules/videoio/src/cap.cpp (392) open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.1.2) /io/opencv/modules/videoio/src/cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): /home/sm/Desktop/nodcontrol.avi in function 'icvExtractPattern'
VIDEOIO ERROR: V4L: can't find camera device
Traceback (most recent call last):
File "nods.py", line 49, in
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.error: OpenCV(4.1.2) /io/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'