G-API: Python. Gaze Estimation sample.#20144
Conversation
| import time | ||
|
|
||
| def weight_path(model_path): | ||
| return model_path.split('.')[0] + '.bin' |
There was a problem hiding this comment.
rfind() should perform better. Or even .endswith('.xml') + model_path[:-3]
(e.g, openvino paths may have dots in near version numbers).
| @@ -0,0 +1,373 @@ | |||
| import cv2 as cv | |||
| import argparse | |||
| import numpy as np | |||
There was a problem hiding this comment.
Please numpy import before cv2 (some issues with some python configurations)
| cap = cv.VideoCapture(arguments.input) | ||
| out = cv.VideoWriter(arguments.out,\ | ||
| cv.VideoWriter_fourcc('M','J','P','G'), 25,\ | ||
| (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)),\ |
| cv.VideoWriter_fourcc('M','J','P','G'), 25,\ | ||
| (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)),\ | ||
| int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))) | ||
| num_frames = cap.get(cv.CAP_PROP_FRAME_COUNT) |
There was a problem hiding this comment.
not available for live streams / demos (e.g, from cameras)
| ccomp.setSource(source) | ||
| ccomp.start() | ||
|
|
||
| cap = cv.VideoCapture(arguments.input) |
There was a problem hiding this comment.
missing .isOpened() check with descriptive error message
There was a problem hiding this comment.
VideoCapture is removed.
| source = cv.gapi.wip.make_capture_src(arguments.input) | ||
| ccomp.setSource(source) | ||
| ccomp.start() | ||
|
|
||
| cap = cv.VideoCapture(arguments.input) |
There was a problem hiding this comment.
make_capture_src
VideoCapture
conflicting calls:
- should be reordered to probe properties before streaming
- VideoCapture should be closed first.
There was a problem hiding this comment.
VideoCapture is removed.
TolyaTalamanov
left a comment
There was a problem hiding this comment.
Let's start with pylint
| if __name__ == '__main__': | ||
| parser = argparse.ArgumentParser(description='This is an OpenCV-based version of Gaze Estimation example') | ||
|
|
||
| parser.add_argument('--input', |
There was a problem hiding this comment.
I would hide this:
def build_argparser():
...
args = build_argparser().parse_args()
| out_r_st += [1 if st[0] < st[1] else 0] | ||
| return out_l_st, out_r_st | ||
|
|
||
| @cv.gapi.op('custom.copy', in_types=[cv.GMat,], out_types=[cv.GMat]) |
3a4e9b8 to
8b6998b
Compare
8b6998b to
6118363
Compare
| return out_poses | ||
|
|
||
|
|
||
| @cv.gapi.op('custom.ParseEyes', in_types=[cv.GArray.GMat, |
There was a problem hiding this comment.
Why don't you do like this ?
@cv.gapi.op('custom.ParseEyes',
in_types=[cv.GArray.GMat, cv.GArray.Rect, cv.GOpaque.Size],
out_types=[cv.GArray.Rect, cv.GArray.Rect, cv.GArray.Point, cv.GArray.Point])
TolyaTalamanov
left a comment
There was a problem hiding this comment.
Everything looks good 👍
Cosmetic fixes are required
|
|
||
| @cv.gapi.op('custom.GetStates', in_types=[cv.GArray.GMat, cv.GArray.GMat], | ||
| out_types=[cv.GArray.Int, cv.GArray.Int]) | ||
| class GetStates: |
There was a problem hiding this comment.
Since GGetStatesImpl, it should be GGetStates.
BTW, how about putting doc string for kernel & operations ?
|
|
||
| # FIXME: the operation should be wrapped soon | ||
| @cv.gapi.op('custom.Copy', in_types=[cv.GMat], out_types=[cv.GMat]) | ||
| class Copy: |
There was a problem hiding this comment.
The same GCopy then
| print('Processing') | ||
| START_TIME = time.time() | ||
|
|
||
| while state: |
There was a problem hiding this comment.
Can it be clearer ?
while True:
has_frame, ... = ccomp.pull()
if not has_frame:
break
...
|
|
||
| fps = int(1. / (time.time() - start_time_cycle)) | ||
| frames += 1 | ||
| ALL_TIME = time.time() - START_TIME |
There was a problem hiding this comment.
total time or execution time
There was a problem hiding this comment.
execution time
|
|
||
|
|
||
| @cv.gapi.kernel(Copy) | ||
| class GCopyImpl: |
There was a problem hiding this comment.
Why don't you just wrap this one on your own ?
It should be pretty straightforward
There was a problem hiding this comment.
Copy is wrapped
| return left_eyes, right_eyes, midpoints, lmarks | ||
|
|
||
|
|
||
| @cv.gapi.op('custom.GetStates', in_types=[cv.GArray.GMat, cv.GArray.GMat], |
There was a problem hiding this comment.
@cv.gapi.op('custom.GetStates',
in_types=[cv.GArray.GMat, cv.GArray.GMat],
out_types=[cv.GArray.Int, cv.GArray.Int])
| eye_net = cv.gapi.ie.params('open-closed-eye', ARGUMENTS.eyem, | ||
| weight_path(ARGUMENTS.eyem), ARGUMENTS.eyed) | ||
|
|
||
| nets = cv.gapi.networks(face_net, head_pose_net, landmarks_net, gaze_net, |
There was a problem hiding this comment.
nets = cv.gapi.networks(face_net, head_pose_net, landmarks_net, gaze_net, eye_net)
Looks like you don't exceed the line limitation in python, do you ?
There was a problem hiding this comment.
I used 80 symbols limit. Removed line break.
| eye_net) | ||
|
|
||
| # Kernels pack | ||
| kernels = cv.gapi.kernels(GParseEyesImpl, GProcessPosesImpl, GGetStatesImpl, |
|
|
||
| FACES_SIZE = len(outr) | ||
|
|
||
| for i in range(FACES_SIZE): |
There was a problem hiding this comment.
You can just:
for i, out_rect in enumerate(outr):
...
| cv.rectangle(oimg, r_eyes[i], color_r, 1) | ||
|
|
||
| # Gaze vectors | ||
| normGazes = np.linalg.norm(outg[i][0]) |
There was a problem hiding this comment.
Every variable in snake_case, right ?
| """ Parse arguments from comand line | ||
|
|
||
| Return: | ||
| Pack of arguments from comand line |
|
|
||
|
|
||
| def build_argparser(): | ||
| """ Parse arguments from comand line |
| @cv.gapi.op('custom.ParseEyes', | ||
| in_types=[cv.GArray.GMat, cv.GArray.Rect, cv.GOpaque.Size], | ||
| out_types=[cv.GArray.Rect, cv.GArray.Rect, cv.GArray.Point, cv.GArray.Point]) | ||
| class ParseEyes: |
There was a problem hiding this comment.
I thought we decided GParseEyes and GParseEyesImpl
| # ------------------------Execution part------------------------ | ||
| ccomp = comp.compileStreaming(args=cv.gapi.compile_args(kernels, nets)) | ||
| source = cv.gapi.wip.make_capture_src(ARGUMENTS.input) | ||
| ccomp.setSource(source) |
There was a problem hiding this comment.
please use:
ccomp.setSource(cv.gin(source))
|
@alalek, can it be merged? |
|
@alalek, #20144 (comment), build is green. Can it be merged? All comments are fixed. |
| Return: | ||
| Arrays with heads poses | ||
| """ | ||
| out_poses = [] |
There was a problem hiding this comment.
Consider this option:
out_poses = [np.array([ys[0], ps[0], rs[0]]).T for ys, ps, rs in zip(in_ys, in_ps, in_rs)]| lmarks = [] | ||
| num_faces = len(in_landm_per_face) | ||
| surface = (0, 0, *frame_size) | ||
| for i in range(num_faces): |
There was a problem hiding this comment.
consider this option:
for landm_face, rect in zip(in_landm_per_face, in_face_rcs):
points = process_landmarks(*rect, landm_face)
lmarks.extend(points)
rect, midpoint_l = eye_box(points[0], points[1])
left_eyes.append(intersection(surface, rect))
rect, midpoint_r = eye_box(points[2], points[3])
right_eyes.append(intersection(surface, rect))
midpoints.append(midpoint_l)
midpoints.append(midpoint_r)| size = len(eyesl) | ||
| out_l_st = [] | ||
| out_r_st = [] | ||
| for i in range(size): |
There was a problem hiding this comment.
Consider this option:
out_l_st = [int(st) for eye_l in eyesl for st in (eye_l[:, 0] < eye_l[:, 1]).ravel()]
out_r_st = [int(st) for eye_r in eyesr for st in (eye_r[:, 0] < eye_r[:, 1]).ravel()]G-API: Python. Gaze Estimation sample. * GE pep8 * Added function description, wrapped copy * Applying review comments * One more change * Added gin * Rstrt bb
Gaze Estimation sample based on GAPI Python api.
Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
Patch to opencv_extra has the same branch name.
Magic commands: