This is an amazing project - excellently well done!
And the BOM is a lot more reasonable than the writeup suggests, too: a Nikon D40 would've run $800 new with a lens kit, but it's over a decade old now - you'd be getting ripped off to pay more than a C-note for a NIB one today. You'd get higher resolution with a newer camera - 20-24mp vs. the 6mp of the D40 - but for this application I'm not sure how much value that'd bring.
One thing I'd note is that the lens, an 18-55 similar to one of mine, doesn't appear to have its zoom ring fixed in place. I'm not sure that is intentional, and if (as seems likely) the camera FOV is a term in the depth calculation, it'd be worth either fixing the zoom or reading the focal length from the images' EXIF data to use as an input to the calculation.
One other note - the Nikon D-series cameras also support an electronic cable release, with shutter triggering done by simply shorting a pair of pins on the connector. While the bare plugs aren't available so far as I know, there are many third-party cable releases available for just a couple of bucks, and it would be easy to cut the cable off one of them, trim it to length, and switch the shutter with a transistor. Might save effort and improve reliability over the IR method. (I do use an IR remote release with my D5300, but only in cases where the cable release presents risks, as for example long-exposure effects with a Tesla coil - I've seen it couple enough EMI into the release cable to trigger the shutter and even reboot the camera. But it's occasionally tricky to trigger the shutter via IR, so I prefer a cable release when I can use one.)
Again, an excellent project, and one I'm glad to see here on Hacker News!
Yeah, it would seem if you're simply looking for the difference between images with and without polarized filtering, you'd pick up all manner of smooth reflective surfaces--water, glass, plastic, etc.
Brilliant, though the metalness maps seem more like low-threshold specular maps (you can see metallic spot readings on the strictly dielectric material [bakelite?] on that handle).†
The way to correctly detect metalness would also involve checking for coloration of the reflected light (which is not present with specular dielectric materials [but may be confused with subsurface scatter coloration]).
Update: † Looks like he knows this, and just hasn't gotten around to implementing it yet.
Normal maps are a technique used in 3D graphics to emulate surface details on a mesh (3D model). Think of a brick house - if you want to render a detailed close-up view of the wall, the naive approach would be to include the seams between individual bricks in the wall mesh itself and render that. But that takes a lot of effort for the modeler and greatly complicates the mesh in terms of how many polygons it consists of. Alternatively, you can use a flat mesh and specify a normal map - an additional 2D image that, when applied on top of the wall texture, encodes which parts of it are protruding/depressed compared to the base level of the mesh. This way you can model a bunch of buildings using simple boxy meshes and then implant details to the walls using a combination of textures and normal maps.
The project above automatically creates normal maps of metallic surfaces using a camera extension. This is useful for 3D modelers, since they no longer need to have special normal maps manually created for each surface type in a scene.
OK, I am familiar with normal maps, now I get what the use case is. Thanks for the clarifications!
In 3D rendering, it is useful to have texture maps which define a number of material characteristics. One such characteristic is metalness. Technically, all materials fall into one of two categories, metal and dielectric (the values in between are a convenience to prevent aliasing, since texels can't address individual atoms), each with different rules for shading. For example, dielectrics have specular reflection which is consistent across the visual spectrum; metals can have a coloured specular reflection.
Recovering specular, metalness, normal, and roughness data in a controlled lighting environment also allows you to capture accurate albedo (aka diffuse color) textures.
Metalness textures are an important part of current "Physically Based Shading" techniques, in both realtime and offline rendering, because they allow materials to react consistently to different lighting environments.
It seems to me that it's ideal for making several channels of textures (color, normal map, metalness, maybe roughness/glossy in the future) as input of a material in a 3D game engine or CGI picture/animation.
Kind of a "3D scanner" for the 2D part of 3D scenes (textures).
OK, I love a good build story like any other geek out there, but I'm not sure what the purpose of this is? The article says to detect metals? Or capture 'textures' of fine grained surfaces?
Any clarifications would be welcome!