3d scanner with Arduino and laser pointer

hi all

i am thinking to make 3d scanner using line laser pointer with rotation table and web camera all hardware is fine with
me Arduino and laser with camera mount is ok
i have reach to result like this

how i could convert this to .stl file with processing

i can convert the avi movie file to 360 photo like this

00000000
Uploading: 00000001.jpg…
00000002
00000003
00000004
00000005
Uploading: 00000006.jpg…
00000007
00000008
etc
etc
etc
etc
00000008

how to start this project any suggestions and help

thanks in advance

You need to incorporate depth values somehow.

from the 360 image how to collect them in one 3d image

deforming a sphere: Spherical Geometry - Coding Challenge #25 · The Coding Train
or deforming a cylinder would work I think!

Instead of a laser pointer, you can take a construction laser rangefinder and a rotating prism with a motor from an old laser printer, for vertical sweep. Leave the turntable.

there is laser pointer gives line laser called line laser pointer gives the same of your idea but standalone

No webcam needed. You need to use the native receiver rangefinder receiver. You will get depth.
Scaner

i made the hardware and finished it

Clear. There was just such an idea.)))

@ZENAR57 9 years ago i made one

thank you my dear i need to convert the images to 3d

Well, yes, a good laser rangefinder is expensive, it will not be possible to keep within 100 euro, and look for a prism. Camera, so camera.)))

I understand your idea.

I think it would be better to buy a real range measurement laser to get depth values as has been suggested.

Your idea is to make a movie while the rotation takes place.

Here you would need an image detection to see where the line is - maybe openCV will help?

Once you have a list of all frames and for each frames a list of all points x,y you are good to go. Just hammer them onto your cylinder shape.

here is some of my pre-results

17.90103,-40.206367,3.0
7.5068836,-16.860735,3.2
16.168673,-36.315426,3.4
7.5068836,-16.860735,3.6
7.891852,-17.725388,3.8
7.891852,-17.725388,4.0
7.891852,-17.725388,4.2
10.009177,-22.480978,4.6
10.009177,-22.480978,4.8
7.5068836,-16.860735,5.0
7.699368,-17.293062,5.2
7.5068836,-16.860735,5.4
5.9670095,-13.402122,5.6
6.544463,-14.699103,5.8
6.736947,-15.131429,6.0
6.736947,-15.131429,6.2
7.121915,-15.996081,6.4
14.821282,-33.289143,6.6
14.821282,-33.289143,6.8
23.868038,-53.608486,7.0
7.121915,-15.996081,7.2
7.5068836,-16.860735,7.4
7.5068836,-16.860735,7.6
6.544463,-14.699103,7.8
8.661789,-19.454695,8.0
5.3895574,-12.105143,8.2
6.544463,-14.699103,8.4
5.0045886,-11.240489,8.6
4.4271364,-9.94351,8.8
4.4271364,-9.94351,9.0
6.159494,-13.834449,9.2
6.544463,-14.699103,9.4
5.1970735,-11.672816,9.6
5.1970735,-11.672816,9.8
5.3895574,-12.105143,10.0
7.891852,-17.725388,10.2
7.121915,-15.996081,10.4
6.736947,-15.131429,10.6
6.736947,-15.131429,10.8
7.121915,-15.996081,11.0
6.736947,-15.131429,11.2

not helpful

is this 3D points from ONE frame? Or from many frames? Then when does one frame end and the next start?

here are your data displayed





import peasy.*;

final int  show2D=0;
final int  show3D=1;
int state; 

