Source Code - DIY 3D Laser Scanner

Below is the source code for my DIY 3D Laser Scanner project and YES...it really is this simple!

I have released the code to let people understand how simple it really is to gather 3D data from any surface using off the shelf laser pointers (with some sort of line generation lens), a webcam, freeware webcam capturing software and a small amount of custom programming in Visual Basic (to process the captured images and output a complete XYZ point cloud).

How it works
The application below reads monochrome images or colour images where the laser line is the only clearly visible object in the scene. Everything else should be dark. Set threshold setting etc in your webcam software prior to using VFMGrab. If a colour texture is required remember to take one colour reference photo named 'rgb.jpg' before setting up the threshold settings.

The application does not have code to grab images through dlls etc. it just reads images collected from another screengrab utility. My choice grabber tool is VFMGrab. Firstly, I run VFMGrab and it immediately starts grabbing images from my webcam and places them in a predefined location every 10th of a second. (default capture setting 320x240). N.B. Only one image is captured during the capture process. It is written over many times for the duration of the scanning period .

My program below loads the captured image, processes it and outputs the XYZRGB text to a basic text file. Once I have completed scanning the object, by continously moving the laser across the object, I stop the application and all digitized points are available in the text file.

The program doesn't stop for user interaction (pausing etc) so speed is quite important. You can view the captured points on screen so just make sure you collect all the points required and stop the program otherwise your text file could get rather large! You will probably end up with lots of duplicate points too but these are usually automatically removed by professional 3D scanning point cloud software.


Naughter Webcam VFWGrab 1.07
http://www.naughter.com/vfwgrab.htm



Physical setup
Laser with linear lens (offset 30 degrees to centre of webcam view)
Flat perpendicular background plane
Webcam
Protractor
Linear movement for laser (an old paper trimmer in my case).

Some images of my setup can be seen here:
DIY 3D Laser Scanning setup

Make sure there is a solid perpindicular back wall or plane behind the object being scanned. This is key to the scanning process and its ability not to use predefined calibration boards etc.
There should be at least 30 pixels of solid vertical laser line visible on the wall. The code reads this as a reference to understand the current location of the laser line on the horizontal plane (or it's X screen value).

When the laser is moved horizontally across the object the X location of the line will change giving new XYZ data for every line of the screen. The Y data value is wherever the current brightest pixel is found down the screen Y axis. The Z or depth value is the difference between this current bright pixel (X) location and the laser line (X) location on the wall.

If an RGB reference image has been loaded into the scanner application the RGB value will be appended to the XYZ text. These values are found by reading the same XY scanning value in the RGB picture (top view) as the XY values being scanned in the bottom reatime view.

The output file format will be:
X Y Z R G B
X Y Z R G B
X Y Z R G B
etc...

This format can easily be read with the Points2Polygons(xyz only), VRMesh(XYZRGB) etc.

Enjoy,
Colin

Source Code (Visual Basic 6)


Private WindowWidth
Private WindowHeight
Private threshold
Private rgbvalue

Private Sub Form_Load()
'
' DIY 3D Laser Scanner 2009, By Colin Ord. 17th September 2009.
' Working for REAL Object scans!!!!!!!
' Just hold laser and sweep across object until done
'
' Notes:
' 24-09-2009 Corrected x skew
' 27-09-2009 Corrected Z depth for 30 degree scan
' 28-09-2009 Correct aspect for 30 degree scans. Rotated laser not a linear movement.
' 8th October: added colour capture with reference image rgb.jpg

WindowWidth = 320
WindowHeight = 240
myy = 1

End Sub

Private Sub Timer1_Timer()

Dim R As Long
Dim G As Long
Dim B As Long

Dim myx
Dim myy
Dim rgbvalue

threshold = Slider1.Value '1600000 '3876853 'Reverse BGR hex value for a red colour
Text1.Text = threshold
threshold = 1585276

myy = 1

mynumber = 1
mytextnumber$ = mynumber

Form1.Picture3 = LoadPicture("D:\Colin Ord\3d scanner\3D Scanner RT 2009\rgb.jpg")

mytextnumber$ = "D:\Colin Ord\3d scanner\3D Scanner RT 2009\" & "1.jpg"

On Error GoTo ErrorHandler

ErrorHandler:
If Err.Number = 53 Or 481 Then
'Debug.Print "Some problem with loading jpg image."
Resume Next
End If

Picture1 = LoadPicture(mytextnumber$)

For xcnt = 0 To WindowWidth
If Picture1.Point(xcnt, 30) > threshold Then '100000 Then
            origin = xcnt
           
            GoTo start:
            End If
Next

start:

For myy = 0 To WindowHeight

        For myx = 0 To WindowWidth
            If Picture1.Point(myx, myy) > threshold Then '1000000 Then
            GoTo here:
            End If
        Next

here:
       
            Picture1.PSet (myx, myy), RGB(255, 255, 0)
            Picture1.Line (0, 30)-(WindowWidth, 30), RGB(0, 255, 0)
           
            If Form1.Picture3.Point(myx, myy) > 100000 Then
            rgbvalue = Form1.Picture3.Point(myx, myy)
            End If
           
            rotx = origin - myx
            roty = myy * 2
            rotz = (rotx + myx) / 2
           
        'Output file
        Open "D:\Colin Ord\3d scanner\3D Scanner RT 2009\freescanRGB_object_01.asc" For Append As #1
           
        'Read RGB values from hex pixel colour     
            R = &HFF& And rgbvalue
            G = (&HFF00& And rgbvalue) \ 256
            B = (&HFF0000 And rgbvalue) \ 65536
            
            ' Aligns scan with laser angle offset and skew
            rot = 30 * 0.0174532  '57.29577951
            rotzz = rotz * Cos(rot) - myx * Sin(rot)
            rotxx = rotz * Sin(rot) + myx * Cos(rot)
            rotyy = roty 'myy '/ 2
           
            'create the vertex string -  'X Y Z R G B'
            Print #1, ((rotxx + rotx) & " " & (rotyy / 2) & " " & ((rotzz * -2) * 2) & " " & R & " " & G & " " & B)
            Close #1
           
            'LASER LINE PREVIEW BOX- Draws each vertex with a red dot.
            Picture2.PSet (myx, myy), RGB(255, 0, 0)
        Next

End Sub

Disclaimer

Free of any license restrictions - do what you want with it!
Please let me know if the code was useful for your projects.

Page Updated - 12th December 2009
Comments