Merged PR 3142: Million Scale Python Sample Update

Code format & update for sample.
This commit is contained in:
Xuan (Sean) Hu 2017-10-11 13:23:38 +00:00 коммит произвёл huxuan
Родитель 0b6a6bb426
Коммит cfb44d8439
11 изменённых файлов: 279 добавлений и 299 удалений

Просмотреть файл

@ -7,7 +7,6 @@ Description: main script for Python SDK sample.
from view import MyApp
if __name__ == "__main__":
app = MyApp(False)
app.MainLoop()

Просмотреть файл

@ -11,6 +11,7 @@ import util
class Rect(object):
"""Face Rectangle."""
def __init__(self, rect):
super(Rect, self).__init__()
self.set_rect(rect)
@ -25,6 +26,7 @@ class Rect(object):
class Attribute(object):
"""Attributes for face."""
def __init__(self, attr):
super(Attribute, self).__init__()
self.set_attr(attr)
@ -41,8 +43,7 @@ class Attribute(object):
else:
self.hair = max(
attr['hair']['hairColor'],
key=lambda x: x['confidence']
)['color']
key=lambda x: x['confidence'])['color']
self.facial_hair = sum(attr['facialHair'].values()) > 0 and 'Yes' \
or 'No'
self.makeup = any(attr['makeup'].values())
@ -50,20 +51,18 @@ class Attribute(object):
self.occlusion = any(attr['occlusion'].values())
self.exposure = attr['exposure']['exposureLevel']
self.head_pose = "Pitch: {}, Roll:{}, Yaw:{}".format(
attr['headPose']['pitch'],
attr['headPose']['roll'],
attr['headPose']['yaw']
)
attr['headPose']['pitch'], attr['headPose']['roll'],
attr['headPose']['yaw'])
if not attr['accessories']:
self.accessories = 'NoAccessories'
else:
self.accessories = ' '.join(
[str(x['type']) for x in attr['accessories']]
)
[str(x['type']) for x in attr['accessories']])
class Face(object):
"""Face Model for each face."""
def __init__(self, res, path, size=util.MAX_THUMBNAIL_SIZE):
super(Face, self).__init__()
self.path = path
@ -76,18 +75,13 @@ class Face(object):
self.persisted_id = res['persistedFaceId']
if res.get('faceRectangle'):
self.rect = Rect(res['faceRectangle'])
self.bmp = self.bmp.GetSubBitmap(wx.Rect(
self.rect.left,
self.rect.top,
self.rect.width,
self.rect.height,
))
self.bmp = self.bmp.GetSubBitmap(
wx.Rect(self.rect.left, self.rect.top, self.rect.width,
self.rect.height))
if res.get('faceAttributes'):
self.attr = Attribute(res['faceAttributes'])
self.bmp = util.scale_image(
self.bmp.ConvertToImage(),
size=size,
).ConvertToBitmap()
self.bmp.ConvertToImage(), size=size).ConvertToBitmap()
def set_name(self, name):
"""Set the name for the face."""

Просмотреть файл

