{"id":325242,"date":"2021-06-21T15:00:17","date_gmt":"2021-06-21T15:00:17","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=325242"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=325242","title":{"rendered":"\u041a\u0430\u043a \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 Web \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0446 \u0438 \u043c\u0430\u0441\u043e\u043a \u0434\u043b\u044f Google Chrome (\u0447\u0430\u0441\u0442\u044c 2)"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/-n\/bv\/hz\/-nbvhzxzi7k4k4djb2xqv6r1ntk.png\" alt=\"\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430 \u0438 \u043c\u0430\u0441\u043a\u0438\"><br \/>  \u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 <a href=\"https:\/\/habr.com\/ru\/post\/547038\/\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043e \u0442\u043e\u043c, \u043c\u043e\u0436\u043d\u043e \u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 (\u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430 \u0438 \u043c\u0430\u0441\u043a\u0438) \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u0445 \u043a \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432.<br \/>  \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<br \/>  <a name=\"habracut\"><\/a><\/p>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438<\/h2>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/lx\/70\/-u\/lx70-urfuhzntynlv8nt7dnnrru.png\"><\/p>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u044f\u0437\u044b\u043a \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u044d\u0442\u043e TypeScript. \u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 React.js.<br \/>  \u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439: \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u044f \u043b\u0438\u0446\u0430, \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u044f \u043c\u0430\u0441\u043a\u0438. \u041a\u0430\u0436\u0434\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c\/\u0441\u0435\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 (Web Worker). \u041d\u0435\u0439\u0440\u043e\u043d\u043d\u044b\u0435 \u0441\u0435\u0442\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c TensorFlow.js \u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 backend-\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Web Assembly \u0438\u043b\u0438 WebGL, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u0434 \u0441\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e \u0431\u043b\u0438\u0437\u043a\u043e\u0439 \u043a \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439. \u0412\u044b\u0431\u043e\u0440 \u0442\u043e\u0433\u043e \u0438\u043b\u0438 \u0438\u043d\u043e\u0433\u043e backend-\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043c\u043e\u0434\u0435\u043b\u0438 (\u043c\u0435\u043b\u043a\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0430 WebAssembly), \u043d\u043e \u043d\u0430\u0434\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c, \u0442\u043e \u0447\u0442\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.<br \/>  \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e \u0441\u0442\u0440\u0438\u043c\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c WebRTC. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 OpenCV.js.<\/p>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0431\u044b\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/1a\/qb\/t1\/1aqbt1ztcekfq3tw7frnc-no-r4.png\"><\/p>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0432\u0441\u0435\u0433\u043e, \u043e\u043d \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0442\u044f\u0436\u0435\u043b\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 OpenCV \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 TensorFlow.js. \u0412\u0441\u0435 \u0447\u0442\u043e \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u0437 \u0432\u0438\u0434\u0435\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c.<br \/>  \u041f\u043e\u043a\u0430 \u0432\u043e\u0440\u043a\u0435\u0440 \u043d\u0435 \u0441\u043e\u043e\u0431\u0449\u0438\u043b \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u043f\u043e\u0442\u043e\u043a\u0443, \u0447\u0442\u043e \u043e\u043d \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u043b\u0441\u044f, \u043d\u043e\u0432\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0435\u0433\u043e, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0440\u043a\u0435\u0440 \u0433\u043e\u0432\u043e\u0440\u0438\u0442, \u0447\u0442\u043e \u043e\u043d \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u043b\u0441\u044f, \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043e \u0441\u0442\u0440\u0438\u043c\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443.<br \/>  \u041f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0438\u0435 \u043b\u0438\u0446\u0430, \u0435\u0441\u043b\u0438 \u043b\u0438\u0446\u043e \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u043e, \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0438\u0435 \u043c\u0430\u0441\u043a\u0438. \u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d \u043d\u0430 UI.<\/p>\n<h1>\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b<\/h1>\n<p>  <\/p>\n<ul>\n<li>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043e \u0441\u0442\u0440\u0438\u043c\u0430 \u2014 <b>31 \u043c\u0441<\/b>  <\/li>\n<li>\u041f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0446\u0430 \u2014 <b>0-1 \u043c\u0441<\/b>  <\/li>\n<li>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430 \u2014 <b>51 \u043c\u0441<\/b>  <\/li>\n<li>\u041f\u043e\u0441\u0442\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0446\u0430\u00a0 \u2014 <b>8 \u043c\u0441<\/b>  <\/li>\n<li>\u041f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u043a\u0438 \u2014 <b>2 \u043c\u0441<\/b>  <\/li>\n<li>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u043a\u0438 \u2014 <b>11 \u043c\u0441<\/b>  <\/li>\n<li>\u041f\u043e\u0441\u0442\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u043a\u0438 \u2014 <b>0-1 \u043c\u0441<\/b>  <\/li>\n<\/ul>\n<p>  \u0418\u0442\u043e\u0433\u043e:\u00a0  <\/p>\n<ul>\n<li>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430 \u2014 <b>60 \u043c\u0441<\/b> + <b>31 \u043c\u0441<\/b> = <b>91 \u043c\u0441<\/b>  <\/li>\n<li>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u043a\u0438 \u2014 <b>14 \u043c\u0441<\/b>  <\/li>\n<\/ul>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0437\u0430 ~<b>105 \u043c\u0441 <\/b>\u0431\u044b \u0437\u043d\u0430\u0435\u043c \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0441 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<br \/>  \u00a0<br \/>  *\u041f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0446\u0430 \u2014 \u044d\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e \u0441\u0442\u0440\u0438\u043c\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0432 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440<br \/>  *\u041f\u043e\u0441\u0442\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0446\u0430 \u2014 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043e\u0442 \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0446\u0430 \u0438 \u0435\u0433\u043e \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u043d\u0430 \u043a\u0430\u043d\u0432\u0430\u0441\u0435<br \/>  *\u041f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u043a\u0438 \u2014 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a\u0430\u043d\u0432\u0430\u0441\u0430 \u0441\u00a0 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0432\u044b\u0440\u043e\u0432\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u043b\u0438\u0446\u0430 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0435\u0433\u043e \u0432 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440<br \/>  *\u041f\u043e\u0441\u0442\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u043a\u0438 \u2014 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u043a\u0438<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/p_\/hr\/rb\/p_hrrbcxpzgboml37nzfjngdjbm.png\"><\/p>\n<p>  \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 (\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u043a\u0438) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 (OpenCV.js, Tensorflow.js, \u043c\u043e\u0434\u0435\u043b\u0438).<\/p>\n<p>  \u0422\u0430\u043a\u0438\u0445 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u0443 \u043d\u0430\u0441 3:  <\/p>\n<ul>\n<li>\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430  <\/li>\n<li>\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u043a\u0438  <\/li>\n<li>\u0432\u043e\u0440\u043a\u0435\u0440-\u0445\u0435\u043b\u043f\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u044f\u0436\u0435\u043b\u044b\u0439 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u0437 OpenCV \u0438 Tensorflow \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0446\u044b \u043a\u0430\u043b\u0438\u0431\u0440\u043e\u0432\u043a\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u0430\u043c\u0435\u0440 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440.  <\/li>\n<\/ul>\n<h1>\u0424\u0438\u0447\u0438 \u0438 \u0442\u0440\u044e\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/h1>\n<p>  <\/p>\n<h2>\u0412\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u044b \u0438 \u043a\u0430\u043a \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0441 \u043d\u0438\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c<\/h2>\n<p>  \u0412\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440 \u2014 \u0441\u043f\u043e\u0441\u043e\u0431 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435.<br \/>  \u041e\u043d\u0438\u00a0 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0442\u044f\u0436\u0435\u043b\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043f\u043e\u0442\u043e\u043a\u043e\u043c \u0431\u0435\u0437 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0432\u0441\u0435 \u0442\u044f\u0436\u0435\u043b\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0432 \u0432\u0435\u0431-\u0432\u043e\u0440\u043a\u0435\u0440\u044b. \u0412\u0435\u0431-\u0432\u043e\u0440\u043a\u0435\u0440\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u0432\u043e \u0432\u0441\u0435\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/tw\/qa\/us\/twqausqk_uazvkz7-7gpdvhcsji.png\"><\/p>\n<h2>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0432\u0435\u0431-\u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432<\/h2>\n<p>  \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438:  <\/p>\n<ul>\n<li>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <b>JavaScript<\/b>  <\/li>\n<li>\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 <b>navigator<\/b>  <\/li>\n<li>\u0414\u043e\u0441\u0442\u0443\u043f \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <b>location<\/b>  <\/li>\n<li>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 <b>XMLHttpRequest<\/b>  <\/li>\n<li>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <b>setTimeout() <\/b>\/ <b>clearTimeout() <\/b>\u0438 <b>setInterval()<\/b> \/ <b>clearInterval()<\/b>  <\/li>\n<li>Application Cache  <\/li>\n<li>\u0418\u043c\u043f\u043e\u0440\u0442 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e\u00a0<b>importScripts()<\/b>  <\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432  <\/li>\n<\/ul>\n<p>  \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f:  <\/p>\n<ul>\n<li>\u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a <b>DOM<\/b>  <\/li>\n<li>\u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 <b>windows<\/b>  <\/li>\n<li>\u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 <b>document<\/b>  <\/li>\n<li>\u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 <b>parent<\/b>  <\/li>\n<\/ul>\n<p>  \u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043f\u043e\u0442\u043e\u043a\u043e\u043c \u0438 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e postMessage \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0439 onmessage.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/vt\/am\/pn\/vtampnoq7s2wimwulmlfakzf0bs.jpeg\"><\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Worker\/postMessage\" rel=\"nofollow noopener noreferrer\">postMessage()<\/a>, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u043e \u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u2014 transferable object.<\/p>\n<pre><code class=\"javascript\">worker.postMessage(message, [transfer]);<\/code><\/pre>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0435\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0435\u0433\u043e.<\/p>\n<p>  Transferable \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430\u043c\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0442\u0430\u043a\u0438\u043c\u0438 \u043a\u0430\u043a \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0438 \u0432\u0435\u0431-\u0432\u043e\u0440\u043a\u0435\u0440\u044b.<\/p>\n<p>  \u041a \u043d\u0438\u043c \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f:  <\/p>\n<ul>\n<li>ImageBitmap\u00a0  <\/li>\n<li>OffscreenCanvas  <\/li>\n<li>ArrayBuffer  <\/li>\n<li>MessagePort  <\/li>\n<\/ul>\n<p>  \u0415\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c 500 \u041c\u0431 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0432\u043e\u0440\u043a\u0435\u0440, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u0431\u0435\u0437 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430, \u043d\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f.<br \/>  \u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0431\u0435\u0437 transfer \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0437\u0430\u0439\u043c\u0435\u0442 149 \u043c\u0441 \u0438 1042 \u041c\u0431 \u0434\u043b\u044f Google Chrome, \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445 \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/bx\/kb\/mi\/bxkbmir8ro_a9sosbwr2uxj98p8.png\"><\/p>\n<p>  \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 transfer \u044d\u0442\u043e \u0437\u0430\u0439\u043c\u0435\u0442 1 \u043c\u0441 \u0438 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 \u0432 2 \u0440\u0430\u0437\u0430!<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/7g\/w5\/8i\/7gw58iwkm5mamilqkn29gouoeso.png\"><\/p>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u0432 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u043e, \u0442\u043e \u043d\u0430\u043c \u0432\u0430\u0436\u043d\u043e \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u043e \u043f\u0430\u043c\u044f\u0442\u0438, \u0438 \u044d\u0442\u0430 \u0444\u0438\u0447\u0430 \u043d\u0430\u043c \u0432 \u044d\u0442\u043e\u043c \u043e\u0447\u0435\u043d\u044c \u0441\u0438\u043b\u044c\u043d\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442.<\/p>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 OffscreenCanvas<\/h2>\n<p>  \u0412 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0435 \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c canvas \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e. \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 OffscreenCanvas.<\/p>\n<p>  \u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430:<br \/>   \u2014 \u041d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 DOM<br \/>   \u2014 \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043a\u0430\u043a \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u0442\u0430\u043a \u0438 \u0432 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u0445<br \/>   \u2014 \u0418\u043c\u0435\u0435\u0442 transferable \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438 \u043d\u0435 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a, \u0435\u0441\u043b\u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0435<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/dy\/hj\/4h\/dyhj4hhaqhxi6oznpjp9uzdoqyo.gif\"><\/p>\n<h2>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f requestAnimationFrame<\/h2>\n<p>  <b>requestAnimationFrame<\/b> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e \u0441\u0442\u0440\u0438\u043c\u0430 \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e (60 FPS) \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043a\u0430\u043c\u0435\u0440\u044b, \u043d\u0435 \u0432\u0441\u0435 \u043a\u0430\u043c\u0435\u0440\u044b \u043e\u0442\u0434\u0430\u044e\u0442 \u0432\u0438\u0434\u0435\u043e \u0441 \u0442\u0430\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439.<\/p>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f:<\/p>\n<p>   \u2014 \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u0437\u043e\u0432\u044b requestAnimationFrame \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f\u043c\u0438 \u0438 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0430\u043c\u0438, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043e\u043a \u0438 \u043a\u0430\u043a \u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435 \u00ab\u043b\u0430\u0433\u043e\u0432\u00bb.<\/p>\n<p>   \u2014 \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0440\u0430\u0441\u0445\u043e\u0434 \u0431\u0430\u0442\u0430\u0440\u0435\u0438 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435, \u044d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u043d\u043e \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0434\u0435\u0432\u0430\u0439\u0441\u043e\u0432.<\/p>\n<p>   \u2014 \u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u0435\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u0430, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<p>   \u2014 \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u0432\u044b\u0437\u043e\u0432\u0430 16.67 \u043c\u0441 (1000 \u043c\u0441 \/ 60 fps = 16.67 \u043c\u0441)<\/p>\n<p>   \u2014 \u041c\u043e\u0436\u043d\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u043e\u0442\u0443 \u0432\u044b\u0437\u043e\u0432\u0430<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/5f\/wj\/8v\/5fwj8vm-m-y7yf8ybxsvg06mzkk.png\"><\/p>\n<h2>\u0421\u043d\u044f\u0442\u0438\u0435 \u0438 \u0430\u043d\u0430\u043b\u0438\u0437 \u043c\u0435\u0442\u0440\u0438\u043a\u00a0<\/h2>\n<p>  \u0414\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u0440\u0438\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u0435\u0439\u0447\u0430\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f stats.js \u0438 \u043f\u043e \u043d\u0430\u0447\u0430\u043b\u0443 \u044d\u0442\u043e \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u0438\u0434\u0435\u0435\u0439, \u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u043e\u0433\u0434\u0430 \u043c\u0435\u0442\u0440\u0438\u043a \u0441\u0442\u0430\u043b\u043e 20+, \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0444\u043b\u043e\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u043b \u0442\u043e\u0440\u043c\u043e\u0437\u0438\u0442\u044c, \u0438\u0437-\u0437\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u0440\u0430\u0443\u0437\u0435\u0440. \u041a\u0430\u0436\u0434\u0430\u044f \u043c\u0435\u0442\u0440\u0438\u043a\u0430 \u2014 \u044d\u0442\u043e \u043a\u0430\u043d\u0432\u0430\u0441, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0433\u0440\u0430\u0444\u0438\u043a (\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u0442\u0443\u0434\u0430) \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0431\u0435\u0437 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439, \u0447\u0442\u043e \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u043e \u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0437\u0430\u043d\u0438\u0436\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f.<\/p>\n<p>  \u0414\u043b\u044f \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043b\u0443\u0447\u0448\u0435 \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u00ab\u043a\u0440\u0430\u0441\u043e\u0442\u044b\u00bb, \u0430 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0435\u0441\u0442\u043e\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0438 \u043f\u0440\u043e\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u043e\u0435 \u0441\u0440\u0435\u0434\u043d\u0435\u0435 \u0437\u0430 \u0432\u0441\u0435 \u0432\u0440\u0435\u043c\u044f. \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 DOM \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430.<\/p>\n<h2>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u0442\u0435\u0447\u0435\u043a \u043f\u0430\u043c\u044f\u0442\u0438<\/h2>\n<p>  \u0414\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043c\u044b \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0441 \u0443\u0442\u0435\u0447\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043d\u0430 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043c\u043e\u0433\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u043e.<br \/>  \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u043d\u0435\u043b\u044c\u0437\u044f \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u043c\u044f\u0442\u0438 \u043e\u043d \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u0442 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 (performance.memory \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u0445).<br \/>  \u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u044d\u0442\u043e\u0433\u043e, \u043c\u044b \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u044b \u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u044f \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u043c\u043e\u0436\u043d\u043e \u0441\u043d\u044f\u0442\u044c \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0433\u0434\u0435 \u0443\u0442\u0435\u0447\u043a\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e.<\/p>\n<h1>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0432 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u0445<\/h1>\n<p>  \u041c\u044b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b\u0438\u0441\u044c \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u0442\u0440\u044e\u043a\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u043f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0430\u043c\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e.<br \/>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c\u0438 \u043c\u044b \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 <a href=\"https:\/\/github.com\/GoogleChromeLabs\/comlink-loader\" rel=\"nofollow noopener noreferrer\">comlink-loader<\/a>. \u041e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u043c \u043a\u0430\u043a \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0430, \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043c\u0435\u0442\u043e\u0434\u044b onmessage \u0438 postMessage, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e async-await. \u0412\u0441\u0435 \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u0443\u0434\u043e\u0431\u043d\u043e, \u043f\u043e\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438 \u043d\u0430 \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u0435 (Samsung Galaxy Tab S7) \u0438 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e \u043e\u043d\u043e \u0447\u0435\u0440\u0435\u0437 2 \u043c\u0438\u043d\u0443\u0442\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0440\u044d\u0448\u0438\u043b\u043e\u0441\u044c.<br \/>  \u041f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0432 \u0432\u0435\u0441\u044c \u043d\u0430\u0448 \u043a\u043e\u0434, \u043c\u044b \u043d\u0435 \u043d\u0430\u0448\u043b\u0438 \u0443\u0442\u0435\u0447\u0435\u043a \u043f\u0430\u043c\u044f\u0442\u0438, \u043a\u0440\u043e\u043c\u0435 \u0447\u0435\u0440\u043d\u043e\u0433\u043e \u044f\u0449\u0438\u043a\u0430 \u0432 \u0432\u0438\u0434\u0435 \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c\u0438. \u041f\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 Tensorflow.js \u043d\u0435 \u043e\u0447\u0438\u0449\u0430\u043b\u0438\u0441\u044c \u0438 \u0433\u0434\u0435-\u0442\u043e \u043f\u043e\u0434\u0432\u0438\u0441\u0430\u043b\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<br \/>  \u0411\u044b\u043b\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/webpack-contrib\/worker-loader\" rel=\"nofollow noopener noreferrer\">worker-loader<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c\u0438 \u043a\u0430\u043a \u0438\u0437 \u0447\u0438\u0441\u0442\u043e\u0433\u043e js \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u043f\u0440\u043e\u0441\u043b\u043e\u0435\u043a. \u0418 \u044d\u0442\u043e \u0440\u0435\u0448\u0438\u043b\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u0443\u0442\u043a\u0430\u043c\u0438 \u0431\u0435\u0437 \u0432\u044b\u043b\u0435\u0442\u043e\u0432.<\/p>\n<p>  <b>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430<\/b><\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0432\u043e\u0440\u043a\u0435\u0440<\/p>\n<pre><code class=\"plaintext\">this.faceDetectionWorker = workers.FaceRgbDetectionWorkerFactory.createWebWorker(); <\/code><\/pre>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438\u0437 \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435.<\/p>\n<pre><code class=\"plaintext\">this.faceDetectionWorker.onmessage = async (event) =&gt; { \u00a0if (event.data.type === 'load') { \u00a0\u00a0\u00a0this.faceDetectionWorker.postMessage({ \u00a0\u00a0\u00a0\u00a0\u00a0type: 'init', \u00a0\u00a0\u00a0\u00a0\u00a0backend, \u00a0\u00a0\u00a0\u00a0\u00a0streamSettings, \u00a0\u00a0\u00a0\u00a0\u00a0faceDetectionSettings, \u00a0\u00a0\u00a0\u00a0\u00a0imageRatio: this.imageRatio, \u00a0\u00a0\u00a0}); \u00a0} else if (event.data.type === 'init') { \u00a0\u00a0\u00a0this.isFaceWorkerInit = event.data.status;  \u00a0\u00a0\u00a0\/\/ When both workers inited it is run processes to grab and process frames only \u00a0\u00a0\u00a0if (this.isFaceWorkerInit &amp;&amp; this.isMaskWorkerInit) { \u00a0\u00a0\u00a0\u00a0\u00a0await this.grabFrame(); \u00a0\u00a0\u00a0} \u00a0} else if (event.data.type === 'faceResults') { \u00a0\u00a0\u00a0this.onFaceDetected(event); \u00a0} else { \u00a0\u00a0\u00a0throw new &lt;i&gt;Error&lt;\/i&gt;(`Type=${event.data.type} is not supported by RgbVideo for FaceRgbDatectionWorker`); \u00a0} }; <\/code><\/pre>\n<p>  \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043b\u0438\u0446\u0430<\/p>\n<pre><code class=\"plaintext\">this.faceDetectionWorker.postMessage( \u00a0{ \u00a0\u00a0\u00a0type: 'detectFace', \u00a0\u00a0\u00a0originalImageToProcess: this.lastImage, \u00a0\u00a0\u00a0lastIndex: lastItem!.index, \u00a0}, \u00a0[this.lastImage], \/\/ transferable object ); <\/code><\/pre>\n<p>  \u041a\u043e\u0434 \u0432\u0435\u0431 \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0446\u0430<\/p>\n<p>  \u041c\u0435\u0442\u043e\u0434 init \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043a\u0430\u043d\u0432\u0430\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u043c\u0443 \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<pre><code class=\"plaintext\">export const init = async (data) =&gt; { \u00a0const { backend, streamSettings, faceDetectionSettings, imageRatio } = data;  \u00a0flipHorizontal = streamSettings.flipHorizontal; \u00a0faceMinWidth = faceDetectionSettings.faceMinWidth; \u00a0faceMinWidthConversionFactor = faceDetectionSettings.faceMinWidthConversionFactor; \u00a0predictionIOU = faceDetectionSettings.predictionIOU; \u00a0recommendedLocation = faceDetectionSettings.useRecommendedLocation ? faceDetectionSettings.recommendedLocation : null; \u00a0detectedFaceThumbnailSize = faceDetectionSettings.detectedFaceThumbnailSize; \u00a0srcImageRatio = imageRatio; \u00a0await tfc.setBackend(backend); \u00a0await tfc.ready();  \u00a0const [blazeModel] = await &lt;i&gt;Promise&lt;\/i&gt;.all([ \u00a0\u00a0\u00a0blazeface.load({ \u00a0\u00a0\u00a0\u00a0\u00a0\/\/ The maximum number of faces returned by the model \u00a0\u00a0\u00a0\u00a0\u00a0maxFaces: faceDetectionSettings.maxFaces, \u00a0\u00a0\u00a0\u00a0\u00a0\/\/ The width of the input image \u00a0\u00a0\u00a0\u00a0\u00a0inputWidth: faceDetectionSettings.faceDetectionImageMinWidth, \u00a0\u00a0\u00a0\u00a0\u00a0\/\/ The height of the input image \u00a0\u00a0\u00a0\u00a0\u00a0inputHeight: faceDetectionSettings.faceDetectionImageMinHeight, \u00a0\u00a0\u00a0\u00a0\u00a0\/\/ The threshold for deciding whether boxes overlap too much \u00a0\u00a0\u00a0\u00a0\u00a0iouThreshold: faceDetectionSettings.iouThreshold, \u00a0\u00a0\u00a0\u00a0\u00a0\/\/ The threshold for deciding when to remove boxes based on score \u00a0\u00a0\u00a0\u00a0\u00a0scoreThreshold: faceDetectionSettings.scoreThreshold, \u00a0\u00a0\u00a0}), \u00a0\u00a0\u00a0isOpenCvLoaded(), \u00a0]);  \u00a0faceDetection = new FaceDetection(); \u00a0originalImageToProcessCanvas = new &lt;i&gt;OffscreenCanvas&lt;\/i&gt;(srcImageRatio.videoWidth, srcImageRatio.videoHeight); \u00a0originalImageToProcessCanvasCtx = originalImageToProcessCanvas.getContext('2d');  \u00a0resizedImageToProcessCanvas = new &lt;i&gt;OffscreenCanvas&lt;\/i&gt;( \u00a0\u00a0\u00a0srcImageRatio.faceDetectionImageWidth, \u00a0\u00a0\u00a0srcImageRatio.faceDetectionImageHeight, \u00a0); \u00a0resizedImageToProcessCanvasCtx = resizedImageToProcessCanvas.getContext('2d'); \u00a0return blazeModel; }; <\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 isOpenCvLoaded \u0434\u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 openCV<\/p>\n<pre><code class=\"plaintext\">export const isOpenCvLoaded = () =&gt; { \u00a0let timeoutId;  \u00a0const resolveOpenCvPromise = (resolve) =&gt; { \u00a0\u00a0\u00a0if (timeoutId) { \u00a0\u00a0\u00a0\u00a0\u00a0clearTimeout(timeoutId); \u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0try { \u00a0\u00a0\u00a0\u00a0\u00a0\/\/ eslint-disable-next-line no-undef \u00a0\u00a0\u00a0\u00a0\u00a0if (cv &amp;&amp; cv.Mat) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return resolve(); \u00a0\u00a0\u00a0\u00a0\u00a0} else { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timeoutId = setTimeout(() =&gt; { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resolveOpenCvPromise(resolve); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}, OpenCvLoadedTimeoutInMs); \u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0} catch { \u00a0\u00a0\u00a0\u00a0\u00a0timeoutId = setTimeout(() =&gt; { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resolveOpenCvPromise(resolve); \u00a0\u00a0\u00a0\u00a0\u00a0}, OpenCvLoadedTimeoutInMs); \u00a0\u00a0\u00a0} \u00a0};  \u00a0return new &lt;i&gt;Promise&lt;\/i&gt;((resolve) =&gt; { \u00a0\u00a0\u00a0resolveOpenCvPromise(resolve); \u00a0}); }; <\/code><\/pre>\n<p>  \u0421\u0430\u043c\u044b\u0439 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u044d\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430.<\/p>\n<pre><code class=\"plaintext\">export const detectFace = async (data, faceModel) =&gt; { \u00a0let { originalImageToProcess, lastIndex } = data; \u00a0const facesThumbnailsImageData = [];  \u00a0\/\/ Resize original image to the recommended BlazeFace resolution \u00a0resizedImageToProcessCanvasCtx.drawImage( \u00a0\u00a0\u00a0originalImageToProcess, \u00a0\u00a0\u00a00, \u00a0\u00a0\u00a00, \u00a0\u00a0\u00a0srcImageRatio.faceDetectionImageWidth, \u00a0\u00a0\u00a0srcImageRatio.faceDetectionImageHeight, \u00a0); \u00a0\/\/ Getting resized image \u00a0let resizedImageDataToProcess = resizedImageToProcessCanvasCtx.getImageData( \u00a0\u00a0\u00a00, \u00a0\u00a0\u00a00, \u00a0\u00a0\u00a0srcImageRatio.faceDetectionImageWidth, \u00a0\u00a0\u00a0srcImageRatio.faceDetectionImageHeight, \u00a0); \u00a0\/\/ Detect faces by BlazeFace \u00a0let predictions = await faceModel.estimateFaces( \u00a0\u00a0\u00a0\/\/ The image to classify. Can be a tensor, DOM element image, video, or canvas \u00a0\u00a0\u00a0resizedImageDataToProcess, \u00a0\u00a0\u00a0\/\/ Whether to return tensors as opposed to values \u00a0\u00a0\u00a0returnTensors, \u00a0\u00a0\u00a0\/\/ Whether to flip\/mirror the facial keypoints horizontally. Should be true for videos that are flipped by default (e.g. webcams) \u00a0\u00a0\u00a0flipHorizontal, \u00a0\u00a0\u00a0\/\/ Whether to annotate bounding boxes with additional properties such as landmarks and probability. Pass in `false` for faster inference if annotations are not needed \u00a0\u00a0\u00a0annotateBoxes, \u00a0); \u00a0\/\/ Normalize predictions \u00a0predictions = faceDetection.normalizePredictions( \u00a0\u00a0\u00a0predictions, \u00a0\u00a0\u00a0returnTensors, \u00a0\u00a0\u00a0annotateBoxes, \u00a0\u00a0\u00a0srcImageRatio.faceDetectionImageRatio, \u00a0); \u00a0\/\/ Filters initial predictions by the criteri that all landmarks should be in area of interest \u00a0predictions = faceDetection.filterPredictionsByFullLandmarks( \u00a0\u00a0\u00a0predictions, \u00a0\u00a0\u00a0srcImageRatio.videoWidth, \u00a0\u00a0\u00a0srcImageRatio.videoHeight, \u00a0); \u00a0\/\/ Filters predictions by min face width \u00a0predictions = faceDetection.filterPredictionsByMinWidth(predictions, faceMinWidth, faceMinWidthConversionFactor); \u00a0\/\/ Filters predictions by recommended location \u00a0predictions = faceDetection.filterPredictionsByRecommendedLocation(predictions, predictionIOU, recommendedLocation);  \u00a0\/\/ If there are any predictions it is started faces thumbnails extraction according to the configured size \u00a0if (predictions &amp;&amp; predictions.length &gt; 0) { \u00a0\u00a0\u00a0\/\/ Draw initial original image \u00a0\u00a0\u00a0originalImageToProcessCanvasCtx.drawImage(originalImageToProcess, 0, 0); \u00a0\u00a0\u00a0const originalImageDataToProcess = originalImageToProcessCanvasCtx.getImageData( \u00a0\u00a0\u00a0\u00a0\u00a00, \u00a0\u00a0\u00a0\u00a0\u00a00, \u00a0\u00a0\u00a0\u00a0\u00a0originalImageToProcess.width, \u00a0\u00a0\u00a0\u00a0\u00a0originalImageToProcess.height, \u00a0\u00a0\u00a0);  \u00a0\u00a0\u00a0\/\/ eslint-disable-next-line no-undef \u00a0\u00a0\u00a0let srcImageData = cv.matFromImageData(originalImageDataToProcess); \u00a0\u00a0\u00a0try { \u00a0\u00a0\u00a0\u00a0\u00a0for (let i = 0; i &lt; predictions.length; i++) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const prediction = predictions[i]; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const facesOriginalLandmarks = &lt;i&gt;JSON&lt;\/i&gt;.parse(&lt;i&gt;JSON&lt;\/i&gt;.stringify(prediction.originalLandmarks));  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (flipHorizontal) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for (let j = 0; j &lt; facesOriginalLandmarks.length; j++) { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0facesOriginalLandmarks[j][0] = srcImageRatio.videoWidth - facesOriginalLandmarks[j][0]; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ eslint-disable-next-line no-undef \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let dstImageData = new cv.Mat(); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ eslint-disable-next-line no-undef \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let thumbnailSize = new cv.Size(detectedFaceThumbnailSize, detectedFaceThumbnailSize);  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let transformation = getOneToOneFaceTransformationByTarget(detectedFaceThumbnailSize);  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ eslint-disable-next-line no-undef \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let similarityTransformation = getSimilarityTransformation(facesOriginalLandmarks, transformation); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ eslint-disable-next-line no-undef \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let similarityTransformationMatrix = cv.matFromArray(3, 3, cv.CV_64F, similarityTransformation.data);  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ eslint-disable-next-line no-undef \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cv.warpPerspective( \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0srcImageData, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dstImageData, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0similarityTransformationMatrix, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0thumbnailSize, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cv.INTER_LINEAR, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cv.BORDER_CONSTANT, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new cv.Scalar(127, 127, 127, 255), \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0);  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0facesThumbnailsImageData.push( \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new &lt;i&gt;ImageData&lt;\/i&gt;( \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new &lt;i&gt;Uint8ClampedArray&lt;\/i&gt;(dstImageData.data, dstImageData.cols, dstImageData.rows), \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0detectedFaceThumbnailSize, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0detectedFaceThumbnailSize, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0), \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} finally { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0similarityTransformationMatrix.delete(); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0similarityTransformationMatrix = null; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} finally { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dstImageData.delete(); \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dstImageData = null; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0} finally { \u00a0\u00a0\u00a0\u00a0\u00a0srcImageData.delete(); \u00a0\u00a0\u00a0\u00a0\u00a0srcImageData = null; \u00a0\u00a0\u00a0} \u00a0}  \u00a0return { resizedImageDataToProcess, predictions, facesThumbnailsImageData, lastIndex }; }; <\/code><\/pre>\n<p>  \u041d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438 \u0438\u043d\u0434\u0435\u043a\u0441, \u0434\u043b\u044f \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0446\u0430 \u0438 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u043c\u0430\u0441\u043a\u0438 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c.<br \/>  \u0422\u0430\u043a \u043a\u0430\u043a blazeface \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u043e\u0439 128 px, \u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441 \u043a\u0430\u043c\u0435\u0440\u044b \u043d\u0443\u0436\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c.<br \/>  \u0412\u044b\u0437\u0432\u0430\u0432 \u043c\u0435\u0442\u043e\u0434 faceModel.estimateFaces \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0430\u043d\u0430\u043b\u0438\u0437 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e\u00a0 blazeface \u0438 \u043d\u0430\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0438\u043a\u0448\u0435\u043d\u044b \u0441 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043b\u0438\u0446\u0430, \u043d\u043e\u0441\u0430, \u0443\u0448\u0435\u0439, \u0433\u043b\u0430\u0437, \u0440\u0442\u0430.\u00a0<br \/>  \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0441 \u043d\u0438\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043d\u0443\u0436\u043d\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0434\u043b\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043c\u044b \u0436\u0435 \u0435\u0433\u043e \u0441\u0436\u0430\u043b\u0438 \u0434\u043e 128 px.<br \/>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438 \u043b\u0438\u0446\u043e \u0432 \u043d\u0443\u0436\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442, \u043a\u0430\u043a\u043e\u0439 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043b\u0438\u0446\u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d, \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/7u\/1_\/jx\/7u1_jxno6dhfxce8sqdodq9ltyi.png\"><\/p>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0432\u044b\u0440\u0435\u0437\u0430\u0435\u0442 \u043b\u0438\u0446\u043e \u0438\u0437 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e, \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u043c\u0430\u0441\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 openCV.<\/p>\n<p>  <b>\u0414\u0435\u0442\u0435\u043a\u0446\u0438\u044f \u043c\u0430\u0441\u043a\u0438<\/b><\/p>\n<p>  \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 webAssembly<\/p>\n<pre><code class=\"plaintext\">export const init = async (data) =&gt; { \u00a0const { backend, streamSettings, maskDetectionsSettings, imageRatio } = data;  \u00a0flipHorizontal = streamSettings.flipHorizontal; \u00a0detectedMaskThumbnailSize = maskDetectionsSettings.detectedMaskThumbnailSize; \u00a0srcImageRatio = imageRatio; \u00a0await tfc.setBackend(backend); \u00a0await tfc.ready(); \u00a0const [maskModel] = await &lt;i&gt;Promise&lt;\/i&gt;.all([ \u00a0\u00a0\u00a0tfconv.loadGraphModel( \u00a0\u00a0\u00a0\u00a0\u00a0`\/rgb_mask_classification_first\/MobileNetV${maskDetectionsSettings.mobileNetVersion}_${maskDetectionsSettings.mobileNetWeight}\/${maskDetectionsSettings.mobileNetType}\/model.json`, \u00a0\u00a0\u00a0), \u00a0]);  \u00a0detectedMaskThumbnailCanvas = new &lt;i&gt;OffscreenCanvas&lt;\/i&gt;(detectedMaskThumbnailSize, detectedMaskThumbnailSize); \u00a0detectedMaskThumbnailCanvasCtx = detectedMaskThumbnailCanvas.getContext('2d'); \u00a0return maskModel; }; <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u043c\u0430\u0441\u043a\u0438 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0433\u043b\u0430\u0437, \u0443\u0448\u0435\u0439, \u043d\u043e\u0441\u0430 \u0438 \u0440\u0442\u0430 \u0438 \u0432\u044b\u0440\u043e\u0432\u043d\u0435\u043d\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0435\u0440\u043d\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u043b\u0438\u0446\u0430.<\/p>\n<pre><code class=\"plaintext\">this.maskDetectionWorker.postMessage({ \u00a0type: 'detectMask', \u00a0prediction: lastItem!.data.predictions[0], \u00a0imageDataToProcess, \u00a0lastIndex: lastItem!.index, }); <\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438<\/p>\n<pre><code class=\"plaintext\">export const detectMask = async (data, maskModel) =&gt; { \u00a0let { prediction, imageDataToProcess, lastIndex } = data; \u00a0const masksScores = []; \u00a0const maskLandmarks = &lt;i&gt;JSON&lt;\/i&gt;.parse(&lt;i&gt;JSON&lt;\/i&gt;.stringify(prediction.landmarks));  \u00a0if (flipHorizontal) { \u00a0\u00a0\u00a0for (let j = 0; j &lt; maskLandmarks.length; j++) { \u00a0\u00a0\u00a0\u00a0\u00a0maskLandmarks[j][0] = srcImageRatio.faceDetectionImageWidth - maskLandmarks[j][0]; \u00a0\u00a0\u00a0} \u00a0} \u00a0\/\/ Draw thumbnail with mask \u00a0detectedMaskThumbnailCanvasCtx.putImageData(imageDataToProcess, 0, 0); \u00a0\/\/ Detect mask via NN \u00a0let predictionTensor = tfc.tidy(() =&gt; { \u00a0\u00a0\u00a0let maskDetectionSnapshotFromPixels = tfc.browser.&lt;i&gt;fromPixels&lt;\/i&gt;(detectedMaskThumbnailCanvas); \u00a0\u00a0\u00a0let maskDetectionSnapshotFromPixelsFlot32 = tfc.&lt;i&gt;cast&lt;\/i&gt;(maskDetectionSnapshotFromPixels, 'float32'); \u00a0\u00a0\u00a0let expandedDims = maskDetectionSnapshotFromPixelsFlot32.expandDims(0);  \u00a0\u00a0\u00a0return maskModel.predict(expandedDims); \u00a0}); \u00a0\/\/ Put mask detection result into the returned array \u00a0try { \u00a0\u00a0\u00a0masksScores.push(predictionTensor.dataSync()[0].toFixed(4)); \u00a0} finally { \u00a0\u00a0\u00a0predictionTensor.dispose(); \u00a0\u00a0\u00a0predictionTensor = null; \u00a0}  \u00a0return { \u00a0\u00a0\u00a0masksScores, \u00a0\u00a0\u00a0lastIndex, \u00a0}; }; <\/code><\/pre>\n<p>  \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u043c\u0430\u0441\u043a\u0430 \u0435\u0441\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0438\u0437 \u0432\u043e\u0440\u043a\u0435\u0440\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0442\u044c \u0438\u043b\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0442\u0440\u044d\u0448\u0445\u043e\u043b\u0434 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u043c\u0430\u0441\u043a\u0438. \u041f\u043e lastIndex \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043b\u0438\u0446\u043e \u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043c\u0430\u0441\u043a\u0438 \u0438 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0443.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435:<\/h2>\n<p>  \u041d\u0430\u0434\u0435\u044e\u0441\u044c \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 ML \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 \u043f\u0443\u0442\u044f\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0442\u0440\u044e\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/563212\/\"> https:\/\/habr.com\/ru\/post\/563212\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/-n\/bv\/hz\/-nbvhzxzi7k4k4djb2xqv6r1ntk.png\" alt=\"\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430 \u0438 \u043c\u0430\u0441\u043a\u0438\"><br \/>  \u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 <a href=\"https:\/\/habr.com\/ru\/post\/547038\/\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043e \u0442\u043e\u043c, \u043c\u043e\u0436\u043d\u043e \u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0435 (\u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043b\u0438\u0446\u0430 \u0438 \u043c\u0430\u0441\u043a\u0438) \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u0445 \u043a \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432.<br \/>  \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-325242","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/325242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=325242"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/325242\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=325242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=325242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=325242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}