Commits

Cliff Biffle committed 46b62d2

New KVDepthMap implementation: KVAveragingDepthMap, which attempts to derive more detail from static scenes by assuming and correcting for normally-distributed depth noise.

Comments (0)

Files changed (6)

English.lproj/MainMenu.xib

 		</object>
 		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
 			<bool key="EncodedWithXMLCoder">YES</bool>
-			<integer value="29"/>
+			<integer value="296"/>
 			<integer value="533"/>
 		</object>
 		<object class="NSArray" key="IBDocument.PluginDependencies">
 									<reference key="NSOnImage" ref="35465992"/>
 									<reference key="NSMixedImage" ref="502551668"/>
 								</object>
-								<object class="NSMenuItem" id="888511339">
+								<object class="NSMenuItem" id="26014547">
 									<reference key="NSMenu" ref="466310130"/>
 									<string key="NSTitle">Anaglyph</string>
 									<string key="NSKeyEquiv">a</string>
 									<reference key="NSOnImage" ref="35465992"/>
 									<reference key="NSMixedImage" ref="502551668"/>
 								</object>
+								<object class="NSMenuItem" id="138643579">
+									<reference key="NSMenu" ref="466310130"/>
+									<string key="NSTitle">No Depth History</string>
+									<string key="NSKeyEquiv">1</string>
+									<int key="NSKeyEquivModMask">1572864</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="63974516">
+									<reference key="NSMenu" ref="466310130"/>
+									<string key="NSTitle">Average Depth Over Time</string>
+									<string key="NSKeyEquiv">2</string>
+									<int key="NSKeyEquivModMask">1572864</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="264846174">
+									<reference key="NSMenu" ref="466310130"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
 								<object class="NSMenuItem" id="719261243">
 									<reference key="NSMenu" ref="466310130"/>
 									<string key="NSTitle">Point Cloud</string>
 					<object class="IBActionConnection" key="connection">
 						<string key="label">toggleAnaglyph:</string>
 						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="888511339"/>
+						<reference key="destination" ref="26014547"/>
 					</object>
 					<int key="connectionID">561</int>
 				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">selectStaticDepthMap:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="138643579"/>
+					</object>
+					<int key="connectionID">565</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">selectAveragingDepthMap:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="63974516"/>
+					</object>
+					<int key="connectionID">566</int>
+				</object>
 			</object>
 			<object class="IBMutableOrderedSet" key="objectRecords">
 				<object class="NSArray" key="orderedObjects">
 							<reference ref="578250298"/>
 							<reference ref="406940919"/>
 							<reference ref="433488773"/>
-							<reference ref="888511339"/>
+							<reference ref="26014547"/>
+							<reference ref="264846174"/>
+							<reference ref="138643579"/>
+							<reference ref="63974516"/>
 						</object>
 						<reference key="parent" ref="586577488"/>
 					</object>
 					</object>
 					<object class="IBObjectRecord">
 						<int key="objectID">560</int>
-						<reference key="object" ref="888511339"/>
+						<reference key="object" ref="26014547"/>
+						<reference key="parent" ref="466310130"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">562</int>
+						<reference key="object" ref="264846174"/>
+						<reference key="parent" ref="466310130"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">563</int>
+						<reference key="object" ref="138643579"/>
+						<reference key="parent" ref="466310130"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">564</int>
+						<reference key="object" ref="63974516"/>
 						<reference key="parent" ref="466310130"/>
 					</object>
 				</object>
 					<string>56.IBPluginDependency</string>
 					<string>56.ImportedFromIB2</string>
 					<string>560.IBPluginDependency</string>
+					<string>562.IBPluginDependency</string>
+					<string>563.IBPluginDependency</string>
+					<string>564.IBPluginDependency</string>
 					<string>57.IBEditorWindowLastContentRect</string>
 					<string>57.IBPluginDependency</string>
 					<string>57.ImportedFromIB2</string>
 					<integer value="1"/>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<integer value="1"/>