@ -20,7 +20,6 @@ except ImportError:
sys.path.insert(0, ROOT_DIR)
import cognitive_face as CF
IMAGE_WILDCARD = 'Image files (*.jpg, *.png)|*.jpg; *.png'
INNER_PANEL_WIDTH = 710
MAX_IMAGE_SIZE = 300
@ -32,17 +31,14 @@ ORIENTATION_TAG = 274
LOG_FACE_LIST_REQUEST = (
'Request: Face List {} will be used for build person database. '
'Checking whether group exists.'
)
'Checking whether group exists.')
LOG_FACE_LIST_NOT_EXIST = 'Response: Face List {} does not exist before.'
LOG_FACE_LIST_EXIST = 'Response: Face List {} exists.'
LABEL_FACE = (
'{}, {} years old\n'
'Hair: {}, Facial Hair: {}\n'
'Makeup: {}, Emotion: {}\n'
'Occluded: {}, Exposure: {}\n'
'{}\n{}\n'
)
LABEL_FACE = ('{}, {} years old\n'
'Hair: {}, Facial Hair: {}\n'
'Makeup: {}, Emotion: {}\n'
'Occluded: {}, Exposure: {}\n'
'{}\n{}\n')
class SubscriptionKey(object):
@ -67,7 +63,7 @@ class SubscriptionKey(object):
"""Set the subscription key."""
cls.key = key
with file(SUBSCRIPTION_KEY_FILENAME, 'w') as fout:
print >>fout, key
print >> fout, key
CF.Key.set(cls.key)
@classmethod
@ -101,7 +97,7 @@ class Endpoint(object):
"""Set the endpoint."""
cls.endpoint = endpoint
with file(ENDPOINT_FILENAME, 'w') as fout:
print >>fout, endpoint
print >> fout, endpoint
CF.BaseUrl.set(cls.endpoint)
@classmethod
@ -151,21 +147,16 @@ def draw_bitmap_rectangle(bitmap, faces):
dc.SetTextBackground('black')
dc.SetTextForeground('white')
dc.SetBackgroundMode(wx.SOLID)
dc.SetFont(wx.Font(8,
wx.FONTFAMILY_DEFAULT,
wx.FONTSTYLE_NORMAL,
wx.FONTWEIGHT_BOLD))
dc.SetFont(
wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
wx.FONTWEIGHT_BOLD))
for face in faces:
dc.DrawRectangle(
face.rect.left * bitmap.scale,
face.rect.top * bitmap.scale,
face.rect.width * bitmap.scale,
face.rect.height * bitmap.scale,
)
face.rect.left * bitmap.scale, face.rect.top * bitmap.scale,
face.rect.width * bitmap.scale, face.rect.height * bitmap.scale)
if face.name:
text_width, text_height = dc.GetTextExtent(face.name)
dc.DrawText(face.name,
face.rect.left * bitmap.scale,
dc.DrawText(face.name, face.rect.left * bitmap.scale,
face.rect.top * bitmap.scale - text_height)
dc.SelectObject(wx.NullBitmap)
bitmap.bitmap.SetBitmap(bitmap.bmp)
@ -185,8 +176,10 @@ def key_with_max_value(item):
def async(func):
"""Async wrapper."""
def wrapper(*args, **kwargs):
"""docstring for wrapper"""
thr = Thread(target=func, args=args, kwargs=kwargs)
thr.start()
return wrapper

Просмотреть файл

@ -24,6 +24,7 @@ TITLE = u"Microsoft Cognitive Services Face Samples"
class MyLabelBook(LB.LabelBook):
"""LabelBook part in Main Frame."""
def __init__(self, parent):
agw_style = INB_LEFT | INB_FIT_LABELTEXT | INB_NO_RESIZE
super(MyLabelBook, self).__init__(parent, agwStyle=agw_style)
@ -44,6 +45,7 @@ class MyLabelBook(LB.LabelBook):
class MyTitle(wx.Panel):
"""Title part in Main Frame."""
def __init__(self, parent):
super(MyTitle, self).__init__(parent)
self.SetBackgroundColour('#00b294')
@ -66,6 +68,7 @@ class MyTitle(wx.Panel):
class MyFrame(wx.Frame):
"""Main Frame."""
def __init__(self, parent):
super(MyFrame, self).__init__(parent, title=TITLE, size=(1280, 768))
@ -83,8 +86,7 @@ class MyFrame(wx.Frame):
status_text = (
'Microsoft will receive the images you upload and may use them to '
'improve Face API and related services. By submitting an image, '
'you confirm you have consent from everyone in it.'
)
'you confirm you have consent from everyone in it.')
self.status = wx.StatusBar(self)
self.status.SetStatusText(status_text)
sizer.Add(self.status, flag=wx.EXPAND)
@ -95,6 +97,7 @@ class MyFrame(wx.Frame):
class MyApp(wx.App):
"""The whole app."""
def OnInit(self):
"""Show main frame."""
frame = MyFrame(None)

Просмотреть файл

