

本文由ScriptEcho平台提供技术支持
项目地址:传送门
本代码可以将一张普通的图片转换为具有景深效果的 3D 图,可用于创建逼真的 3D 场景或增强图片的视觉吸引力。
该代码使用 Transformers.js 中的深度估计模型,分析图片中物体的深度信息,并生成一张位移贴图。然后将位移贴图应用于 3D 模型,使其产生景深效果。用户可以通过滑动条控制景深程度,呈现出更具立体感和真实感的图像。
import { ref, onMounted } from 'vue'; import * as THREE from 'three'; import { OrbitControls } from '/sfc/threejs/jsm/controls/OrbitControls.js'; import { pipeline, env, RawImage } from '@xenova/transformers'; onMounted(async () => { console.log(`Transformers.js version: ${env.version}`); // Since we will download the model from the Hugging Face Hub, we can skip the local model check env.allowLocalModels = false; // Proxy the WASM backend to prevent the UI from freezing env.backends.onnx.wasm.proxy = true; // Constants const EXAMPLE_URL = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/bread_small.png'; const DEFAULT_SCALE = 0.75; // Reference the elements that we will need const status = document.getElementById('status'); const fileUpload = document.getElementById('upload'); const imageCOntainer= document.getElementById('container'); const example = document.getElementById('example'); console.log(`status: `, status) // Create a new depth-estimation pipeline status.textCOntent= '正在加载模型...'; const depth_estimator = await pipeline('depth-estimation', 'Xenova/depth-anything-small-hf'); status.textCOntent= '已完成'; example.addEventListener('click', (e) => { e.preventDefault(); predict(EXAMPLE_URL); }); fileUpload.addEventListener('change', function (e) { const file = e.target.files[0]; if (!file) { return; } const reader = new FileReader(); // Set up a callback when the file is loaded reader.Onload= e2 => predict(e2.target.result); reader.readAsDataURL(file); }); async function predict(url) { imageContainer.innerHTML = ''; const image = await RawImage.fromURL(url); // Set up scene and slider controls const { canvas, setDisplacementMap } = setupScene(url, image.width, image.height); imageContainer.append(canvas); status.textCOntent= '正在分析...'; const { depth } = await depth_estimator(image); setDisplacementMap(depth.toCanvas()); status.textCOntent= ''; // Add slider control const slider = document.createElement('input'); slider.type = 'range'; slider.min = 0; slider.max = 1; slider.step = 0.01; slider.addEventListener('input', (e) => { onSliderChange(parseFloat(e.target.value)); }); slider.defaultValue = DEFAULT_SCALE; imageContainer.append(slider); } function setupScene(url, w, h) { // Create new scene const canvas = document.createElement('canvas'); const width = canvas.width = imageContainer.offsetWidth; const height = canvas.height = imageContainer.offsetHeight; const scene = new THREE.Scene(); // Create camera and add it to the scene const camera = new THREE.PerspectiveCamera(30, width / height, 0.01, 10); camera.position.z = 2; scene.add(camera); const renderer = new THREE.WebGLRenderer({ canvas, antialias: true }); renderer.setSize(width, height); renderer.setPixelRatio(window.devicePixelRatio); // Add ambient light const light = new THREE.AmbientLight(0xffffff, 2); scene.add(light); // Load depth texture const image = new THREE.TextureLoader().load(url); image.colorSpace = THREE.SRGBColorSpace; const material = new THREE.MeshStandardMaterial({ map: image, side: THREE.DoubleSide, }); material.displacementScale = DEFAULT_SCALE; const setDisplacementMap = (canvas) => { material.displacementMap = new THREE.CanvasTexture(canvas); material.needsUpdate = true; } const setDisplacementScale = (scale) => { material.displacementScale = scale; material.needsUpdate = true; } OnSliderChange= setDisplacementScale; // Create plane and rescale it so that max(w, h) = 1 const [pw, ph] = w > h ? [1, h / w] : [w / h, 1]; const geometry = new THREE.PlaneGeometry(pw, ph, w, h); const plane = new THREE.Mesh(geometry, material); scene.add(plane); // Add orbit controls const cOntrols= new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; renderer.setAnimationLoop(() => { renderer.render(scene, camera); controls.update(); }); window.addEventListener('resize', () => { const width = imageContainer.offsetWidth; const height = imageContainer.offsetHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height); }, false); return { canvas: renderer.domElement, setDisplacementMap, }; } 这段代码成功实现了图片景深 3D 图的生成功能,展示了 Transformers.js 和 Three.js 的强大功能。
开发经验与收获:
未来拓展与优化:
更多组件:
获取更多 Echos
本文由ScriptEcho平台提供技术支持
项目地址:传送门
扫码加入 AI 生成前端微信讨论群: 