我有如下问题,如图所示。我有点云和由四面体算法生成的网格。如何使用该算法雕刻网格?地标是点云吗?
算法的伪代码:
for every 3D feature point
convert it 2D projected coordinates
for every 2D feature point
cast a ray toward the polygons of the mesh
get intersection point
if zintersection < z of 3D feature point
for ( every triangle vertices )
cull that triangle.
以下是Guru Spektre提到的算法的后续实现:)
更新算法代码:
int i;
for (i = 0; i < out.numberofpoints; i++)
{
Ogre::Vector3 ray_pos = pos; // camera position);
Ogre::Vector3 ray_dir = (Ogre::Vector3 (out.pointlist[(i*3)], out.pointlist[(3*i)+1], out.pointlist[(3*i)+2]) - pos).normalisedCopy(); // vertex - camea pos ;
Ogre::Ray ray;
ray.setOrigin(Ogre::Vector3( ray_pos.x, ray_pos.y, ray_pos.z));
ray.setDirection(Ogre::Vector3(ray_dir.x, ray_dir.y, ray_dir.z));
Ogre::Vector3 result;
unsigned int u1;
unsigned int u2;
unsigned int u3;
bool rayCastResult = RaycastFromPoint(ray.getOrigin(), ray.getDirection(), result, u1, u2, u3);
if ( rayCastResult )
{
Ogre::Vector3 targetVertex(out.pointlist[(i*3)], out.pointlist[(3*i)+1], out.pointlist[(3*i)+2]);
float distanceTargetFocus = targetVertex.squaredDistance(pos);
float distanceIntersectionFocus = result.squaredDistance(pos);
if(abs(distanceTargetFocus) >= abs(distanceIntersectionFocus))
{
if ( u1 != -1 && u2 != -1 && u3 != -1)
{
std::cout << "Remove index "<< "u1 ==> " <<u1 << "u2 ==>"<<u2<<"u3 ==> "<<u3<< std::endl;
updatedIndices.erase(updatedIndices.begin()+ u1);
updatedIndices.erase(updatedIndices.begin()+ u2);
updatedIndices.erase(updatedIndices.begin()+ u3);
}
}
}
}
if ( updatedIndices.size() <= out.numberoftrifaces)
{
std::cout << "current face list===> "<< out.numberoftrifaces << std::endl;
std::cout << "deleted face list===> "<< updatedIndices.size() << std::endl;
manual->begin("Pointcloud", Ogre::RenderOperation::OT_TRIANGLE_LIST);
for (int n = 0; n < out.numberofpoints; n++)
{
Ogre::Vector3 vertexTransformed = Ogre::Vector3( out.pointlist[3*n+0], out.pointlist[3*n+1], out.pointlist[3*n+2]) - mReferencePoint;
vertexTransformed *=1000.0 ;
vertexTransformed = mDeltaYaw * vertexTransformed;
manual->position(vertexTransformed);
}
for (int n = 0 ; n < updatedIndices.size(); n++)
{
int n0 = updatedIndices[n+0];
int n1 = updatedIndices[n+1];
int n2 = updatedIndices[n+2];
if ( n0 < 0 || n1 <0 || n2 <0 )
{
std::cout<<"negative indices"<<std::endl;
break;
}
manual->triangle(n0, n1, n2);
}
manual->end();
跟进算法:
我现在有两个版本,一个是三角形版本,另一个是雕刻版本。
它不是表面网格。 这是两个文件 http://www.mediafire.com/file/cczw49ja257mnzr/ahmed_non_triangulated.obj http://www.mediafire.com/file/cczw49ja257mnzr/ahmed_triangulated.obj
答案 0 :(得分:1)
我这样看:
所以你从已知matrix和 FOV 和焦距的相机获得了图像。
由此您可以知道焦点的确切位置以及图像在相机芯片上的位置(Z_near平面)。所以任何顶点,其对应的像素和焦点都在同一条线上。
因此,对于每个视图来说,从焦点到点云的每个可见顶点的光线。并且在击中包含目标顶点的面之前测试网格的任何面是否命中。如果是,则删除它,因为它会阻止可见性。
Landmark 在此上下文中只是与pointcloud对应 vertex 的特征点。它可以是任何可检测的(强度,颜色,图案的变化)通常 SIFT / SURF 用于此。你应该已经找到它们,因为这是pointcloud生成的输入。如果不是,您可以查看与每个顶点对应的像素并测试背景颜色。
如果没有输入图像,请不要确定如何执行此操作。为此,您需要确定从哪一侧/视图可见哪个顶点。可能是以某种方式形成附近的顶点(比如使用顶点密度点或对平面的对应...),或者以某种方式改变算法以在网格内部找到未使用的顶点。
要投射光线,请执行以下操作:
ray_pos=tm_eye*vec4(imgx/aspect,imgy,0.0,1.0);
ray_dir=ray_pos-tm_eye*vec4(0.0,0.0,-focal_length,1.0);
其中tm_eye
是相机直接变换矩阵,imgx,imgy
是图像中的2D像素位置,归一化为<-1,+1>
,其中(0,0)
是图像的中间。 focal_length
确定相机的 FOV ,宽高比是图像分辨率的比率image_ys/image_xs
Ray三角交点方程可以在这里找到:
如果我提取它:
vec3 v0,v1,v2; // input triangle vertexes
vec3 e1,e2,n,p,q,r;
float t,u,v,det,idet;
//compute ray triangle intersection
e1=v1-v0;
e2=v2-v0;
// Calculate planes normal vector
p=cross(ray[i0].dir,e2);
det=dot(e1,p);
// Ray is parallel to plane
if (abs(det)<1e-8) no intersection;
idet=1.0/det;
r=ray[i0].pos-v0;
u=dot(r,p)*idet;
if ((u<0.0)||(u>1.0)) no intersection;
q=cross(r,e1);
v=dot(ray[i0].dir,q)*idet;
if ((v<0.0)||(u+v>1.0)) no intersection;
t=dot(e2,q)*idet;
if ((t>_zero)&&((t<=tt)) // tt is distance to target vertex
{
// intersection
}
跟进:
要在尺寸为(imgx,imgy)
的图片的标准化图片(rawx,rawy)
和原始图片(imgxs,imgys)
之间移动,其中(0,0)
位于左上角,(imgxs-1,imgys-1)
位于右下角你需要的角落:
imgx = (2.0*rawx / (imgxs-1)) - 1.0
imgy = 1.0 - (2.0*rawy / (imgys-1))
rawx = (imgx + 1.0)*(imgxs-1)/2.0
rawy = (1.0 - imgy)*(imgys-1)/2.0
[进度更新1]
我终于达到了这个目的,我可以为此编译样本测试输入数据甚至开始(因为你根本无法共享有效数据):
我用硬编码表网格(灰色)和pointcloud(aqua)以及简单的相机控件创建了小应用程序。我可以在哪里保存任意数量的视图(截图+相机直接矩阵)。当加载回来时,它与网格本身对齐(黄色光线穿过图像中的浅绿色点并穿过表格网格)。蓝色线条从相机焦点到其角落。这将模拟您获得的输入。应用程序的第二部分将仅使用这些图像和矩阵与点云(没有网格表面)四角化它(已经完成)现在只是通过每个视图(aqua点)中的每个地标投射光线并在目标顶点之前移除所有四边形在pointcloud被点击(这个东西甚至没有开始,但可能在周末)...最后只存储表面三角形(很容易只使用所有三角形,只使用一次也已经完成除了保存部分,但写入波前obj从很容易......)。
[进度更新2]
我添加了地标检测并与点云匹配
你可以看到只有有效的光线被投射(在图像上可见的光线)所以点云上的某些点不会投射光线(奇异的浅绿色点))。所以现在只需从列表中删除光线/三角形交叉点和四面体即可...