@ -13,6 +13,7 @@ import util
class MyPanel(wx.Panel):
"""Base Panel."""
def __init__(self, parent):
super(MyPanel, self).__init__(parent)
colour_window = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
@ -21,6 +22,7 @@ class MyPanel(wx.Panel):
class MyStaticBitmap(MyPanel):
"""Base StaticBitmap."""
def __init__(self, parent, bitmap=wx.NullBitmap, size=util.MAX_IMAGE_SIZE):
super(MyStaticBitmap, self).__init__(parent)
self.bmp = bitmap
@ -49,7 +51,13 @@ class MyStaticBitmap(MyPanel):
class MyGridStaticBitmap(wx.Panel):
"""Base Grid StaticBitmap."""
def __init__(self, parent, rows=1, cols=0, vgap=0, hgap=0,
def __init__(self,
parent,
rows=1,
cols=0,
vgap=0,
hgap=0,
size=util.MAX_THUMBNAIL_SIZE):
super(MyGridStaticBitmap, self).__init__(parent)
self.sizer = wx.GridSizer(rows, cols, vgap, hgap)
@ -78,6 +86,7 @@ class MyGridStaticBitmap(wx.Panel):
class WrapCaptionFaceList(wx.WrapSizer):
"""Wrap face list with caption under the face."""
def __init__(self, parent, confidence_faces, size=util.MAX_THUMBNAIL_SIZE):
super(WrapCaptionFaceList, self).__init__()
for face, confidence in confidence_faces:
@ -96,6 +105,7 @@ class WrapCaptionFaceList(wx.WrapSizer):
class FindSimilarsResult(wx.Panel):
"""The view for Find Similar result."""
def __init__(self, parent):
super(FindSimilarsResult, self).__init__(parent)
self.sizer = wx.BoxSizer(wx.VERTICAL)
@ -104,7 +114,8 @@ class FindSimilarsResult(wx.Panel):
"""Set the data."""
self.sizer.Clear(True)
static_text_title = wx.StaticText(
self, label='Find {} Similar Candidate Faces Results:'.format(
self,
label='Find {} Similar Candidate Faces Results:'.format(
len(faces)))
self.sizer.Add(static_text_title, 0, wx.EXPAND)
@ -133,6 +144,7 @@ class FindSimilarsResult(wx.Panel):
class WrapFaceList(wx.Panel):
"""Base wrap face list."""
def __init__(self, parent, faces, size=util.MAX_THUMBNAIL_SIZE):
super(WrapFaceList, self).__init__(parent)
self.sizer = wx.WrapSizer()
@ -146,6 +158,7 @@ class WrapFaceList(wx.Panel):
class CaptionWrapFaceList(wx.Panel):
"""Wrap face list with a caption."""
def __init__(self, parent):
super(CaptionWrapFaceList, self).__init__(parent)
self.sizer = wx.BoxSizer(wx.VERTICAL)
@ -165,6 +178,7 @@ class CaptionWrapFaceList(wx.Panel):
class GroupResult(wx.Panel):
"""The view for Group result."""
def __init__(self, parent):
super(GroupResult, self).__init__(parent)
self.sizer = wx.BoxSizer(wx.VERTICAL)
@ -195,6 +209,7 @@ class GroupResult(wx.Panel):
class MyLog(wx.TextCtrl):
"""The window for each scenario."""
def __init__(self, parent):
style = wx.TE_MULTILINE | wx.TE_READONLY
super(MyLog, self).__init__(parent, style=style)
@ -210,6 +225,7 @@ class MyLog(wx.TextCtrl):
class MyFaceList(wx.VListBox):
"""Face List."""
def __init__(self, parent, faces=[], **kwargs):
super(MyFaceList, self).__init__(parent, **kwargs)
self.SetItems(faces)
@ -230,17 +246,10 @@ class MyFaceList(wx.VListBox):
textx = rect.x + 2 + face.bmp.GetWidth() + 2
label_rect = wx.Rect(textx, rect.y, rect.width - textx, rect.height)
label = util.LABEL_FACE.format(
face.attr.gender,
face.attr.age,
face.attr.hair,
face.attr.facial_hair,
face.attr.makeup,
face.attr.emotion,
face.attr.occlusion,
face.attr.exposure,
face.attr.head_pose,
face.attr.accessories
)
face.attr.gender, face.attr.age, face.attr.hair,
face.attr.facial_hair, face.attr.makeup, face.attr.emotion,
face.attr.occlusion, face.attr.exposure, face.attr.head_pose,
face.attr.accessories)
dc.DrawLabel(label, label_rect, wx.ALIGN_LEFT | wx.ALIGN_TOP)
def SetItems(self, faces):

Просмотреть файл

@ -14,6 +14,7 @@ from view import base
class DetectionPanel(base.MyPanel):
"""Detection Panel."""
def __init__(self, parent):
super(DetectionPanel, self).__init__(parent)
@ -25,12 +26,10 @@ class DetectionPanel(base.MyPanel):
self.hvsizer = wx.BoxSizer(wx.VERTICAL)
self.hvsizer.SetMinSize((util.INNER_PANEL_WIDTH, -1))
label = (
"To detect faces in an image, click the 'Choose Image' "
"button. You will see a rectangle surrounding every face "
"that the Face API detects. You will also see a list of "
"attributes related to the faces."
)
label = ("To detect faces in an image, click the 'Choose Image' "
"button. You will see a rectangle surrounding every face "
"that the Face API detects. You will also see a list of "
"attributes related to the faces.")
self.static_text = wx.StaticText(self, label=label)
self.static_text.Wrap(util.INNER_PANEL_WIDTH)
self.hvsizer.Add(self.static_text, 0, wx.ALL, 5)
@ -102,8 +101,7 @@ class DetectionPanel(base.MyPanel):
try:
attributes = (
'age,gender,headPose,smile,facialHair,glasses,emotion,hair,'
'makeup,occlusion,accessories,blur,exposure,noise'
)
'makeup,occlusion,accessories,blur,exposure,noise')
res = util.CF.face.detect(path, False, False, attributes)
faces = [model.Face(face, path) for face in res]
self.face_list.SetItems(faces)

Просмотреть файл

