Medaljong av kärlek: från Kinect till 3D-utskrifter (4 / 10 steg)
Steg 4: Skanna själv med Kinect
ModelBuilder Processing Library
ModelBuilder innehåller verktyg som gör våra liv mycket enklare att skapa och manipulera 3D-geometri bearbetning.
Biblioteket som ska användas med avsökningen förlopp kallas ModelBuilder designad av Marius Watz, som kan fås här.
Installera det som OpenNI bearbetning bibliotek (i föregående steg) genom att flytta mappen till mappen bearbetning bibliotek.
Vanligtvis, dokument -> bearbetning -> bibliotek (se bild 2)
Skissen jag använt för att skanna själv var från typ ut från boken "Att göra saker se böcker" i kapitel 5, den fullständiga koden inte tillgänglig var som helst annars.
Boken ger Detaljer förklaring av skissen och hur det fungerar. Detta är en mycket bra bok, rekommenderade jag!
Jag ändrat några rader av skiss till gör den lämplig vad jag gör för projektet.
Här är skissen:
import processing.opengl.*;
import unlekker.util.*;
import unlekker.modelbuilder.*;
import SimpleOpenNI.*;
SimpleOpenNI kinect;
boolesk sökning = false;
int maxZ = 2000.
int maxZ = 800;
int avstånd = 3;
UGeometry modell;
UVertexList vertexList;
void setup() {
storlek (1024, 768, OPENGL);
storlek (640, 480, OPENGL);
Kinect = nya SimpleOpenNI(this);
kinect.enableDepth();
modell = nya UGeometry();
vertexList = ny UVertexList();
}
void draw() {
Background(0);
Kinect.Update();
Översätt (bredd/2, höjd/2,-1000);
rotateX(radians(180));
IF(scanning) {
model.beginShape(TRIANGLES);
}
PVector [] depthPoints = kinect.depthMapRealWorld();
rensning av pass
för (int y = 0; y < 480; y += avstånd) {
för (int x = 0; x < 640; x += avstånd) {
int jag = y * 640 + x;
PVector p = depthPoints [i];
Om punkten är på kanten eller om den har ingen djup
om (p.z < 10 || p.z > maxZ ||
y == 0 || y == 480 - avstånd ||
x == 0 || x == 640 - avstånd) {
ersätta det med en djup backplane (dvs. maxZ)
PVector realWorld = nya PVector();
PVector projektiva = nya PVector (x, y, maxZ);
för att få punkten på rätt ställe, måste vi översätta
från x / y till realWorld koordinater för att matcha våra andra punkter:
kinect.convertProjectiveToRealWorld (planerande, realWorld);
depthPoints [i] = realWorld;
}
}
}
för (int y = 0, y < 480-avstånd; y += avstånd) {
för (int x = 0, x < 640-avstånd; x += avstånd) {
IF(scanning) {
int nw = x + y * 640;
int ne = (x + avstånd) + y * 640;
int sw = x + (y + avstånd) * 640;
int se = (x + avstånd) + (y + avstånd) * 640;
model.addFace (nya UVec3 (depthPoints [nw] .x, depthPoints [nw] .y, depthPoints[nw].z),
ny UVec3 (depthPoints [ne] .x, depthPoints [ne] .y, depthPoints[ne].z),
ny UVec3 (depthPoints [sw] .x, depthPoints [sw] .y, depthPoints[sw].z));
model.addFace (nya UVec3 (depthPoints [ne] .x, depthPoints [ne] .y, depthPoints[ne].z),
ny UVec3 (depthPoints [se] .x, depthPoints [se] .y, depthPoints[se].z),
ny UVec3 (depthPoints [sw] .x, depthPoints [sw] .y, depthPoints[sw].z));
}
annat {
stroke(255);
int jag = y * 640 + x;
PVector currentPoint = depthPoints [i];
IF(currentPoint.z < maxZ) {
punkt (currentPoint.x, currentPoint.y, currentPoint.z);
}
}
}
}
IF(scanning) {
model.calcBounds();
Model.translate (0, 0, - maxZ);
flyta modelWidth = (model.bb.max.x - model.bb.min.x);
flyta modelHeight = (model.bb.max.y - model.bb.min.y);
UGeometry stöd = Primitive.box (modelWidth/2, modelHeight/2, 10);
Model.Add(backing);
Model.Scale(0.01);
model.rotateY(radians(180));
model.toOrigin();
model.endShape();
Snöre arkivnamnen = "Scan02.stl";
för (int jag = 0; jag < 100; i ++) {
filename.substring(4) = "0" + 1/10;
filename.substring(5) = "0" + 1% 10;
skapa filen om den inte finns på SD-kort
IF (!. SD.exist(filename)) {
bryta;
// }
//}
SimpleDateFormat logFileFmt = ny SimpleDateFormat("'scan_'yyyyMMddHHmmss'.stl'");
model.writeSTL (denna, logFileFmt.format (nya Date()));
model.writeSTL (här, filnamn).
scanning = false;
}
}
void keyPressed() {
println(maxZ);
IF(keycode == up) {
maxZ + = 100.
}
IF(keycode == Down) {
maxZ-= 100.
}
om (nyckel == "") {
scanning = sant;
Model.Reset();
}
}