3D *.stl表面模型转换为2D图像堆栈?

5

首先,让我明确一点,我不想将图像堆转换为3D模型。

我有一个*.stl文件(一个三角形表面网格),我想将其切片成一个图像堆。我看了一下Slic3r和Meshmixer,但它们都只提供Gcode。

因此,考虑到我拥有表面上所有点的顶点(这是非凸的),以及它们之间的连接。那么,有哪些库可以帮助我完成这项任务呢?

我的感觉是,我需要在没有通过已知顶点的切片上插值边界。

我熟悉Python,并能够使用C++,但愿意拓宽自己的视野。


你能否准备提供更多细节? - DrBwts
重写以回答...我猜这可能是为了3D打印机吧 :) ? - Spektre
不,这是为了比较STL文件与图像堆栈的准确性。我看过一些切片程序,但它们只允许导出Gcode。但是,同样的算法必须能够输出轮廓数据吧? - DrBwts
3个回答

2
例如,如果您使用任何方式在应用程序内部使用OpenGL来渲染网格,则只需执行以下操作即可获取切片:

  1. 设置相机,使屏幕投影平面与切片平行...
  2. 使用glClearColor将屏幕缓冲区像往常一样清除为背景颜色
  3. 使用glClearDepth将深度缓冲区清除为相机空间中切片的Z坐标
  4. 设置glDepthFunc(GL_EQUAL)
  5. 渲染网格

类似于:

// here set view
glClearColor( 0.0,0.0,0.0,0.0 ); // <0.0,1.0> r,g,b,a
glClearDepth( 0.5 );             // <0.0,1.0> ... 0.0 = z_near, 1.0 = z_far 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthFunc(GL_EQUAL);
// here render mesh

这将只呈现具有 Z==Slice coordinate 片段的切片。这也可以通过 GLSL 实现,即丢弃所有具有不同 Z 的片段。 DirectX 应该有类似的功能(我不使用它,所以不能确定)。
由于大多数网格都是 BR 模型(空心),因此您将获得切片的周长,因此您很可能需要在之后进行填充以满足您的需求...
您还可以尝试渲染厚切片...其中 Z 大约为预定义值...

好的,这看起来很有前途,我的工作已经被分解了,但我可以看到它的方向,并且似乎是一个迫使我完成那些OpenGL教程的好方法。切片数据将存储在哪里?是否有一个数组可以写成2D文件? - DrBwts
1
@DrBwts,你可以直接渲染到纹理并将其保存为图像......如果你有经验,你还可以渲染成纹理数组,并在单个网格渲染中渲染所有切片(但我从未使用过纹理数组,所以无法提供帮助)。 - Spektre

1
如果HTTP API解决方案符合您的目的,我建议使用以下资源: Server-side 3D mesh to thumbnail image rendering by http://manifold.metamatic.us
您可以将3D网格(STL、OBJ、3DS)POST到API端点并获得JSON响应。它将包含指向您的3D模型的2D图像渲染的URL,以及其他3D测量结果,例如体积、面积、边界框和构建时间。
与Manifold API端点接口的客户端库是用Python、PHP、JavaScript甚至cURL命令行脚本编写的,也可用
希望这能帮助您找到所需的内容。如果您不是在寻找黑匣子解决方案,而是尝试自己实现3D渲染器,请原谅。

0
另一个选项是以下算法。 首先,您需要将网格转换为体素,其中体素值等于到表面的有符号距离(网格必须关闭)。然后,您需要构建切片集。 您可以使用开源库MeshLib来完成此操作,该库可以从C ++和Python代码中调用。
代码可能如下所示:
auto loadRes = MeshLoad::fromAnySupportedFormat( "C:/Meshes/spartan.stl" );
if ( !loadRes.has_value() )
    return false; // loadRes.error() for more info, mesh load failed

const float voxelSize = 0.1f;
const auto grid = meshToLevelSet( loadRes.value(), AffineXf3f{}, Vector3f::diagonal( voxelSize ) );
const auto bbox = loadRes->getBoundingBox();

const auto vdbDims = grid->evalActiveVoxelDim();
const Vector3i dims = { vdbDims.x(),vdbDims.y(),vdbDims.z() };
//The less the difference between min and max is the more contrast the images are.
const float min = 0.0f;
const float max = 0.0f;
const auto axis = SlicePlain::XY;
VdbVolume vdb{ .data = grid, .dims = dims, .voxelSize = Vector3f::diagonal( voxelSize ), .min = min, .max = max };
auto saveRes = VoxelsSave::saveAllSlicesToImage( "C:/Meshes/slices/", vdb, axis );

return saveRes.has_value();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接