@ -18,11 +18,11 @@ from view import base
class FindSimilarPanel(base.MyPanel):
"""FindSimilar Panel."""
def __init__(self, parent):
super(FindSimilarPanel, self).__init__(parent)
self.face_list_id = str(uuid.uuid1())
self.face_list_name = self.face_list_id
self.large_face_list_id = str(uuid.uuid1())
self.face_paths = []
self.detected_face_paths = []
self.faces = {}
@ -38,14 +38,12 @@ class FindSimilarPanel(base.MyPanel):
self.hvsizer = wx.BoxSizer(wx.VERTICAL)
self.hvsizer.SetMinSize((util.INNER_PANEL_WIDTH, -1))
label = (
'Find faces that are similar to a given face (the query '
'face).\nClick "Load Candidate Faces" to select a folder '
'containing images of the faces you want to compare to the '
'query face.\nNext, click "Open Query Face" to select the '
'query face image.\nScroll down to see the results '
'displayed under the query face.\n'
)
label = ('Find faces that are similar to a given face (the query '
'face).\nClick "Load Candidate Faces" to select a folder '
'containing images of the faces you want to compare to the '
'query face.\nNext, click "Open Query Face" to select the '
'query face image.\nScroll down to see the results '
'displayed under the query face.\n')
self.static_text = wx.StaticText(self.panel, label=label)
self.static_text.Wrap(util.INNER_PANEL_WIDTH)
self.hvsizer.Add(self.static_text, 0, wx.ALL, 0)
@ -105,37 +103,40 @@ class FindSimilarPanel(base.MyPanel):
def OnChooseFolder(self, evt):
"""Choose Folder."""
face_list_exists = False
large_face_list_exists = False
try:
self.log.log((
'Request: Face List {} will be used to build a person '
'database. Checking whether the face list exists.'
).format(self.face_list_id))
util.CF.face_list.get(self.face_list_id)
face_list_exists = True
self.log.log('Response: Face List {} exists.'.format(
self.face_list_id))
'Request: List {} will be used to build a person database. '
'Checking whether the list exists.').format(
self.large_face_list_id))
print dir(util.CF)
print util.CF.__file__
util.CF.large_face_list.get(self.large_face_list_id)
large_face_list_exists = True
self.log.log(
'Response: List {} exists.'.format(
self.large_face_list_id))
except util.CF.CognitiveFaceException as exp:
if exp.code != 'FaceListNotFound':
if exp.code != 'LargeFaceListNotFound':
self.log.log('Response: {}. {}'.format(exp.code, exp.msg))
return
else:
self.log.log(
'Response: Face List {} did not exist previously.'.format(
self.face_list_id))
'Response: List {} did not exist previously.'
.format(self.large_face_list_id))
if face_list_exists:
if large_face_list_exists:
text = (
'Requires a clean up for face list "{0}" before setting up a '
'new face list. Click OK to proceed, face list "{0}" will be '
'cleared.'
).format(self.face_list_id)
'Requires a clean up for list "{0}" before setting up a new'
'list. Click OK to proceed, list "{0}" will be cleared.'
).format(self.large_face_list_id)
title = 'Warning'
style = wx.YES_NO | wx.ICON_WARNING
result = wx.MessageBox(text, title, style)
if result == wx.YES:
util.CF.face_list.delete(self.face_list_id)
util.CF.large_face_list.delete(self.large_face_list_id)
self.large_face_list_id = str(uuid.uuid1())
else:
return
@ -145,10 +146,8 @@ class FindSimilarPanel(base.MyPanel):
del self.face_paths[:]
for root, dirs, files in os.walk(path):
if files:
self.face_paths.extend([
os.path.join(root, filename)
for filename in files
])
self.face_paths.extend(
[os.path.join(root, filename) for filename in files])
self.panel.SetupScrolling(scroll_x=False)
self.log.log('Request: Preparing, detecting faces in chosen folder.')
@ -157,21 +156,28 @@ class FindSimilarPanel(base.MyPanel):
self.persisted_faces.clear()
del self.detected_face_paths[:]
util.CF.face_list.create(self.face_list_id)
util.CF.large_face_list.create(self.large_face_list_id)
for path in self.face_paths:
try:
res = util.CF.face_list.add_face(path, self.face_list_id)
res = util.CF.large_face_list_face.add(
path, self.large_face_list_id)
self.log.log(
'Response: Success. Add with Persisted Face Id {}'.format(
res['persistedFaceId']))
except util.CF.CognitiveFaceException as exp:
self.log.log((
'[Error] Add "{}" to FaceList {}: Code: {}, Message: {}'
).format(path, self.face_list_id, exp.code, exp.msg))
'[Error] Add "{}" to List {}: Code: {}, '
'Message: {}').format(
path, self.large_face_list_id, exp.code, exp.msg))
continue
self.detected_face_paths.append(path)
face = model.Face(res, path)
self.persisted_faces[face.persisted_id] = face
self.log.log('Response: Success. Total {0} faces are detected.'.format(
len(self.persisted_faces)))
self.log.log(
'Response: Success. Total {0} faces are detected.'.format(
len(self.persisted_faces)))
'Request: Training List: "{0}"'.format(self.large_face_list_id))
res = util.CF.large_face_list.train(self.large_face_list_id)
self.grid.set_paths(self.detected_face_paths)
self.btn_folder.Enable()
@ -179,6 +185,11 @@ class FindSimilarPanel(base.MyPanel):
def OnChooseImage(self, evt):
"""Choose Image."""
util.CF.util.wait_for_large_face_list_training(self.large_face_list_id)
self.log.log(
'Response: Success. List "{0}" training process is Succeeded'.
format(self.large_face_list_id))
dlg = wx.FileDialog(self, wildcard=util.IMAGE_WILDCARD)
if dlg.ShowModal() != wx.ID_OK:
return
@ -194,31 +205,29 @@ class FindSimilarPanel(base.MyPanel):
self.faces[face.id] = face
util.draw_bitmap_rectangle(self.bitmap, self.faces.values())
self.log.log('Success. Detected {} face(s) in {}'.format(
len(self.faces), path))
self.log.log(
'Success. Detected {} face(s) in {}'.format(len(self.faces), path))
res_tot = {
'matchPerson': {},
'matchFace': {},
}
for face_id in self.faces:
self.log.log((
'Request: Finding similar faces in Personal Match Mode for '
'face {}'
).format(face_id))
'Request: Finding similar faces in Person Match Mode for '
'face {}').format(face_id))
for mode in ('matchPerson', 'matchFace'):
res_tot[mode][face_id] = []
res = util.CF.face.find_similars(
face_id,
face_list_id=self.face_list_id,
mode=mode,
)
self.log.log((
'Response: Found {} similar faces for face {} in {} mode'
).format(len(res), face_id, mode))
large_face_list_id=self.large_face_list_id,
mode=mode)
self.log.log(
'Response: Found {} similar faces for face {} in {} mode'.
format(len(res), face_id, mode))
for entry in res:
persisted_id = entry['persistedFaceId']
confidence = entry['confidence']
res_tot[mode][face_id].append((
self.persisted_faces[persisted_id], confidence))
res_tot[mode][face_id].append(
(self.persisted_faces[persisted_id], confidence))
self.result.set_data(self.faces, res_tot)
self.panel.SetupScrolling(scroll_x=False)

Просмотреть файл

