增加fov和修改dof计算方法

This commit is contained in:
ORANGE SILVER
2025-05-27 16:09:44 +08:00
committed by GitHub
parent ac0e738290
commit d36904b4af
6 changed files with 303 additions and 172 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 635 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 30 KiB

+13 -6
View File
@@ -51,13 +51,14 @@ export const config = {
// Initial values for parameter 参数初始值
defaults: {
depthStrength: 1.0,
dofStrength: 0.0,
focusDistance: 0.0,
depthStrength: 1.5,
dofStrength: 0.5,
focusDistance: 0.95,
zOffset: 0.0,
quiltsNum: 2,
quiltsNum: 4,
quiltsAngleRange: 14,
screenshotSize: 0 // 0 代表 512 * 2^0 = 512
screenshotSize: 1, // 0 代表 512 * 2^0 = 512
cameraFOV: 7,
},
// Slider control settings 滑块控制设置
@@ -77,7 +78,7 @@ export const config = {
focusDistance: {
min: 0,
max: 1,
step: 0.1,
step: 0.01,
label: '对焦点'
},
zOffset: {
@@ -86,6 +87,12 @@ export const config = {
step: 0.1,
label: '轴心偏移'
},
cameraFOV: {
min: 5, // 修改最小值为5度
max: 120,
step: 1,
label: '相机FOV角'
},
quiltsNum: {
min: 1,
max: 48,
-17
View File
@@ -30,23 +30,6 @@
max-height: 100% !important;
object-fit: contain;
}
#progress-dialog {
background-color: rgba(0, 0, 0, 0.8);
color: #ffffff;
border: 1px solid #ffffff;
border-radius: 8px;
padding: 20px;
}
#progress-dialog label {
color: #ffffff;
font-size: 16px;
margin-bottom: 10px;
display: block;
}
#progress-indicator {
width: 100%;
height: 20px;
}
</style>
</head>
+33 -14
View File
@@ -3,12 +3,12 @@ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
let apiURL = '';
let currentDepthStrength = 1.0;
let currentDepthStrength = 1.5;
let currentDofStrength = 0.0;
let currentFocusDistance = 0.0;
let currentZOffset = 0.0; // 添加Z轴偏移变量
let currentDepthMesh = null;
const BASE_CAMERA_DISTANCE = 13.5; // 修改基础相机距离为13.5
const BASE_CAMERA_DISTANCE = 5.0; // 修改基础相机距离为5(fov90时)
let currentScreenshotSize = 1024; // 默认截图尺寸
// 添加Quilts相关变量
@@ -75,6 +75,10 @@ window.addEventListener('message', function(event) {
const finalZOffset = currentZOffset - (currentDepthStrength * 5 / 2);
currentDepthMesh.position.z = finalZOffset;
}
} else if (event.data.type === 'updateCameraFOV') {
// 更新相机FOV
camera.fov = event.data.value;
camera.updateProjectionMatrix();
}
}, false);
@@ -167,7 +171,7 @@ scene.add(axesHelper);
const ambientLight = new THREE.AmbientLight(0xffffff);
const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 1000);
const camera = new THREE.PerspectiveCamera(7, 1, 0.1, 1000); // 设置默认FOV为7度
camera.position.set(0, 0, 10);
const pointLight = new THREE.PointLight(0xffffff, 15);
camera.add(pointLight);
@@ -242,7 +246,13 @@ const onError = function (e) {
// 修改自适应回正函数
function resetView(depthStrength) {
const maxDisplacement = 2.5 * depthStrength;
const cameraDistance = BASE_CAMERA_DISTANCE + maxDisplacement + currentZOffset;
// 计算基于FOV的相机回正距离补偿
const fovRadians = THREE.MathUtils.degToRad(camera.fov);
const fovCompensation = 1 / Math.tan(fovRadians / 2);
// 基础距离 * FOV补偿系数
const cameraDistance = (BASE_CAMERA_DISTANCE* fovCompensation) + (maxDisplacement * 0.5) + currentZOffset ;
// 重置相机位置和旋转
camera.position.set(0, 0, cameraDistance);
@@ -367,13 +377,21 @@ async function main(referenceImageParams, depthMapParams) {
vec4 color = vec4(0.0);
float total = 0.0;
// 使用更高效的采样模式
float weights[5] = float[5](0.227027, 0.316216, 0.070270, 0.008491, 0.000000);
float offsets[5] = float[5](0.0, 1.0, 2.0, 3.0, 4.0);
// 使用高斯函数计算权重
float sigma = 4.0; // 控制高斯分布的宽度
float weights[8];
float offsets[8];
// 计算权重和偏移
for(int i = 0; i < 8; i++) {
offsets[i] = float(i);
// 高斯函数: exp(-(x^2)/(2*sigma^2))
weights[i] =0.005 + exp(-(float(i) * float(i)) / (2.0 * sigma * sigma));
}
// 水平方向
for(int i = 0; i < 5; i++) {
float offset = offsets[i] * blurFactor * 0.015;
for(int i = 0; i < 8; i++) {
float offset = offsets[i] * blurFactor * 0.005;
color += texture2D(tex, uv + vec2(offset, 0.0)) * weights[i];
color += texture2D(tex, uv - vec2(offset, 0.0)) * weights[i];
total += weights[i] * 2.0;
@@ -381,8 +399,8 @@ async function main(referenceImageParams, depthMapParams) {
// 垂直方向
vec4 color2 = vec4(0.0);
for(int i = 0; i < 5; i++) {
float offset = offsets[i] * blurFactor * 0.015;
for(int i = 0; i < 8; i++) {
float offset = offsets[i] * blurFactor * 0.005;
color2 += texture2D(tex, uv + vec2(0.0, offset)) * weights[i];
color2 += texture2D(tex, uv - vec2(0.0, offset)) * weights[i];
total += weights[i] * 2.0;
@@ -395,13 +413,14 @@ async function main(referenceImageParams, depthMapParams) {
vec4 referenceColor = texture2D(referenceTexture, vUv);
// 计算景深模糊
float blurFactor = abs(vDepth - focusDistance) * dofStrength;
float depthDiff = abs(vDepth - focusDistance);
float blurFactor = pow(depthDiff, (0.25 - (0.05 * dofStrength)) ) * dofStrength;
// 应用优化后的高斯模糊
vec4 blurredColor = gaussianBlur(referenceTexture, vUv, blurFactor);
// 调整亮度
blurredColor.rgb *= 0.95; // 略微降低亮度
blurredColor.rgb *= 0.99; // 略微降低亮度
// 混合原始颜色和模糊颜色
gl_FragColor = mix(referenceColor, blurredColor, blurFactor);
@@ -409,7 +428,7 @@ async function main(referenceImageParams, depthMapParams) {
`
});
const planeGeometry = new THREE.PlaneGeometry(imageWidth, imageHeight, 200, 200);
const planeGeometry = new THREE.PlaneGeometry(imageWidth, imageHeight, 360, 360);
currentDepthMesh = new THREE.Mesh(planeGeometry, depthMaterial);
// 设置初始Z轴偏移时也要考虑深度强度
const finalZOffset = currentZOffset - (currentDepthStrength * 5 / 2);
+257 -135
View File
@@ -1,145 +1,252 @@
import { app } from "../../scripts/app.js"
import { api } from '../../scripts/api.js'
import { config } from './config.js'
// 等待 config 加载完成
let configLoaded = false;
const waitForConfig = () => {
if (config && config.defaults) {
configLoaded = true;
return true;
}
return false;
}
// 初始化函数
const initializeVisualizer = () => {
if (!waitForConfig()) {
console.log('[Visualizer] Waiting for config to load...');
setTimeout(initializeVisualizer, 100);
return;
}
console.log('[Visualizer] Config loaded, initializing...');
app.registerExtension({
name: config.extensionName,
async beforeRegisterNodeDef(nodeType, nodeData, app) {
registerVisualizer(nodeType, nodeData, config.node.name, 'threeVisualizer')
// 硬编码配置
const config = {
paths: {
extension: '/extensions/ComfyUI-Depth-Visualization-advanced',
html: '/extensions/ComfyUI-Depth-Visualization-advanced/html'
},
extensionName: 'ORANGESILVER.DepthViewerAndQuilts',
node: {
name: 'DepthViewerAndQuilts',
defaultSize: [600, 500],
minSize: {
width: 600,
height: 500
}
},
controlPanel: {
width: 200,
background: 'rgba(0, 0, 0, 0.75)',
padding: 10,
borderRadius: 5,
zIndex: 1000,
defaultScale: 0.01,
scales: {
large: {
minDimension: 800,
scale: 1.25
},
medium: {
minDimension: 600,
scale: 1.0
},
small: {
minDimension: 400,
scale: 0.6
},
tiny: {
minDimension: 300,
scale: 0.5
}
}
},
defaults: {
depthStrength: 1.5,
dofStrength: 0.5,
focusDistance: 0.95,
zOffset: 0.0,
quiltsNum: 4,
quiltsAngleRange: 14,
screenshotSize: 1,
cameraFOV: 7,
},
sliders: {
depthStrength: {
min: 0,
max: 2,
step: 0.1,
label: '深度强度'
},
nodeCreated(node, app) {
console.log('[DepthViewerAndQuilts] Node created:', node.id)
setTimeout(() => {
let widget = node.widgets?.filter(w => w.name == 'previewRGBD')[0]
let framesWidget = node.widgets?.filter(w => w.name == 'frames')[0]
dofStrength: {
min: 0,
max: 1,
step: 0.1,
label: '景深强度'
},
focusDistance: {
min: 0,
max: 1,
step: 0.01,
label: '对焦点'
},
zOffset: {
min: -5,
max: 5,
step: 0.1,
label: '轴心偏移'
},
cameraFOV: {
min: 5,
max: 120,
step: 1,
label: '相机FOV角'
},
quiltsNum: {
min: 1,
max: 48,
step: 1,
label: 'Quilts数量'
},
quiltsAngleRange: {
min: 2,
max: 180,
step: 1,
label: 'Quilt角度差'
},
screenshotSize: {
min: 0,
max: 3,
step: 1,
label: '截图分辨率',
getValue: (index) => 512 * Math.pow(2, index)
}
},
buttons: {
resetView: {
text: '回正视图',
style: {
padding: '8px',
background: 'rgba(255, 255, 255, 0.1)',
color: 'white',
border: '1px solid rgba(255, 255, 255, 0.2)',
borderRadius: '4px',
cursor: 'pointer',
width: '100%',
marginBottom: '10px'
}
},
quiltsCapture: {
text: '开始QuiltsCapture',
style: {
padding: '8px',
background: 'rgba(255, 255, 255, 0.1)',
color: 'white',
border: '1px solid rgba(255, 255, 255, 0.2)',
borderRadius: '4px',
cursor: 'pointer',
width: '100%',
marginTop: '10px'
}
}
}
};
// 删除config加载检查相关代码
app.registerExtension({
name: config.extensionName,
async beforeRegisterNodeDef(nodeType, nodeData, app) {
registerVisualizer(nodeType, nodeData, config.node.name, 'threeVisualizer')
},
nodeCreated(node, app) {
console.log('[DepthViewerAndQuilts] Node created:', node.id)
console.log('[DepthViewerAndQuilts] Widgets found:', {
preview3d: !!widget,
frames: !!framesWidget
})
if (node.type === 'DepthViewerAndQuilts' && widget) {
let nodeId = node.id
console.log('[DepthViewerAndQuilts] Setting up iframe for node:', nodeId)
//延迟才能获得this.id
widget.visualizer.querySelector('iframe').src += '?id=' + nodeId
console.log('[DepthViewerAndQuilts] iframe src updated:', widget.visualizer.querySelector('iframe').src)
// 添加消息监听器
window.addEventListener('message', async event => {
console.log('[DepthViewerAndQuilts] Message received:', {
source: event.source,
origin: event.origin,
data: event.data
})
try {
// 检查消息的来源,确保消息来自可信的源
if (!event.data || !event.data.id || !event.data.imgs) {
console.error('[DepthViewerAndQuilts] Invalid message format:', event.data)
return
}
const { id, imgs } = event.data
console.log('[DepthViewerAndQuilts] Processing message:', {
receivedId: id,
nodeId: nodeId,
imagesCount: imgs?.length
})
// 验证节点ID - 转换为相同类型进行比较
if (String(id) !== String(nodeId)) {
console.log('[DepthViewerAndQuilts] Message ID mismatch:', {
received: id,
expected: nodeId,
receivedType: typeof id,
expectedType: typeof nodeId
})
return
}
// 初始化frames控件
framesWidget.value = { images: [] }
console.log('[DepthViewerAndQuilts] Frames widget initialized')
// 处理每张图片
for (let i = 0; i < imgs.length; i++) {
const base64Image = imgs[i]
try {
console.log(`[DepthViewerAndQuilts] Processing image ${i + 1}/${imgs.length}`)
// 验证base64数据
if (!base64Image || typeof base64Image !== 'string') {
console.error(`[DepthViewerAndQuilts] Invalid base64 data for image ${i + 1}`)
continue
}
// 上传图片并获取URL
console.log(`[DepthViewerAndQuilts] Uploading image ${i + 1}`)
const file = await uploadBase64ToFile(base64Image)
// 验证返回的文件数据
if (!file || !file.name) {
console.error(`[DepthViewerAndQuilts] Invalid file data for image ${i + 1}:`, file)
continue
}
console.log(`[DepthViewerAndQuilts] Image ${i + 1} uploaded successfully:`, file.name)
// 添加到frames控件
framesWidget.value.images.push(file)
} catch (error) {
console.error(`[DepthViewerAndQuilts] Error processing image ${i + 1}:`, error)
}
}
// 触发更新
framesWidget.value._seed = Math.random()
node.title = 'Input #' + framesWidget.value.images.length
console.log('[DepthViewerAndQuilts] Update completed:', {
imagesCount: framesWidget.value.images.length,
newTitle: node.title
})
// 触发节点更新
node.setDirtyCanvas(true, true)
console.log('[DepthViewerAndQuilts] Canvas marked as dirty')
} catch (error) {
console.error('[DepthViewerAndQuilts] Error in message handler:', error)
}
setTimeout(() => {
let widget = node.widgets?.filter(w => w.name == 'previewRGBD')[0]
let framesWidget = node.widgets?.filter(w => w.name == 'frames')[0]
console.log('[DepthViewerAndQuilts] Widgets found:', {
preview3d: !!widget,
frames: !!framesWidget
})
if (node.type === 'DepthViewerAndQuilts' && widget) {
let nodeId = node.id
console.log('[DepthViewerAndQuilts] Setting up iframe for node:', nodeId)
widget.visualizer.querySelector('iframe').src += '?id=' + nodeId
console.log('[DepthViewerAndQuilts] iframe src updated:', widget.visualizer.querySelector('iframe').src)
// 添加消息监听器
window.addEventListener('message', async event => {
console.log('[DepthViewerAndQuilts] Message received:', {
source: event.source,
origin: event.origin,
data: event.data
})
console.log('[DepthViewerAndQuilts] Message listener setup completed')
}
}, 1000)
}
});
}
// 启动初始化
initializeVisualizer();
try {
// 检查消息的来源,确保消息来自可信的源
if (!event.data || !event.data.id || !event.data.imgs) {
console.error('[DepthViewerAndQuilts] Invalid message format:', event.data)
return
}
const { id, imgs } = event.data
console.log('[DepthViewerAndQuilts] Processing message:', {
receivedId: id,
nodeId: nodeId,
imagesCount: imgs?.length
})
// 验证节点ID - 转换为相同类型进行比较
if (String(id) !== String(nodeId)) {
console.log('[DepthViewerAndQuilts] Message ID mismatch:', {
received: id,
expected: nodeId,
receivedType: typeof id,
expectedType: typeof nodeId
})
return
}
// 初始化frames控件
framesWidget.value = { images: [] }
console.log('[DepthViewerAndQuilts] Frames widget initialized')
// 处理每张图片
for (let i = 0; i < imgs.length; i++) {
const base64Image = imgs[i]
try {
console.log(`[DepthViewerAndQuilts] Processing image ${i + 1}/${imgs.length}`)
// 验证base64数据
if (!base64Image || typeof base64Image !== 'string') {
console.error(`[DepthViewerAndQuilts] Invalid base64 data for image ${i + 1}`)
continue
}
// 上传图片并获取URL
console.log(`[DepthViewerAndQuilts] Uploading image ${i + 1}`)
const file = await uploadBase64ToFile(base64Image)
// 验证返回的文件数据
if (!file || !file.name) {
console.error(`[DepthViewerAndQuilts] Invalid file data for image ${i + 1}:`, file)
continue
}
console.log(`[DepthViewerAndQuilts] Image ${i + 1} uploaded successfully:`, file.name)
// 添加到frames控件
framesWidget.value.images.push(file)
} catch (error) {
console.error(`[DepthViewerAndQuilts] Error processing image ${i + 1}:`, error)
}
}
// 触发更新
framesWidget.value._seed = Math.random()
node.title = 'Input #' + framesWidget.value.images.length
console.log('[DepthViewerAndQuilts] Update completed:', {
imagesCount: framesWidget.value.images.length,
newTitle: node.title
})
// 触发节点更新
node.setDirtyCanvas(true, true)
console.log('[DepthViewerAndQuilts] Canvas marked as dirty')
} catch (error) {
console.error('[DepthViewerAndQuilts] Error in message handler:', error)
}
})
console.log('[DepthViewerAndQuilts] Message listener setup completed')
}
}, 1000)
}
});
function base64ToBlobFromURL (base64URL, contentType) {
return fetch(base64URL).then(response => response.blob())
@@ -192,6 +299,7 @@ class Visualizer {
this.depthStrength = config.defaults.depthStrength;
this.dofStrength = config.defaults.dofStrength;
this.focusDistance = config.defaults.focusDistance;
this.cameraFOV = config.defaults.cameraFOV;
// 创建控制面板容器
this.controlPanel = document.createElement('div')
@@ -299,10 +407,24 @@ class Visualizer {
}
);
// 添加相机FOV控制
const fovControl = this.createSliderControl(
'cameraFOV',
config.sliders.cameraFOV,
(value) => {
this.cameraFOV = value;
this.iframe.contentWindow.postMessage({
type: 'updateCameraFOV',
value: value
}, '*');
}
);
this.controlPanel.appendChild(depthControl)
this.controlPanel.appendChild(dofControl)
this.controlPanel.appendChild(focusControl)
this.controlPanel.appendChild(zOffsetControl)
this.controlPanel.appendChild(fovControl)
// 添加Quilts控制
const quiltsControl = document.createElement('div')