String[] listA = {
  "17.90103,-40.206367,3.0"
  , "7.5068836,-16.860735,3.2"
  , "16.168673,-36.315426,3.4"
  , "7.5068836,-16.860735,3.6"
  , "7.891852,-17.725388,3.8"
  , "7.891852,-17.725388,4.0"
  , "7.891852,-17.725388,4.2"
  , "10.009177,-22.480978,4.6"
  , "10.009177,-22.480978,4.8"
  , "7.5068836,-16.860735,5.0"
  , "7.699368,-17.293062,5.2"
  , "7.5068836,-16.860735,5.4"
  , "5.9670095,-13.402122,5.6"
  , "6.544463,-14.699103,5.8"
  , "6.736947,-15.131429,6.0"
  , "6.736947,-15.131429,6.2"
  , "7.121915,-15.996081,6.4"
  , "14.821282,-33.289143,6.6"
  , "14.821282,-33.289143,6.8"
  , "23.868038,-53.608486,7.0"
  , "7.121915,-15.996081,7.2"
  , "7.5068836,-16.860735,7.4"
  , "7.5068836,-16.860735,7.6"
  , "6.544463,-14.699103,7.8"
  , "8.661789,-19.454695,8.0"
  , "5.3895574,-12.105143,8.2"
  , "6.544463,-14.699103,8.4"
  , "5.0045886,-11.240489,8.6"
  , "4.4271364,-9.94351,8.8"
  , "4.4271364,-9.94351,9.0"
  , "6.159494,-13.834449,9.2"
  , "6.544463,-14.699103,9.4"
  , "5.1970735,-11.672816,9.6"
  , "5.1970735,-11.672816,9.8"
  , "5.3895574,-12.105143,10.0"
  , "7.891852,-17.725388,10.2"
  , "7.121915,-15.996081,10.4"
  , "6.736947,-15.131429,10.6"
  , "6.736947,-15.131429,10.8"
  , "7.121915,-15.996081,11.0"
  , "6.736947,-15.131429,11.2"


};

PeasyCam camera;


// Tool classes 
ToolsArrayList toolsArrayList = new ToolsArrayList();
ToolsPVector toolsPVector     = new ToolsPVector();

// ArrayList<ToolsGrid3D> toolsGrid3D       = new ArrayList(); 

// Turtle turtle                 = new Turtle();

//ArrayList<PVector> list = new ArrayList(); 
ArrayList<PVector> list1 = new ArrayList(); 
//ArrayList<PVector> list2 = new ArrayList();

float a3=0; 

int i_key=0; 

// ---------------------------------------------------------------

void setup() {
  size(1300, 990, P3D);
  createArrayList();
  camera = new PeasyCam(this, width/2, height/2, 0, 900);
  state = show3D;
} //func setup()

void draw() {

  avoidClipping() ; 

  switch(state) {

  case show3D:
    background(111); // gray 
    //  lights(); :
    ambientLight(128, 128, 128) ;
    directionalLight(128, 128, 128, 
      0, 0, 1);
    directionalLight(128, 128, 128, 
      0, 0, -1);
    lightFalloff(1, 0, 0);
    lightSpecular(0, 0, 0);

    // --------

    CheckeredFloor(); 
    toolsArrayList.showArrayListCol (  list1, color(255, 0, 0));  // spherePVCol
    break; 

  default : 
    println("Error"); 
    exit(); 
    break;
  }//switch
  //
} // func draw()

// ---------------------------------------------------------------------------------------------------------------------

void createArrayList() {

  float f1 = 10.0; 

  for (String s : listA) {
    String [] s1 = split(s, ",");
    list1.add(new PVector( f1*float ( s1[0] ), 
      f1* float ( s1[1] ), 
      f1* float ( s1[2] )));
  }
}//func 


void avoidClipping() {
  // avoid clipping (at camera): 
  // https : // 
  // forum.processing.org/two/discussion/4128/quick-q-how-close-is-too-close-why-when-do-3d-objects-disappear
  perspective(PI/3.0, (float) width/height, 1, 1000000);
}//func 

//-----------------------------------------------------------------------------
// floor

void CheckeredFloor() {
  //floor

  noStroke(); 

  for (int i = -40; i < 40; i++) {
    for (int j = -40; j < 40; j++) {

      // get color
      // % is modulo, meaning rest of division 
      if (i%2 == 0) { 
        if (j%2 == 0) { 
          fill (255, 0, 0);
        } else 
        {
          fill ( 103 );
        }
      } else {
        if (j%2 == 0) { 
          fill ( 103 );
        } else 
        {
          fill (255, 0, 0);
        }
      } // if

      pushMatrix(); 
      translate ( 80*i, height/2+210+30+3.5, 80*j ); 
      box ( 80, 7, 80); // one cell / tile 
      popMatrix();
    } // for
  } // for
} // function 

// ==============================================================================================

class Frame {
  ArrayList<Cell> listOfCells = new ArrayList(); 