@ -17,6 +17,7 @@ from view import base
class GroupPanel(base.MyPanel):
"""Group Panel."""
def __init__(self, parent):
super(GroupPanel, self).__init__(parent)
@ -33,12 +34,10 @@ class GroupPanel(base.MyPanel):
self.hvsizer = wx.BoxSizer(wx.VERTICAL)
self.hvsizer.SetMinSize((util.INNER_PANEL_WIDTH, -1))
label = (
'Click the button below to select a folder containing face '
'images.\nThe images will be grouped based on similarity.\n'
'You will see the different groups under the '
'"Grouping Results" label.'
)
label = ('Click the button below to select a folder containing face '
'images.\nThe images will be grouped based on similarity.\n'
'You will see the different groups under the "Grouping '
'Results" label.')
self.static_text = wx.StaticText(self.panel, label=label)
self.static_text.Wrap(util.INNER_PANEL_WIDTH)
self.hvsizer.Add(self.static_text, 0, wx.ALL, 0)
@ -97,17 +96,14 @@ class GroupPanel(base.MyPanel):
self.faces.clear()
for root, dirs, files in os.walk(path):
if files:
self.face_paths.extend([
os.path.join(root, filename)
for filename in files
])
self.face_paths.extend(
[os.path.join(root, filename) for filename in files])
self.btn.Disable()
self.log.log(
self.log.log((
'Request: Preparing faces for grouping, detecting faces in '
'chosen folder.'
)
'chosen folder.'))
self.grid.set_paths(self.face_paths)
for path in self.face_paths:
try:
@ -118,12 +114,11 @@ class GroupPanel(base.MyPanel):
face = model.Face(entry, path)
self.faces[face.id] = face
self.grid.set_faces(self.faces.values())
self.log.log(
'Response: Success. Total {0} faces are detected.'.format(
len(self.faces)))
self.log.log('Response: Success. Total {0} faces are detected.'.
format(len(self.faces)))
self.log.log('Request: Grouping {0} faces.'.format(
len(self.faces)))
self.log.log(
'Request: Grouping {0} faces.'.format(len(self.faces)))
res = util.CF.face.group(self.faces.keys())
self.result.set_data(self.faces, res)
len_groups = len(res['groups'])

Просмотреть файл

