一、实现 将图片映射到三维场景
1、新写一个html展示一张图片实现获取它的x,y地址(需要替换成像素点坐标,还需要图片高度imageHeight、图片宽度imageWidth)
<img src="your-image.jpg" alt="Your Image" usemap="#image-map">
下面是实现方法
document.getElementById('your-image').addEventListener('click', function(event) {
var x = event.clientX - this.offsetLeft;
var y = event.clientY - this.offsetTop;
});
获取图片像素点坐标之后,在test.html中实现以下步骤
2、引入opencv库
<script async src="https://docs.opencv.org/master/opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
3、添加像素点坐标
var pixelCoordinates = [
{ x: 100, y: 100 },
{ x: 200, y: 200 },
];
4、遍历像素点坐标将像素点坐标转换为纹理坐标
var textureCoordinates = pixelCoordinates.map(function(pixelCoord) {
var textureX = pixelCoord.x / imageWidth; // imageWidth 是图片宽度
var textureY = 1.0 - pixelCoord.y / imageHeight; // imageHeight 是图片高度
return new Cesium.Cartesian2(textureX, textureY);
});
5、用插值计算进行映射
var worldCoordinates = textureCoordinates.map(function(textureCoord) {
var position = new Cesium.Cartographic();
var cartographic = Cesium.Cartographic.fromCartesian(your3DPoint); // 替换为三维场景中的点
var longitude = cartographic.longitude + textureCoord.x * yourLongitudeRange;
var latitude = cartographic.latitude + textureCoord.y * yourLatitudeRange;
var height = cartographic.height;
return new Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
});
6、创建存放图片的几何体(忽略此步骤,放到10、11、12步骤执行)
var geometry = new Cesium.PolygonGeometry({
polygonHierarchy: {
positions: worldCoordinates
}
});
7、将几何体存放到三维场景中(忽略此步骤,放到10、11、12步骤执行)
viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: geometry,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
}
})
}));
8、创建图片材质
var imageMaterial = new Cesium.ImageMaterialProperty({
image: 'path_to_your_image.png' // 替换为本地图片路径
});
9、创建外观(Appearance),将图片材质应用到外观上
var appearance = new Cesium.MaterialAppearance({
material: imageMaterial
});
10、创建几何体
var geometry = new Cesium.PolygonGeometry({
polygonHierarchy: {
positions: worldCoordinates
}
});
11、创建包含几何体和外观的 Primitive
var primitive = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: geometry,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
}
}),
appearance: appearance
});
12、将 Primitive 添加到场景中
viewer.scene.primitives.add(primitive);
二、实现 将视频转化为图片帧
以下两个方法选一种执行完毕即可
import org.bytedeco.javacpp.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.opencv_core.IplImage;
public class VideoToImages {
public static void main(String[] args) {
String inputVideoFile = "input.mp4"; // 替换视频文件路径
String outputImageFolder = "output_images/"; // 替换图片帧输出文件夹
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputVideoFile);
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
long frameRate = (long) Math.round(1.0 / 0.5); // 0.5秒一帧,可更改
try {
grabber.start();
Frame frame;
int frameNumber = 1;
while (true) {
frame = grabber.grabImage();
if (frame == null) {
break;
}
if (frameNumber % frameRate == 0) {
IplImage image = converter.convertToIplImage(frame);
saveImage(image, outputImageFolder, frameNumber / frameRate);
}
frameNumber++;
}
grabber.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void saveImage(IplImage image, String outputFolder, int frameNumber) {
try {
String filename = String.format("%s/frame%04d.jpg", outputFolder, frameNumber);
avutil.av_log_set_level(avutil.AV_LOG_QUIET); // 静默输出
org.bytedeco.opencv.global.opencv_imgcodecs.cvSaveImage(filename, image);
} catch (Exception e) {
e.printStackTrace();
}
}
}
import cv2
import os
# 视频文件路径(更改)
video_file = 'input.mp4'
# 图像帧输出文件夹(更改)
output_folder = 'output_images'
# 每帧之间的时间间隔(以毫秒为单位,这里是0.5秒)
frame_interval = 500
# 创建输出文件夹(如果不存在)
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 打开视频文件
cap = cv2.VideoCapture(video_file)
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 计算帧时间
frame_time = frame_count * frame_interval
# 每隔0.5秒保存一帧
if frame_time % 500 == 0:
# 构建输出文件名
output_file = os.path.join(output_folder, f'frame_{frame_count:04d}.jpg')
# 保存图像帧
cv2.imwrite(output_file, frame)
frame_count += 1
# 释放视频捕获对象
cap.release()
# 关闭所有窗口
cv2.destroyAllWindows()
三、设置时间不断替换视频帧图片
// 初始化图片地址列表(做个读取对应文件夹中的图片)
var imageUrls = ['path_to_image1.png', 'path_to_image2.png', 'path_to_image3.png'];
var currentIndex = 0; // 当前图片索引
// 创建图片材质
var imageMaterial = new Cesium.ImageMaterialProperty({
image: imageUrls[currentIndex]
});
// 创建外观(Appearance),将图片材质应用到外观上
var appearance = new Cesium.MaterialAppearance({
material: imageMaterial
});
// 创建几何体,这里使用一个简单的矩形
var geometry = new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(-75.0, 28.0, -74.0, 29.0),
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
});
// 创建包含几何体和外观的 Primitive
var primitive = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: geometry,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
}
}),
appearance: appearance
});
// 将 Primitive 添加到场景中
viewer.scene.primitives.add(primitive);
// 定时更改图片地址并重新加载图片材质
setInterval(function() {
currentIndex = (currentIndex + 1) % imageUrls.length;
imageMaterial.image = imageUrls[currentIndex];
}, 500); // 500 毫秒(0.5秒)为间隔时间
const fs = require('fs');
const path = require('path');
const folderPath = 'E:/01_data/videoframe/X1'; // 本地图片文件夹路径
let imageUrls = [];
let detailUrl = '';
// 读取文件夹中的文件
fs.readdir(folderPath, (err, files) => {
if (err) {
console.error('Error reading folder:', err);
return;
}
// 遍历文件夹中的文件
files.forEach((file) => {
const filePath = path.join(folderPath, file);
// 检查是否是文件
if (fs.statSync(filePath).isFile()) {
imageUrls.push(file); // 存储文件名
detailUrl = filePath; // 存储完整的本地文件路径
}
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<body>
<div id="container">
<img id="your-image" src="frame0.jpg" alt="Image" usemap="#image-map">
</div>
<script>
document.getElementById('your-image').addEventListener('click', function (event) {
var x = event.clientX - this.offsetLeft;
var y = event.clientY - this.offsetTop;
console.log('Clicked at (' + x + ', ' + y + ')');
});
</script>
</body>
</html>