  void display(float xpos) {
    stroke(255); 
    for (Cell c1 : listOfCells) {
      //point(c1.x, c1.y);
      // noStroke();
      fill(i_key*49+60, 0, 0); 
      ellipse(c1.x+xpos, c1.y, 6, 6);
    }
  }
}

// ==============================================================================================

class Cell {

  float x, y; // pos
  int sclx, scly; // size 

  int i, j; // pos in grid (col/row)

  boolean state=false; // ON / OFF

  // Two colors 
  color colorForOff=  color(random(255), random(255), random(255)); // color(0); // 
  color colorForON=color((255), 0, 0); 

  String strImgName  = ""; 
  PImage imgCell  = null; 

  //constr 
  Cell(float x_, float y_) {
    x = x_; 
    y = y_; 

    sclx=1; 
    scly=1; 

    i=1; 
    j=1;
  }  //constr 

  //constr 
  Cell(int x_, int y_, 
    int a_, int b_, 
    int i_, int j_) {
    x = x_; 
    y = y_; 

    sclx=a_; 
    scly=b_; 

    i=i_; 
    j=j_;
  }  //constr 

  void display() {
    // Do we have an image?  
    if (imgCell==null) {
      // NO 
      if (state)  
        fill(colorForON); // RED 
      else fill( colorForOff ); 

      stroke(111); 

      rect(x, y, 
        sclx, scly);
    } else {
      // YES
      image(imgCell, x, y);
    }//else
  }//func 

  //boolean mouseOver() {
  //  // returns whether the mouse is inside the cell 
  //  return
  //    mouseX>x&&
  //    mouseY>y&&
  //    mouseX<x+sclx&&
  //    mouseY<y+scly;
  //}//method

  //void loadImageInCell(String fileLocal) {
  //  if (fileLocal==null) 
  //    return;
  //  if (fileLocal.equals(""))
  //    return; 
  //  strImgName=fileLocal; 
  //  imgCell = loadImage(fileLocal);
  //  if (imgCell!=null)
  //    imgCell.resize(sclx, 0);
  //  else println("Failed to load image");
  //}//func

  //void deleteImage() {
  //  strImgName="";
  //  imgCell = null;
  //}

  //JSONObject getAsJSON() {
  //  // for saving a grid
  //  JSONObject cellAsJSON = new JSONObject();

  //  cellAsJSON.setInt("state", intFromBoolean (state) ); // 
  //  cellAsJSON.setString("imgName", strImgName); // 

  //  return cellAsJSON;
  //}

  //int intFromBoolean ( boolean bool_) {
  //  if (bool_) return 1; 
  //  else return 0;
  //}
  //
}//class

//=================================================================================

class Turtle {
  // Turtle functions 

  boolean tPenUp = true; 

  // -----

  void setPenToUp() {
    tPenUp = true; // not drawing
  } // method

  void setPenToDown() {
    tPenUp = false; // drawing
  } // method

  // -----

  void tRotateX(float angle_) { 
    rotateX(radians(angle_));
  } // method 

  void tRotateY(float angle_) { 
    rotateY(radians(angle_));
  } // method

  void tRotateZ(float angle_) { 
    rotateZ(radians(angle_));
  } // method

  // -----

  void tLine(float distance_) {
    // Depending on penUp
    // we move or draw 
    if (tPenUp) { 
      tStep(distance_); // move only
    } else {
      tLineDraw(distance_); // draw and move
    }
  } // method

  void tLineDraw(float distance_) {
    // draw and move (pen is down, penUp=false)
    line(0, 0, 0, 
      distance_, 0, 0); 
    translate(distance_, 0, 0);
  } // method

  void tStep(float distance_) {
    // just move (if pen is up, penUp=true) 
    translate(distance_, 0, 0);
  } // method
} // class

// ===========================================================================================

class ToolsArrayList {

  // not a class for an object like a car but a class that collects Tools 

  final float numberOfItems=360.0; 

  ArrayList<PVector> getArrayListLine3D() {

    ArrayList<PVector> result = new ArrayList(); 

    float x1= width/2-520; 
    float y1= -200; 
    float z1= -40; 

    float x2= width/2+520; 
    float y2= y1; 
    float z2= -40; 

    final float steps = numberOfItems; 
    for (int i2 = 0; i2 < steps; i2++) {
      float x = lerp(x1, x2, i2/steps); // + 10 ? 
      float y = lerp(y1, y2, i2/steps); 
      float z = lerp(z1, z2, i2/steps); 

      result.add(new PVector(x, y, z));
    }//for 

    return 
      result;
  }//method 

