通过COM组件在Web上实现Kinect骨骼追踪、声控截屏保存的功能
????? 前些天在淘寶上訂購了Kinect,剛剛到貨,對于這個新鮮的玩意兒,自己趕緊卸開包裹,插上PC機,先前已經裝好了Kinect SDK(官方下載地址:http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/download.aspx)
希望自己的機子能夠跑得動DEMO,最后送了一口氣,正常運行:)。當然了,既然Kinect已經入手,自己打算也小小地練一下手,因為自己目前主要從事Web方面的開發,自然想到,如果能夠在網頁上能夠運行Kinect該有多好啊!后來考慮了三種方案:
?
1)在Web應用程序上引用Kinect SDK的DLL(Microsoft.Research.Kinect.dll),可以正常引用,通過img標簽或者頁面輸出圖像流的方式顯示Bitmap圖像,當然你還需要定時刷新頁面,當然這種方式的缺點可想而知,就是不夠實時性。并且增加了服務器的負擔。
2)通過Silverlight應用程序的方式,但是目前SL4/5均不支持Kinect的dll,這是由于Kinect是個.Net Framework的類庫,非SL支持的客戶端類庫。另外,在非OOB的模式下,也SL目前不支持自定義的COM組件,希望微軟團隊將來能夠讓SL也支持Kinect。
3)通過ActiveX的COM組件技術,通過開發窗體組件,產生ActiveX插件,嵌套在IE瀏覽器中進行顯示。
?
????? 于是,我考慮了最簡單的方式,通過ActiveX的技術在網頁上對Kinect相關基本功能進行展示。
本文會分成三個部分來敘述:
一、ActiveX插件的實現;
二、Kinect基本功能的實現;
三、ActiveX的安裝;
?
具體實現
第一部分? ActiveX插件的實現
1) 創建一個新的解決方案,叫做MyFirstKinect。
?
2)接著創建一個Windows窗體控件庫,用于做ActiveX的插件,項目叫做MyFirstKinectControl
?
3)在MyFirstKinectControl項目的右鍵點擊“屬性”,選擇“生成”項:
將”為COM互操作注冊”勾上,然后關閉。
?
4)打開AssemblyInfo.cs:
將ComVisible設置為true,并將下面這行注釋掉(這個很重要,切記!)
對應地,需要在自定義窗體控件上加上該Guid:
至此,一個基本的COM組件已經實現了,現在來看下該如何在瀏覽器上顯示ActiveX插件。
?
5)打開Visual Studio的命令提示符:輸入“oleview”,頁面會打開一個“OLE/COM Object Viewer”應用程序:
由于我是使用C#創建的COM組件,于是在“.NET Category”尋找剛才創建的”MyFirstKinectControl”:
右鍵選擇“Copy HTML<object> Tag to Clipboard”,得到:
?
6)然后我在自定義窗體控件上(SkeletalControl.cs),隨便加入點東西上去,比如按鈕、標簽等等。
?
7)然后新創建一個Web應用程序的項目(WebApp),重新編譯。將上面的代碼復制到Html或相關頁面中。
在IE正常狀態下,發現插件無法正常顯示。于是,把瀏覽器的安全級別調低:
繼續運行:
就可以正常顯示插件了。當然這種方式造成了瀏覽器使用上的危害性,所以不建議這樣來使用。
?
8)如果想要在不調整瀏覽器安全級別的情況下,又能夠在瀏覽器上正常顯示插件,這樣就必須調整一些代碼:
[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IObjectSafety {// methods void GetInterfacceSafyOptions(System.Int32 riid,out System.Int32 pdwSupportedOptions,out System.Int32 pdwEnabledOptions);void SetInterfaceSafetyOptions(System.Int32 riid,System.Int32 dwOptionsSetMask,System.Int32 dwEnabledOptions); }添加一個IObjectSafety的接口,并且Guid是固定的。
SkeletalControl繼承這個接口:
[Guid("d678c286-b26f-4f72-ae22-2dcb1952851b")] public partial class SkeletalControl : UserControl, IObjectSafety {public SkeletalControl(){InitializeComponent();}#region IObjectSafety 成員public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions){pdwSupportedOptions = 1;pdwEnabledOptions = 2;}public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions){}#endregion }接著重新編譯并運行Web程序,運行結果為:
這樣,你就不需要調整瀏覽器的安全級別,就可以正常顯示ActiveX插件了。
?
第二部分 Kinect的基本功能實現
?
????? 從這一部分起,我將開始介紹Kinect如何實現一些基本功能:包括視頻監控、骨骼追蹤以及聲控截屏的功能。
1)項目中引用以下的Dll:
其中Microsoft.Research.Kinect就是在電腦上裝好Kinect SDK后可以引用的類庫;
另外地,Coding4Fun.Kinect.WinForm是一個基于SDK的DLL的相關封裝好的一些功能類庫,網上開源地址為:http://c4fkinect.codeplex.com/;
Microsoft.Speech是一個微軟提供的語音識別的基本類庫,也包含相關的SDK,并且和Kinect進行綁定的相關類庫,具體地址在Kinect SDK中的相關文檔也有說明:
- Speech Platform Runtime (v10.2) x86. Even on x64 platforms the x86 needs to be used because the MSR Kinect SDK runtime is x86
? http://www.microsoft.com/downloads/en/details.aspx?FamilyID=bb0f72cb-b86b-46d1-bf06-665895a313c7
- Speech Platform SDK (v10.2)
? http://www.microsoft.com/downloads/en/details.aspx?FamilyID=1b1604d3-4f66-4241-9a21-90a294a5c9a4&displaylang=en
- Kinect English Language Pack: MSKinectLangPack_enUS.msi (available in the same location as the Kinect For Windows SDK)
?
2)在控件頁面上創建三個PictureBox的控件:
三個圖片框將分別用來存放:深度圖視頻、普通視頻、以及骨骼追蹤。
?
3)編寫相關代碼:
using Microsoft.Research.Kinect.Nui; using Coding4Fun.Kinect.WinForm;Runtime nui;private void SkeletalControl_Load(object sender, EventArgs e) {nui = new Runtime();try{nui.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseColor);}catch (InvalidOperationException){MessageBox.Show("Runtime initialization failed. Please make sure Kinect device is plugged in.");return;}try{nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);}catch (InvalidOperationException){MessageBox.Show("Failed to open stream. Please make sure to specify a supported image type and resolution.");return;}nui.DepthFrameReady += new EventHandler(nui_DepthFrameReady);nui.SkeletonFrameReady += new EventHandler(nui_SkeletonFrameReady);nui.VideoFrameReady += new EventHandler(nui_VideoFrameReady); }其中DepthFrameReady,VideoFrameReady,SkeletonFrameReady分別用來追蹤深度圖、普通視圖、骨骼圖所產生的事件。
void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e){pictureBoxDepth.Image = e.ImageFrame.ToBitmap();}void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e){pictureBoxVideo.Image = e.ImageFrame.ToBitmap();}void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e){Graphics graphics = this.pictureBoxSkeleton.CreateGraphics();pictureBoxSkeleton.Refresh();SkeletonFrame skeletonFrame = e.SkeletonFrame;int iSkeleton = 0;foreach (SkeletonData data in skeletonFrame.Skeletons){if (SkeletonTrackingState.Tracked == data.TrackingState){// Draw bonesgraphics.DrawLines(pen, getBodySegment(data.Joints, JointID.HipCenter, JointID.Spine, JointID.ShoulderCenter, JointID.Head));graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.ShoulderCenter, JointID.ShoulderLeft, JointID.ElbowLeft, JointID.WristLeft, JointID.HandLeft));graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.ShoulderCenter, JointID.ShoulderRight, JointID.ElbowRight, JointID.WristRight, JointID.HandRight));graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.HipCenter, JointID.HipLeft, JointID.KneeLeft, JointID.AnkleLeft, JointID.FootLeft));graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.HipCenter, JointID.HipRight, JointID.KneeRight, JointID.AnkleRight, JointID.FootRight));}iSkeleton++;} // for each skeleton}private Point getDisplayPosition(Joint joint){float depthX, depthY;nui.SkeletonEngine.SkeletonToDepthImage(joint.Position, out depthX, out depthY);depthX = Math.Max(0, Math.Min(depthX * 320, 320)); //convert to 320, 240 spacedepthY = Math.Max(0, Math.Min(depthY * 240, 240)); //convert to 320, 240 spaceint colorX, colorY;ImageViewArea iv = new ImageViewArea();// only ImageResolution.Resolution640x480 is supported at this pointnui.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(ImageResolution.Resolution640x480, iv, (int)depthX, (int)depthY, (short)0, out colorX, out colorY);// map back to skeleton.Width & skeleton.Heightreturn new Point((int)(this.pictureBoxSkeleton.Width * colorX / 640.0), (int)(this.pictureBoxSkeleton.Height * colorY / 480));}Point[] getBodySegment(Microsoft.Research.Kinect.Nui.JointsCollection joints, params JointID[] ids){Point[] points = new Point[ids.Length];for (int i = 0; i < ids.Length; ++i){points[i] = getDisplayPosition(joints[ids[i]]);}return points;}其中,getBodySegment,getDisplayPosition方法將確定骨骼追蹤中的20個骨骼點的具體位置。
?
4)接著編譯并運行程序,查看Web頁面,連上Kinect傳感設備,運行結果為:
?
5)接著,來實現一些聲控截屏功能:
using Microsoft.Research.Kinect.Audio; using Microsoft.Speech.AudioFormat; using Microsoft.Speech.Recognition;private const string RecognizerId = "SR_MS_en-US_Kinect_10.0"; private KinectAudioSource kinectSource; private SpeechRecognitionEngine sre;// 聲控截屏功能 RecognizerInfo ri = SpeechRecognitionEngine.InstalledRecognizers().Where(r => r.Id == RecognizerId).FirstOrDefault(); if (ri == null) {MessageBox.Show("Could not find speech recognizer: {0}. Please refer to the sample requirements.", RecognizerId);return; }sre = new SpeechRecognitionEngine(ri.Id);var colors = new Choices(); colors.Add("cut"); //添加cut的英文發音var gb = new GrammarBuilder(); gb.Culture = ri.Culture; //本地化處理 gb.Append(colors);var g = new Grammar(gb);sre.LoadGrammar(g); sre.SpeechRecognized += SreSpeechRecognized; //發音匹配以后的后續處理事件 sre.SpeechHypothesized += SreSpeechHypothesized; //發音的英文識別事件 sre.SpeechRecognitionRejected += SreSpeechRecognitionRejected; //拒絕之后的后續處理事件var thread = new Thread(StartDMO); thread.Start();private void StartDMO(){kinectSource = new KinectAudioSource();kinectSource.SystemMode = SystemMode.OptibeamArrayOnly;kinectSource.FeatureMode = true;kinectSource.AutomaticGainControl = false;kinectSource.MicArrayMode = MicArrayMode.MicArrayAdaptiveBeam;var kinectStream = kinectSource.Start();sre.SetInputToAudioStream(kinectStream, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1,32000, 2, null));sre.RecognizeAsync(RecognizeMode.Multiple);}void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e){}void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e){}void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e){lblSpeech.Text = e.Result.Text;//屏幕截屏Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);Graphics g = Graphics.FromImage(bmp);g.CopyFromScreen(0, 0, 0, 0, bmp.Size);g.Dispose();SaveFileDialog fileDialog = new SaveFileDialog();fileDialog.Filter = "JPG File(*.jpg)|*.jpg||";DialogResult result = fileDialog.ShowDialog();if (result == DialogResult.OK){bmp.Save(fileDialog.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);}}在代碼中發現,var colors = new Choices(); colors.Add("cut"); //添加cut的英文發音 ,這樣當你在傳感器前發音“cut”就會進行相關事件的觸發,當發音和英文庫的單詞語音識別向匹配時,將觸發SreSpeechRecognized事件。執行屏幕截圖的相關操作。
(注:記得這里需要添加代碼gb.Culture = ri.Culture; 如果沒有這句代碼,有可能導致sre.LoadGrammar(g); 語法加載失敗!)
?
6. 運行結果:
我將剛才發的英文單詞,通過文本的方式顯示在頁面中。
?
第三部分 ActiveX插件的安裝
????? 由于本文使用的是C#來開發ActiveX插件,所以當你需要安裝插件的時候,需要使用regasm命令。那么開始編寫腳本:
1)安裝腳本:
@echo off echo 開始安裝MyFirstKinectControl...... echo. set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319 if exist "%FrameworkPath%\regasm.exe" goto :Start set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v3.5 if exist "%FrameworkPath%\regasm.exe" goto :Start set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v3.0 if exist "%FrameworkPath%\regasm.exe" goto :Start set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727 if exist "%FrameworkPath%\regasm.exe" goto :Start set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v1.1.4322 if exist "%FrameworkPath%\regasm.exe" goto :Startv set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\1.0.3705 if exist "%FrameworkPath%\regasm.exe" goto :Start:Start %FrameworkPath%\regasm.exe MyFirstKinectControl.dll /codebase MyFirstKinectControl.dllecho 安裝完成! echo.pause?
2)卸載腳本:
@echo off echo 開始卸載MyFirstKinectControl...... echo. set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319 if exist "%FrameworkPath%\regasm.exe" goto :Start set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v3.5 if exist "%FrameworkPath%\regasm.exe" goto :Start set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v3.0 if exist "%FrameworkPath%\regasm.exe" goto :Start set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727 if exist "%FrameworkPath%\regasm.exe" goto :Start set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v1.1.4322 if exist "%FrameworkPath%\regasm.exe" goto :Startv set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\1.0.3705 if exist "%FrameworkPath%\regasm.exe" goto :Start:Start %FrameworkPath%\regasm.exe /u MyFirstKinectControl.dllecho 卸載完成! echo.pause?
這樣通過注冊COM組件就可以實現Kinect的插件在瀏覽器上的展示。
?
附上本文的源代碼:MyFirstKinect.rar?? 謝謝大家閱讀!
轉載于:https://www.cnblogs.com/liping13599168/archive/2011/06/28/2091710.html
總結
以上是生活随笔為你收集整理的通过COM组件在Web上实现Kinect骨骼追踪、声控截屏保存的功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电子商务之网购魅力何在?(网购用户行为分
- 下一篇: 随即产生验证码