Merge pull request #8 from ChrisTopherTa54321/improve_manual_selection

Improve manual selection
This commit is contained in:
iperov 2018-07-03 21:40:06 +04:00 committed by GitHub
commit f11da9acfc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 8 deletions

View file

@ -27,6 +27,15 @@ mean_face_y = np.array([
landmarks_2D = np.stack( [ mean_face_x, mean_face_y ], axis=1 )
# 68 point landmark definitions
landmarks_68_pt = { "mouth": (48,68),
"right_eyebrow": (17,22),
"left_eyebrow": (22,27),
"right_eye": (36,42),
"left_eye": (42,48),
"nose": (27,35),
"jaw": (0,17) }
def get_transform_mat (image_landmarks, output_size, face_type):
if not isinstance(image_landmarks, np.ndarray):
image_landmarks = np.array (image_landmarks)
@ -169,6 +178,13 @@ def draw_landmarks (image, image_landmarks, color):
cv2.circle(image, (x, y), 2, color, -1)
#text_color = colorsys.hsv_to_rgb ( (i%4) * (0.25), 1.0, 1.0 )
#cv2.putText(image, str(i), (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.1,text_color,1)
if len(image_landmarks) == 68:
for feat,idx_range in landmarks_68_pt.items():
for idx in range( idx_range[0], idx_range[1] - 1 ):
pt1 = tuple(image_landmarks[idx])
pt2 = tuple(image_landmarks[idx + 1])
cv2.line( image, pt1, pt2, color )
def draw_rect_landmarks (image, rect, image_landmarks, face_size, face_type):
image_utils.draw_rect (image, rect, (255,0,0), 2 )

View file

@ -44,13 +44,16 @@ class ExtractSubprocessor(SubprocessorBase):
self.param_x = -1
self.param_y = -1
self.param_rect_size = -1
self.param = {'x': 0, 'y': 0, 'rect_size' : 5}
self.param = {'x': 0, 'y': 0, 'rect_size' : 5, 'rect_locked' : False, 'redraw_needed' : False }
def onMouse(event, x, y, flags, param):
if event == cv2.EVENT_MOUSEWHEEL:
mod = 1 if flags > 0 else -1
param['rect_size'] = max (5, param['rect_size'] + 10*mod)
else:
elif event == cv2.EVENT_LBUTTONDOWN:
param['rect_locked'] = not param['rect_locked']
param['redraw_needed'] = True
elif not param['rect_locked']:
param['x'] = x
param['y'] = y
@ -108,10 +111,26 @@ class ExtractSubprocessor(SubprocessorBase):
if len (self.input_data) > 0:
return self.input_data.pop(0)
else:
skip_remaining = False
allow_remark_faces = False
while len (self.input_data) > 0:
data = self.input_data[0]
filename, faces = data
is_frame_done = False
go_to_prev_frame = False
# Can we mark an image that already has a marked face?
if allow_remark_faces:
allow_remark_faces = False
# If there was already a face then lock the rectangle to it until the mouse is clicked
if len(faces) > 0:
prev_rect = faces.pop()[0]
self.param['rect_locked'] = True
faces.clear()
self.param['rect_size'] = ( prev_rect[2] - prev_rect[0] ) / 2
self.param['x'] = ( ( prev_rect[0] + prev_rect[2] ) / 2 ) * self.view_scale
self.param['y'] = ( ( prev_rect[1] + prev_rect[3] ) / 2 ) * self.view_scale
if len(faces) == 0:
self.original_image = cv2.imread(filename)
@ -122,10 +141,12 @@ class ExtractSubprocessor(SubprocessorBase):
(h,w,c) = self.original_image.shape
self.text_lines_img = (image_utils.get_draw_text_lines ( self.original_image, (0,0, self.original_image.shape[1], min(100, self.original_image.shape[0]) ),
[ 'Match landmarks with face exactly.',
'[Enter] - confirm frame',
'[Space] - skip frame',
'[Mouse wheel] - change rect'
[ 'Match landmarks with face exactly. Click to confirm/unconfirm selection',
'[Enter] - confirm and continue to next unmarked frame',
'[Space] - skip to next unmarked frame',
'[Mouse wheel] - change rect',
'[,] [.]- prev frame, next frame',
'[Q] - skip remaining frames'
], (1, 1, 1) )*255).astype(np.uint8)
while True:
@ -138,6 +159,22 @@ class ExtractSubprocessor(SubprocessorBase):
elif key == ord(' '):
is_frame_done = True
break
elif key == ord('.'):
allow_remark_faces = True
# Only save the face if the rect is still locked
if self.param['rect_locked']:
faces.append ( [(self.rect), self.landmarks] )
is_frame_done = True
break
elif key == ord(',') and len(self.result) > 0:
# Only save the face if the rect is still locked
if self.param['rect_locked']:
faces.append ( [(self.rect), self.landmarks] )
go_to_prev_frame = True
break
elif key == ord('q'):
skip_remaining = True
break
new_param_x = self.param['x'] / self.view_scale
new_param_y = self.param['y'] / self.view_scale
@ -148,7 +185,8 @@ class ExtractSubprocessor(SubprocessorBase):
if self.param_x != new_param_x or \
self.param_y != new_param_y or \
self.param_rect_size != new_param_rect_size:
self.param_rect_size != new_param_rect_size or \
self.param['redraw_needed']:
self.param_x = new_param_x
self.param_y = new_param_y
@ -164,6 +202,18 @@ class ExtractSubprocessor(SubprocessorBase):
self.result.append ( data )
self.input_data.pop(0)
self.inc_progress_bar(1)
self.param['redraw_needed'] = True
self.param['rect_locked'] = False
elif go_to_prev_frame:
self.input_data.insert(0, self.result.pop() )
self.inc_progress_bar(-1)
allow_remark_faces = True
self.param['redraw_needed'] = True
self.param['rect_locked'] = False
elif skip_remaining:
while len(self.input_data) > 0:
self.result.append( self.input_data.pop(0) )
self.inc_progress_bar(1)
return None
@ -298,6 +348,10 @@ class ExtractSubprocessor(SubprocessorBase):
view_landmarks = (np.array(self.landmarks) * self.view_scale).astype(np.int).tolist()
facelib.LandmarksProcessor.draw_rect_landmarks (image, view_rect, view_landmarks, self.image_size, self.face_type)
if self.param['rect_locked']:
facelib.draw_landmarks(image, view_landmarks, (255,255,0) )
self.param['redraw_needed'] = False
cv2.imshow (self.wnd_name, image)
return 0
else:

View file

@ -75,7 +75,8 @@ class SubprocessorBase(object):
return None
def inc_progress_bar(self, c):
self.progress_bar.update(c)
self.progress_bar.n += c
self.progress_bar.refresh()
def safe_print(self, msg):
self.print_lock.acquire()