  ArrayList<PVector> getArrayListCircle3D(float radius1, float yIn_) {

    ArrayList<PVector> result = new ArrayList(); 

    float centerX = width/2; 
    float centerZ = -40; 

    for (int angleC = 0; angleC < numberOfItems; angleC += 1) {

      float cX = centerX + (cos (radians(angleC)) * radius1); 
      float cY = yIn_; 
      float cZ = centerZ + (sin (radians(angleC)) * radius1); 

      result.add(new PVector(cX, cY, cZ));
    }//for 

    return 
      result;
  }//method 

  ArrayList<PVector> getArrayListCircle3DSin(float radius1, float yIn_) {

    ArrayList<PVector> result = new ArrayList(); 

    float centerX = width/2; 
    float centerZ = -40; 

    for (int angleC = 0; angleC < numberOfItems; angleC += 1) {

      float cX = centerX + (cos (radians(angleC)) * radius1); 
      float cY = yIn_ + sin(radians(angleC*10)) * 120; 
      float cZ = centerZ + (sin (radians(angleC)) * radius1); 

      result.add(new PVector(cX, cY, cZ));
    }//for 

    return 
      result;
  }//method 

  ArrayList<PVector> getArrayListCircle3DCos(float radius1, float yIn_) {

    ArrayList<PVector> result = new ArrayList(); 

    float centerX = width/2; 
    float centerZ = -40; 

    for (int angleC = 0; angleC < numberOfItems; angleC += 1) {

      float cX = centerX + (cos (radians(angleC)) * radius1); 
      float cY = yIn_ + cos(radians(angleC*2)) * 120; 
      float cZ = centerZ + (sin (radians(angleC)) * radius1); 

      result.add(new PVector(cX, cY, cZ));
    }//for 

    return 
      result;
  }//method 

  void showArrayList( ArrayList<PVector> result ) {
    // drawSphereAtPositionXYZ(width/2+60, 200, -40);
    for (PVector pv : result) {
      toolsPVector.spherePV(pv);
    }//for
  }

  void showArrayListCol( ArrayList<PVector> result, color c1 ) {
    // drawSphereAtPositionXYZ(width/2+60, 200, -40);
    for (PVector pv : result) {
      //fill(c1); 
      toolsPVector.spherePVCol(pv, c1);
    }//for
  }

  void showTwoArrayListsConnectedWithLines( ArrayList<PVector> result1, ArrayList<PVector> result2   ) {
    // drawSphereAtPositionXYZ(width/2+60, 200, -40);
    for (int i=0; i<result1.size(); i++) {
      // toolsPVector.spherePV(pv);
      stroke(255, 0, 0); 
      toolsPVector.linePV(result1.get(i), result2.get(i));
    }//for
  }//method
  //
}//class

//===================================================================================

class ToolsPVector {

  // not a class for an object like a car but a class that collects Tools - FOR 3D -----------!!!! 

  void linePV ( PVector pv1, PVector pv2) {
    line(pv1.x, pv1.y, pv1.z, 
      pv2.x, pv2.y, pv2.z);
  }//func

  void pointPV ( PVector pv) {
    point(pv.x, pv.y, pv.z);
  }//func

  void spherePV ( PVector pv) {
    pushMatrix(); 
    translate(pv.x, pv.y, pv.z); 
    noStroke(); 
    fill(255, 0, 0); 
    sphere(17); 
    popMatrix();
  }//func

  void spherePVCol ( PVector pv, color c1) {
    pushMatrix(); 
    translate(pv.x, pv.y, pv.z); 
    noStroke(); 
    fill(c1); 
    sphere(13.5); 
    popMatrix();
  }//func

  void vertexPV(color col_, PVector pv_) {
    fill(col_); 
    vertex(pv_.x, pv_.y, pv_.z);
  }
  //
}//class

//===================================================================================

class ToolsGrid3D {

  // not a class for an object like a car but a class that collects Tools - FOR 3D -----------!!!! 

  // ArrayLists
  //  ArrayList<PVector> result; 

  QUAD3D[][] points; //= new  QUAD3D[resultInner.size()][10];

