privatevoidbtnRun_Click(objectsender,EventArgse){Task.Run(()=>Play());}privatevoidPlay(){using(varvideo=newVideoCapture(@".\768x576.avi")){varcolor_diff=newMat();vargray_diff=newMat();varblack_diff=newMat();varhist_color=newMat();varhist_gray=newMat();varmask=newMat();varorientation=newMat();doubleduration=1.0;varLINE_LENGTH_ALL=60;varLINE_LENGTH_GRID=20;varGRID_WIDTH=40;varCIRCLE_RADIUS=2;varframe_next=newMat();varend_flag=video.Read(frame_next);varframe_pre=frame_next.Clone();varwidth=video.FrameWidth;varheight=video.FrameHeight;varmotion_history=newMat<float>(height,width);intcount=0;varsw=System.Diagnostics.Stopwatch.StartNew();while(end_flag){Cv2.Absdiff(frame_next,frame_pre,color_diff);Cv2.CvtColor(color_diff,gray_diff,ColorConversionCodes.BGR2GRAY);Cv2.Threshold(gray_diff,black_diff,30,1,ThresholdTypes.Binary);vartimestamp=sw.Elapsed.TotalSeconds;// 履歴画像の更新CvOptFlow.UpdateMotionHistory(black_diff,motion_history,timestamp,duration);Cv2.Normalize(motion_history,hist_gray,0,255,NormTypes.MinMax,MatType.CV_8UC1);Cv2.CvtColor(hist_gray,hist_color,ColorConversionCodes.GRAY2BGR);// 履歴画像のモーション方向の計算doubledelta1=0.25;doubledelta2=0.05;intapertureSize=5;CvOptFlow.CalcMotionGradient(motion_history,mask,orientation,delta1,delta2,apertureSize);doubleangle_deg;doubleangle_rad;// 各座標のモーション方向を緑色の線で描画varwidth_i=GRID_WIDTH;while(width_i<width){varheight_i=GRID_WIDTH;while(height_i<height){Cv2.Circle(hist_color,width_i,height_i,CIRCLE_RADIUS,newScalar(0,255,0),2,LineTypes.AntiAlias);angle_deg=orientation.At<float>(height_i-1,width_i-1);if(angle_deg>0){angle_rad=angle_deg*Math.PI/180;Cv2.Line(hist_color,width_i,height_i,(int)(width_i+Math.Cos(angle_rad)*LINE_LENGTH_GRID),(int)(height_i+Math.Sin(angle_rad)*LINE_LENGTH_GRID),newScalar(0,255,0),2,LineTypes.AntiAlias);}height_i+=GRID_WIDTH;}width_i+=GRID_WIDTH;}// 全体的なモーション方向を計算angle_deg=CvOptFlow.CalcGlobalOrientation(orientation,mask,motion_history,timestamp,duration);// 全体のモーション方向を黄色い線で描画Cv2.Circle(hist_color,width/2,height/2,CIRCLE_RADIUS,newScalar(0,215,255),2,LineTypes.AntiAlias);angle_rad=angle_deg*Math.PI/180;Cv2.Line(hist_color,width/2,height/2,(int)(width/2+Math.Cos(angle_rad)*LINE_LENGTH_ALL),(int)(height/2+Math.Sin(angle_rad)*LINE_LENGTH_ALL),newScalar(0,215,255),2,LineTypes.AntiAlias);Invoke(newAction(()=>{Cv2.ImShow("hist_color",hist_color);}));vartime=(int)(count*(1000/video.Fps)-sw.Elapsed.TotalMilliseconds);if(time>0){System.Threading.Thread.Sleep(time);}frame_pre=frame_next.Clone();end_flag=video.Read(frame_next);++count;}}}
※ソースコードはこちらのサイトを参考にさせていただきました。
OpenCVを使ったモーションテンプレート解析 @hitomatagi
※動画ファイルはこちらのサイトからダウンロードさせていただきました。
opencv-tests @shirmung