หากสังเกตโค้ดเดิม จะเห็นว่าทุกครั้งที่มีการอ่าน frame ของวิดีโอจาก Kinect จะมีการสร้างบิตแมพด้วยคำสั่ง BitmapSource.Create() เพื่อนำไปแสดงผล
สมมติว่าในหนึ่งวินาทีเราทำการอ่านภาพจากวิดีโอ 30 ภาพ ก็จะมีการสร้างบิตแมพถึง 30 ครั้ง ซึ่งก็จะใช้หน่วยความจำเพิ่มขึ้นเรื่อยๆ จนกระทั่ง .NET framework เห็นว่าใช้มากไป ก็จะเรียก garbage collector มาทำลายหน่วยความจำของบิตแมพที่เราไม่ได้ใช้แล้ว หน่วยความจำที่ใช้ก็จะลดลง แต่ต่อมาก็จะใช้เพิ่มขึ้นอีกตามบิตแมพที่สร้าง วนไปแบบนี้เรื่อยๆ
วิธีที่สามารถทำให้การใช้หน่วยความจำมีประสิทธิภาพมากขึ้น โดยไม่ขึ้นๆลงๆตามที่ได้อธิบายไป คือ การเปลี่ยนจากการใช้ BitmapSource มาเป็น WritableBitmap ซึ่งสามารถเขียนทับได้เรื่อยๆโดยไม่ต้องสร้างบิตแมพใหม่ ก็จะทำให้การใช้หน่วยความจำลดลงและคงที่มากกว่า
โค้ดใหม่ที่ปรับปรุงก็จะเป็นตามนี้ครับ สังเกตว่ามีการเปลี่ยนเฉพาะส่วนของเหตุการณ์ ColorImageFrameReadyEvent
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Microsoft.Kinect; namespace KinectCam { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { KinectSensor myKinect; private void Window_Loaded(object sender, RoutedEventArgs e) { //Check if there is any connecting Kinect if (KinectSensor.KinectSensors.Count == 0) { MessageBox.Show("No Kinect detected!", "Error"); //end this app Application.Current.Shutdown(); } //Try to initialize Kinect try { //Get the first Kinect connected to this computer myKinect = KinectSensor.KinectSensors[0]; //Enable the color video stream myKinect.ColorStream.Enable(); //Start the sensor myKinect.Start(); } catch { MessageBox.Show("Initialize Kinect failed!", "Error"); //end this app Application.Current.Shutdown(); } //Video event handler myKinect.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(myKinect_ColorFrameReady); } byte[] colorData = null; WriteableBitmap imageBitmap = null; void myKinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e) { using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) { //if get new video frame if (colorFrame == null) return; //create an array of pixel data if(colorData==null) colorData = new byte[colorFrame.PixelDataLength]; //extract pixel data from the frame to the array colorFrame.CopyPixelDataTo(colorData); //For the first video frame, no bitmap, create a writable bitmap of video size if (imageBitmap == null) { imageBitmap = new WriteableBitmap( colorFrame.Width, colorFrame.Height, 96, //dpiX 96, //dpiY PixelFormats.Bgr32, null //palette:none ); } //For other video frames, write video data to bitmap imageBitmap.WritePixels( new Int32Rect(0, 0, colorFrame.Width, colorFrame.Height), colorData, //video data colorFrame.Width * colorFrame.BytesPerPixel, //stride 0 //offset to the array ); //set bitmap to image view kinectVideo.Source = imageBitmap; } } } }
No comments:
Post a Comment