@ -18,10 +18,11 @@ from view import base
class IdentificationPanel(base.MyPanel):
"""Identification Panel."""
def __init__(self, parent):
super(IdentificationPanel, self).__init__(parent)
self.person_group_id = str(uuid.uuid1())
self.large_person_group_id = str(uuid.uuid1())
self.person_id_names = {}
self.person_name_faces = {}
self.faces = {}
@ -37,19 +38,17 @@ class IdentificationPanel(base.MyPanel):
self.hvsizer = wx.BoxSizer(wx.VERTICAL)
self.hvsizer.SetMinSize((util.INNER_PANEL_WIDTH, -1))
label = (
'1) Place face images of one person in a folder and give '
'the folder the same name as that person.\n'
'2) Repeat the step above one or more times, creating '
'different folders for different people.\n'
'3) Place all of the person folders in one root folder.\n'
'4) Click "Load PersonGroup" and select the root folder '
'you created above.\n'
'5) Click "Choose Image" to select a different image '
'representing one of the people for whom you created '
'folders above. The face in the image will be framed and '
'tagged with the name of the person.'
)
label = ('1) Place face images of one person in a folder and give '
'the folder the same name as that person.\n'
'2) Repeat the step above one or more times, creating '
'different folders for different people.\n'
'3) Place all of the person folders in one root folder.\n'
'4) Click "Load Group" and select the root folder you '
'created above.\n'
'5) Click "Choose Image" to select a different image '
'representing one of the people for whom you created '
'folders above. The face in the image will be framed and '
'tagged with the name of the person.')
self.static_text = wx.StaticText(self.panel, label=label)
self.static_text.Wrap(util.INNER_PANEL_WIDTH)
self.hvsizer.Add(self.static_text, 0, wx.ALL, 0)
@ -60,7 +59,7 @@ class IdentificationPanel(base.MyPanel):
self.lsizer.SetMinSize((util.MAX_IMAGE_SIZE, -1))
flag = wx.EXPAND | wx.ALIGN_CENTER | wx.ALL
self.btn_folder = wx.Button(self.panel, label='Load PersonGroup')
self.btn_folder = wx.Button(self.panel, label='Load Group')
self.lsizer.Add(self.btn_folder, 0, flag, 5)
self.Bind(wx.EVT_BUTTON, self.OnChooseFolder, self.btn_folder)
@ -108,38 +107,38 @@ class IdentificationPanel(base.MyPanel):
"""Choose Folder."""
self.log.log((
'Request: Group {0} will be used to build a person database. '
'Checking whether the group exists.'
).format(self.person_group_id))
'Checking whether the group exists.').format(
self.large_person_group_id))
try:
util.CF.person_group.get(self.person_group_id)
self.log.log('Response: Group {0} exists.'.format(
self.person_group_id))
text = (
'Requires a clean up for group "{0}" before setting up a '
'new person database. Click YES to proceed, group "{0}" '
'will be cleared.'
).format(self.person_group_id)
util.CF.large_person_group.get(self.large_person_group_id)
self.log.log(
'Response: Group {0} exists.'.format(
self.large_person_group_id))
text = ('Requires a clean up for group "{0}" before setting up a '
'new person database. Click YES to proceed, group "{0}" '
'will be cleared.').format(self.large_person_group_id)
title = 'Warning'
style = wx.YES_NO | wx.ICON_WARNING
result = wx.MessageBox(text, title, style)
if result == wx.YES:
util.CF.person_group.delete(self.person_group_id)
util.CF.large_person_group.delete(self.large_person_group_id)
self.large_person_group_id = str(uuid.uuid1())
else:
return
except util.CF.CognitiveFaceException as exp:
if exp.code != 'PersonGroupNotFound':
if exp.code != 'LargePersonGroupNotFound':
self.log.log('Response: {}. {}'.format(exp.code, exp.msg))
return
else:
self.log.log((
'Response: Group {0} does not exist previously.'
).format(self.person_group_id))
self.log.log(
'Response: Group {0} does not exist previously.'.format(
self.large_person_group_id))
self.log.log('Request: Creating group "{0}"'.format(
self.person_group_id))
util.CF.person_group.create(self.person_group_id)
self.log.log(
'Request: Creating group "{0}"'.format(self.large_person_group_id))
util.CF.large_person_group.create(self.large_person_group_id)
self.log.log('Response: Success. Group "{0}" created'.format(
self.person_group_id))
self.large_person_group_id))
self.log.log((
'Preparing faces for identification, detecting faces in chosen '
'folder.'))
@ -157,48 +156,44 @@ class IdentificationPanel(base.MyPanel):
for person_name in os.listdir(path):
path_person = os.path.join(path, person_name)
if os.path.isdir(path_person):
self.log.log('Request: Creating person "{0}"'.format(
person_name))
res = util.CF.person.create(self.person_group_id,
person_name)
self.log.log(
'Request: Creating person "{0}"'.format(person_name))
res = util.CF.large_person_group_person.create(
self.large_person_group_id, person_name)
person_id = res['personId']
self.log.log((
'Response: Success. Person "{0}" (PersonID: {1}) '
'created'
).format(
person_name, person_id
))
self.log.log(
'Response: Success. Person "{0}" (PersonID: {1}) created'.
format(person_name, person_id))
self.person_id_names[person_id] = person_name
self.person_name_faces[person_name] = []
for entry in os.listdir(path_person):
path_face = os.path.join(path_person, entry)
if os.path.isfile(path_face):
res = util.CF.person.add_face(
path_face,
self.person_group_id,
person_id)
res = util.CF.large_person_group_person_face.add(
path_face, self.large_person_group_id, person_id)
if res.get('persistedFaceId'):
face_count += 1
face = model.Face(res, path_face)
self.person_name_faces[person_name].append(face)
self.log.log((
'Response: Success. Total {0} faces are detected.'
).format(face_count))
self.log.log('Request: Training group "{0}"'.format(
self.person_group_id))
res = util.CF.person_group.train(self.person_group_id)
self.log.log('Response: Success. Total {0} faces are detected.'.
format(face_count))
self.log.log(
'Request: Training group "{0}"'.format(
self.large_person_group_id))
res = util.CF.large_person_group.train(self.large_person_group_id)
self.grid.set_data(self.person_name_faces)
self.panel.SetupScrolling(scroll_x=False)
self.btn_file.Enable()
self.grid.set_data(self.person_name_faces)
self.panel.SetupScrolling(scroll_x=False)
self.btn_file.Enable()
def OnChooseImage(self, evt):
"""Choose Image."""
util.CF.util.wait_for_training(self.person_group_id)
self.log.log((
'Response: Success. Group "{0}" training process is Succeeded'
).format(self.person_group_id))
util.CF.util.wait_for_large_person_group_training(
self.large_person_group_id)
self.log.log(
'Response: Success. Group "{0}" training process is Succeeded'.
format(self.large_person_group_id))
dlg = wx.FileDialog(self, wildcard=util.IMAGE_WILDCARD)
if dlg.ShowModal() != wx.ID_OK:
@ -217,8 +212,10 @@ class IdentificationPanel(base.MyPanel):
self.face_ids.append(face.id)
self.log.log('Request: Identifying {0} face(s) in group "{1}"'.format(
len(self.faces), self.person_group_id))
res = util.CF.face.identify(self.face_ids, self.person_group_id)
len(self.faces), self.large_person_group_id))
res = util.CF.face.identify(
self.face_ids,
large_person_group_id=self.large_person_group_id)
for entry in res:
face_id = entry['faceId']
if entry['candidates']:

Просмотреть файл

@ -14,6 +14,7 @@ from view.base import MyPanel
class SubscriptionPanel(MyPanel):
"""Subscription Panel."""
def __init__(self, parent):
super(SubscriptionPanel, self).__init__(parent)
@ -25,8 +26,7 @@ class SubscriptionPanel(MyPanel):
'Speech, etc.) has its own subscription keys.\nAnd each '
'subscription key belongs to one specific endpoint.\nYou can use '
'the link below to get a key.\nWhen ready, paste your key '
'into the textbox below.'
)
'into the textbox below.')
style = wx.ALIGN_LEFT | wx.ST_ELLIPSIZE_END
self.static_text = wx.StaticText(self, label=label, style=style)
self.sizer.Add(self.static_text, flag=wx.EXPAND | wx.ALL, border=5)
@ -87,12 +87,10 @@ class SubscriptionPanel(MyPanel):
"""Save the key and endpoint."""
util.SubscriptionKey.set(
self.subscription_key_text.GetValue().encode('utf-8'))
util.Endpoint.set(
self.endpoint_text.GetValue().encode('utf-8'))
util.Endpoint.set(self.endpoint_text.GetValue().encode('utf-8'))
text = (
'Settings successfully saved on your disk.\n'
'You do not need to paste the key next time.'
)
'Settings successfully saved on your disk.\nYou do not need to '
'paste the key next time.')
title = 'Settings'
style = wx.OK | wx.ICON_INFORMATION
wx.MessageBox(text, title, style)

