开源项目SUSTechPOINTS的点云数据加载过程
1.程序启动
依次安装requirement.txt中的以下相关库:
tensorflow>=2.1
jinja2
cherrypy
filterpy
cheroot != 8.4.4
安装方法:
例如执行pip3 install tensorflow安装 tensorflow
如果安装速度慢,可以使用镜像,执行以下命令安装:
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple/ tensorflow
执行命令:python main.py,启动程序。
2.editor.js
// 监听帧变化事件
this.frame_changed= function(event){
var sceneName = this.editorUi.querySelector("#scene-selector").value;
if (sceneName.length == 0 && this.data.world)
{
sceneName = this.data.world.frameInfo.scene;
}
if (sceneName.length == 0){
return;
}
var frame = event.currentTarget.value;
// 加载当前帧
this.load_world(sceneName, frame);
event.currentTarget.blur();
};
// 加载当前帧数据
this.load_world = async function(sceneName, frame, onFinished){
var world = await this.data.getWorld(sceneName, frame);
// 渲染
this.data.activate_world(
world,
function(){
self.on_load_world_finished(world);
if (onFinished)
onFinished();
}
);
}
// 渲染过程
this.on_load_world_finished= function(world){
this.moveAxisHelper(world);
this.moveRangeCircle(world);
this.lookAtWorld(world);
this.unselectBox(null, true);
this.render();
this.imageContextManager.attachWorld(world);
this.imageContextManager.render_2d_image();
this.render2dLabels(world);
// 刷新当前帧信息
this.update_frame_info(world.frameInfo.scene, world.frameInfo.frame);
this.select_locked_object();
//load_obj_ids_of_scene(world.frameInfo.scene);
objIdManager.setCurrentScene(world.frameInfo.scene);
// preload after the first world loaded
// otherwise the loading of the first world would be too slow
this.data.preloadScene(world.frameInfo.scene, world);
};
3.data.js
// 加载当前帧数据
getWorld(sceneName, frame, on_preload_finished){
world = this._createWorld(sceneName, frame, on_preload_finished);
}
_createWorld(sceneName, frame, on_preload_finished){
........
let world = new World(this, sceneName, frame, [this.worldGap*x, this.worldGap*y, this.worldGap*z], on_preload_finished);
........
}
4.world.js 一帧的数据处理
function World(data, sceneName, frame, coordinatesOffset, on_preload_finished){
......
// 相机数据
this.cameras = new Images(this.sceneMeta, sceneName, frame);
// 雷达数据
this.radars = new RadarManager(this.sceneMeta, this, this.frameInfo);
// 激光雷达数据
this.lidar = new Lidar(this.sceneMeta, this, this.frameInfo);
// 标注数据
this.annotation = new Annotation(this.sceneMeta, this, this.frameInfo);
......
}
this.go=function(){
if (this.everythingDone){
//console.error("re-activate world?");
//however we still call on_finished
if (this.on_finished){
this.on_finished();
}
return;
}
if (this.preloaded()){
//this.points.material.size = data.cfg.point_size;
if (this.destroy_old_world){
this.destroy_old_world();
}
if (this.destroyed){
console.log("go after destroyed.");
this.unload();
return;
}
this.scene.add(this.webglGroup);
this.lidar.go(this.scene);
this.annotation.go(this.scene);
this.radars.go(this.scene);
this.aux_lidars.go(this.scene);
-----lidar.js 激光雷达点云数据-----
this.preload=function(on_preload_finished){
this.on_preload_finished = on_preload_finished;
var loader = new PCDLoader();
var _self = this;
loader.load( this.frameInfo.get_pcd_path(),
//ok
function ( pcd ) {
_self.points_parse_time = new Date().getTime();
console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "parse pionts ", _self.points_parse_time - _self.create_time, "ms");
if (_self.data.cfg.enableFilterPoints)// do some filtering work here
{
pcd = _self.remove_high_ponts(pcd, _self.data.cfg.filterPointsZ);
}
let position = pcd.position;
// build geometry
_self.world.data.dbg.alloc();
var geometry = new THREE.BufferGeometry();
if ( position.length > 0 )
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( position, 3 ) );
let normal = pcd.normal;
// normal and colore are note used in av scenes.
if ( normal.length > 0 )
geometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( normal, 3 ) );
let color = pcd.color;
if ( color.length == 0 ) {
color = []
// by default we set all points to same color
for (let i =0; i< position.length; ++i){
color.push(_self.data.cfg.point_brightness);
}
// if enabled intensity we color points by intensity.
if(_self.data.cfg.color_points=="intensity" && pcd.intensity.length>0){
// map intensity to color
for (var i =0; i< pcd.intensity.length; ++i){
let intensity = pcd.intensity[i];
intensity *= 8;
if (intensity > 1)
intensity = 1.0;
//color.push( 2 * Math.abs(0.5-intensity));
color[i*3] = intensity;
color[i*3+1] = intensity;
color[i*3+2] = 1 - intensity;
}
}
// save color, in case color needs to be restored.
pcd.color = color;
}
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute(color, 3 ) );
geometry.computeBoundingSphere();
// build material
var material = new THREE.PointsMaterial( { size: _self.data.cfg.point_size, vertexColors: THREE.VertexColors } );
/*
if ( color.length > 0 ) {
material.vertexColors = color;
} else {
//material.color.setHex(0xffffff);
material.color.r = 0.6;
material.color.g = 0.6;
material.color.b = 0.6;
}
*/
//material.size = 2;
material.sizeAttenuation = false;
// build mesh
var mesh = new THREE.Points( geometry, material );
mesh.name = "pcd";
//return mesh;
// add to parent.
_self.world.webglGroup.add(mesh);
_self.points = mesh;
_self.pcd = pcd;
//_self.points_backup = mesh;
_self.build_points_index();
_self.points_load_time = new Date().getTime();
console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "loaded pionts ", _self.points_load_time - _self.create_time, "ms");
_self._afterPreload();
},
// on progress,
function(){
},
// on error
function(){
//error
console.log("load pcd failed.");
_self._afterPreload();
},
// on file loaded
function(){
_self.points_readfile_time = new Date().getTime();
console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "read file ", _self.points_readfile_time - _self.create_time, "ms");
}
);
};
5.annotation.js 标注数据
function Annotation(sceneMeta, world, frameInfo)
this.world = world
this.load_annotation((boxes)=>this.proc_annotation(boxes))
// 加载标注数据
this.load_annotation=function(on_load){
debugger
if (this.data.cfg.disableLabels){
on_load([]);
}else {
var xhr = new XMLHttpRequest();
// we defined the xhr
var _self = this;
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status == 200) {
let ann = _self.frameInfo.anno_to_boxes(this.responseText);
on_load(ann);
}
// end of state change: it can be after some time (async)
};
xhr.open('GET', "/load_annotation"+"?scene="+this.frameInfo.scene+"&frame="+this.frameInfo.frame, true);
xhr.send();
}
};
// 处理标注数据
this.proc_annotation = function(boxes){
// .......
// by kinlong 参数boxes是标注数据,this.boxes是对象
this.boxes = this.createBoxes(boxes); //create in future world
this.boxes.forEach(b=>this.webglGroup.add(b));
this.world.webglGroup.add(this.webglGroup); // this.webglGroup.children
//this.world.webglGroup.children[0].children-->this.boxes--> [LineSegments]
}
this.createBoxes = function(annotations){
return annotations.map((b)=>{
return this.createOneBoxByAnn(b);
});
};
this.createOneBoxByAnn = function(annotation){
let b = annotation;
let mesh = this.createCuboid(b.psr.position,
b.psr.scale,
b.psr.rotation,
b.obj_type,
b.obj_id,
b.obj_attr);
if (b.annotator){
mesh.annotator = b.annotator;
}
if (b.follows)
mesh.follows = b.follows;
return mesh;
};
// 附加标注信息,创建长方体
this.createCuboid = function(pos, scale, rotation, obj_type, track_id, obj_attr){
let mesh = this.new_bbox_cube(parseInt("0x"+globalObjectCategory.get_obj_cfg_by_type(obj_type).color.slice(1)));
mesh.position.x = pos.x;
mesh.position.y = pos.y;
mesh.position.z = pos.z;
mesh.scale.x = scale.x;
mesh.scale.y = scale.y;
mesh.scale.z = scale.z;
mesh.rotation.x = rotation.x;
mesh.rotation.y = rotation.y;
mesh.rotation.z = rotation.z;
mesh.obj_track_id = track_id; //tracking id
mesh.obj_type = obj_type;
mesh.obj_attr = obj_attr;
mesh.obj_local_id = this.get_new_box_local_id();
mesh.world = this.world;
return mesh;
};
this.new_bbox_cube=function(color){
var h = 0.5;
var body = [
//top
-h,h,h, h,h,h,
h,h,h, h,-h,h,
h,-h,h, -h,-h,h,
-h,-h,h, -h, h, h,
//botom
-h,h,-h, h,h,-h,
h,h,-h, h,-h,-h,
h,-h,-h, -h,-h,-h,
-h,-h,-h, -h, h, -h,
// vertical lines
-h,h,h, -h,h,-h,
h,h,h, h,h,-h,
h,-h,h, h,-h,-h,
-h,-h,h, -h,-h,-h,
//direction
h, 0, h, 1.5*h, 0, h,
];
this.world.data.dbg.alloc();
var bbox = new THREE.BufferGeometry();
bbox.setAttribute( 'position', new THREE.Float32BufferAttribute(body, 3 ) );
if (!color){
color = 0x00ff00;
}
/*
https://threejs.org/docs/index.html#api/en/materials/LineBasicMaterial
linewidth is 1, regardless of set value.
*/
var material = new THREE.LineBasicMaterial( { color: color, linewidth: 1, opacity: this.data.cfg.box_opacity, transparent: true } );
var box = new THREE.LineSegments( bbox, material );
box.scale.x=1.8;
box.scale.y=4.5;
box.scale.z=1.5;
box.name="bbox";
box.obj_type="car";
return box;
};