i trying write application saves depth , color streams of kinect windows v2 image files (like png or jpg). so, used kinect sdk v2 examples(since have no prior experience c# or kinect api). modified colorbasics-wpf sample code achieve goal. here code convert color stream png files(the part modified reader_colorframearrived function):
//------------------------------------------------------------------------------ // <copyright file="mainwindow.xaml.cs" company="microsoft"> // copyright (c) microsoft corporation. rights reserved. // </copyright> //------------------------------------------------------------------------------ namespace microsoft.samples.kinect.colorbasics { using system; using system.componentmodel; using system.diagnostics; using system.globalization; using system.io; using system.windows; using system.windows.media; using system.windows.media.imaging; using microsoft.kinect; using system.collections.generic; /// <summary> /// interaction logic mainwindow /// </summary> public partial class mainwindow : window, inotifypropertychanged { static int count = 0; /// <summary> /// active kinect sensor /// </summary> private kinectsensor kinectsensor = null; /// <summary> /// reader color frames /// </summary> private colorframereader colorframereader = null; /// <summary> /// bitmap display /// </summary> private writeablebitmap colorbitmap = null; /// <summary> /// current status text display /// </summary> private string statustext = null; /// <summary> /// initializes new instance of mainwindow class. /// </summary> public mainwindow() { // kinectsensor object this.kinectsensor = kinectsensor.getdefault(); // open reader color frames this.colorframereader = this.kinectsensor.colorframesource.openreader(); // wire handler frame arrival this.colorframereader.framearrived += this.reader_colorframearrived; // create colorframedescription colorframesource using bgra format framedescription colorframedescription = this.kinectsensor.colorframesource.createframedescription(colorimageformat.bgra); // create bitmap display this.colorbitmap = new writeablebitmap(colorframedescription.width, colorframedescription.height, 96.0, 96.0, pixelformats.bgr32, null); // set isavailablechanged event notifier this.kinectsensor.isavailablechanged += this.sensor_isavailablechanged; // open sensor this.kinectsensor.open(); // set status text this.statustext = this.kinectsensor.isavailable ? properties.resources.runningstatustext : properties.resources.nosensorstatustext; // use window object view model in simple example this.datacontext = this; // initialize components (controls) of window this.initializecomponent(); } /// <summary> /// inotifypropertychangedpropertychanged event allow window controls bind changeable data /// </summary> public event propertychangedeventhandler propertychanged; /// <summary> /// gets bitmap display /// </summary> public imagesource imagesource { { return this.colorbitmap; } } /// <summary> /// gets or sets current status text display /// </summary> public string statustext { { return this.statustext; } set { if (this.statustext != value) { this.statustext = value; // notify bound elements text has changed if (this.propertychanged != null) { this.propertychanged(this, new propertychangedeventargs("statustext")); } } } } /// <summary> /// execute shutdown tasks /// </summary> /// <param name="sender">object sending event</param> /// <param name="e">event arguments</param> private void mainwindow_closing(object sender, canceleventargs e) { if (this.colorframereader != null) { // colorframereder idisposable this.colorframereader.dispose(); this.colorframereader = null; } if (this.kinectsensor != null) { this.kinectsensor.close(); this.kinectsensor = null; } } /// <summary> /// handles user clicking on screenshot button /// </summary> /// <param name="sender">object sending event</param> /// <param name="e">event arguments</param> private void screenshotbutton_click(object sender, routedeventargs e) { if (this.colorbitmap != null) { // create png bitmap encoder knows how save .png file bitmapencoder encoder = new pngbitmapencoder(); // create frame writable bitmap , add encoder encoder.frames.add(bitmapframe.create(this.colorbitmap)); //bitmaps.add(bitmapframe.create(this.colorbitmap.clone())); string time = count.tostring(); //string time = system.datetime.now.tostring("hh'-'mm'-'ss", cultureinfo.currentuiculture.datetimeformat); string myphotos = environment.getfolderpath(environment.specialfolder.mypictures); string path = path.combine(myphotos, "kinectscreenshot-color-" + time + ".png"); count++; // write new file disk try { // filestream idisposable using (filestream fs = new filestream(path, filemode.create)) { encoder.save(fs); } this.statustext = string.format(properties.resources.savedscreenshotstatustextformat, path); } catch (ioexception) { this.statustext = string.format(properties.resources.failedscreenshotstatustextformat, path); } } } /// <summary> /// handles color frame data arriving sensor /// </summary> /// <param name="sender">object sending event</param> /// <param name="e">event arguments</param> private void reader_colorframearrived(object sender, colorframearrivedeventargs e) { // colorframe idisposable using (colorframe colorframe = e.framereference.acquireframe()) { if (colorframe != null) { framedescription colorframedescription = colorframe.framedescription; using (kinectbuffer colorbuffer = colorframe.lockrawimagebuffer()) { this.colorbitmap.lock(); // verify data , write new color frame data display bitmap if ((colorframedescription.width == this.colorbitmap.pixelwidth) && (colorframedescription.height == this.colorbitmap.pixelheight)) { colorframe.copyconvertedframedatatointptr( this.colorbitmap.backbuffer, (uint)(colorframedescription.width * colorframedescription.height * 4), colorimageformat.bgra); this.colorbitmap.adddirtyrect(new int32rect(0, 0, this.colorbitmap.pixelwidth, this.colorbitmap.pixelheight)); } this.colorbitmap.unlock(); } } // modification : save current frame png file. if (this.colorbitmap != null) { // create png bitmap encoder knows how save .png file bitmapencoder encoder = new pngbitmapencoder(); // create frame writable bitmap , add encoder encoder.frames.add(bitmapframe.create(this.colorbitmap)); string time = count.tostring(); //string time = system.datetime.now.tostring("hh'-'mm'-'ss", cultureinfo.currentuiculture.datetimeformat); string myphotos = environment.getfolderpath(environment.specialfolder.mypictures); string path = path.combine(myphotos, "kinectscreenshot-color-" + time + ".png"); count++; // write new file disk try { // filestream idisposable using (filestream fs = new filestream(path, filemode.create)) { encoder.save(fs); } this.statustext = string.format(properties.resources.savedscreenshotstatustextformat, path); } catch (ioexception) { this.statustext = string.format(properties.resources.failedscreenshotstatustextformat, path); } } } } /// <summary> /// handles event sensor becomes unavailable (e.g. paused, closed, unplugged). /// </summary> /// <param name="sender">object sending event</param> /// <param name="e">event arguments</param> private void sensor_isavailablechanged(object sender, isavailablechangedeventargs e) { // on failure, set status text this.statustext = this.kinectsensor.isavailable ? properties.resources.runningstatustext : properties.resources.sensornotavailablestatustext; } } } the problem code generates 200 png files during recording time starting frame 90 end, frames identical each other(it starts recording run , stops whenever close it).
1) me understand why happens? why doesn't record rest of frames , repeats frame again , again?
2) have advice or pointer how can record depth , color streams image files simultaneously in efficient way , frame rate(say 20-30 fps) using kinect windows v2?
writing simultaneously color , depth streams same fps without loosing frames little tricky. in order check problem identical frames suggest try write color , depth images separate buffers (you can keep frame timestamp in buffer too) , write them disk after recording over. i'll give example , can ajust problem.
saving color frames buffer:
private void mykinectsensor_colorframeready(object sender, colorimageframereadyeventargs e) { using (colorimageframe color = e.opencolorimageframe()) { if (color != null) { colorbits = new byte[color.pixeldatalength]; color.copypixeldatato(colorbits); image1.source = bitmapsource.create(color.width, color.height, 96, 96, pixelformats.bgr32, null, colorbits, color.width * color.bytesperpixel); if (startsavingframes) { savecolortimestamps.addlast(datetime.now.tostring("hhmmssfff")); savecolorframes.addlast(colorbits); } } } } saving depth frames buffer:
private void mykinectsensor_depthframeready(object sender, depthimageframereadyeventargs e) { using (depthimageframe depth = e.opendepthimageframe()) { depthpixels = new depthimagepixel[mykinectsensor.depthstream.framepixeldatalength]; if (depth != null) { frame = new short[depth.pixeldatalength]; depth.copypixeldatato(frame); (int = 0; < frame.length; i++) { frame[i] = (short)(((ushort)frame[i]) >> 3); } image3.source = bitmapsource.create(depth.width, depth.height, 96, 96, pixelformats.gray16, null, frame, depth.width * depth.bytesperpixel); if (startsavingframes) { savedepthtimestamps.addlast(datetime.now.tostring("hhmmssfff")); savedepthframes.addlast(frame); } } } } finally, loop in each buffer , write frames disk:
e = savecolortimestamps.getenumerator(); foreach (byte[] node in savecolorframes) { e.movenext(); pngbitmapencoder enc = new pngbitmapencoder(); enc.frames.add(bitmapframe.create(bitmapsource.create(640, 480, 96, 96, pixelformats.bgr32, null, node, 640*4))); string temppath = system.io.path.combine(@"../output/kinect1/color/", e.current + ".png"); using (filestream fs = new filestream(temppath, filemode.create)) { enc.save(fs); fs.close(); } } savecolortimestamps.clear(); savecolorframes.clear(); e.dispose(); e = savedepthtimestamps.getenumerator(); foreach (short[] node in savedepthframes) { e.movenext(); pngbitmapencoder enc = new pngbitmapencoder(); enc.frames.add(bitmapframe.create(bitmapsource.create(640, 480, 96, 96, pixelformats.gray16, null, node, 640 * 2))); string temppath = system.io.path.combine(@"../output/kinect1/depth/", e.current + ".png"); using (filestream fs = new filestream(temppath, filemode.create)) { enc.save(fs); fs.close(); } } it not optimal way it, understand how frame-writing works , not have drop-frames.
Comments
Post a Comment