{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Image processing APIs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You will need to generate a private key at [RapidAPI](https://rapidapi.com/), then you can use it here." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import requests\n", "\n", "# I keep mine in another file, which is not sent to GitHub\n", "# Or put yours in the string 'key' below\n", "try:\n", " from secrets import mashape as key\n", "except ImportError as e:\n", " key = \" KEY GOES HERE \"" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Face recognition\n", "\n", "Face++ has a comprehensive API, some of which is free. [Their site](http://www.faceplusplus.com/) allows you to build apps to do all kinds of clever things.\n", "\n", "We're going to use their free API via RapidAPI, which is a convenient place to try APIs for all sorts of things. Let's try a simple detection on this face...\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "url = \"https://faceplusplus-faceplusplus.p.rapidapi.com/facepp/v3/detect\"\n", "target = \"https://static1.squarespace.com/static/549dcda5e4b0a47d0ae1db1e/t/5af31248562fa79d0f19ca68/1525879588450/?format=300w\"\n", "\n", "params = {'image_url': target}\n", "\n", "headers={\n", " \"X-Mashape-Key\": key,\n", " \"Content-Type\": \"application/x-www-form-urlencoded\"\n", " }\n", "\n", "response = requests.post(url, headers=headers, data=params)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'image_id': 'NOknGGbV/+A3ERkzEq8tJw==',\n", " 'request_id': '1553365760,c737662c-c122-40a1-bf0d-153021043a4d',\n", " 'time_used': 376,\n", " 'faces': [{'face_rectangle': {'width': 82,\n", " 'top': 78,\n", " 'left': 60,\n", " 'height': 82},\n", " 'face_token': '167b1cf6cd8b52093596f1327dc3c8e3'}]}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "response.json()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## With face attributes\n", "\n", "Turns out we can ask for lots of other information, e.g. about the facial expression." ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "attributes = ['gender',\n", " 'age',\n", " 'smiling',\n", " 'headpose',\n", " 'facequality',\n", " 'blur',\n", " 'eyestatus',\n", " 'emotion',\n", " 'ethnicity',\n", " 'beauty',\n", " 'mouthstatus',\n", " 'eyegaze',\n", " 'skinstatus'\n", "]" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "params = {'image_url': target,\n", " 'return_attributes': ','.join(attributes),\n", " }\n", "\n", "response = requests.post(url, headers=headers, data=params)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'image_id': 'sAqOk498IudAZHDVDfWUJg==',\n", " 'request_id': '1553186533,491b9f79-18a5-460e-8f7f-3cd69cd713e5',\n", " 'time_used': 288,\n", " 'faces': [{'attributes': {'emotion': {'sadness': 0.0,\n", " 'neutral': 0.0,\n", " 'disgust': 0.008,\n", " 'anger': 0.002,\n", " 'surprise': 0.002,\n", " 'fear': 0.002,\n", " 'happiness': 99.987},\n", " 'beauty': {'female_score': 67.194, 'male_score': 56.279},\n", " 'gender': {'value': 'Male'},\n", " 'age': {'value': 49},\n", " 'mouthstatus': {'close': 0.01,\n", " 'surgical_mask_or_respirator': 0.0,\n", " 'open': 99.99,\n", " 'other_occlusion': 0.0},\n", " 'glass': {'value': 'None'},\n", " 'skinstatus': {'dark_circle': 3.044,\n", " 'stain': 40.645,\n", " 'acne': 20.696,\n", " 'health': 2.109},\n", " 'headpose': {'yaw_angle': -13.445905,\n", " 'pitch_angle': 4.7359223,\n", " 'roll_angle': 11.515112},\n", " 'blur': {'blurness': {'threshold': 50.0, 'value': 8.219},\n", " 'motionblur': {'threshold': 50.0, 'value': 8.219},\n", " 'gaussianblur': {'threshold': 50.0, 'value': 8.219}},\n", " 'smile': {'threshold': 50.0, 'value': 100.0},\n", " 'eyestatus': {'left_eye_status': {'normal_glass_eye_open': 0.037,\n", " 'no_glass_eye_close': 0.0,\n", " 'occlusion': 0.002,\n", " 'no_glass_eye_open': 99.959,\n", " 'normal_glass_eye_close': 0.0,\n", " 'dark_glasses': 0.002},\n", " 'right_eye_status': {'normal_glass_eye_open': 1.236,\n", " 'no_glass_eye_close': 0.0,\n", " 'occlusion': 0.0,\n", " 'no_glass_eye_open': 98.763,\n", " 'normal_glass_eye_close': 0.0,\n", " 'dark_glasses': 0.0}},\n", " 'facequality': {'threshold': 70.1, 'value': 58.089},\n", " 'ethnicity': {'value': 'WHITE'},\n", " 'eyegaze': {'right_eye_gaze': {'position_x_coordinate': 0.442,\n", " 'vector_z_component': 0.992,\n", " 'vector_x_component': -0.058,\n", " 'vector_y_component': 0.108,\n", " 'position_y_coordinate': 0.367},\n", " 'left_eye_gaze': {'position_x_coordinate': 0.377,\n", " 'vector_z_component': 0.794,\n", " 'vector_x_component': -0.361,\n", " 'vector_y_component': -0.49,\n", " 'position_y_coordinate': 0.363}}},\n", " 'face_rectangle': {'width': 130, 'top': 131, 'left': 80, 'height': 130},\n", " 'face_token': '1512868d91c3e9ea2095207ae3ce9c85'}]}" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "response.json()" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Daydreaming\n", "\n", "This is completely made up.\n", "\n", "\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "{u'seismic': [{u'attribute': {u'f_peak': {u'range': 7, u'value': 39},\n", " u'wavelet': {u'confidence': 89.932, u'value': u'ricker'},\n", " u'phase': {u'error': 12.23421, u'value': 1.73568},\n", " u'fresnel': {u'error': 400, u'value': 1750},\n", " u'colourbar': {u'confidence': 98.53456, u'value': u'black-red'}},\n", " u'facies': [{u'center': {u'x': 58.583333, u'y': 20.989305},\n", " u'name': 'parallel',\n", " u'confidence': 76.45311},\n", " {u'center': {u'x': 213.556323, u'y': 202.234543},\n", " u'name': 'mounded',\n", " u'confidence': 67.3253245},\n", " {u'center': {u'x': 458.346354, u'y': 120.345636},\n", " u'name': 'noisy',\n", " u'confidence': 54.353466}],\n", " u'img_height': 387,\n", " u'img_id': u'524305ff333db315e583a4bdb5d03d0d',\n", " u'img_width': 620,\n", " u'session_id': u'928365a231974ae1a87ab51ca2066700',\n", " u'url': u'https://dl.dropboxusercontent.com/u/14965965/seismic_example.png'}\n", " \n" ] } ], "source": [ "# Don't execute this cell.\n", "url = \"https://imageclass.io/classify/seismic.json\"\n", "target = \"https://dl.dropboxusercontent.com/u/14965965/seismic_example.png\"\n", "params = {'url': target,\n", " 'time': '600,1600', # time range in ms\n", " 'trace': '1000,1400', # trace range\n", " 'dx': '25', # trace spacing in m\n", " 'attribute': 'frequency,facies,resolution', # optional\n", " }\n", "headers={\n", " \"API_key\": key,\n", " \"Accept\": \"application/json\"\n", " }\n", "\n", "response = unirest.post(url, headers=headers, params=params)\n", "response.body" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## For realz\n", "\n", "I found [some code](https://gist.github.com/endolith/255291) by *[endolith](https://github.com/endolith)* to do frequency estimation.\n", "\n", "I got it working for seismic stuff in another notebook, [Frequency_from_image](./Frequency_from_image.ipynb). Then I set up a `Flask` app on [PythonAnywhere](https://www.pythonanywhere.com), which was surprisingly easy. It's serving at http://kwinkunks.pythonanywhere.com.\n", "\n", "It's headless — it only accepts API calls. See below for an example.\n", "\n", "Let's get the frequency content of the seismic in [this image](https://math.berkeley.edu/~sethian/2006/Applications/Seismic/time_mig_img.jpg). I have already measured the pixel positions of region of the image that I want, in the time range 0 to 3 s, and the *x* range 8 to 16 km.\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'job_uuid': 'eef5f2a0-4bf6-11e9-819f-0a84fd45cba2',\n", " 'parameters': {'avg': 'trim',\n", " 'method': 'xing',\n", " 'region': '199,141,1608,1087',\n", " 'time_range': [0.0, 3.0],\n", " 'trace_spacing': 'regular',\n", " 'traces': [128, 256, 384, 512, 640, 769, 897, 1025, 1153, 1281],\n", " 'url': 'https://math.berkeley.edu/~sethian/2006/Applications/Seismic/time_mig_img.jpg'},\n", " 'result': {'freq': {'max': 157.57,\n", " 'min': 1.09,\n", " 'n': 10,\n", " 'peak': 20.3,\n", " 'sd': 1.12},\n", " 'greyscale': True,\n", " 'histogram': {'bins': [-128.0,\n", " -99.66666666666667,\n", " -71.33333333333334,\n", " -43.0,\n", " -14.666666666666671,\n", " 13.666666666666657,\n", " 42.0,\n", " 70.33333333333331,\n", " 98.66666666666666,\n", " 127.0],\n", " 'counts': [147566,\n", " 166666,\n", " 248099,\n", " 325574,\n", " 155382,\n", " 89953,\n", " 69530,\n", " 54919,\n", " 75225]},\n", " 'img_size': {'height': 1409, 'width': 946},\n", " 'phase': {'avg': 3.35, 'n': 10, 'sd': 26.32},\n", " 'snr': {'avg': 0.46, 'sd': 0.05}}}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import requests\n", "\n", "url = \"http://kwinkunks.pythonanywhere.com/freq\"\n", "target = \"https://math.berkeley.edu/~sethian/2006/Applications/Seismic/time_mig_img.jpg\"\n", "params = {'url': target,\n", " 'method': 'xing',\n", " 'tmin': 0.0,\n", " 'tmax': 3.0,\n", " 'region': '199,141,1608,1087',\n", " 'avg': 'trim'\n", " }\n", "headers={\n", " \"Accept\": \"application/json\"\n", " }\n", "\n", "response = requests.get(url, headers=headers, params=params)\n", "response.json()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "geocomp", "language": "python", "name": "geocomp" }, "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.7.1" } }, "nbformat": 4, "nbformat_minor": 1 }