Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ncouture/7957f6a0f222bd61823b54e6bb73ed38 to your computer and use it in GitHub Desktop.
Save ncouture/7957f6a0f222bd61823b54e6bb73ed38 to your computer and use it in GitHub Desktop.
Simple Python app show you easy way to identify particular face among the other faces
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"import httplib2\n",
"import os\n",
"\n",
"# matplot\n",
"from matplotlib import pyplot as plt\n",
"\n",
"from face_tools import *\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"os.environ[\"GOOGLE_APPLICATION_CREDENTIALS\"] = '{}/google_cloud_vision.json'.format(os.getcwd())\n",
"\n",
"group = '{}/../../test/g7.jpg'.format(os.getcwd())\n",
"single = '{}/../../test/s7.jpg'.format(os.getcwd())\n",
"# group = '/Users/alex/Downloads/g.jpg'\n",
"# single = '/Users/alex/Downloads/s.png'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# plot group image\n",
"fig = plt.figure(figsize=(15,15))\n",
"plt.subplot(121)\n",
"plt.imshow(Image.open(group)) \n",
"plt.axis(\"off\")\n",
"\n",
"# plot single image\n",
"plt.subplot(122)\n",
"plt.imshow(Image.open(single)) \n",
"plt.axis(\"off\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"result = dict(group=dict(image_file=group, original_image=None, labeled_image=None, faces=None, total_faces=None, faces_matrix=None),\n",
" single=dict(image_file=single, original_image=None, labeled_image=None, faces=None, total_faces=None, faces_matrix=None))\n",
"\n",
"for item in result:\n",
" with open(result[item]['image_file'], 'rb') as image:\n",
" result[item]['original_image'] = Image.open(result[item]['image_file'])\n",
" result[item]['faces'], result[item]['total_faces'] = detect_face(image)\n",
" \n",
" print('{}: found {} face{}'.format(item, result[item]['total_faces'], '' if result[item]['total_faces'] == 1 else 's'))\n",
"\n",
" # Reset the file pointer, so we can read the file again\n",
" image.seek(0)\n",
" \n",
" result[item]['labeled_image'] = highlight_faces(image, result[item]['faces'])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# plot group image\n",
"fig = plt.figure(figsize=(15,15))\n",
"plt.subplot(121)\n",
"plt.imshow(result['group']['labeled_image']) \n",
"plt.axis(\"off\")\n",
"\n",
"# plot single image\n",
"plt.subplot(122)\n",
"plt.imshow(result['single']['labeled_image']) \n",
"plt.axis(\"off\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Show detected faces\n",
"=="
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"for item in result:\n",
" \n",
" fig = plt.figure(figsize=(15,2))\n",
"\n",
" for i, face in enumerate(result[item]['faces']):\n",
" pos = i+1\n",
" plt.subplot(1, result[item]['total_faces'], pos)\n",
" vertices = face['fdBoundingPoly']['vertices']\n",
" box = (vertices[0]['x'], vertices[1]['y'], vertices[1]['x'], vertices[2]['y'],) \n",
" cropped_face = result[item]['original_image'].crop(box)\n",
" plt.imshow(cropped_face) \n",
" plt.axis(\"off\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create matrix\n",
"=="
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"'''Transform faces to matrices.'''\n",
"\n",
"for item in result:\n",
" result[item]['faces_matrix'] = np.zeros(shape=(result[item]['total_faces'], FACE_RESOLUTION ** 2))\n",
" \n",
" fig = plt.figure(figsize=(15,15))\n",
"\n",
" for i in range(result[item]['total_faces']):\n",
" vertices = result[item]['faces'][i]['fdBoundingPoly']['vertices']\n",
" \n",
" box = (vertices[0]['x'], vertices[1]['y'], vertices[1]['x'], vertices[2]['y'],)\n",
" rotated_box = (vertices[0]['x']-50, vertices[1]['y']-50, vertices[1]['x']+50, vertices[2]['y']+50,)\n",
" original_face = result[item]['original_image'].crop(rotated_box)\n",
" \n",
" pos = i*3+1\n",
" plt.subplot(result[item]['total_faces'], 3, pos)\n",
" plt.imshow(original_face) \n",
" plt.axis(\"off\")\n",
" \n",
" rotated_face = original_face.rotate(result[item]['faces'][i]['rollAngle'])\n",
" \n",
" cropped_face = rotated_face.crop((50, 50, box[2]-box[0]+50, box[3]-box[1]+50,))\n",
"\n",
" pos = i*3+2\n",
" plt.subplot(result[item]['total_faces'], 3, pos)\n",
" plt.imshow(cropped_face) \n",
" plt.axis(\"off\")\n",
" \n",
" scaled_face = cropped_face.resize(([FACE_RESOLUTION, FACE_RESOLUTION]))\n",
" \n",
" pos = i*3+3\n",
" plt.subplot(result[item]['total_faces'], 3, pos)\n",
" plt.imshow(scaled_face) \n",
" plt.axis(\"off\")\n",
" \n",
" converted_face = scaled_face.convert('L')\n",
" \n",
"# lbp_features = calc_lbp_features(converted_face)\n",
" \n",
" result[item]['faces_matrix'][i] = np.asmatrix(converted_face).A1\n",
"# result[item]['faces_matrix'][i] = np.asmatrix(lbp_features).A1 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Calc disimilarity matrix\n",
"=="
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"predicted = np.argmin(np.linalg.norm(result['group']['faces_matrix']-result['single']['faces_matrix'], axis=1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Show result\n",
"=="
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"draw = ImageDraw.Draw(result['group']['original_image'])\n",
"box = [(v.get('x', 0.0), v.get('y', 0.0)) for v in result['group']['faces'][predicted]['fdBoundingPoly']['vertices']]\n",
"print(box)\n",
"draw.line(box + [box[0]], width=5, fill='#00ff00')\n",
"del draw\n",
" \n",
" \n",
"# plot group image\n",
"fig = plt.figure(figsize=(15,15))\n",
"plt.subplot(111)\n",
"plt.imshow(result['group']['original_image']) \n",
"plt.axis(\"off\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Link to gist\n",
"==\n",
"\n",
"https://gist.github.com/onidzelskyi/2878f78d499da7d6a5c4e0b2b2cd8111\n",
"\n",
"Requirements\n",
"==\n",
"\n",
"```bash\n",
"sudo apt-get install python-pip libtiff5-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python-tk python-matplotlib\n",
"\n",
"sudo pip install google-api-python-client==1.5.0 Pillow==3.1.1 numpy\n",
"```"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
import base64
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials
from PIL import Image, ImageDraw
# Google' variables and environments
DISCOVERY_URL='https://{api}.googleapis.com/$discovery/rest?version={apiVersion}'
# variables
FACE_RESOLUTION = 100 # Face' size 100 by 100 pixels
def get_vision_service():
credentials = GoogleCredentials.get_application_default()
return discovery.build('vision', 'v1', credentials=credentials,
discoveryServiceUrl=DISCOVERY_URL)
def detect_face(face_file, max_results=10):
"""Uses the Vision API to detect faces in the given file.
Args:
face_file: A file-like object containing an image with faces.
Returns:
An array of dicts with information about the faces in the picture.
"""
image_content = face_file.read()
batch_request = [{
'image': {
'content': base64.b64encode(image_content).decode('UTF-8')
},
'features': [{
'type': 'FACE_DETECTION',
'maxResults': max_results,
}]
}]
service = get_vision_service()
request = service.images().annotate(body={
'requests': batch_request,
})
response = request.execute()
if not response['responses'][0]:
raise ValueError('No faces were detected in {}.'.format(face_file))
return response['responses'][0]['faceAnnotations'], len(response['responses'][0]['faceAnnotations'])
def highlight_faces(image, faces, output_filename=None):
"""Draws a polygon around the faces, then saves to output_filename.
Args:
image: a file containing the image with the faces.
faces: a list of faces found in the file. This should be in the format
returned by the Vision API.
output_filename: the name of the image file to be created, where the faces
have polygons drawn around them.
"""
im = Image.open(image)
draw = ImageDraw.Draw(im)
for face in faces:
box = [(v.get('x', 0.0), v.get('y', 0.0)) for v in face['fdBoundingPoly']['vertices']]
draw.line(box + [box[0]], width=15, fill='#00ff00')
del draw
if output_filename:
im.save(output_filename)
return im
def extract_faces(image, faces):
"""Extract faces from image.
Args:
image: a file containing the image with the faces.
faces: a list of faces found in the file. This should be in the format
returned by the Vision API.
Return array of faces
"""
arr = np.zeros()
I = Image.open(image)
for face in faces:
box = [(v.get('x', 0.0), v.get('y', 0.0)) for v in face['fdBoundingPoly']['vertices']]
Arr.line(box + [box[0]], width=5, fill='#00ff00')
return arr
def calc_lbp_features(img):
from skimage.feature import local_binary_pattern
radius = 2
n_points = 8 * radius
METHOD = 'uniform'
return local_binary_pattern(img, n_points, radius, METHOD)
{
"type": "service_account",
"project_id": "amiable-hour-128508",
"private_key_id": "b45e3f6b9e403fdd0ac1ab8f836ba28763f7739a",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCLw1Mv6RxL0eUU\n20uLcJXmVdu6MD+Vo0xb/N+3A12sRlfi6Jqe0ncxiY+vpQrujxgB0tuRuOLKKEue\nSACZ9pHPwcpLJnZeBIlBfAVQdHYH3FD+0HEPKWydwpPRAgL1iy684CUtXZ/n9fsv\neCugh5ziRNC9CbUHz+19jJ4H0vw9tLO8zNOL2ZJGL7BribX6F2MOQT+BkDbQlJlT\nlNU+7mU0I/i5s9uQqppo7bR7D7x8s5pyssB9ZzH1x+uKHqCAVPH+0JHLz7KXUd9j\nhtztuga2+LYjd3KTlDC/9XxvyJX4oBC6RHR6Wc1qC6fkfiyj/8WKbyzI4czw3Jt4\nryFwufHpAgMBAAECggEADIJ9Laql17t/z7AZQO/g2u8QbcfnyRMGwK0PsSfh+IuL\nTkoXnOOlu49ehxA0vEmekns3IAH2erXEnvQ+6YkCYCAuZS+aJKwvROc+6oaiEe4M\naeJqXDsO98f0xx5w+V1t34YIjdj1eSOxSfxtmz7IMhCKxoDZ7UsVLMmrU3P1E+i4\nbxzYwyaTtT3RbPBVDHHCpIx/M22Aw10j+29PjD2f/a4SIQdnwsSOzGwY1PNLICkM\nhAWaQW8f4dmFG3RJgkNphG8m2oGChZEy1SL7rWVi+OoNUQncjU2eb2EtcM5uIxaH\noMPVhyGxynbPLQQDRmoGxxC2Sfl7YvZHXIjm3835IQKBgQDdJ4obPC9VXz1E2ccu\njSKv1A4LvCSo0//+fPQJu2VhPQhtE97BmoEjthW5hqS6j+I2to3BmKMJtufKd6CO\nunecxXikc+4Ex0C+68gdabGifmcn3/GeKJ1BY+O39lt16fVb5iYHkJu8Nw+AVioZ\naq7wCCMNU7LW1BjLQ4RQJ1n6NQKBgQChyMntHgeuHZtIct9VNEYsthd1D9dtesuf\nFxLUnFwOCHlh90mW2wDPErpsjRHjfL1I+s7sQdYq0lJtfUP8A/g5vJZdhDSNeJ80\nnYvqAX+w142H2DNz62/rkBtVMI0HjUjrJjAhi8Xh4pJL34lkYMxJdcA8qt9M2hh2\nnsSMTXCvZQKBgE1vQcElgqFO1qIb6s0W59VO15guSVu/1zuhPsWFkwrIFwIyWeXK\nFnuNju/GADm+lYN4ygvGSRfmriRLXLF9AtKmpgZW/Tk5FyeCYTBDSMpPngjtName\nKOmzcxF/tiiEQb/qxtgRPyZY1RmnkdgSbaxn/PX2n4DvBLtvKY3zKWMdAoGBAIyF\nFPZSXgNajdR4igi8lbMiGe/AabIatR+ib+WhRceejqeLnSxdXi99qdS9FuuLHfF0\nfyPv7zBUa+nToqgTXpfveH8TZH34ZffSW4NN9/XG05RJMi+eMCDfkw4EVIpZqhss\nmSOZ/q87Fyy1pOU9ulKX5vgKxlc/G350Wm0umhCNAoGAQkNlZFKGV00iRQzLHtps\n4djapGJM8gcO14ZUZK8mkkb53IWMeTbI4wDwoh7qbZaSzUErINeyZW5regribwiU\n3eU8AECdqrV5a9mcf+ta4kMTmSnk+cg8r2h7BNpR2y8Ux2N2w5ZhhxVjByxfkPTL\n85yY46iU0goNXBdoCq8zWcU=\n-----END PRIVATE KEY-----\n",
"client_email": "[email protected]",
"client_id": "106183748320275873602",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/996116364663-compute%40developer.gserviceaccount.com"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment