How much would you spend for a fairly good 3d scanner? I chose one that is about 50$.
[EDIT: yes, it's DephtInition, and not DepthInition as it should probably be. Long story ]
UPDATE: introduction to new OpenCL accelerated code here.
The idea is very simple:
In an image, we can fairly easily estimate how much a pixel is focused by subtracting the luminance component of a suitable neighborhood to each pixel and summing absolute values.
I mean: take two adjacent pixels that picture adjeacent different points that have different colors in real life; if they are alike in the picture, then they've probably been blurred because of focus not being perfectly set on those points. If we subtract their luminance values, the absolute value of the result will be higher if the picture is in focus, lower if not, and everything in between.
If we take multiple shots changing the focusing distance, then we're able to obtain a curve of "focus rank" for each pixel.
Finding the maximum for that curve, allows us to find the depth (distance from camera) of that point, provided we know exactly the focus distance for each shot.
So the plan is:
- take a focus stack of an object
- estimate the "focus rank" of each pixel for each shot
- for each fixed x,y take the curve of focus rank across shots
- fit a curve on the found points (discarding worst fitting ones)
- find the maximum for that curve
- get the depth at which that maximum occurs
This kind of process is not new; turns out it is often used in microscopy, but the softwares dealing with focus stacks i found were disappointing for a reason or another: not free, not suitable for commercial purposes, not open source, not currently mantained and designed for old systems, not very precise, not producing a real 3d model... i decided to reinvent the wheel and experiment with a code that is free and open source; i called it DephtInition.
First problem i came across, was how to reliably take a focus stack. No camera I know of allows to programmatically take tens of shots while automatically incrementing focus distance, and very few record into EXIF data the actual focus distance the picture was taken with.
I managed to hack my Android phone (LG p500) to take 10 shots at incremental focus distances, but being at the beginning i just wanted to have more quality data to test the idea before refining the method: CHDK came to the rescue.
This firmware replacement for Canon Powershot cameras allowed exactly what I needed; I just had to adjust a script to fit my needs.
Several problem arose:
- the camera has to be very close to the object, or the difference in focus would not be noticeable, and this exagerates the proportions of the object
- illumination plays a central role: areas with deep shadows or visible reflections are detected like crap (must use a softener next time)
- in the case of faces, the subject has to be perfectly still while taking pics
By the way i got some results: a depth map, that together with RGB is then converted into a point cloud (I display with MeshLab in the pictures).
My next steps will be:
- implement .OBJ output with focus-fused stack as texture
- correct distorsion (together with the hilight/shadow problem this alters the shape badly)
- improve user interface
- make everything a little faster (I'm experimenting with OpenCl; I considered CUDA, but then I opted for larger availability)
- try playing with the outcome of a LYTRO camera
- have some scanned stuff 3D printed by my fellow coworker Luca
In the meanwhile, you can take a look at this noisy and far from perfect point cloud in .PLY format (textured .OBJ will come shortly) or play with the code yourself.
HAVE FUN with DephtInition!
PS: Enjoy the pictures of a scan process: