1. Projecting gray patterns and capturing images from two cameras "SL3DS1.projcapt.py"
2. Processing the 42 images of each camera and capture points codes " SL3DS2.procimages.py"
3. Adjusting threshold to select masking for areas to be processed "SL3DS3.adjustthresh.py"
4. Find and save similar points in each camera "SL3DS4.calcpxpy.py"
5 Calculate X,Y and Z coordinates of point cloud "SL3DS5.calcxyz.py"
The output is a PLY file with coordinate and color information of points on object surface. You can open PLY files with CAD software like Autodesk products or an open source sofware like Meshlab.
I have also developed a GUI for this software in TKINTER that you can find in step six with two sample data sets . You can find additional information on this subject on the following websites:
Hardware consists of :
1. Two webcameras (Logitech C920C)
2. Infocus LP330 projector
3. Camera and projector stand (made from 3 mm Acrylic plates and 6 mm HDF wood cut with a laser cutter)
The projector is an Infocus LP330 (Native resolution 1024X768) with following specs.Brightness:650 Lumens
Color Light Output:**Contrast (Full On/Off):400:1
Auto Iris:No
Native Resolution:1024x768
Aspect Ratio:4:3 (XGA)
Video Modes:**
Data Modes:MAX 1024x768
Max Power:200 Watts
Voltage:100V - 240V
Size(cm) (HxWxD):6 x 22 x 25
Weight:2.2 kg
Lamp Life(Full Power):1,000 hours
Lamp Type:UHPLamp
Wattage:120 Watts
Lamp Quantity:1
Display Type:2 cm DLP (1)
Standard Zoom Lens:1.25:1
Focus:Manual
Throw Dist (m): 1.5 - 30.5
Image Size(cm):76 - 1971
This video projector is used to project structured light patterns on the object to be scanned. The structured pattern consists of vertical and horizontal white light strips that are saved on a data file and webcams capture those distorted strips.
Preferably use those cameras that are software controllable because you need to adjust focus, brightness, resolution and image quality. It is possible to use DSLR cameras with SDKs that are provided by each brand.
Assembly and tests were conducted in Copenhagen Fablab with its support.
For testing the 3d scan software in this step I add two data sets one is scan of a fish and another is just a plane wall to see the accuracy of it. Open ZIP files and run SL3DGUI.py. For installation check step 2.
For using 3d scan part you need to install two cameras and projector but for other parts just click on the button. For testing the sample data first click on process then threshold, stereo match and finally point cloud. Install Meshlab to see the point cloud.
Q & A :
Q:how do you convert gray code to decimal?
A:Each pixel in projector screen has a horizontal and a vertical gray code, by grayimg=grayimg+(2**xx)*ff in a loop I convert it to decimal. Horizontal and vertical decimal code is then combined to get a unique number for each pixel among 1024*768 pixel of the projector.
colocright.append(np.uint32([rightcamcode[jj][ii][0]+rightcamcode[jj][ii][1]*1024 ,ii, jj])) is the line that combines horizontal and vertical so that global code is equal to horizontal code plus vertical code multiplied with 1024
file "graykod" is my gray to decimal conversion
rightcod and leftcod files have three columns, first column is the decimal code related to projector pixel, second is horizontal pixel coordinate of the camera and third is vertical pixel coordinate of the camera
aa=a[a[:,0].argsort(),] is for sorting based on the decimal code of projector pixels so that makes it easy to find similar projector pixels in left and right camera
if you need more explanation please ask, also please read the references precisely before asking more questions.
Later you can send me your code for checking and debuging. Try to run programs with the fish and wall data
=================================================================
More specifically, the decoding is performed as follows:
• Determine whether a pixel p is lit or not (1 or 0) in the images capturing the projected sequence of patterns encoding the columns.
• Calculate its binary form Bp.
• Convert the binary form Bp into the equivalent decimal number x.
Similarly, the process is repeated for the images capturing the projected sequence of patterns encoding the rows and results in a decimal number y. Thus, (x, y) are the image coordinates of the projector’s pixel corresponding to the pixel being decoded in a camera. By repeating the process for all the cameras, we can map the pixels not only to the projector’s pixels but rather to the other cameras viewing the object. It should be noted that a camera pixel may be mapped to more than one pixels of another camera due to differences between the camera and projector resolutions.
The decoded captured images result in a set of a many-to-many mappings between the pixels of the different cameras. Next, by triangulating the rays corresponding to each pair, a 3D point is computed at their intersection. The projection of this point falls onto the mapped pixels in the different cameras.
file "graykod" is my gray to decimal conversion
rightcod and leftcod files have three columns, first column is the decimal code related to projector pixel, second is horizontal pixel coordinate of the camera and third is vertical pixel coordinate of the camera
aa=a[a[:,0].argsort(),] is for sorting based on the decimal code of projector pixels so that makes it easy to find similar projector pixels in left and right camera
pixel size and focal length are parameters that you should get from camera manufacturer. x0l,x0r,y0l,y0r,z0l,z0r phi and tet are values that should be set based on your geometrical design(installation of cameras)
For calibration you need accurate calibration board and good algorithm. I used a calibration board from a commercial 3d scanner and found out that my settings are accurate enough for me. But if you need accuracy of 100th of millimeter you need calibration. A good calibration board costs more than 1000 Euros!!
I made camera base and stands with a laser cutter so I could have accurate installation of cameras without calibration.
img12=(((img1//2)+(img2//2)))
img123=(np.divide(img1,img12))
img123=(np.divide(img123,img123))
img123=(np.divide(img1,img12))
img123=(np.divide(img123,img123))
Above part is for thresholding the images and make a binary black and white image read page six of this document:
imgbin3[jj][ii][1]= grayimg[jj][ii]%256
imgbin3[jj][ii][2]= 40*grayimg[jj][ii]//256
imgbin3[jj][ii][0]= 4
imgbin3[jj][ii][2]= 40*grayimg[jj][ii]//256
imgbin3[jj][ii][0]= 4
this part is just for demonstration of stripes with different color, so you can omit this part.
Ref : http://www.instructables.com/id/DIY-3D-scanner-based-on-structured-light-and-stere/?ALLSTEPS
沒有留言:
張貼留言