├── Demo └── bvengine.html ├── README.md ├── postman-collection └── bvengine.postman_collection.json └── swagger-spec └── BiometricVision_Swagger.yml /Demo/bvengine.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FaceMatch 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 64 | 65 | 66 | 67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | 82 | 83 |
84 |
85 |
86 |
87 |
88 |
89 | 90 | 91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | 100 | 101 |
102 |
103 |
104 |
105 |
106 | 107 | 108 | 109 |
110 |
111 | 112 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](https://biometricvision.com/git_images/logo_white_sm.png) 2 | 3 | # Introduction 4 | 5 | Recognize and compare faces in minutes with this simple to use cloud based facial recognition API. This model has a match accuracy of 99.9% so it works under extreme conditions (Long distance, pixelation, blurred images and high/low contrast). 6 | 7 | (https://biometricvision.com) Has released it's API for free to the community for the next 3 months. We are really excited for everyone to test the technology and let us know what you think. 8 | 9 | **This tutorial shows you how to compare between two images.** 10 | 11 | ### Example 12 | 13 | This image below is a demo showing the results of two images matching as the same person: 14 | ![Demo](https://biometricvision.com/git_images/match_man.jpg) 15 | 16 | #### Results 17 | 18 | ```json 19 | { 20 | "Confidence": "Match", 21 | "Features": { 22 | "Left Eye": "92.52", 23 | "Right Eye": "86.04", 24 | "Left Brow": "91.45", 25 | "Right Brow": "90.31", 26 | "Forehead": "90.91", 27 | "Middle Forehead": "89.70", 28 | "Nose": "87.82", 29 | "Philtrum": "93.20", 30 | "Mouth": "91.65", 31 | "Jaw": "93.75", 32 | "Left Cheek": "86.44", 33 | "Right Cheek": "88.50" 34 | } 35 | ``` 36 | [You can find a working demo UI here](https://bvengine.com) 37 | 38 | The 99.9% match accuracy means it will work under extreme conditions: 39 | ![Demo](https://biometricvision.com/git_images/extreme_matching.gif) 40 | 41 | # Getting Started 42 | 43 | There are three steps to use the API: 44 | 1. Get your the API Key, Client ID and Secret Key. 45 | 2. Create an OAuth 2.0 Token. 46 | 3. Upload two images to the compare API. 47 | 48 | You can use our postman collection to test your API. 49 | * [Download PostMan Collection][PlDb] 50 | 51 | ### Step 1: Get your the API Key, Client ID and Secret Key 52 | 53 | You can quickly generate your API Key, Client ID and Secret Key by signing up here. Don't worry it's free for 90 days and you don't need to enter credit card details. 54 | 55 | * [Get your free API access details](https://app.biometricvision.com/auth/sign-up) 56 | 57 | ### Step 2: Create an OAuth 2.0 Token 58 | 59 | To access the compare API you will need an OAuth 2.0 Token. So, you will need your Client ID and Secret Key to create it. 60 | Below is an example for creating OAuth 2.0 Token using CURL. 61 | ```sh 62 | curl -X POST -H "Content-Type: application/json" \ 63 | --data "{\"client_id\": \"CLIENT_ID\",\"client_secret\": \"SECRET_KEY\", \"grant_type\":\"client_credentials\"}" \ 64 | https://bvengine.com/oauth/token 65 | ``` 66 | 67 | **Response:** 68 | 69 | ```json 70 | { 71 | "token_type": "Bearer", 72 | "expires_in": 3600, 73 | "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIyNTQxMTQ1NiIsImp0aSI6IjNiNTg2YzZjMDdkODBhZThjYWYwMGFlYWI3ZDFiN2E2MjZjZjM0YjgxODJiZjlhOWE0MWMyNjI1YWEzN2YxNTYzNWFjYzVjM2JiNWNhODY2IiwiaWF0IjoxNTgzMjg4OTA4LCJuYmYiOjE1ODMyODg5MDgsImV4cCI6MTU4MzI5MjUwOCwic3ViIjoiIiwic2NvcGVzIjpbXX0.NdZyMzYgYt4dtnFa3ph9MiJGhF00tauH3yy7quBPHcUNkY7ZEysQSWt1YOvQXr1L5E5eMMsaidojYLU8Zknc112TYtbUsdiQMJQyNves_dJpE-0kna3TzE4rDwNFqZXdRCul6FGVb5AzYeH2sAmkny03584cnVZC6WsOsOJacccl1kIjKe0zBS2pKi3EqiDka8z_Er3GboXD4qxSUOvkrO4JN0qNXckIhl7q1SgXwX_JwbwU6Sxzd8y_q7tjCptca3JimRf_ad3U4k3Bp-gErhMby_SoTADrexE3uHuOK8gM1aLW8JH-Vg8rX-rX0m78OgFcC8mpLVtm2a4g1NT_o1ZFCIuJNBxa-cpE13uYgjMwyj8LKQ_xeBGJu7eaOeu5wxMqTa26IKp35lwVFcF8bHCcfjIm1JwrPoEowlBDFUd1thBaprKBRJeguHg4foO4RNK08wQrG_S0m34x_jfhpo5ljlZQyrbGb4x0FB3b-IRV5tXNE1rX8h5UnFexQX5zDHTKtr_nSFl8_HtIHAOYOywPfxpMSWHEyzq6-KY1u1rmnhRIJSVC5VledVjW8lvAfKXtAJK6K315nYWvDoDN2aZ-wftpWkPBDYzjMf9NwoA7AvlvS95_mSsiQC0l6rJor6lqMW2ELBYgRCaqwJ5ebQ1xGB_DnNXx_zwsg7Y6vV0" 74 | } 75 | ``` 76 | ### Step 3: Upload two images to the compare API 77 | Once you get `access_token` now you will be able to use the compare API with your API Key. 78 | Below is an example for using the API. 79 | 80 | **Request:** 81 | 82 | ```sh 83 | curl -X POST -H "Content-Type: application/json" \ 84 | -H "Authorization: Bearer ACESS_TOKEN" \ 85 | -H "X-API-KEY: API_KEY" \ 86 | -F "image1=@/home/user/image1.jpg" \ 87 | -F "image2=@/home/user/image2.jpg" \ 88 | https://bvengine.com/api/compare 89 | ``` 90 | 91 | **Response:** 92 | 93 | ```json 94 | { 95 | "Confidence": "Match", 96 | "Features": { 97 | "Left Eye": "92.52", 98 | "Right Eye": "86.04", 99 | "Left Brow": "91.45", 100 | "Right Brow": "90.31", 101 | "Forehead": "90.91", 102 | "Middle Forehead": "89.70", 103 | "Nose": "87.82", 104 | "Philtrum": "93.20", 105 | "Mouth": "91.65", 106 | "Jaw": "93.75", 107 | "Left Cheek": "86.44", 108 | "Right Cheek": "88.50" 109 | } 110 | ``` 111 | 112 | If the two images are not the same person `Confidence` will be "No Match". 113 | 114 | ### Step 4: Track and monitor the API stats via the dashboard 115 | 116 | Can be accessed here (https://app.biometricvision.com/dashboard) 117 | 118 | ![Demo](https://biometricvision.com/git_images/Dashboard4.jpg) 119 | 120 | 121 | ### Swagger Spec 122 | 123 | We do have the swagger for those two APIs. You can download it here: 124 | * [Download Swagger Spec][PlGh] 125 | 126 | ### Need Support 127 | 128 | If you run into any issues or problems you are welcome to file a github issue or simple talk to me via (https://app.biometricvision.com/dashboard) once you have access. Or you can chat with me directly at (https://biometricvision.com/) via intercom. 129 | 130 | | Technical Features | 131 | | ------ | 132 | | Face match time of 130ms| 133 | | False Accept Rate is 0.1%, False Reject Rate is 0.14% | 134 | | Proprietary method for storing face templates as an anonymous alphanumeric string of code (binary) | 135 | | Threshold for ‘Match’ is >=70% | 136 | | Image formats supported: jpg, jpeg, png, bmp | 137 | | Built using Python with machine learning | 138 | | Uses 180 landmarks to create a face template | 139 | 140 | ### Release Plan 141 | | Feature | Release Date | 142 | | ------ | ------ | 143 | | Verification (1:1) | Live | 144 | | Identification (1:N) | March 2020| 145 | | Anti-spoofing | April 2020 | 146 | | Liveness detection | April 2020 | 147 | 148 | **Enjoy!** 149 | 150 | [//]: # () 151 | 152 | [PlDb]: 153 | [PlGh]: 154 | -------------------------------------------------------------------------------- /postman-collection/bvengine.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "8ba10852-a5fd-c98b-9d1d-52f04af65b1b", 3 | "name": "bvengine", 4 | "description": "", 5 | "order": [ 6 | "2e2fa586-8256-68fc-ee2f-d47c3946feab", 7 | "d5ab788e-3143-46fd-53f9-a4cf72439579", 8 | "9240b79a-f3f4-acab-ea4f-a98bc905b06a" 9 | ], 10 | "folders": [], 11 | "folders_order": [], 12 | "timestamp": 1579050356237, 13 | "owner": "3036925", 14 | "public": false, 15 | "requests": [ 16 | { 17 | "id": "2e2fa586-8256-68fc-ee2f-d47c3946feab", 18 | "headers": "Content-Type: application/json\n", 19 | "headerData": [ 20 | { 21 | "key": "Content-Type", 22 | "value": "application/json", 23 | "description": "", 24 | "enabled": true 25 | } 26 | ], 27 | "url": "https://bvengine.com/oauth/token", 28 | "queryParams": [], 29 | "preRequestScript": null, 30 | "pathVariables": {}, 31 | "pathVariableData": [], 32 | "method": "POST", 33 | "data": [], 34 | "dataMode": "raw", 35 | "tests": null, 36 | "currentHelper": "normal", 37 | "helperAttributes": {}, 38 | "time": 1582261962005, 39 | "name": "Create OAuth Token", 40 | "description": "", 41 | "collectionId": "8ba10852-a5fd-c98b-9d1d-52f04af65b1b", 42 | "responses": [], 43 | "rawModeData": "{\"client_id\": {{client_id}},\"client_secret\": \"{{secret}}\", \"grant_type\":\"client_credentials\"}" 44 | }, 45 | { 46 | "id": "9240b79a-f3f4-acab-ea4f-a98bc905b06a", 47 | "headers": "Accept: application/json\nAuthorization: Bearer TOKEN_HERE\nX-Token: {{token}}\n", 48 | "headerData": [ 49 | { 50 | "key": "Accept", 51 | "value": "application/json", 52 | "description": "", 53 | "enabled": true 54 | }, 55 | { 56 | "key": "Authorization", 57 | "value": "Bearer TOKEN_HERE", 58 | "description": "", 59 | "enabled": true 60 | }, 61 | { 62 | "key": "X-Token", 63 | "value": "{{token}}", 64 | "description": "", 65 | "enabled": true 66 | } 67 | ], 68 | "url": "https://bvengine.com/api/compare", 69 | "queryParams": [], 70 | "preRequestScript": null, 71 | "pathVariables": {}, 72 | "pathVariableData": [], 73 | "method": "POST", 74 | "data": [ 75 | { 76 | "key": "image1", 77 | "value": "fr_F.jpg", 78 | "description": "", 79 | "type": "file", 80 | "enabled": true 81 | }, 82 | { 83 | "key": "image2", 84 | "value": "fr_F.jpg", 85 | "description": "", 86 | "type": "file", 87 | "enabled": true 88 | } 89 | ], 90 | "dataMode": "params", 91 | "version": 2, 92 | "tests": null, 93 | "currentHelper": "normal", 94 | "helperAttributes": {}, 95 | "time": 1582261997925, 96 | "name": "Campare", 97 | "description": "", 98 | "collectionId": "8ba10852-a5fd-c98b-9d1d-52f04af65b1b", 99 | "responses": [] 100 | }, 101 | { 102 | "id": "d5ab788e-3143-46fd-53f9-a4cf72439579", 103 | "headers": "Accept: application/json\nAuthorization: Bearer TOKEN_HERE\n", 104 | "headerData": [ 105 | { 106 | "key": "Accept", 107 | "value": "application/json", 108 | "description": "", 109 | "enabled": true 110 | }, 111 | { 112 | "key": "Authorization", 113 | "value": "Bearer TOKEN_HERE", 114 | "description": "" 115 | } 116 | ], 117 | "url": "https://bvengine.com/api/oauth/create?client_id=CLIENT_ID_HERE&secret=YOUR_SECRET_HERE", 118 | "queryParams": [ 119 | { 120 | "key": "client_id", 121 | "value": "CLIENT_ID_HERE", 122 | "equals": true, 123 | "description": "", 124 | "enabled": true 125 | }, 126 | { 127 | "key": "secret", 128 | "value": "YOUR_SECRET_HERE", 129 | "equals": true, 130 | "description": "", 131 | "enabled": true 132 | } 133 | ], 134 | "preRequestScript": null, 135 | "pathVariables": {}, 136 | "pathVariableData": [], 137 | "method": "POST", 138 | "data": null, 139 | "dataMode": "params", 140 | "tests": null, 141 | "currentHelper": "normal", 142 | "helperAttributes": {}, 143 | "time": 1582262128512, 144 | "name": "Create OAuth Client", 145 | "description": "", 146 | "collectionId": "8ba10852-a5fd-c98b-9d1d-52f04af65b1b", 147 | "responses": [] 148 | } 149 | ] 150 | } -------------------------------------------------------------------------------- /swagger-spec/BiometricVision_Swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: '1.0.0' 4 | title: 'BVEngine APIs' 5 | description: '' 6 | contact: 7 | name: 'Support BiometricVision' 8 | email: 'support@biometricvision.com' 9 | host: 'bvengine.com' 10 | basePath: '/api' 11 | schemes: 12 | - 'https' 13 | paths: 14 | /compare: 15 | post: 16 | description: 'Compares Two Face Images' 17 | produces: 18 | - application/json 19 | consumes: 20 | - multipart/form-data 21 | parameters: 22 | - in: header 23 | name: Authorization 24 | description: The token from biometricOAuth2. 25 | type: string 26 | format: hash 27 | required: true 28 | - in: formData 29 | name: image1 30 | type: file 31 | x-mimetype: image/png, image/jpeg 32 | required: true 33 | - in: formData 34 | name: image2 35 | type: file 36 | x-mimetype: image/png, image/jpeg 37 | required: true 38 | security: 39 | - biometricOAuth2: 40 | - 'read:data' 41 | responses: 42 | 200: 43 | description: 'OK' 44 | 209: 45 | $ref: '#/responses/UnexpectedError' 46 | 400: 47 | $ref: '#/responses/BadRequest' 48 | 401: 49 | $ref: '#/responses/Unauthenticated' 50 | 404: 51 | $ref: '#/responses/NotFound' 52 | 405: 53 | $ref: '#/responses/MethodNotAllowed' 54 | 408: 55 | $ref: '#/responses/RequestTimeout' 56 | 422: 57 | $ref: '#/responses/UnprocessableEntity' 58 | 429: 59 | $ref: '#/responses/TooManyRequests' 60 | 500: 61 | $ref: '#/responses/InternalServerError' 62 | 502: 63 | $ref: '#/responses/BadGateway' 64 | 503: 65 | $ref: '#/responses/ServiceUnavailable' 66 | 504: 67 | $ref: '#/responses/GatewayTimeout' 68 | 69 | responses: 70 | UnexpectedError: 71 | description: The request has been received but it has an unexpected error. 72 | schema: 73 | type: object 74 | properties: 75 | message: 76 | type: string 77 | example: This session has been expired. 78 | BadRequest: 79 | description: The server could not understand the request due to invalid syntax. 80 | schema: 81 | type: object 82 | properties: 83 | message: 84 | type: string 85 | example: Bad Request. 86 | Unauthenticated: 87 | description: Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. 88 | schema: 89 | type: object 90 | properties: 91 | message: 92 | type: string 93 | example: Unauthenticated. 94 | NotFound: 95 | description: The server can not find requested resource. 96 | schema: 97 | type: object 98 | properties: 99 | message: 100 | type: string 101 | example: Not Found. 102 | UnprocessableEntity: 103 | description: The request was well-formed but was unable to be followed due to semantic errors. 104 | schema: 105 | type: object 106 | properties: 107 | message: 108 | type: string 109 | example: The given data was invalid. 110 | errors: 111 | type: object 112 | example: 113 | - image1: 114 | - The image uploaded is invalid. 115 | MethodNotAllowed: 116 | description: The request method is known by the server but has been disabled and cannot be used. 117 | schema: 118 | type: object 119 | properties: 120 | message: 121 | type: string 122 | example: Method Not Allowed. 123 | RequestTimeout: 124 | description: This response is sent on an idle connection by some servers, even without any previous request by the client. It means that the server would like to shut down this unused connection. 125 | schema: 126 | type: object 127 | properties: 128 | message: 129 | type: string 130 | example: Request Timeout. 131 | TooManyRequests: 132 | description: The user has sent too many requests in a given amount of time ("rate limiting"). 133 | schema: 134 | type: object 135 | properties: 136 | message: 137 | type: string 138 | example: Too Many Requests. 139 | InternalServerError: 140 | description: The server has encountered a situation it doesn't know how to handle. 141 | schema: 142 | type: object 143 | properties: 144 | message: 145 | type: string 146 | example: Internal Server Error. 147 | BadGateway: 148 | description: This error response means that the server, while working as a gateway to get a response needed to handle the request, got an invalid response. 149 | schema: 150 | type: object 151 | properties: 152 | message: 153 | type: string 154 | example: Bad Gateway. 155 | ServiceUnavailable: 156 | description: The server is not ready to handle the request. 157 | schema: 158 | type: object 159 | properties: 160 | message: 161 | type: string 162 | example: Service Unavailable. 163 | GatewayTimeout: 164 | description: This error response is given when the server is acting as a gateway and cannot get a response in time. 165 | schema: 166 | type: object 167 | properties: 168 | message: 169 | type: string 170 | example: Gateway Timeout. 171 | 172 | securityDefinitions: 173 | biometricOAuth2: 174 | type: oauth2 175 | flow: application 176 | tokenUrl: 'https://bvengine.com/oauth/token' 177 | scopes: 178 | 'write:data': '' 179 | 'read:data': '' 180 | --------------------------------------------------------------------------------