我是3js的新手,我有2张图像,即RGB图像和Depth图像。我可以使用3js创建将这两者结合在一起的点云吗? 如果是,那怎么办?
答案 0 :(得分:4)
为解决此问题,我去了three.js examples并搜索了“ point”。我检查了每个匹配的样本中每个粒子的颜色是否不同。然后,我单击“查看源代码”按钮以检出代码。我最终从this example开始,看着the source。很清楚地说明了如何设置一组不同颜色的点。
因此,在那之后,我只需要加载RGB和Depth这两个图像,就形成点网格,对于每个点,将Z位置设置为深度,将颜色设置为图像的颜色。
我用手机使用this app
拍摄了这些RGB和景深图像
要获取数据,我将图像绘制到画布中,然后调用getImageData
。这样一来,每个通道(红色,绿色,蓝色,alpha)的数据值都在0到255之间。
然后,我编写了一个函数来获取单个像素并返回0到1范围内的颜色。为了安全起见,它会检查边界。
// return the pixel at UV coordinates (0 to 1) in 0 to 1 values
function getPixel(imageData, u, v) {
const x = u * (imageData.width - 1) | 0;
const y = v * (imageData.height - 1) | 0;
if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) {
return [0, 0, 0, 0];
} else {
const offset = (y * imageData.width + x) * 4;
return Array.from(imageData.data.slice(offset, offset + 4)).map(v => v / 255);
}
}
结果
'use strict';
/* global THREE */
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "anonymous";
img.onload = (e) => { resolve(img); };
img.onerror = reject;
img.src = url;
});
}
function getImageData(img) {
const ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = img.width;
ctx.canvas.height = img.height;
ctx.drawImage(img, 0, 0);
return ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
}
// return the pixel at UV coordinates (0 to 1) in 0 to 1 values
function getPixel(imageData, u, v) {
const x = u * (imageData.width - 1) | 0;
const y = v * (imageData.height - 1) | 0;
if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) {
return [0, 0, 0, 0];
} else {
const offset = (y * imageData.width + x) * 4;
return Array.from(imageData.data.slice(offset, offset + 4)).map(v => v / 255);
}
}
async function main() {
const images = await Promise.all([
loadImage("https://i.imgur.com/UKBsvV0.jpg"), // RGB
loadImage("https://i.imgur.com/arPMCZl.jpg"), // Depth
]);
const data = images.map(getImageData);
const canvas = document.querySelector('canvas');
const renderer = new THREE.WebGLRenderer({canvas: canvas});
const fov = 75;
const aspect = 2; // the canvas default
const near = 1;
const far = 4000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2000;
const controls = new THREE.OrbitControls(camera, canvas);
controls.target.set(0, 0, 0);
controls.update();
const scene = new THREE.Scene();
const rgbData = data[0];
const depthData = data[1];
const skip = 20;
const across = Math.ceil(rgbData.width / skip);
const down = Math.ceil(rgbData.height / skip);
const positions = [];
const colors = [];
const color = new THREE.Color();
const spread = 1000;
const depthSpread = 1000;
const imageAspect = rgbData.width / rgbData.height;
for (let y = 0; y < down; ++y) {
const v = y / (down - 1);
for (let x = 0; x < across; ++x) {
const u = x / (across - 1);
const rgb = getPixel(rgbData, u, v);
const depth = 1 - getPixel(depthData, u, v)[0];
positions.push(
(u * 2 - 1) * spread * imageAspect,
(v * -2 + 1) * spread,
depth * depthSpread,
);
colors.push( ...rgb.slice(0,3) );
}
}
const geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
geometry.computeBoundingSphere();
const material = new THREE.PointsMaterial( { size: 15, vertexColors: THREE.VertexColors } );
const points = new THREE.Points( geometry, material );
scene.add( points );
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
body {
margin: 0;
}
canvas {
width: 100vw;
height: 100vh;
display: block;
}
<canvas></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r94/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r94/js/controls/OrbitControls.js"></script>