三维扫描仪[11]——总结并展望基于Kinect的三维扫描仪
到这里,我相信绝大多数大一的相关专业学生都可以完成这样一台扫描仪了。
让我们全局看一下这个小项目。
机械方面
可以参考三维扫描仪[8]——如何设计一台云台式扫描仪(机械结构)
我们需要一个支架,支起Kinect和云台,同时我们也需要一套齿轮组,获得精确的角度变化。
开发环境方面
可以参考:
三维扫描仪[6]——常用软件及开发环境
三维扫描仪[7]——认识Processing和Arduino开发环境
其中
Meshlab
Arduino
Processing
和其他的中间件是必须的
项目代码方面
可以参考:
三维扫描仪[9]——如何设计一台云台式扫描仪(初步软件设计)
三维扫描仪[10]——如何设计一台云台式扫描仪(代码详解)
这里也附上全套代码
Arduino
步进电机代码
int xdir = 13;
int Step = 12;
int xen = 9;void setup() {// put your setup code here, to run once:pinMode(xen, OUTPUT);pinMode(xdir, OUTPUT);pinMode(Step, OUTPUT);digitalWrite(xen, LOW);digitalWrite(xdir, LOW);
}void loop() {// put your main code here, to run repeatedly:digitalWrite(Step, LOW);delay(10);digitalWrite(Step, HIGH);delay(10);
}
角度传感器代码
int potPin = A0;
int Pos = 0;void setup() {// put your setup code here, to run once:pinMode(potPin, INPUT);Serial.begin(9600);
}void loop() {// put your main code here, to run repeatedly:Pos = analogRead(potPin);delay(250);Serial.println(Pos);
}
Processing
import processing.serial.*;
import processing.opengl.*;
import SimpleOpenNI.*;
import kinectOrbit.*;
//Init Orbit and OpenNI Class.
KinectOrbit myOrbit;
SimpleOpenNI kinect;
//Serial data.
Serial myPort;
boolean serial = true;
//!
String turnTableAngle = "0";
int turnAngle = 0;
float Angle = 0;
//!
//Init pointClouds and ArrayList with clolors.
ArrayList<PVector> scanPoints = new ArrayList<PVector>();//pointCloud
ArrayList<PVector> scanColors = new ArrayList<PVector>();//obj color
ArrayList<PVector> objectPoints = new ArrayList<PVector>();//pointCloud
ArrayList<PVector> objectColors = new ArrayList<PVector>();//obj color//Height
float baseHeight = -180;
float modelWidth = 1000;
float modelHeight = 1000;
PVector axis = new PVector(0, baseHeight, 1200);int scanLines = 300;
int scanRes = 1; //high ppx
boolean scanning = false;
boolean arrived = false;
float[] shotNumber = new float[30];
int currentShot = 0;int dataNum = 1;public void setup()
{size(800, 600, OPENGL);//Init orbitmyOrbit = new KinectOrbit(this, 0, "kinect");myOrbit.drawCS(true);myOrbit.drawGizmo(true);myOrbit.setCSScale(200);myOrbit.drawGround(true);//Init SimpleOpenNIkinect = new SimpleOpenNI(this);kinect.setMirror(false);kinect.enableDepth();kinect.enableRGB();kinect.alternativeViewPointDepthToImage();//Serialif(serial) {String portName = Serial.list()[0];myPort = new Serial(this, portName, 9600);//!myPort.bufferUntil('\n');//!}
}public void draw()
{kinect.update();background(0);myOrbit.pushOrbit(this); //Start OrbitdrawPointCloud(1);//!!!!!updateObject(scanLines, scanRes);//!!!!!drawObjects();drawBoundingBox();kinect.drawCamFrustum();myOrbit.popOrbit(this);
}void drawPointCloud(int steps)
{int index;PVector realWorldPoint;stroke(255);for(int y = 0; y < kinect.depthHeight(); y += steps) {for(int x = 0; x < kinect.depthWidth(); x += steps) {index = x + y * kinect.depthWidth();realWorldPoint = kinect.depthMapRealWorld()[index];stroke(150);point(realWorldPoint.x, realWorldPoint.y, realWorldPoint.z);}}
}void drawObjects()
{pushStyle();strokeWeight(1);for(int i = 1; i < objectPoints.size(); i++) {stroke(objectColors.get(i).x, objectColors.get(i).y, objectColors.get(i).z);point(objectPoints.get(i).x, objectPoints.get(i).y, objectPoints.get(i).z + axis.z);}for(int i = 1; i < scanPoints.size(); i++) {stroke(scanColors.get(i).x, scanColors.get(i).y, scanColors.get(i).z);point(scanPoints.get(i).x, scanPoints.get(i).y, scanPoints.get(i).z + axis.z);}popStyle();
}void drawBoundingBox()
{stroke(255, 0, 0);line(axis.x, axis.y, axis.z, axis.x, axis.y+100, axis.z);noFill();pushMatrix();translate(axis.x, axis.x + baseHeight + (modelHeight / 2), axis.z);box(modelWidth, modelHeight, modelWidth);popMatrix();
}void scan()
{for(PVector v : scanPoints) {objectPoints.add(v.get());int index = scanPoints.indexOf(v);objectColors.add(scanColors.get(index).get());}if(currentShot < shotNumber.length-1) {currentShot ++;println("scan angle = " + Angle);}else {scanning = false;}arrived = false;
}void updateObject(int scanWidth, int step)
{int index;PVector realWorldPoint;scanPoints.clear();scanColors.clear();serialEvent(myPort);Angle = radians(map(turnAngle, 0, 1023, 0, 360));//println("angle = " + Angle);//draw linepushMatrix();translate(axis.x, axis.y, axis.z);rotateY(Angle);line(0, 0, 100, 0);popMatrix();int xMin = (int)(kinect.depthWidth() / 2 - scanWidth / 2);int xMax = (int)(kinect.depthWidth() / 2 + scanWidth / 2);for(int y = 0; y < kinect.depthHeight(); y += step) {for(int x = xMin; x < xMax; x += step) {index = x + (y * kinect.depthWidth());realWorldPoint = kinect.depthMapRealWorld()[index];color pointCol = kinect.rgbImage().pixels[index];if(realWorldPoint.y < (modelHeight + baseHeight) && realWorldPoint.y > baseHeight) {if(abs(realWorldPoint.x - axis.x) < modelWidth / 2) {if(realWorldPoint.z < axis.z + modelWidth / 2 && realWorldPoint.z > axis.z - modelWidth / 2) {PVector rotatedPoint;realWorldPoint.z -= axis.z;realWorldPoint.x -= axis.x;rotatedPoint = vecRotY(realWorldPoint, Angle);scanPoints.add(rotatedPoint.get());scanColors.add(new PVector(red(pointCol), green(pointCol), blue(pointCol)));}}}}}
}PVector vecRotY(PVector vecIn, float phi)
{PVector rotatedVec = new PVector();rotatedVec.x = vecIn.x * cos(phi) - vecIn.z * sin(phi);rotatedVec.z = vecIn.x * sin(phi) + vecIn.z * cos(phi);rotatedVec.y = vecIn.y;return rotatedVec;
}public void keyPressed()
{switch(key) {case 'c':objectPoints.clear();objectColors.clear();currentShot = 0;break;case 'e':String stringNum = String.valueOf(dataNum);char key = stringNum.charAt(0);exportPly(key);dataNum ++;println("save success!");break;case 's':scan();break;}
}public void serialEvent(Serial myPort)
{String inString = myPort.readStringUntil('\n');if(inString != null) {//cut spaceturnTableAngle = trim(inString);turnAngle = Integer.parseInt(turnTableAngle);}
}void exportPly(char key)
{PrintWriter output;String viewPointFileName;viewPointFileName = "myPoints" + key + ".ply";output = createWriter(dataPath(viewPointFileName));//!!!!//head fileoutput.println("ply");output.println("format ascii 1.0");output.println("comment This is your Processing ply file");output.println("element vertex " + (objectPoints.size()-1));output.println("property float x");output.println("property float y");output.println("property float z");output.println("property uchar red");output.println("property uchar green");output.println("property uchar blue");output.println("end_header");//!!!!for(int i = 0; i < objectPoints.size() - 1; i++) {output.println((objectPoints.get(i).x / 1000) + " "+ (objectPoints.get(i).y / 1000) + " "+ (objectPoints.get(i).z / 1000) + " "+ (int) objectColors.get(i).x + " "+ (int) objectColors.get(i).y + " "+ (int) objectColors.get(i).z);}output.flush();output.close();
}
三维重建原理方面
可以参考:
三维扫描仪[2]——大恒、微软、还是淘宝一下双目摄像头?
三维扫描仪[3]——标定·理论
本项目并不涉及、但是接下来会用到的标定方面
可以参考:
三维扫描仪[4]——标定·Matlab单目标定
三维扫描仪[5]——标定·Matlab双目标定
展望
本来没有这个部分的
然而我昨天(2017.4.21)散步的时候突然想到:
用两个Kinect
KinectA保持不动 KinectB在A的视野下运动 由KinectB扫描
我们需要确定A的空间位置 获得B实时的空间位置和角度
最终!根据多个空间坐标系的转换 实现手持Kinect扫描并叠加
没有实验过,也没考虑过优势。
只是作为一个二本大三的软件工程学生,感觉扫描仪再贴点,再有庞杂的机械结构,挺不好的。
希望廉价的扫描仪能服务更多的普通人吧。
希望我将来去漫展的时候,真的能把你们变成我的手办。
扫描仪这个部分并没有结束。
这只是一个小例子,用来体会逆向工程的。
接下来我们干个酷炫的
要不这几年真白读了
三维扫描仪[11]——总结并展望基于Kinect的三维扫描仪相关推荐
- 本科毕设论文——基于Kinect的拖拉机防撞系统
基于Kinect的拖拉机防撞系统 电子信息科学与技术专业学生 sukeysun 摘要:随着智能车辆技术的发展,智能导航定位和实时车载监控等技术被更多的应用到日常生活照.在农业领域上,车辆自主感知道路环 ...
- 基于kinect的人体动作识别系统
基于kinect的人体动作识别系统(算法和代码都放出) 首先声明一下,本系统所使用的开发环境版本是计算机系统Windows 10.Visual Studio 2013.Opencv3.0和Kinect ...
- 基于kinect的人体动作识别系统(算法和代码都放出)
基于kinect的人体动作识别系统(算法和代码都放出) 首先声明一下,本系统所使用的开发环境版本是计算机系统Windows 10.Visual Studio 2013.Opencv3.0和Kinect ...
- 基于Kinect体感器控制的机械臂项目记录
基于Kinect体感器控制的机械臂 项目介绍 上位机代码说明 1.识别部分 1.1GetPosition.cpp 1.2 KinetJiointFilter.cpp 1.3 1.4 SerialPor ...
- python面对对象建立自己的电子宠物的编码_一种基于Kinect技术的电子宠物的制作方法...
本发明涉及电子宠物技术领域,特别涉及一种基于Kinect技术的电子宠物. 背景技术: 目前人工智能发展迅速,现在的电子宠物动作单一,并且不能够与人进行交互,对周围的环境不能够准确识别,面对用户的动作只 ...
- 基于slam的三维重建_实时三维重建算法的实现 基于Kinect与单目视觉SLAM的三维重建.docx...
实时三维重建算法的实现 基于Kinect与单目视觉SLAM的三维重建 实时三维重建算法的实现--基于Kinect与单目视觉SLAM的三维重建夏文玲1,顾照鹏2,杨唐胜2XIAWenling1,GUZh ...
- 基于kinect + EmguCV 的监控小应用(视频录制保存)
kinectMonitor 源码位置 家庭监控小应用–https://gitee.com/ellecommander/kinecMonitor 介绍 基于kinect的家庭监控系统,主要是为了监控我爸 ...
- 基于Kinect Azure的多相机数据采集(二)
基于Kinect Azure的多相机数据采集(二) 在基于Kinect Azure的多相机数据采集(一)中以双相机数据采集为例,介绍了Kinect Azure进行多相机数据采集的方法,主要包括 ...
- java kinect 人体识别_基于kinect的人体动作识别系统
[实例简介] 基于kinect v2的人体动作识别,配套博客(http://blog.csdn.net/baolinq/article/),基于mfc,可以识别左移右移.上蹦下跳等,也可以自己自定义其 ...
- 基于Kinect体感的仿真对抗游戏系统
项目意义: 1.Kinect的研究和应用在国内外都呈现出比较高的热潮,相关技术,如人脸识别.动态跟踪.手势识别等均出现了比较优越的实际效果.让机器人能够实时跟踪人的动作功能并完成与人的沟通互动是机器人 ...
最新文章
- 威纶通触摸屏与单片机MODBUS_威纶通案例集锦51-55
- dns-sd._udp.domain. 域名发现 本质和MDNS同
- JAVA语言中的反射机制
- checkbox选中和不选中 jqu_jquery checkbox 选中不选中
- 计算机专业可以报考放射医学吗吗,文科生可以报考医学影像技术专业吗
- Linux中常用的命令
- 配置SCCM 2012 SP1(七)操作系统部署
- [BJOI2017]开车
- win8这台计算机到桌面上,Win8如何在桌面上显示“我的电脑”图标,小编教你Win8如何在桌面上显示我的电脑...
- 通过存储介质(例如 USB)传送项目到操作面板
- 51单片机学习笔记(7)——74HC138三八译码器
- ORB SLAM 2 demo 复现
- 需求分析——需求分析的步骤
- Codeforces 1077B Disturbed People(思维题)
- autorun.vbs病毒的清除办法
- hbase踩坑记录(二):Can not resolve promote.cache-dns.local, please check your network
- Android 百度地图marker中图片不显示的解决方案
- 查询选修“张三“老师所授课程的学生中,成绩最高的学生信息及其成绩
- 虚拟试衣-DiOr论文解读
- 【目标检测·yolo系列】YOLOV3目标检测论文笔记(参考 同济子豪兄的解读)