  void init2222222222222222222222(  ArrayList<PVector> resultInner, ArrayList<PVector> resultOuter) {

    points = new  QUAD3D[resultInner.size()][11]; 

    //  make it
    for (int i=0; i <  resultInner.size(); i++) {
      // for (PVector pvInner : resultInner) {
      //  for (PVector pvOuter : resultOuter) {
      PVector pvInner = resultInner.get(i); 
      PVector pvOuter = resultOuter.get(i); 
      float x1=pvInner.x; 
      float x2=pvOuter.x; 

      float y1=pvInner.y; 
      float y2=pvOuter.y; 

      float z1=pvInner.z; 
      float z2=pvOuter.z; 

      int j=0; 
      for (int i2 = 0; i2 <= 10; i2++) {
        float x = lerp(x1, x2, i2/10.0); // + 10  ? 
        float y = lerp(y1, y2, i2/10.0); 
        float z = lerp(z1, z2, i2/10.0); 

        points[i][j] = new  QUAD3D(); 
        points[i][j].col = color(255, 0, 0); //      0xff000000 | (red << 0x10) | (green << 0x08) | blue;

        points[i][j].pos.set(x, y, z); 
        j++;
      }
    }
  }

  void init2( ) {
    points = new  QUAD3D[41][44];
  }

  void addToolsGrid3D(  ArrayList<PVector> resultInner, ArrayList<PVector> resultOuter) {

    //  points = new  QUAD3D[resultInner.size()][11];

    //  make it
    for (int i=0; i <  resultInner.size(); i++) {
      // for (PVector pvInner : resultInner) {
      //  for (PVector pvOuter : resultOuter) {
      PVector pvInner = resultInner.get(i); 
      PVector pvOuter = resultOuter.get(i); 
      float x1=pvInner.x; 
      float x2=pvOuter.x; 

      float y1=pvInner.y; 
      float y2=pvOuter.y; 

      float z1=pvInner.z; 
      float z2=pvOuter.z; 

      int j=0; 
      for (int i2 = 0; i2 <= 43; i2++) {
        float x = lerp(x1, x2, i2/10.0); // + 10  ? 
        float y = lerp(y1, y2, i2/10.0); 
        float z = lerp(z1, z2, i2/10.0); 

        points[i][j] = new  QUAD3D(); 
        points[i][j].col = color(255, 0, 0); //      0xff000000 | (red << 0x10) | (green << 0x08) | blue;

        points[i][j].pos.set(x, y, z); 
        j++;
      }
    }
  }

  void display() {
    // output 
    beginShape(QUADS); 
    for (int i = 0; i < points.length-1; i++) {    
      for (int j = 0; j < points[i].length-1; j++) {

        // stroke(0);
        noStroke(); 
        if  (points[i][j] == null || points[i+1][j] == null || points[i+1][j+1] == null ) 
          continue; 
        //println(points[i][j].pos);
        points[i][j].display(); 
        points[i+1][j].display(); 
        points[i+1][j+1].display(); 
        points[i][j+1].display();
      }
    }

    int i=points.length-2; // resultInner.size()-2;
    int i2=0; 
    for (int j = 0; j < 11-1; j++) {
      //println(points[i][j].pos);
      if  (points[i][j] == null || points[i+1][j] == null || points[i+1][j+1] == null ) 
        continue; 
      points[i][j].display(); 
      points[i2][j].display(); 
      points[i2][j+1].display(); 
      points[i][j+1].display();
    }
    endShape(CLOSE);
  }//func 

  //void vertexQUAD3D(QUAD3D quad3D) {
  //  fill(quad3D.col);
  //  vertex(quad3D.pos.x, quad3D.pos.y, quad3D.pos.z);
  //}
}//class

// ====================================================================================

class QUAD3D {
  PVector pos=new PVector(); 
  color col=color(0); 

  void display() {
    fill(col); 
    vertex(pos.x, pos.y, pos.z);
  }
  //
}//class 
//

i have chose random images just to see how things going on

apply this obj.file to your code it is open with any text editor can you ?
when ever you can i am not in harry i just have to be here with good people

this is the shape

Unfortunately I don’t have time

But I wish you luck.

Chrisir

1 Like

@Chrisir
first test
It looks like a spaceship hit by a meteor

@Chrisir

the second test gives more results