Skip to content
This repository has been archived by the owner on Nov 8, 2021. It is now read-only.

Commit

Permalink
Initial version for sample. (#6)
Browse files Browse the repository at this point in the history
* Initial version for sample.

* README update.

- Remove TODO section.
- Remove redundant empty lines.

* Remove Jupyter Notebook and corresponding README.

* Several logic bug fix.

* Several view bugs have been fixed.
  • Loading branch information
huxuan authored and wangjun-microsoft committed Sep 26, 2016
1 parent d4041d6 commit 856d9bc
Show file tree
Hide file tree
Showing 17 changed files with 1,719 additions and 296 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -91,3 +91,4 @@ ENV/
# Custom
*.swp
config.py
Subscription.txt
Binary file added Assets/Microsoft-logo_rgb_c-gray.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
283 changes: 0 additions & 283 deletions Jupyter Notebook/Face Detection Example.ipynb

This file was deleted.

8 changes: 4 additions & 4 deletions Makefile
Expand Up @@ -4,7 +4,7 @@ clean:
find . -name '*.pyc' -print0 | xargs -0 rm -f
find . -name '*.swp' -print0 | xargs -0 rm -f
find . -name '__pycache__' -print0 | xargs -0 rm -rf
-rm -rf build dist *.egg-info
-rm -rf build dist *.egg-info .eggs

deps:
pip install -r requirements.txt
Expand All @@ -15,13 +15,13 @@ install:
lint: pep8 pyflakes pylint

pep8:
-pep8 --statistics --count cognitive_face setup.py
-pep8 --statistics --count cognitive_face setup.py sample

pyflakes:
-pyflakes cognitive_face setup.py
-pyflakes cognitive_face setup.py sample

pylint:
-pylint --rcfile=.pylintrc cognitive_face setup.py
-pylint --rcfile=.pylintrc cognitive_face setup.py sample/*

test:
python setup.py test
24 changes: 15 additions & 9 deletions README.md
Expand Up @@ -38,18 +38,25 @@ result = CF.face.detect(img_url)
print result
```

## TODO
## Sample

- More robust unittests (Only test the most basic functionality currently).
- Add native support for json response by adding some models like `Face`, `FaceList`, `Person` and `PersonGroup`.
A Python SDK sample built with wxPython is also provided, before execution,
please install all components listed below.

# Microsoft Face API: Jupyter Notebook
This [Jupyter Notebook](<http://jupyter.org/>) demonstrates how to use Python with the Microsoft Face API, an offering within [Microsoft Cognitive Services](https://www.microsoft.com/cognitive-services), formerly known as Project Oxford.
* [Learn about the Face API](https://www.microsoft.com/cognitive-services/en-us/face-api)
* [Read the documentation](https://www.microsoft.com/cognitive-services/en-us/face-api/documentation/overview)
* [Find more SDKs & Samples](https://www.microsoft.com/cognitive-services/en-us/SDK-Sample?api=face)
### Sample Prerequisite

- [Python 2.7](https://www.python.org/downloads/) (only Python 2 supported due
to limitation of wxPython)
- [wxPython](https://wxpython.org/)
- [cognitive_face package](https://pypi.python.org/pypi/cognitive_face)

### Sample Execution

```bash
git clone https://github.com/Microsoft/Cognitive-Face-Python.git
cd Cognitive-Face-Python
python sample
```

## Contributing
We welcome contributions. Feel free to file issues and pull requests on the repo and we'll address them as we can. Learn more about how you can help on our [Contribution Rules & Guidelines](</CONTRIBUTING.md>).
Expand All @@ -69,6 +76,5 @@ All Microsoft Cognitive Services SDKs and samples are licensed with the MIT Lice

Sample images are licensed separately, please refer to [LICENSE-IMAGE](</LICENSE-IMAGE.md>)


## Developer Code of Conduct
Developers using Cognitive Services, including this sample, are expected to follow the “Developer Code of Conduct for Microsoft Cognitive Services”, found at [http://go.microsoft.com/fwlink/?LinkId=698895](http://go.microsoft.com/fwlink/?LinkId=698895).
13 changes: 13 additions & 0 deletions sample/__main__.py
@@ -0,0 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: main.py
Description: main script for Python SDK sample.
"""

from view import MyApp


if __name__ == "__main__":
app = MyApp(False)
app.MainLoop()
7 changes: 7 additions & 0 deletions sample/model/__init__.py
@@ -0,0 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: __init__.py
Description: Model components for Python SDK sample.
"""
from model.face import Face
42 changes: 42 additions & 0 deletions sample/model/face.py
@@ -0,0 +1,42 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: face.py
Description: Face model for Python SDK Sample.
"""

import wx

import util


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
self.bmp = wx.Bitmap(path)
self.name = None
if res.get('faceId'):
self.id = res['faceId']
if res.get('persistedFaceId'):
self.persisted_id = res['persistedFaceId']
if res.get('faceRectangle'):
rect = res['faceRectangle']
self.left = int(rect['left'])
self.top = int(rect['top'])
self.width = int(rect['width'])
self.height = int(rect['height'])
self.bmp = self.bmp.GetSubBitmap(wx.Rect(
self.left, self.top, self.width, self.height))
if res.get('faceAttributes'):
attr = res['faceAttributes']
self.age = int(attr['age'])
self.gender = attr['gender']
self.smile = float(attr['smile']) > 0 and 'Smile' or 'Not Smile'
self.glasses = attr['glasses']
self.bmp = util.scale_bitmap(self.bmp, size)

def set_name(self, name):
"""Set the name for the face."""
self.name = name
120 changes: 120 additions & 0 deletions sample/util.py
@@ -0,0 +1,120 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: util.py
Description: util module for Python SDK sample.
"""

from threading import Thread
import os.path

import wx

try:
import cognitive_face as CF
except ImportError:
import sys
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
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
MAX_THUMBNAIL_SIZE = 75
STYLE = wx.SIMPLE_BORDER
SUBSCRIPTION_KEY_FILENAME = 'Subscription.txt'

LOG_FACE_LIST_REQUEST = (
'Request: Face List {} will be used for build person database. '
'Checking whether group exists.'
)
LOG_FACE_LIST_NOT_EXIST = 'Response: Face List {} does not exist before.'
LOG_FACE_LIST_EXIST = 'Response: Face List {} exists.'


class SubscriptionKey(object):
"""Subscription Key."""

@classmethod
def get(cls):
"""Get the subscription key."""
if not hasattr(cls, 'key'):
cls.key = ''
if not cls.key:
if os.path.isfile(SUBSCRIPTION_KEY_FILENAME):
with file(SUBSCRIPTION_KEY_FILENAME) as fin:
cls.key = fin.read().strip()
else:
cls.key = ''
CF.Key.set(cls.key)
return cls.key

@classmethod
def set(cls, key):
"""Set the subscription key."""
cls.key = key
with file(SUBSCRIPTION_KEY_FILENAME, 'w') as fout:
print >>fout, key
CF.Key.set(cls.key)

@classmethod
def delete(cls):
"""Delete the subscription key."""
cls.key = ''
if os.path.isfile(SUBSCRIPTION_KEY_FILENAME):
os.remove(SUBSCRIPTION_KEY_FILENAME)
CF.Key.set(cls.key)


def scale_bitmap(bitmap, size=MAX_IMAGE_SIZE):
"""Scale the image."""
img = bitmap.ConvertToImage()
width = img.GetWidth()
height = img.GetHeight()
if width > height:
new_width = size
new_height = size * height / width
else:
new_height = size
new_width = size * width / height
img = img.Scale(new_width, new_height)
return wx.BitmapFromImage(img)


def draw_bitmap_rectangle(bitmap, faces):
"""Draw rectangle on bitmap."""
dc = wx.MemoryDC(bitmap.bmp)
dc.SetPen(wx.BLUE_PEN)
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetTextBackground('black')
dc.SetTextForeground('white')
dc.SetBackgroundMode(wx.SOLID)
dc.SetFont(wx.Font(8,
wx.FONTFAMILY_DEFAULT,
wx.FONTSTYLE_NORMAL,
wx.FONTWEIGHT_BOLD))
for face in faces:
dc.DrawRectangle(
face.left * bitmap.scale,
face.top * bitmap.scale,
face.width * bitmap.scale,
face.height * bitmap.scale,
)
if face.name:
text_width, text_height = dc.GetTextExtent(face.name)
dc.DrawText(face.name,
face.left * bitmap.scale,
face.top * bitmap.scale - text_height)
dc.SelectObject(wx.NullBitmap)
bitmap.bitmap.SetBitmap(bitmap.bmp)


def async(func):
"""Async wrapper."""
def wrapper(*args, **kwargs):
"""docstring for wrapper"""
thr = Thread(target=func, args=args, kwargs=kwargs)
thr.start()
return wrapper
102 changes: 102 additions & 0 deletions sample/view/__init__.py
@@ -0,0 +1,102 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
File: __init__.py
Description: View components for Python SDK sample.
"""

import wx
import wx.lib.agw.labelbook as LB

from wx.lib.agw.fmresources import INB_FIT_LABELTEXT
from wx.lib.agw.fmresources import INB_LEFT
from wx.lib.agw.fmresources import INB_NO_RESIZE

from view.panel_detection import DetectionPanel
from view.panel_subscription import SubscriptionPanel
from view.panel_find_similar import FindSimilarPanel
from view.panel_group import GroupPanel
from view.panel_identification import IdentificationPanel
from view.panel_verification import VerificationPanel

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)

subscription_panel = SubscriptionPanel(self)
subscription_text = u"Subscription Key Management"
self.AddPage(subscription_panel, subscription_text, True)

self.AddPage(wx.Panel(self), u"Select a scenario:")
self.EnableTab(1, False)

self.AddPage(DetectionPanel(self), u" - Face Detection")
self.AddPage(FindSimilarPanel(self), u" - Face Find Similar")
self.AddPage(GroupPanel(self), u" - Face Grouping")
self.AddPage(IdentificationPanel(self), u" - Face Identification")
self.AddPage(VerificationPanel(self), u" - Face Verification")


class MyTitle(wx.Panel):
"""Title part in Main Frame."""
def __init__(self, parent):
super(MyTitle, self).__init__(parent)
self.SetBackgroundColour('#00b294')
self.SetMinSize((-1, 80))

sizer = wx.BoxSizer()
sizer.AddStretchSpacer()

family = wx.FONTFAMILY_DEFAULT
style = wx.FONTSTYLE_NORMAL
weight = wx.FONTWEIGHT_NORMAL
font = wx.Font(20, family, style, weight)
self.text = wx.StaticText(self, label=TITLE, style=wx.ALIGN_CENTER)
self.text.SetFont(font)
sizer.Add(self.text, flag=wx.ALIGN_CENTER_VERTICAL)

sizer.AddStretchSpacer()
self.SetSizer(sizer)


class MyFrame(wx.Frame):
"""Main Frame."""
def __init__(self, parent):
super(MyFrame, self).__init__(parent, title=TITLE, size=(1280, 768))

icon_path = 'Assets/Microsoft-logo_rgb_c-gray.png'
self.SetIcon(wx.Icon(icon_path))

sizer = wx.BoxSizer(wx.VERTICAL)

self.title = MyTitle(self)
sizer.Add(self.title, flag=wx.EXPAND)

self.book = MyLabelBook(self)
sizer.Add(self.book, 1, flag=wx.EXPAND)

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.'
)
self.status = wx.StatusBar(self)
self.status.SetStatusText(status_text)
sizer.Add(self.status, flag=wx.EXPAND)

self.SetSizer(sizer)
self.Layout()


class MyApp(wx.App):
"""The whole app."""
def OnInit(self):
"""Show main frame."""
frame = MyFrame(None)
frame.Show()
return True

0 comments on commit 856d9bc

Please sign in to comment.