The objective of this project is to construct a fully functional laser scanner that is inexpensive and easily portable. This involves a combination of hardware and software engineering.
The scanner is based around a 25mW red diode laser and an X-Y laser scanning head from a laserdisc player:
These components are controlled by a PIC microcontroller which accepts commands over the serial port and outputs a pulse width modulated signal on two channels. These signals are lowpass filtered and run through a voltage->current amplifier which drives the galvos in the scanning head. The Y mirror oscillates up and down with a set frequency, while the X mirror it set to a constant position. This projects a bright line on the object to be scanned:
The assembly has a mounting hole where a digital camera (we use the Kodak DC290) can be attached. The assembly can then be mounted on a tripod for positioning.
A computer is used to control the position of the scanline and to take pictures using the camera. We tried to find software that would allow us to control the camera from a computer, so that the scanning process could be automated. After trying the programs referenced in the Kodak Digital Camera HOWTO unsucsessfully, we found that the camera had a hardware input for a remote trigger. We implemented a function on the PIC which would operate this input when instructed by the computer.
Due to mechanical resonance, the scanner sometimes tends to project a narrow oval when in the middle of its scan range. We tried to compensate for this by increasing the frequency of the vertical scan. Unfortunately we overloaded the current capacity of the galvo and melted it. We got a replacement set of galvos, but these required a voltage input instead of a current input, so our amplifier does not work with them very well.
The first task of the software is to calibrate the system. To do this, the user first sets up the camera to scan a regular grid of squares. A baseline image is taken without the laser, and then a series of images are taken with the laser at regularly varying angles. From the baseline image, we implement an extension of the code we worked with in class that performs all of the necessary camera calibration. This also gives us the parameters (length, rotation, et c.) relating the grid plane to the camera, which is useful in calibrating the laser.
The next task is to find the curve traced out by the laser, as perceived by the camera, at a given laser angle-step. We first subtract the red channel of the baseline image from that of the image with the laser at that step, and then perform a gaussian smoothing to get rid of non-laser noise. This allows us easily to find the general location of the laser at a given y-value. Using these x-values as centers, we multiply the image by a gaussian centered along the laser path, which further decreases non-laser noise. We then compute the moment of each row to give a better estimate of the x-coordinate of the laser for that y-value; taking advantage of the generic continuity of the laser scan, we smooth the result, with each row weighted according to its signal strength. Rows with insufficient signal strength are thrown out. The result provides a very good fit of the laser's path provided that the objects along its path are not highly reflective.
Using the known plane of the grid, as well as the known coefficients of the camera, we convert the curves traced out by the laser to their correct 3D coordinates and then fit them with lines. Projecting these lines onto the X-Z plane and finding their approximate common intersection in the least-squares sense tells us the X and Z coordinates of the laser origin in the camera's coordinate frame. Because the camera is mounted on the same platform as the laser, the Y coordinate of the laser source is 0. Now, for a given angular deflection of the galvos we have a line and a point not on that line, which gives us a plane. These planes are all vertical, so we parametrize them by the angle they form with the plane parallel to the camera's Y-Z plane. We then fit these values to a cubic polynomial in the angular deflection sent to the galvos, to account for observed nonlinearity in response, which we believe to be caused by an unfortunate discord between these particular galvos and this particular amplifier. This gives us the equation of the plane scanned by the laser for any given computer-fed angular deflection of the galvos.
Having calibrated both camera and laser, we now photograph a new series of images, this time featuring the object to be scanned. The user can specify the angles so that the laser spends all its trace time in the region containing the object, because we have a function describing the plane produced by any input deflection current. The user can also specify the number of images he wishes to record and the number of points he ultimately wants his range image to have. The deflection current to the galvos is incremented linearly across the relevant range, which produces a noticeably nonlinear response from the galvos.
When these images are taken, the same laser-finding analysis used earlier is employed to find the curves traced out by the laser. These curves follow the laser closely, and fit the image quite well. The curves are filtered, and values that fall below a certain threshold of signal strength are discarded, so that they are only present where the laser is also present.
For each point in one of these curves, we use our laser calibration polynomial to find the plane of the laser. The x and y coordinates of the point in the camera image give us a direction, and the camera itself gives us an origin. Thus, we have the equation for a plane and the equation for a non-parallel line, so it is a relatively straightforward procedure to find the intersection of these systems of equations, which is the 3D point observed. We calculate enough points on each curve to produce approximately the number of total points specified by the user. These points constitute a range image. Here is the range image, plotted in Matlab, for the chesspiece being scanned in the picture above (rotated significantly):
In the future we might improve the matching between the galvos and amplifier; while our polynomial fitting takes care of the nonlinearity problem, we are currently constrained to using a fairly small vertical scan angle, because of a resonance which currently produces very pronounced ovals for larger angles.
To use the code, name your calibration baseline "cbase.jpg", your calibration laser images "cscan_1.jpg"..."cscan_(however many such images you have).jpg", your object baseline "sbase.jpg", and your objects laser images "sscan_1.jpg"..."sscan(the number or total sscan images).jpg". Be sure to have these images as well as all the code included in the same driectory, which you should make the active directory in matlab. Make sure the .zip files are unzipped. Run calibrate and save the outcome (I will call it calibout). Then run scan and save the outcome (I will call it scanout). Finally, run scan2(calibout, scanout, object series initial angle, object series angle step size) where 0 is the leftmost angle of the calibration series and 2^16-1 is the rightmost such angle.