-					<string>{{707, 763}, {194, 73}}</string>
+					<string>{{597, 763}, {194, 73}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<integer value="1"/>
 					<string>{{525, 802}, {197, 73}}</string>
 					<string>{74, 862}</string>
 					<string>{{6, 978}, {478, 20}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>{{591, 663}, {232, 173}}</string>
+					<string>{{547, 613}, {264, 223}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<string>{{475, 832}, {234, 43}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<integer value="1"/>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<string>{{392, 653}, {223, 183}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<integer value="1"/>
 				</object>
 			</object>
 			<nil key="sourceID"/>
-			<int key="maxID">561</int>
+			<int key="maxID">566</int>
 		</object>
 		<object class="IBClassDescriber" key="IBDocument.Classes">
 			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
 						<bool key="EncodedWithXMLCoder">YES</bool>
 						<object class="NSArray" key="dict.sortedKeys">
 							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>selectAveragingDepthMap:</string>
 							<string>selectFilledQuadRenderer:</string>
 							<string>selectFilledTriRenderer:</string>
 							<string>selectPointCloudRenderer:</string>
+							<string>selectStaticDepthMap:</string>
 							<string>toggleAnaglyph:</string>
 							<string>toggleDepthFieldUpdates:</string>
 							<string>toggleLighting:</string>
 							<string>id</string>
 							<string>id</string>
 							<string>id</string>
+							<string>id</string>
+							<string>id</string>
 						</object>
 					</object>
 					<object class="NSMutableDictionary" key="actionInfosByName">
 						<bool key="EncodedWithXMLCoder">YES</bool>
 						<object class="NSArray" key="dict.sortedKeys">
 							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>selectAveragingDepthMap:</string>
 							<string>selectFilledQuadRenderer:</string>
 							<string>selectFilledTriRenderer:</string>
 							<string>selectPointCloudRenderer:</string>
+							<string>selectStaticDepthMap:</string>
 							<string>toggleAnaglyph:</string>
 							<string>toggleDepthFieldUpdates:</string>
 							<string>toggleLighting:</string>
 						<object class="NSMutableArray" key="dict.values">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<object class="IBActionInfo">
+								<string key="name">selectAveragingDepthMap:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
 								<string key="name">selectFilledQuadRenderer:</string>
 								<string key="candidateClassName">id</string>
 							</object>
 								<string key="candidateClassName">id</string>
 							</object>
 							<object class="IBActionInfo">
+								<string key="name">selectStaticDepthMap:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
 								<string key="name">toggleAnaglyph:</string>
 								<string key="candidateClassName">id</string>
 							</object>

KVAveragingDepthMap.h

+/*
+ * Copyright 2010 Cliff L. Biffle.  All Rights Reserved.
+ * Use of this source code is governed by the Apache License 2.0,
+ * which can be found in the LICENSE file.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import "types.h"
+#import "KVDepthMap.h"
+
+@interface KVAveragingDepthMap : NSObject <KVDepthMap> {
+ @private
+  GLfloat linearizationTable[2048];
+  linear_depth_t zs;
+  uint32_t sampleCount[480][640];
+}
+
+@end

KVAveragingDepthMap.m

+/*
+ * Copyright 2010 Cliff L. Biffle.  All Rights Reserved.
+ * Use of this source code is governed by the Apache License 2.0,
+ * which can be found in the LICENSE file.
+ */
+
+#import "KVAveragingDepthMap.h"
+#import "KVRenderer.h"
+
+@interface KVAveragingDepthMap ()
+- (void) buildLinearizationTable;
+@end
+
+@implementation KVAveragingDepthMap
+
+- init {
+  if ((self = [super init])) {
+    [self buildLinearizationTable];
+  }
+  return self;
+}
+
+#pragma mark --- KVDepthMap implementation
+
+- (void) update: (const depth_t *)rawDepthSamples {
+  linear_depth_t *out = &zs;  // Avoid ivar indirection during loop.
+  
+  for (int y = 0; y < 480; y++) {
+    for (int x = 0; x < 640; x++) {
+      float linear = linearizationTable[rawDepthSamples->samples[y][x]];
+      uint32_t n = sampleCount[y][x]++;
+      if (linear == 0.F) continue;
+      
+      float prev = out->z[y][x];
+      if (prev == 0.F) {
+        // If we've never gotten data for this point,
+        // we take what we can get!
+        out->z[y][x] = linear;
+        sampleCount[y][x] = 1;
+      } else {
+        // Add to the presumed normal distribution.
+        float nf = (float) n;
+        out->z[y][x] = (nf * out->z[y][x] + linear) / (nf + 1.F);
+      }
+    }
+  }
+}
+
+- (void) drawInCurrentOpenGLContextWithRenderer: (id <KVRenderer>) renderer {
+  [renderer drawInCurrentOpenGLContext: &zs];
+}
+
+#pragma mark --- Internals
+
+// The Kinect produces 11-bit depth samples.  Z-resolution decreases
+// with distance, following a curve that looks suspiciously like the
+// one used for perspective projection.  The ROS folks at CCNY derived
+// the equation below, for converting Kinect depth samples to meters.
+// This method memoizes the function over the entire 2048-element
+// domain.  This implies replacing a couple of floating-point constant
+// loads, an addition, and a division with an indirection to very hot
+// memory.  On my machine this eliminates 60% of time spent calculating
+// linear depths.
+- (void) buildLinearizationTable {
+  for (uint16_t depth = 0; depth < 2048; depth++) {
+    linearizationTable[depth] = -325.616F / ((GLfloat) depth + -1084.61F);
+    
+    // Simplification: when the Kinect reports "no data" for a point
+    // (typically because the IR projector is occluded) the result is
+    // a "very close" reading of nearly zero meters.  All my renderers
+    // filter out such readings, so we coerce it to exactly 0.F here
+    // to simplify that.
+    if (linearizationTable[depth] < 0.1F) {
+      linearizationTable[depth] = 0.F;
+    }
+  }
+}
+
+@end
 - (IBAction) selectFilledQuadRenderer: sender;
 - (IBAction) selectFilledTriRenderer: sender;
 
+- (IBAction) selectStaticDepthMap: sender;
+- (IBAction) selectAveragingDepthMap: sender;
+
 - (IBAction) toggleDepthFieldUpdates: sender;
 - (IBAction) toggleLighting: sender;
 - (IBAction) toggleRecording: sender;
 #import "KVQuadRenderer.h"
 #import "KVTriStripRenderer.h"
 #import "KVSinglePlaneDepthMap.h"
+#import "KVAveragingDepthMap.h"
 #import "trackball.h"
 #import "utility.h"
 
   deviceWhite = [[NSColor colorWithDeviceRed: 1.F green: 1.F blue: 1.F alpha: 1.F] retain];
   devicePurplish = [[NSColor colorWithDeviceRed: 1.F green: 0.5F blue: 1.F alpha: 1.F] retain];
   [self selectPointCloudRenderer: nil];
-  self.depthMap = [[[KVSinglePlaneDepthMap alloc] init] autorelease];
+  [self selectStaticDepthMap: nil];
 }
 
 #pragma mark --- NSOpenGLView Overrides ---
 #pragma mark --- Actions ---
 
 - (IBAction) selectPointCloudRenderer: sender {
-  self.renderer = [[KVPointCloudRenderer alloc] init];
+  self.renderer = [[[KVPointCloudRenderer alloc] init] autorelease];
 }
 
 - (IBAction) selectFilledQuadRenderer: sender {
-  self.renderer = [[KVQuadRenderer alloc] init];
+  self.renderer = [[[KVQuadRenderer alloc] init] autorelease];
 }
 
 - (IBAction) selectFilledTriRenderer: sender {
-  self.renderer = [[KVTriStripRenderer alloc] init];
+  self.renderer = [[[KVTriStripRenderer alloc] init] autorelease];
+}
+
+- (IBAction) selectStaticDepthMap: sender {
+  self.depthMap = [[[KVSinglePlaneDepthMap alloc] init] autorelease];
+}
+
+- (IBAction) selectAveragingDepthMap: sender {
+  self.depthMap = [[[KVAveragingDepthMap alloc] init] autorelease];
 }
 
 - (IBAction) toggleDepthFieldUpdates: sender {

KinectViewer.xcodeproj/project.pbxproj

 		C708F46A12A03E8F00656901 /* KVPointCloudRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = C708F46712A03E8F00656901 /* KVPointCloudRenderer.m */; };
 		C708F46B12A03E8F00656901 /* KVQuadRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = C708F46912A03E8F00656901 /* KVQuadRenderer.m */; };
 		C708F55912A0728800656901 /* KVSinglePlaneDepthMap.m in Sources */ = {isa = PBXBuildFile; fileRef = C708F55812A0728800656901 /* KVSinglePlaneDepthMap.m */; };
+		C708F5E412A0779500656901 /* KVAveragingDepthMap.m in Sources */ = {isa = PBXBuildFile; fileRef = C708F5E312A0779500656901 /* KVAveragingDepthMap.m */; };
 		C70E62AF129C5055004A44B3 /* KVDepthView.m in Sources */ = {isa = PBXBuildFile; fileRef = C70E62AE129C5055004A44B3 /* KVDepthView.m */; };
 		C70E62FB129C572E004A44B3 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C70E62FA129C572E004A44B3 /* OpenGL.framework */; };
 		C70E635F129C63BE004A44B3 /* trackball.c in Sources */ = {isa = PBXBuildFile; fileRef = C70E635D129C63BE004A44B3 /* trackball.c */; };
 		C708F55412A0726800656901 /* KVDepthMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KVDepthMap.h; sourceTree = "<group>"; };
 		C708F55712A0728800656901 /* KVSinglePlaneDepthMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KVSinglePlaneDepthMap.h; sourceTree = "<group>"; };
 		C708F55812A0728800656901 /* KVSinglePlaneDepthMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KVSinglePlaneDepthMap.m; sourceTree = "<group>"; };
+		C708F5E212A0779500656901 /* KVAveragingDepthMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KVAveragingDepthMap.h; sourceTree = "<group>"; };
+		C708F5E312A0779500656901 /* KVAveragingDepthMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KVAveragingDepthMap.m; sourceTree = "<group>"; };
 		C70E62AD129C5055004A44B3 /* KVDepthView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KVDepthView.h; sourceTree = "<group>"; };
 		C70E62AE129C5055004A44B3 /* KVDepthView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KVDepthView.m; sourceTree = "<group>"; };
 		C70E62FA129C572E004A44B3 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
 				C708F55412A0726800656901 /* KVDepthMap.h */,
 				C708F55712A0728800656901 /* KVSinglePlaneDepthMap.h */,
 				C708F55812A0728800656901 /* KVSinglePlaneDepthMap.m */,
+				C708F5E212A0779500656901 /* KVAveragingDepthMap.h */,
+				C708F5E312A0779500656901 /* KVAveragingDepthMap.m */,
 				C70E62AD129C5055004A44B3 /* KVDepthView.h */,
 				C70E62AE129C5055004A44B3 /* KVDepthView.m */,
 				C708F45F12A03E6500656901 /* KVRenderer.h */,
 				C708F46A12A03E8F00656901 /* KVPointCloudRenderer.m in Sources */,
 				C708F46B12A03E8F00656901 /* KVQuadRenderer.m in Sources */,
 				C708F55912A0728800656901 /* KVSinglePlaneDepthMap.m in Sources */,
+				C708F5E412A0779500656901 /* KVAveragingDepthMap.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};