github js程序怎么用(登顶GitHub趋势榜标星1.8k)
整理 | 夕颜
出品 | CSDN(ID:CSDNnews)
今天,一个名为 Real-Time-Person-Removal(实时人物去除)项目在GitHub上火了,登上近日GitHub Trending第一,目前已经获得1.8k star。
这个项目的神奇之处在于,只需要在网络浏览器中使用JavaScript,用200多行TensorFlow.js代码,就可以实时让视频画面中的人物对象从复杂的背景中凭空消失!
这虽然不能让你在现实生活中像哈利·波特一样隐身的梦想成真,但至少在视频、动画里可以体验一把隐身的快感!
首先奉上GitHub地址:https://github.com/jasonmayes/Real-Time-Person-Removal
这个项目能干啥?
本项目的作者@jasonmayes(Jason Mayes)是谷歌的一名资深开发者,是机器智能研究和高级开发的倡导者,作为一名TensorFlow.js专家,他拥有超过15年使用新技术开发创新Web解决方案的经验。
他在项目介绍中表示,这段代码的目的在于随着时间的推移学习视频背景的构成,让作者可以尝试从背景中移除任何人物,而所有效果都是使用TensorFlow.js在浏览器中实时实现的。
但同时作者表示,这只是一个实验,并非在所有情况下都是完美的。
消失的人
废话不多说,上代码!
可能有人会觉得在复杂的背景下实现“隐身”是很复杂的吧,而且还是实时的,但实际上实现这样的效果却只需要200多行JS代码:
1/**
2*@License
3*Copyright2018GoogleLLC.AllRightsReserved.
4*LicensedundertheApacheLicense,Version2.0(the"License");
5*youmaynotusethisfileexceptincompliancewiththeLicense.
6*YoumayobtainacopyoftheLicenseat
7*
8*http://www.apache.org/licenses/LICENSE-2.0
9*
10*Unlessrequiredbyapplicablelaworagreedtoinwriting,software
11*distributedundertheLicenseisdistributedonan"ASIS"BASIS,
12*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
13*SeetheLicenseforthespecificlanguagegoverningpermissionsand
14*limitationsundertheLicense.
15*=============================================================================
16*/
17
18/********************************************************************
19*Real-Time-Person-RemovalCreatedbyJasonMayes2020.
20*
21*GetlatestcodeonmyGithub:
22*https://github.com/jasonmayes/Real-Time-Person-Removal
23*
24*Gotquestions?Reachouttomeonsocial:
25*Twitter:@jason_mayes
26*LinkedIn:https://www.linkedin.com/in/creativetech
27********************************************************************/
28
29constvideo=document.getElementById('webcam');
30constliveView=document.getElementById('liveView');
31constdemosSection=document.getElementById('demos');
32constDEBUG=false;
33
34//Anobjecttoconfigureparameterstosetforthebodypixmodel.
35//Seegithubdocsforexplanations.
36constbodyPixProperties={
37architecture:'MobileNetV1',
38outputStride:16,
39multiplier:0.75,
40quantBytes:4
41};
42
43//Anobjecttoconfigureparametersfordetection.Ihaveraised
44//thesegmentationthresholdto90%confidencetoreducethe
45//numberoffalsepositives.
46constsegmentationProperties={
47flipHorizontal:false,
48internalResolution:'high',
49segmentationThreshold:0.9
50};
51
52//Mustbeeven.Thesizeofsquarewewishtosearchforbodyparts.
53//Thisisthesmallestareathatwillrender/notrenderdependingon
54//ifabodypartisfoundinthatsquare.
55constSEARCH_RADIUS=300;
56constSEARCH_OFFSET=SEARCH_RADIUS/2;
57
58
59//RESOLUTION_MINshouldbesmallerthanSEARCHRADIUS.About10xsmallerseemsto
60//workwell.Effectsoverlapinsearchspacetocleanupbodyoverspillforthings
61//thatwerenotclassifiedasbodybutinfactwere.
62constRESOLUTION_MIN=20;
63
64
65//Renderreturnedsegmentationdatatoagivencanvascontext.
66functionprocessSegmentation(canvas,segmentation){
67varctx=canvas.getContext('2d');
68
69//Getdatafromouroverlaycanvaswhichisattemptingtoestimatebackground.
70varimageData=ctx.getImageData(0,0,canvas.width,canvas.height);
71vardata=imageData.data;
72
73//Getdatafromthelivewebcamviewwhichhasalldata.
74varliveData=videoRenderCanvasCtx.getImageData(0,0,canvas.width,canvas.height);
75vardataL=liveData.data;
76
77//Nowloopthroughandseeifpixelscontainhumanparts.Ifnot,update
78//backgoundunderstandingwithnewdata.
79for(letx=RESOLUTION_MIN;x<canvas.width;x =RESOLUTION_MIN){
80for(lety=RESOLUTION_MIN;y<canvas.height;y =RESOLUTION_MIN){
81//Convertxyco-ordstoarrayoffset.
82letn=y*canvas.width x;
83
84letfoundBodyPartNearby=false;
85
86//Let'scheckaroundagivenpixelifanyotherpixelswerebodylike.
87letyMin=y-SEARCH_OFFSET;
88yMin=yMin<0?0:yMin;
89
90letyMax=y SEARCH_OFFSET;
91yMax=yMax>canvas.height?canvas.height:yMax;
92
93letxMin=x-SEARCH_OFFSET;
94xMin=xMin<0?0:xMin;
95
96letxMax=x SEARCH_OFFSET;
97xMax=xMax>canvas.width?canvas.width:xMax;
98
99for(leti=xMin;i<xMax;i ){
100for(letj=yMin;j<yMax;j ){
101
102letoffset=j*canvas.width i;
103//Ifanyofthepixelsinthesquareweareanalysinghasabody
104//part,markascontaminated.
105if(segmentation.data[offset]!==0){
106foundBodyPartNearby=true;
107break;
108}
109}
110}
111
112//Updatepatchifpatchwasclean.
113if(!foundBodyPartNearby){
114for(leti=xMin;i<xMax;i ){
115for(letj=yMin;j<yMax;j ){
116//Convertxyco-ordstoarrayoffset.
117letoffset=j*canvas.width i;
118
119
120data[offset*4]=dataL[offset*4];
121data[offset*4 1]=dataL[offset*4 1];
122data[offset*4 2]=dataL[offset*4 2];
123data[offset*4 3]=255;
124}
125}
126}else{
127if(DEBUG){
128for(leti=xMin;i<xMax;i ){
129for(letj=yMin;j<yMax;j ){
130//Convertxyco-ordstoarrayoffset.
131letoffset=j*canvas.width i;
132
133
134data[offset*4]=255;
135data[offset*4 1]=0;
136data[offset*4 2]=0;
137data[offset*4 3]=255;
138}
139}
140}
141}
142
143
144}
145}
146ctx.putImageData(imageData,0,0);
147}
148
149//Let'sloadthemodelwithourparametersdefinedabove.
150//Beforewecanusebodypixclasswemustwaitforittofinish
151//loading.MachineLearningmodelscanbelargeandtakeamomentto
152//geteverythingneededtorun.
153varmodelHasLoaded=false;
154varmodel=undefined;
155
156model=bodyPix.load(bodyPixProperties).then(function(loadedModel){
157model=loadedModel;
158modelHasLoaded=true;
159//Showdemosectionnowmodelisreadytouse.
160demosSection.classList.remove('invisible');
161});
162
163/********************************************************************
164//Continuouslygrabimagefromwebcamstreamandclassifyit.
165********************************************************************/
166
167varpreviousSegmentationComplete=true;
168
169//Checkifwebcamaccessissupported.
170functionhasGetUserMedia(){
171return!!(navigator.mediaDevices&&
172navigator.mediaDevices.getUserMedia);
173}
174
175//Thisfunctionwillrepeatidlycallitselfwhenthebrowserisreadytoprocess
176//thenextframefromwebcam.
177functionpredictWebcam(){
178if(previousSegmentationComplete){
179//Copythevideoframefromwebcamtoatemporycanvasinmemoryonly(notintheDOM).
180videoRenderCanvasCtx.drawImage(video,0,0);
181previousSegmentationComplete=false;
182//Nowclassifythecanvasimagewehaveavailable.
183model.segmentPerson(videoRenderCanvas,segmentationProperties).then(function(segmentation){
184processSegmentation(webcamCanvas,segmentation);
185previousSegmentationComplete=true;
186});
187}
188
189//Callthisfunctionagaintokeeppredictingwhenthebrowserisready.
190window.requestAnimationFrame(predictWebcam);
191}
192
193//Enablethelivewebcamviewandstartclassification.
194functionenableCam(event){
195if(!modelHasLoaded){
196return;
197}
198
199//Hidethebutton.
200event.target.classList.add('removed');
201
202//getUsermediaparameters.
203constconstraints={
204video:true
205};
206
207//Activatethewebcamstream.
208navigator.mediaDevices.getUserMedia(constraints).then(function(stream){
209video.addEventListener('loadedmetadata',function(){
210//Updatewidthsandheightsoncevideoissuccessfullyplayedotherwise
211//itwillhavewidthandheightofzeroinitiallycausingclassification
212//tofail.
213webcamCanvas.width=video.videoWidth;
214webcamCanvas.height=video.videoHeight;
215videoRenderCanvas.width=video.videoWidth;
216videoRenderCanvas.height=video.videoHeight;
217letwebcamCanvasCtx=webcamCanvas.getContext('2d');
218webcamCanvasCtx.drawImage(video,0,0);
219});
220
221video.srcObject=stream;
222
223video.addEventListener('loadeddata',predictWebcam);
224});
225}
226
227//Wewillcreateatemporycanvastorendertostoreframesfrom
228//thewebcamstreamforclassification.
229varvideoRenderCanvas=document.createElement('canvas');
230varvideoRenderCanvasCtx=videoRenderCanvas.getContext('2d');
231
232//LetscreateacanvastorenderourfindingstotheDOM.
233varwebcamCanvas=document.createElement('canvas');
234webcamCanvas.setAttribute('class','overlay');
235liveView.appendChild(webcamCanvas);
236
237//Ifwebcamsupported,addeventlistenertobuttonforwhenuser
238//wantstoactivateit.
239if(hasGetUserMedia()){
240constenableWebcamButton=document.getElementById('webcamButton');
241enableWebcamButton.addEventListener('click',enableCam);
242}else{
243console.warn('getUserMedia()isnotsupportedbyyourbrowser');
244}
CSS:
1/**
2*@license
3*Copyright2018GoogleLLC.AllRightsReserved.
4*LicensedundertheApacheLicense,Version2.0(the"License");
5*youmaynotusethisfileexceptincompliancewiththeLicense.
6*YoumayobtainacopyoftheLicenseat
7*
8*http://www.apache.org/licenses/LICENSE-2.0
9*
10*Unlessrequiredbyapplicablelaworagreedtoinwriting,software
11*distributedundertheLicenseisdistributedonan"ASIS"BASIS,
12*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
13*SeetheLicenseforthespecificlanguagegoverningpermissionsand
14*limitationsundertheLicense.
15*=============================================================================
16*/
17
18
19
20
21/******************************************************
22*StylesheetbyJasonMayes2020.
23*
24*GetlatestcodeonmyGithub:
25*https://github.com/jasonmayes/Real-Time-Person-Removal
26*Gotquestions?Reachouttomeonsocial:
27*Twitter:@jason_mayes
28*LinkedIn:https://www.linkedin.com/in/creativetech
29*****************************************************/
30
31
32
33
34body{
35font-family:helvetica,arial,sans-serif;
36margin:2em;
37color:#3D3D3D;
38}
39
40
41
42
43h1{
44font-style:italic;
45color:#FF6F00;
46}
47
48
49
50
51h2{
52clear:both;
53}
54
55
56
57
58em{
59font-weight:bold;
60}
61
62
63
64
65video{
66clear:both;
67display:block;
68}
69
70
71
72
73section{
74opacity:1;
75transition:opacity500msease-in-out;
76}
77
78
79
80
81header,footer{
82clear:both;
83}
84
85
86
87
88button{
89z-index:1000;
90position:relative;
91}
92
93
94
95
96.removed{
97display:none;
98}
99
100
101
102
103.invisible{
104opacity:0.2;
105}
106
107
108
109
110.note{
111font-style:italic;
112font-size:130%;
113}
114
115
116
117
118.webcam{
119position:relative;
120}
121
122
123
124
125.webcam,.classifyOnClick{
126position:relative;
127float:left;
128width:48%;
129margin:2%1%;
130cursor:pointer;
131}
132
133
134
135
136.webcamp,.classifyOnClickp{
137position:absolute;
138padding:5px;
139background-color:rgba(255,111,0,0.85);
140color:#FFF;
141border:1pxdashedrgba(255,255,255,0.7);
142z-index:2;
143font-size:12px;
144}
145
146
147
148
149.highlighter{
150background:rgba(0,255,0,0.25);
151border:1pxdashed#fff;
152z-index:1;
153position:absolute;
154}
155
156
157
158
159.classifyOnClick{
160z-index:0;
161position:relative;
162}
163
164
165
166
167.classifyOnClickcanvas,.webcamcanvas.overlay{
168opacity:1;
169
170top:0;
171left:0;
172z-index:2;
173}
174
175
176
177
178#liveView{
179transform-origi
Html:
1<!DOCTYPEhtml>
2<htmllang="en">
3<head>
4<title>DisappearingPeopleProject</title>
5<metacharset="utf-8">
6<metahttp-equiv="X-UA-Compatible"content="IE=edge">
7<metaname="viewport"content="width=device-width,initial-scale=1">
8<metaname="author"content="JasonMayes">
9
10
11
12
13<!--Importthewebpage'sstylesheet-->
14<linkrel="stylesheet"href="/style.css">
15
16
17
18
19<!--ImportTensorFlow.jslibrary-->
20<scriptsrc="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js"type="text/javascript"></script>
21</head>
22<body>
23<h1>DisappearingPeopleProject</h1>
24
25<headerclass="note">
26<h2>RemovingpeoplefromcomplexbackgroundsinrealtimeusingTensorFlow.js</h2>
27</header>
28
29
30
31
32<h2>Howtouse</h2>
33<p>Pleasewaitforthemodeltoloadbeforetryingthedemosbelowatwhichpointtheywillbecomevisiblewhenreadytouse.</p>
34<p>Hereisavideoofwhatyoucanexpecttoachieveusingmycustomalgorithm.Thetopistheactualfootage,thebottomvideoiswiththerealtimeremovalofpeopleworkinginJavaScript!</p>
35<iframewidth="540"height="812"src="https://www.youtube.com/embed/0LqEuc32uTc?controls=0&autoplay=1"frameborder="0"allow="accelerometer;autoplay;encrypted-media;gyroscope;picture-in-picture"allowfullscreen></iframe>
36
37<sectionid="demos"class="invisible">
38
39
40
41
42<h2>Demo:Webcamliveremoval</h2>
43<p>Trythisoutusingyourwebcam.Standafewfeetawayfromyourwebcamandstartwalkingaround...Watchasyouslowlydisappearinthebottompreview.</p>
44
45<divid="liveView"class="webcam">
46<buttonid="webcamButton">EnableWebcam</button>
47<videoid="webcam"autoplay></video>
48</div>
49</section>
50
51
52
53
54
55<!--IncludetheGlitchbuttontoshowwhatthewebpageisaboutand
56tomakeiteasierforfolkstoviewsourceandremix-->
57<divclass="glitchButton"style="position:fixed;top:20px;right:20px;"></div>
58<scriptsrc="https://button.glitch.me/button.js"></script>
59
60<!--Loadthebodypixmodeltorecognizebodypartsinimages-->
61<scriptsrc="https://cdn.jsdelivr.net/npm/@tensorflow-models/body-pix@2.0"></script>
62
63<!--Importthepage'sJavaScripttodosomestuff-->
64<scriptsrc="/script.js"defer></script>
65</bod
66
实时演示
你也可以在自己的Web浏览器中根据自己的喜好试着复现一下:
Codepen.io:https://codepen.io/jasonmayes/pen/GRJqgma
Glitch.com:https://glitch.com/~disappearing-people
等待模型加载完成,然后就可以使用了。
这是使用作者自定义算法实现的视频。上半部分是实际镜头,底部是用JavaScript实时删除人物的视频。
用你自己的网络摄像头试一下,要距离摄像头几英尺远,然后来回走动,在底部预览中你会慢慢从画面中消失。赶快试试吧,使用效果别忘了留言和大家一起分享哦!
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com