Просмотреть файл

@ -18,6 +18,7 @@ from view import base
class VerificationPanel(base.MyPanel):
"""Verification Panel."""
def __init__(self, parent):
super(VerificationPanel, self).__init__(parent)
@ -26,7 +27,7 @@ class VerificationPanel(base.MyPanel):
'another_face_id': None,
'person_face_id': None,
}
self.person_group_id = str(uuid.uuid1())
self.large_person_group_id = str(uuid.uuid1())
self.person_name = None
self.person_id = None
self.face_paths = []
@ -42,12 +43,10 @@ class VerificationPanel(base.MyPanel):
self.hvsizer = wx.BoxSizer(wx.VERTICAL)
self.hvsizer.SetMinSize((util.INNER_PANEL_WIDTH, -1))
label = (
"Demo 1: Face-to-face verification determines whether "
"two faces belong to the same person. Choose two images "
"with a single face each. Then click 'Verify' to get "
"the verification result."
)
label = ("Demo 1: Face-to-face verification determines whether "
"two faces belong to the same person. Choose two images "
"with a single face each. Then click 'Verify' to get "
"the verification result.")
self.static_text = wx.StaticText(self.panel, label=label)
self.static_text.Wrap(util.INNER_PANEL_WIDTH)
self.hvsizer.Add(self.static_text, 0, wx.ALL, 0)
@ -68,7 +67,8 @@ class VerificationPanel(base.MyPanel):
self.btn_face2face_1.Bind(
wx.EVT_BUTTON,
lambda evt: self.OnChooseImage(
evt, self.bitmap_face2face_1, 'face_id'))
evt, self.bitmap_face2face_1, 'face_id')
)
self.vhsizer1.Add(self.lsizer1, 1, wx.EXPAND)
@ -101,20 +101,19 @@ class VerificationPanel(base.MyPanel):
self.btn_face2face_2.Bind(
wx.EVT_BUTTON,
lambda evt: self.OnChooseImage(
evt, self.bitmap_face2face_2, 'another_face_id'))
evt, self.bitmap_face2face_2, 'another_face_id')
)
self.vhsizer1.Add(self.rsizer1, 1, wx.EXPAND)
self.hvsizer.Add(self.vhsizer1)
label = (
"Demo 2: Face-to-person verification determines whether a "
"face belongs to a given person. Click 'Load Person' to "
"pick a folder containing the images of one person's face. "
"Next, click 'Choose Image' to pick a face image of the "
"same person (or of a different person). Finally, click "
"'Verify' to see the verification result."
)
label = ("Demo 2: Face-to-person verification determines whether a "
"face belongs to a given person. Click 'Load Person' to "
"pick a folder containing the images of one person's face. "
"Next, click 'Choose Image' to pick a face image of the "
"same person (or of a different person). Finally, click "
"'Verify' to see the verification result.")
self.static_text = wx.StaticText(self.panel, label=label)
self.static_text.Wrap(util.INNER_PANEL_WIDTH)
self.hvsizer.Add(self.static_text, 0, wx.ALL, 0)
@ -164,7 +163,8 @@ class VerificationPanel(base.MyPanel):
self.btn_face2person_2.Bind(
wx.EVT_BUTTON,
lambda evt: self.OnChooseImage(
evt, self.bitmap_face2person, 'person_face_id'))
evt, self.bitmap_face2person, 'person_face_id')
)
self.vhsizer2.Add(self.rsizer2, 1, wx.EXPAND)
@ -203,9 +203,8 @@ class VerificationPanel(base.MyPanel):
if len(faces) > 1:
text = (
'Verification accepts two faces as input, please pick images'
'with only one detectable face in it.'
)
'Verification accepts two faces as input, please pick images '
'with only one detectable face in it.')
title = 'Warning'
style = wx.OK | wx.ICON_WARNING
wx.MessageBox(text, title, style)
@ -220,33 +219,33 @@ class VerificationPanel(base.MyPanel):
"""Choose Folder."""
self.log.log((
'Request: Group {0} will be used to build a person database. '
'Checking whether the group exists.'
).format(self.person_group_id))
'Checking whether the group exists.').format(
self.large_person_group_id))
try:
util.CF.person_group.get(self.person_group_id)
self.log.log('Response: Group {0} exists.'.format(
self.person_group_id))
util.CF.large_person_group.get(self.large_person_group_id)
self.log.log(
'Response: Group {0} exists.'.format(
self.large_person_group_id))
text = (
'Requires a clean up for group "{0}" before setting up a '
'new person database. Click YES to proceed, group "{0}" '
'will be cleared.'
).format(self.person_group_id)
'Requires a clean up for group "{0}" before setting up a new '
'person database. Click YES to proceed, group "{0}" will be '
'cleared.').format(self.large_person_group_id)
title = 'Warning'
style = wx.YES_NO | wx.ICON_WARNING
result = wx.MessageBox(text, title, style)
if result == wx.YES:
util.CF.person_group.delete(self.person_group_id)
util.CF.large_person_group.delete(self.large_person_group_id)
self.large_person_group_id = str(uuid.uuid1())
self.person_id = None
else:
return
except util.CF.CognitiveFaceException as exp:
if exp.code != 'PersonGroupNotFound':
if exp.code != 'LargePersonGroupNotFound':
self.log.log('Response: {}. {}'.format(exp.code, exp.msg))
return
else:
self.log.log((
'Response: Group {0} does not exist previously.'
).format(self.person_group_id))
self.log.log('Response: Group {0} does not exist previously.'.
format(self.large_person_group_id))
dlg = wx.DirDialog(self)
if dlg.ShowModal() == wx.ID_OK:
@ -255,38 +254,35 @@ class VerificationPanel(base.MyPanel):
del self.face_paths[:]
for root, dirs, files in os.walk(path):
if files:
self.face_paths.extend([
os.path.join(root, filename)
for filename in files
])
self.log.log('Request: Creating group "{0}"'.format(
self.person_group_id))
util.CF.person_group.create(self.person_group_id)
self.log.log('Response: Success. Group "{0}" created'.format(
self.person_group_id))
self.face_paths.extend(
[os.path.join(root, filename) for filename in files])
self.log.log(
'Request: Creating group "{0}"'.format(
self.large_person_group_id))
util.CF.large_person_group.create(self.large_person_group_id)
self.log.log(
'Response: Success. Group "{0}" created'.format(
self.large_person_group_id))
self.log.log((
'Preparing person for verification, detecting faces in chosen '
'folder.'))
self.log.log('Request: Creating person "{0}"'.format(
self.person_name))
res = util.CF.person.create(self.person_group_id, self.person_name)
'Preparing person for verification, detecting faces in '
'chosen folder.'))
self.log.log(
'Request: Creating person "{0}"'.format(self.person_name))
res = util.CF.large_person_group_person.create(
self.large_person_group_id, self.person_name)
self.person_id = res['personId']
self.log.log((
'Response: Success. Person "{0}" (PersonID:{1}) created'
).format(
self.person_name, self.person_id
))
self.log.log(
'Response: Success. Person "{0}" (PersonID:{1}) created'.
format(self.person_name, self.person_id))
del self.detected_face_paths[:]
for path in self.face_paths:
res = util.CF.person.add_face(path,
self.person_group_id,
self.person_id)
res = util.CF.large_person_group_person_face.add(
path, self.large_person_group_id, self.person_id)
if res.get('persistedFaceId'):
self.detected_face_paths.append(path)
self.log.log((
'Response: Success. Total {0} faces are detected.'
).format(len(self.detected_face_paths)))
res = util.CF.person_group.train(self.person_group_id)
self.log.log('Response: Success. Total {0} faces are detected.'.
format(len(self.detected_face_paths)))
res = util.CF.large_person_group.train(self.large_person_group_id)
self.grid.set_paths(self.detected_face_paths)
self.panel.SetupScrolling(scroll_x=False)
self.check_btn_verify()
@ -301,56 +297,45 @@ class VerificationPanel(base.MyPanel):
if res['isIdentical']:
self.log.log((
'Response: Success. Face {0} and {1} belong to the same '
'person'
).format(
self.face_ids['face_id'],
self.face_ids['another_face_id']
))
'person').format(
self.face_ids['face_id'],
self.face_ids['another_face_id']))
text = (
'Results: \nConfidence = {0}, two faces belong to the '
'same person'
).format(res['confidence'])
'same person').format(res['confidence'])
else:
self.log.log((
'Response: Success. Face {0} and {1} do not belong to the '
'same person'
).format(
self.face_ids['face_id'],
self.face_ids['another_face_id']
))
'Response: Success. Face {0} and {1} do not belong to '
'the same person').format(
self.face_ids['face_id'],
self.face_ids['another_face_id']))
text = (
'Results: \nConfidence = {0}, two faces do not belong to '
'the same person'
).format(res['confidence'])
'the same person').format(res['confidence'])
else:
util.CF.util.wait_for_training(self.person_group_id)
util.CF.util.wait_for_large_person_group_training(
self.large_person_group_id)
self.log.log('Request: Verifying face {0} and person {1}'.format(
self.face_ids['person_face_id'], self.person_id))
res = util.CF.face.verify(self.face_ids['person_face_id'],
person_group_id=self.person_group_id,
person_id=self.person_id)
res = util.CF.face.verify(
self.face_ids['person_face_id'],
large_person_group_id=self.large_person_group_id,
person_id=self.person_id)
if res['isIdentical']:
self.log.log((
'Response: Success. Face {0} belongs to person {1}'
).format(
self.face_ids['person_face_id'],
self.person_name
))
self.log.log(
'Response: Success. Face {0} belongs to person {1}'.format(
self.face_ids['person_face_id'], self.person_name))
text = (
'Results: \n'
'Confidence = {0}, the face belongs to the person'
).format(res['confidence'])
'Results: \nConfidence = {0}, the face belongs to the '
'person').format(res['confidence'])
else:
self.log.log((
'Response: Success. Face {0} does not belong to person {1}'
).format(
self.face_ids['person_face_id'],
self.person_name
))
'Response: Success. Face {0} does not belong to person '
'{1}').format(
self.face_ids['person_face_id'], self.person_name))
text = (
'Results: \nConfidence = {0}, the face does not belong to'
'the person'
).format(res['confidence'])
'Results: \nConfidence = {0}, the face does not belong to '
'the person').format(res['confidence'])
result.SetLabelText(text)
result.Wrap(88)