Spaces:
Running
Running
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1.0, user-scalable=no"> | |
| <title> | |
| facemesh v220725 x joserpagil@gmail.com | |
| </title> | |
| <style> | |
| body { | |
| margin : 0 ; | |
| overflow : hidden ; | |
| font-family : Arial ; | |
| font-size : 2vmax ; | |
| } | |
| button { | |
| font-family : Arial ; | |
| font-size : 2vmax ; | |
| } | |
| .close_button { | |
| position : absolute ; | |
| top : 0.5vmax ; | |
| right : 1vmax ; | |
| cursor : pointer ; | |
| color : white ; | |
| } | |
| .window { | |
| resize : both ; | |
| display : block ; | |
| overflow : hidden ; | |
| position : absolute ; | |
| left : 0 ; | |
| top : 1vh ; | |
| width : 46vh ; | |
| margin : auto ; | |
| z-index : 1 ; | |
| background-color : #888 ; | |
| border : 2px solid black ; | |
| padding : 0 ; | |
| } | |
| .window_title { | |
| font-family : Arial ; | |
| font-size : 3vh ; | |
| padding : 0.5vmax ; | |
| cursor : move ; | |
| z-index : 10 ; | |
| background-color : black ; | |
| color : white ; | |
| resize : both ; | |
| height : 4vh ; | |
| } | |
| .window_content { | |
| padding : 1vmax ; | |
| } | |
| .animate { | |
| -webkit-animation : animatezoom 0.6s ; | |
| animation : animatezoom 0.6s ; | |
| } | |
| @-webkit-keyframes animatezoom { | |
| from {-webkit-transform: scale(0)} | |
| to {-webkit-transform: scale(1)} | |
| } | |
| @keyframes animatezoom { | |
| from {transform: scale(0)} | |
| to {transform: scale(1)} | |
| } | |
| .switch { | |
| vertical-align : bottom ; | |
| background-color : transparent ; | |
| position: relative; | |
| display: inline-block; | |
| width: 2em; | |
| height: 1em; | |
| } | |
| .switch input { | |
| opacity: 0; | |
| width: 0; | |
| height: 0; | |
| } | |
| .slider { | |
| position: absolute; | |
| cursor: pointer; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background-color: #ccc; | |
| -webkit-transition: .4s; | |
| transition: .4s; | |
| } | |
| .slider:before { | |
| position: absolute; | |
| content: ""; | |
| height: 1em; | |
| width: 1em; | |
| left: 0vw; | |
| top: 0vw; | |
| bottom: 1vw; | |
| background-color: white; | |
| -webkit-transition: .4s; | |
| transition: .4s; | |
| } | |
| input:checked + .slider { | |
| background-color: green; | |
| } | |
| input:focus + .slider { | |
| box-shadow: 0 0 1px #2196F3; | |
| } | |
| input:checked + .slider:before { | |
| -webkit-transform: translateX(1em); | |
| -ms-transform: translateX(1em); | |
| transform: translateX(1em); | |
| } | |
| .slider.round { | |
| border-radius: 5vw; | |
| } | |
| .slider.round:before { | |
| border-radius: 50%; | |
| } | |
| .loading-circle { | |
| position : absolute ; | |
| border : 6px solid rgba(0, 0, 0, 0) ; | |
| border-top : 6px solid rgb(221, 144, 29) ; | |
| border-radius : 50% ; | |
| } | |
| #loading0 { | |
| top: calc(50% - 45px); | |
| left: calc(50% - 45px); | |
| width: 90px; | |
| height: 90px; | |
| animation: spin 1.5s linear infinite; | |
| } | |
| #loading1 { | |
| top: calc(50% - 60px); | |
| left: calc(50% - 60px); | |
| width: 120px; | |
| height: 120px; | |
| animation: spin 2s linear infinite; | |
| } | |
| #loading2 { | |
| top: calc(50% - 75px); | |
| left: calc(50% - 75px); | |
| width: 150px; | |
| height: 150px; | |
| animation: spin 2.5s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { | |
| transform: rotate(0deg); | |
| } | |
| 100% { | |
| transform: rotate(360deg); | |
| } | |
| } | |
| #throbber_div { | |
| position : absolute ; | |
| left : 0px ; | |
| top : 0px ; | |
| width : 100% ; | |
| height : 100% ; | |
| } | |
| table { | |
| width : 100% ; | |
| } | |
| #wind_of_the_west_slider { | |
| width : 100% ; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id = 'log_div'></div > | |
| <div id = 'tools_window' class = 'window animate' style = 'z-index : 2 ;'> | |
| <div id = 'tools_window_title' class = 'window_title' onmousedown ='Drag_element ( this )'>facemesh v220725 | |
| <a class = 'close_button' onclick='tools_window . style . display = "none"'>×</a> | |
| </div> | |
| <div class = 'window_content'> | |
| FPS | |
| <label id = 'fps_label'>calculating ...</label> | |
| <br> | |
| <hr> | |
| <table> | |
| <tr> | |
| <td> | |
| Camera | |
| </td> | |
| <td> | |
| <button id = 'switch_camera_button' onclick = 'Switch_camera ()'>switch</button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <label>flip x</label> | |
| </td> | |
| <td> | |
| <label class = 'switch'> | |
| <input id = 'flip_y_switch' onclick = 'Flip_x_switch_change ()' type = 'checkbox' checked> | |
| <span class = 'slider round'></span> | |
| </label> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <label>flip y</label> | |
| </td> | |
| <td> | |
| <label class = 'switch'> | |
| <input id = 'flip_y_switch' onclick = 'Flip_y_switch_change ()' type = 'checkbox' unchecked> | |
| <span class = 'slider round'></span> | |
| </label> | |
| </td> | |
| </tr> | |
| </table> | |
| <hr> | |
| Show | |
| <br> | |
| <table> | |
| <tr> | |
| <td> | |
| <label>eyes</label> | |
| </td> | |
| <td> | |
| <label class = 'switch'> | |
| <input id = 'eyes_switch' onclick = 'Eyes_switch_change ()' type = 'checkbox' checked> | |
| <span class = 'slider round'></span> | |
| </label> | |
| </td> | |
| <td> | |
| <input id = 'eyes_color_input' type = 'color' value = '#ff0000'> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <label>lips</label> | |
| </td> | |
| <td> | |
| <label class = 'switch'> | |
| <input id = 'lips_switch' onclick = 'Lips_switch_change ()' type = 'checkbox' unchecked> | |
| <span class = 'slider round'></span> | |
| </label> | |
| </td> | |
| <td> | |
| <input id = 'lips_color_input' type = 'color' value = '#ff0000'> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <label>hair</label> | |
| </td> | |
| <td> | |
| <label class = 'switch'> | |
| <input id = 'hair_switch' onclick = 'Hair_switch_change ()' type = 'checkbox' unchecked> | |
| <span class = 'slider round'></span> | |
| </label> | |
| </td> | |
| <td> | |
| <input id = 'hair_color_input' type = 'color' value = '#ffff00'> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <label>beard</label> | |
| </td> | |
| <td> | |
| <label class = 'switch'> | |
| <input id = 'beard_switch' onclick = 'Beard_switch_change ()' type = 'checkbox' unchecked> | |
| <span class = 'slider round'></span> | |
| </label> | |
| </td> | |
| <td> | |
| <input id = 'beard_color_input' type = 'color' value = '#ffffff'> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <label>mask</label> | |
| </td> | |
| <td> | |
| <label class = 'switch'> | |
| <input id = 'mask_switch' onclick = 'Mask_switch_change ()' type = 'checkbox'> | |
| <span class = 'slider round'></span> | |
| </label> | |
| </td> | |
| </tr> | |
| </table> | |
| <hr> | |
| Wind of the west | |
| <br> | |
| <input type = 'range' min = '0' max = '100' value = '0' id = 'wind_of_the_west_slider'> | |
| </div> | |
| </div> | |
| <div id = 'throbber_div'> | |
| <div id = 'loading0' class = 'loading-circle'></div> | |
| <div id = 'loading1' class = 'loading-circle'></div> | |
| <div id = 'loading2' class = 'loading-circle'></div> | |
| </div> | |
| <script> | |
| // Log messages over the display | |
| // usefull when developing on mobile | |
| const Log = args => { | |
| log_div . innerHTML += args . html + '<br>' | |
| } | |
| addEventListener ( 'error' , errorEvent => { Log ( { html : errorEvent . lineno + ' , ' + errorEvent . colno + ' - ' + errorEvent . message } ) } ) | |
| const Hair_indexes = [ 127 , 162 , 21 , 54 , 103 , 67 , 109 , 10 , 338 , 297 , 332 , 284 , 251 , 389 , 356 ] | |
| const Beard_indexes = [ 454 , 323 , 361 , 288 , 397 , 365 , 379 , 378 , 400 , 377 , 152 , 148 , 176 , 149 , 150 , 136 , 172 , 58 , 132 , 93 , 234 ] | |
| // FPS vars | |
| let start = 0 | |
| let nof = 0 | |
| const Number_of_iterations = 10 | |
| const Minimal_interface_size = 64 | |
| const constraints = { | |
| audio : false , | |
| video : { | |
| facingMode : 'user' | |
| } | |
| } | |
| let mediaStream = null | |
| let flip_x = true | |
| let flip_y = false | |
| let canvas | |
| let context | |
| let frame_canvas | |
| let frame_context | |
| let scaled_canvas | |
| let scaled_context | |
| let model = null | |
| let antigravity | |
| let gravity | |
| let hair_state = null | |
| let beard_state = null | |
| let point = null | |
| let first_points = [] | |
| let tearable_elements = [] | |
| let mouse = { x : 0 , y : 0 } | |
| let old_mouse = { x : 0 , y : 0 } | |
| let delta_mouse = { x : 0 , y : 0 } | |
| let image = null | |
| let video = null | |
| let file_button | |
| let show_mask = false | |
| let show_hair = false | |
| let hair_color = 0xffff00 | |
| let show_beard = false | |
| let beard_color = 0xffffff | |
| let show_eyes = true | |
| let eyes_color = 0xff0000 | |
| let show_lips = false | |
| let lips_color = 0xff0000 | |
| let wind_factor = 0 | |
| class Vector { | |
| constructor ( args ) { | |
| this . x = 0 | |
| this . y = 0 | |
| this . z = 0 | |
| if ( args != null ) { | |
| if ( 'x' in args ) this . x = args . x | |
| if ( 'y' in args ) this . y = args . y | |
| if ( 'z' in args ) this . z = args . z | |
| } | |
| } | |
| set_vector ( args ) { | |
| if ( args == null ) return | |
| if ( 'vector' in args ) { | |
| this . x = args . vector . x | |
| this . y = args . vector . y | |
| this . z = args . vector . z | |
| } | |
| } | |
| clone ( args ) { | |
| if ( args == null ) return | |
| if ( 'x' in args ) this . x = args . x | |
| if ( 'y' in args ) this . y = args . y | |
| if ( 'z' in args ) this . z = args . z | |
| } | |
| multiply_scalar ( args ) { | |
| this . x *= args . scalar | |
| this . y *= args . scalar | |
| this . z *= args . scalar | |
| return this | |
| } | |
| reset ( args ) { | |
| this . x = 0 | |
| this . y = 0 | |
| this . z = 0 | |
| } | |
| add ( args ) { | |
| this . x += args . vector . x | |
| this . y += args . vector . y | |
| this . z += args . vector . z | |
| return this | |
| } | |
| subtract ( args ) { | |
| this . x -= args . vector . x | |
| this . y -= args . vector . y | |
| this . z -= args . vector . z | |
| return this | |
| } | |
| length ( args ) { | |
| return Math . sqrt ( this . x * this . x + this . y * this . y + this . z * this . z ) | |
| } | |
| normalize ( args ) { | |
| let length = this . length () | |
| if ( length > 0 ) { | |
| this . x /= length | |
| this . y /= length | |
| this . z /= length | |
| } | |
| return this | |
| } | |
| negate ( args ) { | |
| this . x *= - 1 | |
| this . y *= - 1 | |
| this . z *= - 1 | |
| return this; | |
| } | |
| } | |
| class Rectangle extends Vector { | |
| constructor ( args ) { | |
| super ( args ) | |
| this . width = 0 | |
| this . height = 0 | |
| this . ants = false | |
| this . visible = true | |
| if ( args != null ) { | |
| if ( 'ants' in args ) this . ants = args . ants | |
| if ( 'right' in args ) this . width = args . right - this . x | |
| if ( 'bottom' in args ) this . height = args . bottom - this . y | |
| if ( 'width' in args ) this . width = args . width | |
| if ( 'height' in args ) this . height = args . height | |
| } | |
| } | |
| clone ( args ) { | |
| if ( args == null ) return | |
| super . clone ( args ) | |
| if ( 'width' in args ) this . width = args . width | |
| if ( 'height' in args ) this . height = args . height | |
| if ( 'ants' in args ) this . ants = args . ants | |
| } | |
| get right () { | |
| return this . x + this . width | |
| } | |
| get bottom () { | |
| return this . y + this . height | |
| } | |
| get center_x () { | |
| return this . width / 2 + this . x | |
| } | |
| get center_y () { | |
| return this . height / 2 + this . y | |
| } | |
| set_rectangle ( args ) { | |
| if ( args == null ) return | |
| if ( 'rectangle' in args ) { | |
| super . set_vector ( { vector : args . rectangle } ) | |
| this . width = args . rectangle . width | |
| this . height = args . rectangle . height | |
| this . ants = args . rectangle . ants | |
| } | |
| } | |
| contains ( args ) { | |
| if ( args == null ) return false | |
| let x = null | |
| let y = null | |
| if ( 'x' in args ) x = args . x | |
| if ( 'y' in args ) y = args . y | |
| if ( x == null || y == null ) return false | |
| return x >= this . x && x <= this . x + this . width && | |
| y >= this . y && y <= this . y + this . height | |
| } | |
| draw ( args ) { | |
| if ( ! this . visible ) return | |
| let context = args . context | |
| let ants = this . ants | |
| if ( 'ants' in args ) ants = args . ants | |
| context . lineWidth = 2 | |
| if ( ants ) context . setLineDash ( [ 8 , 4 ] ) | |
| context . strokeStyle = "#000000" | |
| context . strokeRect ( this . x , this . y , this . width , this . height ) | |
| if ( ants ) context . setLineDash ( [] ) | |
| } | |
| } | |
| class Point extends Vector { | |
| constructor ( args ) { | |
| super ( args ) | |
| this . previous_position = new Vector ( { x : this . x , y : this . y } ) | |
| this . acceleration = new Vector () | |
| this . fixed = false | |
| this . visible = true | |
| this . selected = true | |
| if ( args == null ) return | |
| if ( 'acceleration' in args ) this . acceleration = args . acceleration | |
| if ( 'fixed' in args ) this . fixed = args . fixed | |
| if ( 'visible' in args ) this . visible = args . visible | |
| if ( 'selected' in args ) this . selected = args . selected | |
| } | |
| contains ( args ) { | |
| return this . rectangle . contains ( args ) | |
| } | |
| handlepointer_down ( args ) { | |
| if ( ! this . contains ( args ) ) return false | |
| return true | |
| } | |
| get rectangle () { | |
| return new Rectangle ( { x : this . x - Minimal_interface_size / 2 , | |
| y : this . y - Minimal_interface_size / 2 , | |
| width : Minimal_interface_size , | |
| height : Minimal_interface_size } ) | |
| } | |
| clone ( args ) { | |
| super . clone ( args ) | |
| this . previous_position . clone ( args . previous_position ) | |
| this . acceleration = args . acceleration | |
| this . fixed = args . fixed | |
| } | |
| draw ( args ) { | |
| if ( this . selected ) context . setLineDash ( [ 8 , 4 ] ) | |
| context . strokeStyle = "#000000" | |
| context . beginPath () | |
| context . ellipse ( this . x , this . y , Minimal_interface_size / 2 , Minimal_interface_size / 2 , Math . PI / 4 , 0 , 2 * Math . PI ) | |
| context . stroke () | |
| if ( this . selected ) context . setLineDash ( [] ) | |
| } | |
| moveBy ( args ) { | |
| this . x += args . delta_x | |
| this . y += args . delta_y | |
| this . previous_position . x = this . x | |
| this . previous_position . y = this . y | |
| state . constraints . forEach ( constraint => { | |
| constraint . length = Distance ( { from : constraint . point_b , to : constraint . point_a } ) | |
| } ) | |
| } | |
| addForce ( args ) { | |
| this . acceleration . x += args . force . x | |
| this . acceleration . y += args . force . y | |
| } | |
| Do_Physics ( args ) { | |
| if ( this . fixed ) return | |
| const delta = args . delta * args . delta | |
| let x = this . x | |
| let y = this . y | |
| this . acceleration . multiply_scalar ( { scalar : delta } ) | |
| this . x += x - this . previous_position . x + this . acceleration . x | |
| this . y += y - this . previous_position . y + this . acceleration . y | |
| this . acceleration . reset () | |
| this . previous_position . x = x | |
| this . previous_position . y = y | |
| } | |
| check_bounds ( args ) { | |
| this . x = Math . max ( 1 , Math . min ( window_width - 1 , this . x ) ) | |
| this . y = Math . max ( 1 , Math . min ( window_height - 1 , this . y ) ) | |
| if ( this . y >= window_height - 1 ) this . x -= ( this . x - this . previous_position . x + this . acceleration . x ) | |
| } | |
| move ( args ) { | |
| if ( this . fixed ) return | |
| this . add ( { vector : args . vector } ) | |
| } | |
| } | |
| class Constraint { | |
| constructor ( args ) { | |
| this . point_a = null | |
| this . point_b = null | |
| this . length = null | |
| this . elasticity = 0.5 | |
| this . visible = true | |
| this . selected = false | |
| if ( args != null ) { | |
| if ( 'point_a' in args ) this . point_a = args . point_a | |
| if ( 'point_b' in args ) this . point_b = args . point_b | |
| if ( 'length' in args ) this . length = args . length | |
| if ( 'elasticity' in args ) this . elasticity = args . elasticity | |
| if ( 'visible' in args ) this . visible = args . visible | |
| } | |
| if ( this . point_a == null || this . point_b == null ) return | |
| if ( this . length == null ) this . length = Distance ( { from : this . point_a , to : this . point_b } ) | |
| } | |
| draw ( args ) { | |
| context . lineWidth = 10 | |
| if ( this . selected ) context . setLineDash ( [ 8 , 4 ] ) | |
| context . strokeStyle = '#' + args . color . toString ( 16 ) | |
| context . beginPath () | |
| context . moveTo ( this . point_a . x , this . point_a . y ) | |
| context . lineTo ( this . point_b . x , this . point_b . y ) | |
| context . stroke () | |
| if ( this . selected ) context . setLineDash ( [] ) | |
| } | |
| constrain ( args ) { | |
| let dists = new Vector ( { x : this . point_b . x - this . point_a . x , y : this . point_b . y - this . point_a . y } ) | |
| let l = dists . length () | |
| let delta = l - this . length | |
| dists . normalize () | |
| let f = dists . multiply_scalar ( { scalar : delta * this . elasticity } ) | |
| this . point_a . move ( { vector : f } ) | |
| this . point_b . move ( { vector : f . negate () } ) | |
| } | |
| } | |
| class State { | |
| static Instances = [] | |
| constructor ( args ) { | |
| this . root_points = [] | |
| this . points = [] | |
| this . constraints = [] | |
| this . color = 'black' | |
| this . gravity = new Vector () | |
| this . threads = [] | |
| if ( args ) { | |
| if ( 'color' in args ) this . color = args . color | |
| if ( 'gravity' in args ) this . gravity = args . gravity | |
| } | |
| State . Instances . push ( this ) | |
| } | |
| add_threads = args => { | |
| for ( let i = 0 ; i < args . threads_count ; i ++ ) { | |
| const point = new Point ( { fixed : true } ) | |
| const point2 = new Point ( { fixed : false } ) | |
| const point3 = new Point ( { fixed : false } ) | |
| const point4 = new Point ( { fixed : false } ) | |
| this . points . push ( point ) | |
| this . points . push ( point2 ) | |
| this . points . push ( point3 ) | |
| this . points . push ( point4 ) | |
| this . root_points . push ( point ) | |
| this . threads . push ( [ point , point2 , point3 , point4 ] ) | |
| this . constraints . push ( new Constraint ( { point_a : point , point_b : point2 , length : 50 } ) ) | |
| this . constraints . push ( new Constraint ( { point_a : point2 , point_b : point3 , length : 40 } ) ) | |
| this . constraints . push ( new Constraint ( { point_a : point3 , point_b : point4 , length : 30 } ) ) | |
| } | |
| } | |
| } | |
| class Curve extends Vector { | |
| constructor ( args ) { | |
| super ( args ) | |
| this . points = [] | |
| this . control_points = [] | |
| this . closed = false | |
| this . tension = .5 | |
| this . fillStyle = 'blue' | |
| this . strokeStyle = 'black' | |
| this . lineWidth = 5 | |
| if ( args ) { | |
| if ( 'points' in args ) this . points = Array . from ( args . points ) | |
| if ( 'control_points' in args ) this . control_points = Array . from ( args . control_points ) | |
| if ( 'closed' in args ) this . closed = args . closed | |
| if ( 'tension' in args ) this . tension = args . tension | |
| if ( 'fillStyle' in args ) this . fillStyle = args . fillStyle | |
| if ( 'strokeStyle' in args ) this . strokeStyle = args . strokeStyle | |
| if ( 'lineWidth' in args ) this . lineWidth = args . lineWidth | |
| } | |
| if ( this . closed ) { | |
| this . points . push ( this . points [ 0 ] ) | |
| this . points . unshift ( this . points [ this . points . length - 1 ] ) | |
| } | |
| if ( this . control_points . length == 0 ) this . build () | |
| } | |
| build ( args ) { | |
| this . control_points = [] | |
| const n = this . points . length - 2 //this . closed ? this . points . length : this . points . length - 2 | |
| for ( let i = 0 ; i < n ; i ++ ) { | |
| const control_points = this . get_control_points ( { p0 : this . points [ i ] , p1 : this . points [ i + 1 ] , p2 : this . points [ i + 2 ] , tension : this . tension } ) | |
| this . control_points . push ( control_points [ 0 ] , control_points [ 1 ] ) | |
| } | |
| } | |
| get_control_points ( args ) { | |
| const d01 = Math . sqrt ( Math . pow ( args . p1 . x - args . p0 . x , 2 ) + Math . pow ( args . p1 . y - args . p0 . y , 2 ) ) | |
| const d12 = Math . sqrt ( Math . pow ( args . p2 . x - args . p1 . x , 2 ) + Math . pow ( args . p2 . y - args . p1 . y , 2 ) ) | |
| const fa = args . tension * d01 / ( d01 + d12 ) | |
| const fb = args . tension - fa | |
| const c1 = new Vector ( { x : args . p1 . x + fa * ( args . p0 . x - args . p2 . x ) , y : args . p1 . y + fa * ( args . p0 . y - args . p2 . y ) } ) | |
| const c2 = new Vector ( { x : args . p1 . x - fb * ( args . p0 . x - args . p2 . x ) , y : args . p1 . y - fb * ( args . p0 . y - args . p2 . y ) } ) | |
| return [ c1 , c2 ] | |
| } | |
| draw ( args ) { | |
| context . fillStyle = this . fillStyle | |
| context . strokeStyle = this . strokeStyle | |
| context . lineWidth = this . lineWidth | |
| if ( this . closed ) { | |
| context . beginPath () | |
| context . moveTo ( this . points [ 0 ] . x , this . points [ 0 ] . y ) | |
| for ( var i = 1 ; i < this . points . length ; i ++ ) | |
| context . bezierCurveTo ( | |
| this . control_points [ i * 2 - 1 ] . x , | |
| this . control_points [ i * 2 - 1 ] . y , | |
| this . control_points [ i * 2 ] . x , | |
| this . control_points [ i * 2 ] . y , | |
| this . points [ i ] . x , | |
| this . points [ i ] . y ) | |
| context . bezierCurveTo ( | |
| this . control_points [ this . control_points . length - 1 ] . x , | |
| this . control_points [ this . control_points . length - 1 ] . y , | |
| this . control_points [ 0 ] . x , | |
| this . control_points [ 0 ] . y , | |
| this . points [ 0 ] . x , | |
| this . points [ 0 ] . y ) | |
| context . fill () | |
| context . stroke () | |
| } else { | |
| context . beginPath () | |
| context . moveTo ( this . points [ 0 ] . x , this . points [ 0 ] . y ) | |
| context . quadraticCurveTo ( | |
| this . control_points [ 0 ] . x , | |
| this . control_points [ 0 ] . y , | |
| this . points [ 1 ] . x , | |
| this . points [ 1 ] . y ) | |
| for ( var i = 0 ; i < this . points . length - 3 ; i ++ ) | |
| context . bezierCurveTo ( | |
| this . control_points [ i * 2 + 1 ] . x , | |
| this . control_points [ i * 2 + 1 ] . y , | |
| this . control_points [ i * 2 + 2 ] . x , | |
| this . control_points [ i * 2 + 2 ] . y , | |
| this . points [ i + 2 ] . x , | |
| this . points [ i + 2 ] . y ) | |
| var n = this . control_points . length | |
| context . quadraticCurveTo ( | |
| this . control_points [ this . control_points . length - 1 ] . x , | |
| this . control_points [ this . control_points . length - 1 ] . y , | |
| this . points [ this . points . length - 1 ] . x , | |
| this . points [ this . points . length - 1 ] . y ) | |
| context . stroke () | |
| } | |
| } | |
| } | |
| const Hex_to_color = args => { | |
| const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i . exec ( args . hex ) | |
| return result ? | |
| parseInt ( result [ 1 ] , 16 ) * 256 * 256 + | |
| parseInt ( result [ 2 ] , 16 ) * 256 + | |
| parseInt ( result [ 3 ] , 16 ) | |
| : null | |
| } | |
| const Flip_x_switch_change = element => { | |
| flip_x = ! flip_x | |
| } | |
| const Flip_y_switch_change = element => { | |
| flip_y = ! flip_y | |
| } | |
| const Eyes_switch_change = element => { | |
| show_eyes = ! show_eyes | |
| } | |
| const Lips_switch_change = element => { | |
| show_lips = ! show_lips | |
| } | |
| const Hair_switch_change = element => { | |
| show_hair = ! show_hair | |
| } | |
| const Beard_switch_change = element => { | |
| show_beard = ! show_beard | |
| } | |
| const Mask_switch_change = element => { | |
| show_mask = ! show_mask | |
| } | |
| const Drag_element = element => { | |
| tearable_elements . push ( element . parentElement ) | |
| } | |
| const Pointer_down = args => { | |
| if ( args . event . target == canvas ) { | |
| if ( tools_window . style . display == 'none' ) tools_window . style . display = 'block' | |
| else tools_window . style . display = 'none' | |
| } | |
| } | |
| const Pointer_move = args => { | |
| for ( const drag_element of tearable_elements ) { | |
| drag_element . style . left = drag_element . offsetLeft + delta_mouse . x + 'px' | |
| drag_element . style . top = drag_element . offsetTop + delta_mouse . y + 'px' | |
| } | |
| } | |
| const Pointer_up = args => { | |
| tearable_elements = [] | |
| } | |
| const Do_Physics = args => { | |
| //if ( ! play ) return | |
| //return | |
| for ( const state of State . Instances ) { | |
| for ( let iteration = 0 ; iteration < Number_of_iterations ; iteration ++ ) { | |
| state . points . forEach ( point => { | |
| point . addForce ( { force : state . gravity } ) | |
| point . addForce ( { force : { x : Math . random () * wind_factor , y : 0 } } ) | |
| point . Do_Physics ( { delta : 1 / Number_of_iterations } ) | |
| //point . check_bounds ( ) | |
| } ) | |
| state . constraints . forEach ( constraint => { | |
| constraint . constrain () | |
| } ) | |
| } | |
| } | |
| } | |
| const Distance = args => { | |
| let from = null | |
| let to = null | |
| if ( args == null ) return 0 | |
| if ( 'from' in args ) from = args . from | |
| if ( 'to' in args ) to = args . to | |
| if ( from == null || to == null ) return 0 | |
| let dx = to . x - from . x | |
| let dy = to . y - from . y | |
| return Math . sqrt ( dx * dx + dy * dy ) | |
| } | |
| const Switch_camera = args => { | |
| constraints . video . facingMode = constraints . video . facingMode == 'user' ? 'environment' : 'user' | |
| Open_camera () | |
| } | |
| const Get_media_stream = async args => { | |
| try { | |
| mediaStream = await navigator . mediaDevices . getUserMedia ( constraints ) | |
| video . srcObject = mediaStream | |
| video . onloadedmetadata = event => { | |
| video . play () | |
| } | |
| } catch ( err ) { | |
| alert ( err . message ) | |
| } | |
| } | |
| const Open_camera = async element => { | |
| try { | |
| if ( mediaStream != null && mediaStream . active ) { | |
| const tracks = mediaStream . getVideoTracks () | |
| tracks . forEach ( track => { | |
| track . stop () | |
| }) | |
| } | |
| video . srcObject = null | |
| await Get_media_stream () | |
| } catch ( err ) { | |
| alert ( err . message ) | |
| } | |
| } | |
| const Draw = async args => { | |
| const now = performance . now () | |
| if ( video == null ) return | |
| frame_canvas . width = video . videoWidth | |
| frame_canvas . height = video . videoHeight | |
| if ( frame_canvas . width == 0 || frame_canvas . height == 0 ) return | |
| frame_context . save () | |
| if ( flip_x && flip_y ) { | |
| frame_context . translate ( frame_canvas . width , frame_canvas . height ) | |
| frame_context . scale ( - 1 , - 1 ) | |
| } else if ( flip_x ) { | |
| frame_context . translate ( frame_canvas . width , 0 ) | |
| frame_context . scale ( - 1 , 1 ) | |
| } else if ( flip_y ) { | |
| frame_context . translate ( 0 , frame_canvas . height ) | |
| frame_context . scale ( 1 , - 1 ) | |
| } | |
| frame_context . drawImage ( video , 0 , 0 ) | |
| frame_context . restore () | |
| let factor = Math . max ( frame_canvas . width / canvas . width , frame_canvas . height / canvas . height ) | |
| const w = frame_canvas . width / factor | |
| const h = frame_canvas . height / factor | |
| scaled_canvas . width = w | |
| scaled_canvas . height = h | |
| scaled_context . drawImage ( frame_canvas , 0 , 0 , frame_canvas . width , frame_canvas . height , 0 , 0 , w , h ) | |
| const faces = await model . estimateFaces ( { input : scaled_canvas } ) | |
| if ( throbber_div . style . display != 'none' ) throbber_div . style . display = 'none' | |
| context . clearRect ( 0 , 0 , canvas . width , canvas . height ) | |
| context . drawImage ( scaled_canvas , 0 , 0 ) | |
| const Draw_polygon = args => { | |
| let first = true | |
| for ( let xy of args . polygon ) { | |
| if ( first ) { | |
| first = false | |
| context . moveTo ( xy [ 0 ] , xy [ 1 ] ) | |
| } else context . lineTo ( xy [ 0 ] , xy [ 1 ] ) | |
| } | |
| context . closePath () | |
| } | |
| for ( let face of faces ) { | |
| if ( show_eyes ) { | |
| const Draw_iris = args => { | |
| const radius = Math . abs ( Math . max ( args . iris [ 3 ][ 0 ] - args . iris [ 1 ][ 0 ] , args . iris [ 4 ][ 1 ] - args . iris [ 2 ][ 1 ] ) )/ 2 | |
| context . arc ( args . iris [ 0 ][ 0 ] , args . iris [ 0 ][ 1 ] , radius , 0 , 2 * Math . PI ) | |
| } | |
| context . fillStyle = '#' + eyes_color . toString ( 16 ) | |
| context . globalAlpha = .25 | |
| context . beginPath () | |
| Draw_iris ( { iris : face . annotations . leftEyeIris } ) | |
| Draw_iris ( { iris : face . annotations . rightEyeIris } ) | |
| context . fill () | |
| context . globalAlpha = 1 | |
| context . save () | |
| context . beginPath () | |
| Draw_polygon ( { polygon : face . annotations . leftEyeUpper1 } ) | |
| Draw_polygon ( { polygon : face . annotations . leftEyeLower3 } ) | |
| Draw_polygon ( { polygon : face . annotations . rightEyeUpper1 } ) | |
| Draw_polygon ( { polygon : face . annotations . rightEyeLower3 } ) | |
| context . clip () | |
| context . drawImage ( scaled_canvas , 0 , 0 ) | |
| context . restore () | |
| } | |
| if ( show_lips ) { | |
| let outer_lip = Array . from ( face . annotations . lipsLowerOuter ) | |
| outer_lip . pop () | |
| outer_lip = outer_lip . concat ( face . annotations . lipsUpperOuter . reverse () ) | |
| outer_lip . push ( outer_lip [ 0 ] ) | |
| let inner_lip = Array . from ( face . annotations . lipsLowerInner ) | |
| inner_lip . pop () | |
| inner_lip = inner_lip . concat ( face . annotations . lipsUpperInner . reverse () ) | |
| inner_lip . push ( inner_lip [ 0 ] ) | |
| context . fillStyle = '#' + lips_color . toString ( 16 ) | |
| context . globalAlpha = .25 | |
| context . beginPath () | |
| Draw_polygon ( { polygon : outer_lip } ) | |
| Draw_polygon ( { polygon : inner_lip } ) | |
| context . fill ( 'evenodd' ) | |
| context . globalAlpha = 1 | |
| } | |
| if ( show_mask ) { | |
| context . strokeStyle = 'white' | |
| context . globalAlpha = .25 | |
| context . lineWidth = 1 | |
| for ( let tis of Triangle_indexes ) { | |
| context . beginPath () | |
| context . moveTo ( face . scaledMesh [ tis [ 0 ] ] [ 0 ] , face . scaledMesh [ tis [ 0 ] ] [ 1 ] ) | |
| context . lineTo ( face . scaledMesh [ tis [ 1 ] ] [ 0 ] , face . scaledMesh [ tis [ 1 ] ] [ 1 ] ) | |
| context . lineTo ( face . scaledMesh [ tis [ 2 ] ] [ 0 ] , face . scaledMesh [ tis [ 2 ] ] [ 1 ] ) | |
| context . lineTo ( face . scaledMesh [ tis [ 0 ] ] [ 0 ] , face . scaledMesh [ tis [ 0 ] ] [ 1 ] ) | |
| context . stroke () | |
| } | |
| context . fillStyle = 'white' | |
| for ( let xy of face . scaledMesh ) { | |
| context . fillRect ( xy [ 0 ] - 3 , xy [ 1 ] - 3 , 6 , 6 ) | |
| } | |
| context . globalAlpha = 1 | |
| } | |
| if ( show_hair ) { | |
| if ( ! hair_state ) { | |
| hair_state = new State ( { color : hair_color , gravity : antigravity } ) | |
| hair_state . add_threads ( { threads_count : Hair_indexes . length } ) | |
| } | |
| let i = 0 | |
| for ( let index of Hair_indexes ) { | |
| const point = hair_state . root_points [ i ++ ] | |
| const vector = new Vector ( { x : face . scaledMesh [ index ] [ 0 ] , y : face . scaledMesh [ index ] [ 1 ] , z : face . scaledMesh [ index ] [ 2 ] } ) | |
| point . set_vector ( { vector : vector } ) | |
| } | |
| for ( const thread of hair_state . threads ) { | |
| const points = [] | |
| for ( const point of thread ) { | |
| points . push ( point ) | |
| } | |
| const curve = new Curve ( { strokeStyle : '#' + hair_color . toString ( 16 ) , points : points } ) . draw () | |
| } | |
| } | |
| if ( show_beard ) { | |
| if ( ! beard_state ) { | |
| beard_state = new State ( { color : beard_color , gravity : gravity } ) | |
| beard_state . add_threads ( { threads_count : Beard_indexes . length } ) | |
| } | |
| let i = 0 | |
| for ( let index of Beard_indexes ) { | |
| const point = beard_state . root_points [ i ++ ] | |
| const vector = new Vector ( { x : face . scaledMesh [ index ] [ 0 ] , y : face . scaledMesh [ index ] [ 1 ] , z : face . scaledMesh [ index ] [ 2 ] } ) | |
| point . set_vector ( { vector : vector } ) | |
| } | |
| for ( const thread of beard_state . threads ) { | |
| const points = [] | |
| for ( const point of thread ) { | |
| points . push ( point ) | |
| } | |
| const curve = new Curve ( { strokeStyle : '#' + beard_color . toString ( 16 ) , points : points } ) . draw () | |
| } | |
| } | |
| } | |
| { // update the fps label | |
| const delta = now - start | |
| if ( start == 0 || delta > 5000 ) { | |
| start = now | |
| nof = 0 | |
| } | |
| fps_label . innerHTML = Math . floor ( nof ++ * 1000 / delta ) | |
| } | |
| // requestAnimationFrame ( Draw ) | |
| } | |
| const Tik = args => { | |
| Do_Physics () | |
| Draw () | |
| } | |
| const Load_file = args => { | |
| let filename = args . file . name | |
| let splits = filename . split ( '.' ) | |
| let extension = splits . pop () . toLowerCase () | |
| let name = splits . pop () . split ( '/' ) . pop () | |
| let fileReader = new FileReader () | |
| fileReader . filename_name = name | |
| fileReader . onload = function ( event ) { | |
| let base_64 = event . target . result | |
| if ( base_64 . startsWith ( 'data:image/' ) ) { | |
| img = document . createElement ( 'img' ) | |
| img . addEventListener ( 'load' , function ( event ) { | |
| image = img | |
| } ) | |
| img . src = base_64 | |
| } else if ( base_64 . startsWith ( 'data:video/' ) ) { | |
| body_max_dx = 0 | |
| video = document . createElement ( 'video' ) | |
| video . muted = true | |
| video . autoplay = false | |
| video . controls = true | |
| video . oncanplaythrough = () => { | |
| frame_canvas . width = video . videoWidth | |
| frame_canvas . height = video . videoHeight | |
| video . play () | |
| }; | |
| video . onended = () => { | |
| video . play () | |
| } | |
| video . src = base_64 | |
| } | |
| } | |
| fileReader . readAsDataURL ( args . file ) | |
| } | |
| const Load_files = args => { | |
| for ( let i = 0 ; i < args . files . length ; i ++ ) | |
| Load_file ( { at : Pointers . position , file : args . files [ i ] } ) | |
| } | |
| const Allow_drop = event => { | |
| event . preventDefault () | |
| } | |
| const Drop = event => { | |
| event . preventDefault () | |
| if ( event . dataTransfer . items ) | |
| for ( let i = 0 ; i < event . dataTransfer . items . length ; i++ ) { | |
| if ( event . dataTransfer . items [ i ] .kind === 'file' ) | |
| Load_file ( { file : event . dataTransfer . items [ i ] . getAsFile () } ) | |
| } | |
| else | |
| Load_files ( { files : event . dataTransfer . files } ) | |
| } | |
| const Main = async args => { | |
| file_button = document . createElement ( 'input' ) | |
| file_button . type = 'file' | |
| document . ondrop = Drop | |
| document . ondragover = Allow_drop | |
| canvas = document . createElement ( 'canvas' ) | |
| canvas . width = window . innerWidth | |
| canvas . height = window . innerHeight | |
| context = canvas . getContext ( '2d' ) | |
| document . body . appendChild ( canvas ) | |
| frame_canvas = document . createElement ( 'canvas' ) | |
| frame_context = frame_canvas . getContext ( '2d' ) | |
| scaled_canvas = document . createElement ( 'canvas' ) | |
| scaled_context = scaled_canvas . getContext ( '2d' ) | |
| video = document . createElement ( 'video' ) | |
| video . muted = true | |
| video . setAttribute ( "playsinline" , "true" ) | |
| Open_camera () | |
| model = await faceLandmarksDetection . load () | |
| antigravity = new Vector ( { x : 0 , y : - 10 } ) | |
| gravity = new Vector ( { x : 0 , y : 10 } ) | |
| state = new State () | |
| window . addEventListener ( 'pointerdown' , event => { | |
| mouse = { x : event . x , y : event . y } | |
| delta_mouse = { x : mouse . x - old_mouse . x , y : mouse . y - old_mouse . y } | |
| old_mouse = { x : mouse . x , y : mouse . y } | |
| Pointer_down ( { event : event } ) | |
| } ) | |
| window . addEventListener ( 'touchstart' , event => { | |
| //event . preventDefault () | |
| mouse = { x : event . touches [ 0 ] . clientX , y : event . touches [ 0 ] . clientY } | |
| delta_mouse = { x : mouse . x - old_mouse . x , y : mouse . y - old_mouse . y } | |
| old_mouse = { x : mouse . x , y : mouse . y } | |
| Pointer_down ( { event : event } ) | |
| } ) | |
| window . addEventListener ( 'pointermove' , event => { | |
| mouse = { x : event . x , y : event . y } | |
| delta_mouse = { x : mouse . x - old_mouse . x , y : mouse . y - old_mouse . y } | |
| Pointer_move ( { event : event } ) | |
| old_mouse = { x : mouse . x , y : mouse . y } | |
| } ) | |
| window . addEventListener ( 'touchmove' , event => { | |
| //event . preventDefault () | |
| mouse = { x : event . touches [ 0 ] . clientX , y : event . touches [ 0 ] . clientY } | |
| delta_mouse = { x : mouse . x - old_mouse . x , y : mouse . y - old_mouse . y } | |
| Pointer_move ( { event : event } ) | |
| old_mouse = { x : mouse . x , y : mouse . y } | |
| } ) | |
| window . addEventListener ( 'pointerup' , event => { | |
| Pointer_up ( { event : event } ) | |
| } ) | |
| window . addEventListener ( 'touchend' , event => { | |
| //event . preventDefault () | |
| Pointer_up ( { event : event } ) | |
| } ) | |
| eyes_color_input . addEventListener ( 'input' , event => { eyes_color = Hex_to_color ( { hex : event . target . value } ) } ) | |
| lips_color_input . addEventListener ( 'input' , event => { lips_color = Hex_to_color ( { hex : event . target . value } ) } ) | |
| hair_color_input . addEventListener ( 'input' , event => { hair_color = Hex_to_color ( { hex : event . target . value } ) } ) | |
| beard_color_input . addEventListener ( 'input' , event => { beard_color = Hex_to_color ( { hex : event . target . value } ) } ) | |
| wind_of_the_west_slider . oninput = args => { | |
| wind_factor = wind_of_the_west_slider . value | |
| } | |
| setInterval ( Tik , 33 ) | |
| //Draw () | |
| } | |
| </script> | |
| <script src = './tfjs.js'></script> | |
| <script src = './tf-backend-wasm.js'></script> | |
| <script src = './face-landmarks-detection.js'></script> | |
| <script> | |
| const Triangle_indexes = [ | |
| [127, 34, 139], | |
| [ 11, 0, 37], | |
| [232, 231, 120], | |
| [ 72, 37, 39], | |
| [128, 121, 47], | |
| [232, 121, 128], | |
| [104, 69, 67], | |
| [175, 171, 148], | |
| [118, 50, 101], | |
| [ 73, 39, 40], | |
| [ 9, 151, 108], | |
| [ 48, 115, 131], | |
| [194, 204, 211], | |
| [ 74, 40, 185], | |
| [ 80, 42, 183], | |
| [ 40, 92, 186], | |
| [230, 229, 118], | |
| [202, 212, 214], | |
| [ 83, 18, 17], | |
| [ 76, 61, 146], | |
| [160, 29, 30], | |
| [ 56, 157, 173], | |
| [106, 204, 194], | |
| [135, 214, 192], | |
| [203, 165, 98], | |
| [ 21, 71, 68], | |
| [ 51, 45, 4], | |
| [144, 24, 23], | |
| [ 77, 146, 91], | |
| [205, 50, 187], | |
| [201, 200, 18], | |
| [ 91, 106, 182], | |
| [ 90, 91, 181], | |
| [ 85, 84, 17], | |
| [206, 203, 36], | |
| [148, 171, 140], | |
| [ 92, 40, 39], | |
| [193, 189, 244], | |
| [159, 158, 28], | |
| [247, 246, 161], | |
| [236, 3, 196], | |
| [ 54, 68, 104], | |
| [193, 168, 8], | |
| [117, 228, 31], | |
| [189, 193, 55], | |
| [ 98, 97, 99], | |
| [126, 47, 100], | |
| [166, 79, 218], | |
| [155, 154, 26], | |
| [209, 49, 131], | |
| [135, 136, 150], | |
| [ 47, 126, 217], | |
| [223, 52, 53], | |
| [ 45, 51, 134], | |
| [211, 170, 140], | |
| [ 67, 69, 108], | |
| [ 43, 106, 91], | |
| [230, 119, 120], | |
| [226, 130, 247], | |
| [ 63, 53, 52], | |
| [238, 20, 242], | |
| [ 46, 70, 156], | |
| [ 78, 62, 96], | |
| [ 46, 53, 63], | |
| [143, 34, 227], | |
| [123, 117, 111], | |
| [ 44, 125, 19], | |
| [236, 134, 51], | |
| [216, 206, 205], | |
| [154, 153, 22], | |
| [ 39, 37, 167], | |
| [200, 201, 208], | |
| [ 36, 142, 100], | |
| [ 57, 212, 202], | |
| [ 20, 60, 99], | |
| [ 28, 158, 157], | |
| [ 35, 226, 113], | |
| [160, 159, 27], | |
| [204, 202, 210], | |
| [113, 225, 46], | |
| [ 43, 202, 204], | |
| [ 62, 76, 77], | |
| [137, 123, 116], | |
| [ 41, 38, 72], | |
| [203, 129, 142], | |
| [ 64, 98, 240], | |
| [ 49, 102, 64], | |
| [ 41, 73, 74], | |
| [212, 216, 207], | |
| [ 42, 74, 184], | |
| [169, 170, 211], | |
| [170, 149, 176], | |
| [105, 66, 69], | |
| [122, 6, 168], | |
| [123, 147, 187], | |
| [ 96, 77, 90], | |
| [ 65, 55, 107], | |
| [ 89, 90, 180], | |
| [101, 100, 120], | |
| [ 63, 105, 104], | |
| [ 93, 137, 227], | |
| [ 15, 86, 85], | |
| [129, 102, 49], | |
| [ 14, 87, 86], | |
| [ 55, 8, 9], | |
| [100, 47, 121], | |
| [145, 23, 22], | |
| [ 88, 89, 179], | |
| [ 6, 122, 196], | |
| [ 88, 95, 96], | |
| [138, 172, 136], | |
| [215, 58, 172], | |
| [115, 48, 219], | |
| [ 42, 80, 81], | |
| [195, 3, 51], | |
| [ 43, 146, 61], | |
| [171, 175, 199], | |
| [ 81, 82, 38], | |
| [ 53, 46, 225], | |
| [144, 163, 110], | |
| [ 52, 65, 66], | |
| [229, 228, 117], | |
| [ 34, 127, 234], | |
| [107, 108, 69], | |
| [109, 108, 151], | |
| [ 48, 64, 235], | |
| [ 62, 78, 191], | |
| [129, 209, 126], | |
| [111, 35, 143], | |
| [117, 123, 50], | |
| [222, 65, 52], | |
| [ 19, 125, 141], | |
| [221, 55, 65], | |
| [ 3, 195, 197], | |
| [ 25, 7, 33], | |
| [220, 237, 44], | |
| [ 70, 71, 139], | |
| [122, 193, 245], | |
| [247, 130, 33], | |
| [ 71, 21, 162], | |
| [170, 169, 150], | |
| [188, 174, 196], | |
| [216, 186, 92], | |
| [ 2, 97, 167], | |
| [141, 125, 241], | |
| [164, 167, 37], | |
| [ 72, 38, 12], | |
| [ 38, 82, 13], | |
| [ 63, 68, 71], | |
| [226, 35, 111], | |
| [101, 50, 205], | |
| [206, 92, 165], | |
| [209, 198, 217], | |
| [165, 167, 97], | |
| [220, 115, 218], | |
| [133, 112, 243], | |
| [239, 238, 241], | |
| [214, 135, 169], | |
| [190, 173, 133], | |
| [171, 208, 32], | |
| [125, 44, 237], | |
| [ 86, 87, 178], | |
| [ 85, 86, 179], | |
| [ 84, 85, 180], | |
| [ 83, 84, 181], | |
| [201, 83, 182], | |
| [137, 93, 132], | |
| [ 76, 62, 183], | |
| [ 61, 76, 184], | |
| [ 57, 61, 185], | |
| [212, 57, 186], | |
| [214, 207, 187], | |
| [ 34, 143, 156], | |
| [ 79, 239, 237], | |
| [123, 137, 177], | |
| [ 44, 1, 4], | |
| [201, 194, 32], | |
| [ 64, 102, 129], | |
| [213, 215, 138], | |
| [ 59, 166, 219], | |
| [242, 99, 97], | |
| [ 2, 94, 141], | |
| [ 75, 59, 235], | |
| [ 24, 110, 228], | |
| [ 25, 130, 226], | |
| [ 23, 24, 229], | |
| [ 22, 23, 230], | |
| [ 26, 22, 231], | |
| [112, 26, 232], | |
| [189, 190, 243], | |
| [221, 56, 190], | |
| [ 28, 56, 221], | |
| [ 27, 28, 222], | |
| [ 29, 27, 223], | |
| [ 30, 29, 224], | |
| [247, 30, 225], | |
| [238, 79, 20], | |
| [166, 59, 75], | |
| [ 60, 75, 240], | |
| [147, 177, 215], | |
| [ 20, 79, 166], | |
| [187, 147, 213], | |
| [112, 233, 244], | |
| [233, 128, 245], | |
| [128, 114, 188], | |
| [114, 217, 174], | |
| [131, 115, 220], | |
| [217, 198, 236], | |
| [198, 131, 134], | |
| [177, 132, 58], | |
| [143, 35, 124], | |
| [110, 163, 7], | |
| [228, 110, 25], | |
| [356, 389, 368], | |
| [ 11, 302, 267], | |
| [452, 350, 349], | |
| [302, 303, 269], | |
| [357, 343, 277], | |
| [452, 453, 357], | |
| [333, 332, 297], | |
| [175, 152, 377], | |
| [347, 348, 330], | |
| [303, 304, 270], | |
| [ 9, 336, 337], | |
| [278, 279, 360], | |
| [418, 262, 431], | |
| [304, 408, 409], | |
| [310, 415, 407], | |
| [270, 409, 410], | |
| [450, 348, 347], | |
| [422, 430, 434], | |
| [313, 314, 17], | |
| [306, 307, 375], | |
| [387, 388, 260], | |
| [286, 414, 398], | |
| [335, 406, 418], | |
| [364, 367, 416], | |
| [423, 358, 327], | |
| [251, 284, 298], | |
| [281, 5, 4], | |
| [373, 374, 253], | |
| [307, 320, 321], | |
| [425, 427, 411], | |
| [421, 313, 18], | |
| [321, 405, 406], | |
| [320, 404, 405], | |
| [315, 16, 17], | |
| [426, 425, 266], | |
| [377, 400, 369], | |
| [322, 391, 269], | |
| [417, 465, 464], | |
| [386, 257, 258], | |
| [466, 260, 388], | |
| [456, 399, 419], | |
| [284, 332, 333], | |
| [417, 285, 8], | |
| [346, 340, 261], | |
| [413, 441, 285], | |
| [327, 460, 328], | |
| [355, 371, 329], | |
| [392, 439, 438], | |
| [382, 341, 256], | |
| [429, 420, 360], | |
| [364, 394, 379], | |
| [277, 343, 437], | |
| [443, 444, 283], | |
| [275, 440, 363], | |
| [431, 262, 369], | |
| [297, 338, 337], | |
| [273, 375, 321], | |
| [450, 451, 349], | |
| [446, 342, 467], | |
| [293, 334, 282], | |
| [458, 461, 462], | |
| [276, 353, 383], | |
| [308, 324, 325], | |
| [276, 300, 293], | |
| [372, 345, 447], | |
| [352, 345, 340], | |
| [274, 1, 19], | |
| [456, 248, 281], | |
| [436, 427, 425], | |
| [381, 256, 252], | |
| [269, 391, 393], | |
| [200, 199, 428], | |
| [266, 330, 329], | |
| [287, 273, 422], | |
| [250, 462, 328], | |
| [258, 286, 384], | |
| [265, 353, 342], | |
| [387, 259, 257], | |
| [424, 431, 430], | |
| [342, 353, 276], | |
| [273, 335, 424], | |
| [292, 325, 307], | |
| [366, 447, 345], | |
| [271, 303, 302], | |
| [423, 266, 371], | |
| [294, 455, 460], | |
| [279, 278, 294], | |
| [271, 272, 304], | |
| [432, 434, 427], | |
| [272, 407, 408], | |
| [394, 430, 431], | |
| [395, 369, 400], | |
| [334, 333, 299], | |
| [351, 417, 168], | |
| [352, 280, 411], | |
| [325, 319, 320], | |
| [295, 296, 336], | |
| [319, 403, 404], | |
| [330, 348, 349], | |
| [293, 298, 333], | |
| [323, 454, 447], | |
| [ 15, 16, 315], | |
| [358, 429, 279], | |
| [ 14, 15, 316], | |
| [285, 336, 9], | |
| [329, 349, 350], | |
| [374, 380, 252], | |
| [318, 402, 403], | |
| [ 6, 197, 419], | |
| [318, 319, 325], | |
| [367, 364, 365], | |
| [435, 367, 397], | |
| [344, 438, 439], | |
| [272, 271, 311], | |
| [195, 5, 281], | |
| [273, 287, 291], | |
| [396, 428, 199], | |
| [311, 271, 268], | |
| [283, 444, 445], | |
| [373, 254, 339], | |
| [282, 334, 296], | |
| [449, 347, 346], | |
| [264, 447, 454], | |
| [336, 296, 299], | |
| [338, 10, 151], | |
| [278, 439, 455], | |
| [292, 407, 415], | |
| [358, 371, 355], | |
| [340, 345, 372], | |
| [346, 347, 280], | |
| [442, 443, 282], | |
| [ 19, 94, 370], | |
| [441, 442, 295], | |
| [248, 419, 197], | |
| [263, 255, 359], | |
| [440, 275, 274], | |
| [300, 383, 368], | |
| [351, 412, 465], | |
| [263, 467, 466], | |
| [301, 368, 389], | |
| [395, 378, 379], | |
| [412, 351, 419], | |
| [436, 426, 322], | |
| [ 2, 164, 393], | |
| [370, 462, 461], | |
| [164, 0, 267], | |
| [302, 11, 12], | |
| [268, 12, 13], | |
| [293, 300, 301], | |
| [446, 261, 340], | |
| [330, 266, 425], | |
| [426, 423, 391], | |
| [429, 355, 437], | |
| [391, 327, 326], | |
| [440, 457, 438], | |
| [341, 382, 362], | |
| [459, 457, 461], | |
| [434, 430, 394], | |
| [414, 463, 362], | |
| [396, 369, 262], | |
| [354, 461, 457], | |
| [316, 403, 402], | |
| [315, 404, 403], | |
| [314, 405, 404], | |
| [313, 406, 405], | |
| [421, 418, 406], | |
| [366, 401, 361], | |
| [306, 408, 407], | |
| [291, 409, 408], | |
| [287, 410, 409], | |
| [432, 436, 410], | |
| [434, 416, 411], | |
| [264, 368, 383], | |
| [309, 438, 457], | |
| [352, 376, 401], | |
| [274, 275, 4], | |
| [421, 428, 262], | |
| [294, 327, 358], | |
| [433, 416, 367], | |
| [289, 455, 439], | |
| [462, 370, 326], | |
| [ 2, 326, 370], | |
| [305, 460, 455], | |
| [254, 449, 448], | |
| [255, 261, 446], | |
| [253, 450, 449], | |
| [252, 451, 450], | |
| [256, 452, 451], | |
| [341, 453, 452], | |
| [413, 464, 463], | |
| [441, 413, 414], | |
| [258, 442, 441], | |
| [257, 443, 442], | |
| [259, 444, 443], | |
| [260, 445, 444], | |
| [467, 342, 445], | |
| [459, 458, 250], | |
| [289, 392, 290], | |
| [290, 328, 460], | |
| [376, 433, 435], | |
| [250, 290, 392], | |
| [411, 416, 433], | |
| [341, 463, 464], | |
| [453, 464, 465], | |
| [357, 465, 412], | |
| [343, 412, 399], | |
| [360, 363, 440], | |
| [437, 399, 456], | |
| [420, 456, 363], | |
| [401, 435, 288], | |
| [372, 383, 353], | |
| [339, 255, 249], | |
| [448, 261, 255], | |
| [133, 243, 190], | |
| [133, 155, 112], | |
| [ 33, 246, 247], | |
| [ 33, 130, 25], | |
| [398, 384, 286], | |
| [362, 398, 414], | |
| [362, 463, 341], | |
| [263, 359, 467], | |
| [263, 249, 255], | |
| [466, 467, 260], | |
| [ 75, 60, 166], | |
| [238, 239, 79], | |
| [162, 127, 139], | |
| [ 72, 11, 37], | |
| [121, 232, 120], | |
| [ 73, 72, 39], | |
| [114, 128, 47], | |
| [233, 232, 128], | |
| [103, 104, 67], | |
| [152, 175, 148], | |
| [119, 118, 101], | |
| [ 74, 73, 40], | |
| [107, 9, 108], | |
| [ 49, 48, 131], | |
| [ 32, 194, 211], | |
| [184, 74, 185], | |
| [191, 80, 183], | |
| [185, 40, 186], | |
| [119, 230, 118], | |
| [210, 202, 214], | |
| [ 84, 83, 17], | |
| [ 77, 76, 146], | |
| [161, 160, 30], | |
| [190, 56, 173], | |
| [182, 106, 194], | |
| [138, 135, 192], | |
| [129, 203, 98], | |
| [ 54, 21, 68], | |
| [ 5, 51, 4], | |
| [145, 144, 23], | |
| [ 90, 77, 91], | |
| [207, 205, 187], | |
| [ 83, 201, 18], | |
| [181, 91, 182], | |
| [180, 90, 181], | |
| [ 16, 85, 17], | |
| [205, 206, 36], | |
| [176, 148, 140], | |
| [165, 92, 39], | |
| [245, 193, 244], | |
| [ 27, 159, 28], | |
| [ 30, 247, 161], | |
| [174, 236, 196], | |
| [103, 54, 104], | |
| [ 55, 193, 8], | |
| [111, 117, 31], | |
| [221, 189, 55], | |
| [240, 98, 99], | |
| [142, 126, 100], | |
| [219, 166, 218], | |
| [112, 155, 26], | |
| [198, 209, 131], | |
| [169, 135, 150], | |
| [114, 47, 217], | |
| [224, 223, 53], | |
| [220, 45, 134], | |
| [ 32, 211, 140], | |
| [109, 67, 108], | |
| [146, 43, 91], | |
| [231, 230, 120], | |
| [113, 226, 247], | |
| [105, 63, 52], | |
| [241, 238, 242], | |
| [124, 46, 156], | |
| [ 95, 78, 96], | |
| [ 70, 46, 63], | |
| [116, 143, 227], | |
| [116, 123, 111], | |
| [ 1, 44, 19], | |
| [ 3, 236, 51], | |
| [207, 216, 205], | |
| [ 26, 154, 22], | |
| [165, 39, 167], | |
| [199, 200, 208], | |
| [101, 36, 100], | |
| [ 43, 57, 202], | |
| [242, 20, 99], | |
| [ 56, 28, 157], | |
| [124, 35, 113], | |
| [ 29, 160, 27], | |
| [211, 204, 210], | |
| [124, 113, 46], | |
| [106, 43, 204], | |
| [ 96, 62, 77], | |
| [227, 137, 116], | |
| [ 73, 41, 72], | |
| [ 36, 203, 142], | |
| [235, 64, 240], | |
| [ 48, 49, 64], | |
| [ 42, 41, 74], | |
| [214, 212, 207], | |
| [183, 42, 184], | |
| [210, 169, 211], | |
| [140, 170, 176], | |
| [104, 105, 69], | |
| [193, 122, 168], | |
| [ 50, 123, 187], | |
| [ 89, 96, 90], | |
| [ 66, 65, 107], | |
| [179, 89, 180], | |
| [119, 101, 120], | |
| [ 68, 63, 104], | |
| [234, 93, 227], | |
| [ 16, 15, 85], | |
| [209, 129, 49], | |
| [ 15, 14, 86], | |
| [107, 55, 9], | |
| [120, 100, 121], | |
| [153, 145, 22], | |
| [178, 88, 179], | |
| [197, 6, 196], | |
| [ 89, 88, 96], | |
| [135, 138, 136], | |
| [138, 215, 172], | |
| [218, 115, 219], | |
| [ 41, 42, 81], | |
| [ 5, 195, 51], | |
| [ 57, 43, 61], | |
| [208, 171, 199], | |
| [ 41, 81, 38], | |
| [224, 53, 225], | |
| [ 24, 144, 110], | |
| [105, 52, 66], | |
| [118, 229, 117], | |
| [227, 34, 234], | |
| [ 66, 107, 69], | |
| [ 10, 109, 151], | |
| [219, 48, 235], | |
| [183, 62, 191], | |
| [142, 129, 126], | |
| [116, 111, 143], | |
| [118, 117, 50], | |
| [223, 222, 52], | |
| [ 94, 19, 141], | |
| [222, 221, 65], | |
| [196, 3, 197], | |
| [ 45, 220, 44], | |
| [156, 70, 139], | |
| [188, 122, 245], | |
| [139, 71, 162], | |
| [149, 170, 150], | |
| [122, 188, 196], | |
| [206, 216, 92], | |
| [164, 2, 167], | |
| [242, 141, 241], | |
| [ 0, 164, 37], | |
| [ 11, 72, 12], | |
| [ 12, 38, 13], | |
| [ 70, 63, 71], | |
| [ 31, 226, 111], | |
| [ 36, 101, 205], | |
| [203, 206, 165], | |
| [126, 209, 217], | |
| [ 98, 165, 97], | |
| [237, 220, 218], | |
| [237, 239, 241], | |
| [210, 214, 169], | |
| [140, 171, 32], | |
| [241, 125, 237], | |
| [179, 86, 178], | |
| [180, 85, 179], | |
| [181, 84, 180], | |
| [182, 83, 181], | |
| [194, 201, 182], | |
| [177, 137, 132], | |
| [184, 76, 183], | |
| [185, 61, 184], | |
| [186, 57, 185], | |
| [216, 212, 186], | |
| [192, 214, 187], | |
| [139, 34, 156], | |
| [218, 79, 237], | |
| [147, 123, 177], | |
| [ 45, 44, 4], | |
| [208, 201, 32], | |
| [ 98, 64, 129], | |
| [192, 213, 138], | |
| [235, 59, 219], | |
| [141, 242, 97], | |
| [ 97, 2, 141], | |
| [240, 75, 235], | |
| [229, 24, 228], | |
| [ 31, 25, 226], | |
| [230, 23, 229], | |
| [231, 22, 230], | |
| [232, 26, 231], | |
| [233, 112, 232], | |
| [244, 189, 243], | |
| [189, 221, 190], | |
| [222, 28, 221], | |
| [223, 27, 222], | |
| [224, 29, 223], | |
| [225, 30, 224], | |
| [113, 247, 225], | |
| [ 99, 60, 240], | |
| [213, 147, 215], | |
| [ 60, 20, 166], | |
| [192, 187, 213], | |
| [243, 112, 244], | |
| [244, 233, 245], | |
| [245, 128, 188], | |
| [188, 114, 174], | |
| [134, 131, 220], | |
| [174, 217, 236], | |
| [236, 198, 134], | |
| [215, 177, 58], | |
| [156, 143, 124], | |
| [ 25, 110, 7], | |
| [ 31, 228, 25], | |
| [264, 356, 368], | |
| [ 0, 11, 267], | |
| [451, 452, 349], | |
| [267, 302, 269], | |
| [350, 357, 277], | |
| [350, 452, 357], | |
| [299, 333, 297], | |
| [396, 175, 377], | |
| [280, 347, 330], | |
| [269, 303, 270], | |
| [151, 9, 337], | |
| [344, 278, 360], | |
| [424, 418, 431], | |
| [270, 304, 409], | |
| [272, 310, 407], | |
| [322, 270, 410], | |
| [449, 450, 347], | |
| [432, 422, 434], | |
| [ 18, 313, 17], | |
| [291, 306, 375], | |
| [259, 387, 260], | |
| [424, 335, 418], | |
| [434, 364, 416], | |
| [391, 423, 327], | |
| [301, 251, 298], | |
| [275, 281, 4], | |
| [254, 373, 253], | |
| [375, 307, 321], | |
| [280, 425, 411], | |
| [200, 421, 18], | |
| [335, 321, 406], | |
| [321, 320, 405], | |
| [314, 315, 17], | |
| [423, 426, 266], | |
| [396, 377, 369], | |
| [270, 322, 269], | |
| [413, 417, 464], | |
| [385, 386, 258], | |
| [248, 456, 419], | |
| [298, 284, 333], | |
| [168, 417, 8], | |
| [448, 346, 261], | |
| [417, 413, 285], | |
| [326, 327, 328], | |
| [277, 355, 329], | |
| [309, 392, 438], | |
| [381, 382, 256], | |
| [279, 429, 360], | |
| [365, 364, 379], | |
| [355, 277, 437], | |
| [282, 443, 283], | |
| [281, 275, 363], | |
| [395, 431, 369], | |
| [299, 297, 337], | |
| [335, 273, 321], | |
| [348, 450, 349], | |
| [359, 446, 467], | |
| [283, 293, 282], | |
| [250, 458, 462], | |
| [300, 276, 383], | |
| [292, 308, 325], | |
| [283, 276, 293], | |
| [264, 372, 447], | |
| [346, 352, 340], | |
| [354, 274, 19], | |
| [363, 456, 281], | |
| [426, 436, 425], | |
| [380, 381, 252], | |
| [267, 269, 393], | |
| [421, 200, 428], | |
| [371, 266, 329], | |
| [432, 287, 422], | |
| [290, 250, 328], | |
| [385, 258, 384], | |
| [446, 265, 342], | |
| [386, 387, 257], | |
| [422, 424, 430], | |
| [445, 342, 276], | |
| [422, 273, 424], | |
| [306, 292, 307], | |
| [352, 366, 345], | |
| [268, 271, 302], | |
| [358, 423, 371], | |
| [327, 294, 460], | |
| [331, 279, 294], | |
| [303, 271, 304], | |
| [436, 432, 427], | |
| [304, 272, 408], | |
| [395, 394, 431], | |
| [378, 395, 400], | |
| [296, 334, 299], | |
| [ 6, 351, 168], | |
| [376, 352, 411], | |
| [307, 325, 320], | |
| [285, 295, 336], | |
| [320, 319, 404], | |
| [329, 330, 349], | |
| [334, 293, 333], | |
| [366, 323, 447], | |
| [316, 15, 315], | |
| [331, 358, 279], | |
| [317, 14, 316], | |
| [ 8, 285, 9], | |
| [277, 329, 350], | |
| [253, 374, 252], | |
| [319, 318, 403], | |
| [351, 6, 419], | |
| [324, 318, 325], | |
| [397, 367, 365], | |
| [288, 435, 397], | |
| [278, 344, 439], | |
| [310, 272, 311], | |
| [248, 195, 281], | |
| [375, 273, 291], | |
| [175, 396, 199], | |
| [312, 311, 268], | |
| [276, 283, 445], | |
| [390, 373, 339], | |
| [295, 282, 296], | |
| [448, 449, 346], | |
| [356, 264, 454], | |
| [337, 336, 299], | |
| [337, 338, 151], | |
| [294, 278, 455], | |
| [308, 292, 415], | |
| [429, 358, 355], | |
| [265, 340, 372], | |
| [352, 346, 280], | |
| [295, 442, 282], | |
| [354, 19, 370], | |
| [285, 441, 295], | |
| [195, 248, 197], | |
| [457, 440, 274], | |
| [301, 300, 368], | |
| [417, 351, 465], | |
| [251, 301, 389], | |
| [394, 395, 379], | |
| [399, 412, 419], | |
| [410, 436, 322], | |
| [326, 2, 393], | |
| [354, 370, 461], | |
| [393, 164, 267], | |
| [268, 302, 12], | |
| [312, 268, 13], | |
| [298, 293, 301], | |
| [265, 446, 340], | |
| [280, 330, 425], | |
| [322, 426, 391], | |
| [420, 429, 437], | |
| [393, 391, 326], | |
| [344, 440, 438], | |
| [458, 459, 461], | |
| [364, 434, 394], | |
| [428, 396, 262], | |
| [274, 354, 457], | |
| [317, 316, 402], | |
| [316, 315, 403], | |
| [315, 314, 404], | |
| [314, 313, 405], | |
| [313, 421, 406], | |
| [323, 366, 361], | |
| [292, 306, 407], | |
| [306, 291, 408], | |
| [291, 287, 409], | |
| [287, 432, 410], | |
| [427, 434, 411], | |
| [372, 264, 383], | |
| [459, 309, 457], | |
| [366, 352, 401], | |
| [ 1, 274, 4], | |
| [418, 421, 262], | |
| [331, 294, 358], | |
| [435, 433, 367], | |
| [392, 289, 439], | |
| [328, 462, 326], | |
| [ 94, 2, 370], | |
| [289, 305, 455], | |
| [339, 254, 448], | |
| [359, 255, 446], | |
| [254, 253, 449], | |
| [253, 252, 450], | |
| [252, 256, 451], | |
| [256, 341, 452], | |
| [414, 413, 463], | |
| [286, 441, 414], | |
| [286, 258, 441], | |
| [258, 257, 442], | |
| [257, 259, 443], | |
| [259, 260, 444], | |
| [260, 467, 445], | |
| [309, 459, 250], | |
| [305, 289, 290], | |
| [305, 290, 460], | |
| [401, 376, 435], | |
| [309, 250, 392], | |
| [376, 411, 433], | |
| [453, 341, 464], | |
| [357, 453, 465], | |
| [343, 357, 412], | |
| [437, 343, 399], | |
| [344, 360, 440], | |
| [420, 437, 456], | |
| [360, 420, 363], | |
| [361, 401, 288], | |
| [265, 372, 353], | |
| [390, 339, 249] | |
| ] | |
| /* | |
| {faceInViewConfidence: 1, boundingBox: {…}, mesh: Array(468), scaledMesh: Array(468), annotations: {…}} | |
| annotations: | |
| leftCheek: [Array(3)] | |
| leftEyeLower0: (9) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| leftEyeLower1: (9) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| leftEyeLower2: (9) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| leftEyeLower3: (9) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| leftEyeUpper0: (7) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| leftEyeUpper1: (7) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| leftEyeUpper2: (7) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| leftEyebrowLower: (6) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| leftEyebrowUpper: (8) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| lipsLowerInner: (11) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| lipsLowerOuter: (10) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| lipsUpperInner: (11) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| lipsUpperOuter: (11) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| midwayBetweenEyes: [Array(3)] | |
| noseBottom: [Array(3)] | |
| noseLeftCorner: [Array(3)] | |
| noseRightCorner: [Array(3)] | |
| noseTip: [Array(3)] | |
| rightCheek: [Array(3)] | |
| rightEyeLower0: (9) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| rightEyeLower1: (9) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| rightEyeLower2: (9) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| rightEyeLower3: (9) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| rightEyeUpper0: (7) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| rightEyeUpper1: (7) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| rightEyeUpper2: (7) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| rightEyebrowLower: (6) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| rightEyebrowUpper: (8) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| silhouette: (36) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)] | |
| [[Prototype]]: Object | |
| boundingBox: {topLeft: Array(2), bottomRight: Array(2)} | |
| faceInViewConfidence: 1 | |
| mesh: (468) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), …] | |
| scaledMesh: (468) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), …] | |
| [[Prototype]]: Object | |
| */ | |
| Main () | |
| </script> | |
| </body> | |
| </html> | |