-
-
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'