├── LICENSE ├── README.md ├── defaultphoto.png ├── defaultupload.png ├── index.html ├── style.css └── verify.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 shango44 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTML5 and JavaScript Face Matching Using Facesoft API 2 | Simply verify if 2 photos contain the same person using HTML5 and JavaScript. 3 | 4 | -------------------------------------------------------------------------------- /defaultphoto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattshango/facesoft-html5-javascript-face-match/18bb733d5e806d28199d7953e7d94527d828fddd/defaultphoto.png -------------------------------------------------------------------------------- /defaultupload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattshango/facesoft-html5-javascript-face-match/18bb733d5e806d28199d7953e7d94527d828fddd/defaultupload.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Face Verification 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 |

Face Verification

24 |

Quick and simple face verification using HTML5 and JavaScript

25 |
26 |
27 |
28 |
29 |

Verification Photo

30 | 31 | 32 | 33 | Default Upload Photo 34 | 35 | 36 | 37 |
38 |
39 |

Video

40 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

Photo Taken

49 | 50 | 51 | 52 | Default 53 | 54 | 55 |
56 |
57 |
58 |
59 | 60 |

61 |

62 |
63 |
64 | 65 |
66 |
67 |
68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .camera-container { 2 | max-width: 100%; 3 | border: 1px solid black; 4 | } 5 | 6 | .verification-image { 7 | width: 300px; 8 | height: auto; 9 | max-width: 100%; 10 | } 11 | 12 | .btn { 13 | margin-top: 10px; 14 | } 15 | 16 | #captureCanvas, #uploadCanvas { 17 | display: none; 18 | } 19 | 20 | input[name="image-upload"] { 21 | display: none; 22 | } 23 | 24 | #errorAlert, #warningAlert { 25 | display: none; 26 | } -------------------------------------------------------------------------------- /verify.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function() { 2 | var video = document.getElementById('video'), // Video 3 | captureCanvas = document.getElementById('captureCanvas'), // Canvas for captured photo 4 | uploadCanvas = document.getElementById('uploadCanvas'), // Canvas for uploaded photo 5 | captureContext = captureCanvas.getContext('2d'), // Context for captured photo canvas 6 | uploadContext = uploadCanvas.getContext('2d'), // Context for uploaded photo canvas 7 | uploadedPhoto = document.getElementById('uploadedPhoto'), // Uploaded photo ID 8 | capturedPhoto = document.getElementById('capturedPhoto'), // Captured Photo ID 9 | imageUploadInput = document.querySelector('[name="image-upload"]'), // Image Upload Input 10 | apiKey = '', // Facesoft API Key 11 | 12 | errorAlert = document.getElementById('errorAlert'), // Error Alert 13 | warningAlert = document.getElementById('warningAlert'), // Warning Alert 14 | matchText = document.getElementById('match'), // Match Text 15 | scoreText = document.getElementById('score'); // Score Text 16 | 17 | // Stream Camera To Video Element 18 | if(navigator.mediaDevices.getUserMedia){ 19 | navigator.mediaDevices.getUserMedia({ video: true }) 20 | .then(function(stream) { 21 | video.srcObject = stream; 22 | }).catch(function(error) { 23 | console.log(error) 24 | }) 25 | } 26 | 27 | // On Upload Photo Button Click 28 | document.getElementById('upload').addEventListener('click', function(){ 29 | imageUploadInput.click(); 30 | }) 31 | 32 | // On Uploaded Photo Change 33 | imageUploadInput.addEventListener('change', function(){ 34 | // Get File Extension 35 | var ext = imageUploadInput.files[0]['name'].substring(imageUploadInput.files[0]['name'].lastIndexOf('.') + 1).toLowerCase(); 36 | // If File Exists & Image 37 | if (imageUploadInput.files && imageUploadInput.files[0] && (ext == "png" || ext == "jpeg" || ext == "jpg")) { 38 | // Set Photo To Canvas 39 | var reader = new FileReader(); 40 | reader.onload = function (e) { 41 | var img = new Image(); 42 | img.src = event.target.result; 43 | img.onload = function() { 44 | setImageToCanvas(img, uploadedPhoto, uploadCanvas, uploadContext); 45 | } 46 | } 47 | reader.readAsDataURL(imageUploadInput.files[0]); 48 | } 49 | }) 50 | 51 | // On Take Photo Button Click 52 | document.getElementById('capture').addEventListener('click', function(){ 53 | setImageToCanvas(video, capturedPhoto, captureCanvas, captureContext, video.videoWidth, video.videoHeight); 54 | }) 55 | 56 | // On Verify Photo Button Click 57 | document.getElementById('verify').addEventListener('click', function(){ 58 | // Remove Results & Alerts 59 | errorAlert.style.display = "none"; 60 | warningAlert.style.display = "none"; 61 | matchText.innerHTML = ""; 62 | scoreText.innerHTML = ""; 63 | 64 | // Get Base64 65 | var image1 = captureCanvas.toDataURL().split(',')[1]; // Split to get ASCII 66 | var image2 = uploadCanvas.toDataURL().split(',')[1]; // Split to get ASCII 67 | 68 | // Verify if images are of the same person 69 | verifyImages(image1, image2, function(response){ 70 | if(response){ 71 | var obj = JSON.parse(response); 72 | 73 | // If Warning Message 74 | if(obj.message){ 75 | errorAlert.style.display = "none"; 76 | warningAlert.style.display = "block"; 77 | warningAlert.innerHTML = obj.message; 78 | matchText.innerHTML = ""; 79 | scoreText.innerHTML = ""; 80 | } 81 | // If Error 82 | else if(obj.error){ 83 | errorAlert.style.display = "block"; 84 | errorAlert.innerHTML = obj.error; 85 | warningAlert.style.display = "none"; 86 | matchText.innerHTML = ""; 87 | scoreText.innerHTML = ""; 88 | } 89 | // If Valid 90 | else{ 91 | errorAlert.style.display = "none"; 92 | warningAlert.style.display = "none"; 93 | matchText.innerHTML = obj.match; 94 | scoreText.innerHTML = (obj.score*100).toFixed(2) + "% Score"; 95 | } 96 | } 97 | }) 98 | }) 99 | 100 | // Set Photo To Canvas Function 101 | function setImageToCanvas(image, id, canvas, context, width=image.width, height=image.height) { 102 | var ratio = width / height; 103 | var newWidth = canvas.width; 104 | var newHeight = newWidth / ratio; 105 | if (newHeight > canvas.height) { 106 | newHeight = canvas.height; 107 | newWidth = newHeight * ratio; 108 | } 109 | context.clearRect(0, 0, canvas.width, canvas.height); 110 | context.drawImage(image, 0, 0, newWidth, newHeight); 111 | id.setAttribute('src', canvas.toDataURL('image/png')); 112 | } 113 | 114 | // Facesoft Face Match API Function 115 | function verifyImages(image1, image2, callback){ 116 | var params = { 117 | image1: image1, 118 | image2: image2, 119 | } 120 | var xhr = new XMLHttpRequest(); 121 | xhr.open("POST", "https://api.facesoft.io/v1/face/match"); 122 | xhr.setRequestHeader("apikey", apiKey); 123 | xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); 124 | xhr.onload = function(){ 125 | callback(xhr.response); 126 | } 127 | xhr.send(JSON.stringify(params)); 128 | } 129 | 130 | 131 | // Set Default Images For Uploaded & Captured Photo 132 | setImageToCanvas(uploadedPhoto, uploadedPhoto, uploadCanvas, uploadContext); 133 | setImageToCanvas(capturedPhoto, capturedPhoto, captureCanvas, captureContext); 134 | }); --------------------------------------------------------------------------------