误差可视化小结

误差可视化小结

问题描述

在做水印工作的时候,需要衡量原模型与水印模型之间的误差。为了更加直观的看出误差的大小,可以将误差进行可视化。下图是可视化误差的一个例子,其中左边的模型为原始模型A,右边第二行的模型是某个算法计算出的原模型的近似模型B,右边第三行的模型是一个有色的模型,通过颜色表示出模型A、B之间的误差,颜色条显示不同颜色与误差大小的关系。
enter description here

在水印工作中,也许要对原始模型和水印模型的误差进行衡量,误差可简单计算为两个模型上对应点之间的欧氏距离。在计算误差之前,首先要确保两个模型已经对齐(最简单的处理可以将两个模型的中点放置在一起),代码如下:

//将两个模型的中心移到一起
    //将原始中心读取出来
    double *RCenter = new double[6];

    char center_name[100];
    ifstream centerfile;
    sprintf(center_name, "D:\code\GeometryProcessing-1\Txt\Offset\Center.txt");
    centerfile.open(center_name,ios_base::in );
    if (centerfile)
    {
        // read into memory
        centerfile.seekg (0, centerfile.end);
        int length = centerfile.tellg();
        centerfile.seekg (0, centerfile.beg);

        char *buffer = new char[length];
        centerfile.read(buffer, length);
        centerfile.close();

        // parse into array
        std::istringstream iss(buffer);
        int i = 0;
        while ( i < 6)
        {
            iss >> RCenter[i++];
        }
        delete [] buffer;
        // print or use it.
    }
    centerfile.close();

    double currEntityCenter[3]; //** store the center of current entity's bounding box *//
    double firstMeshCenter[3];
    entity_meshA->get_bb_center(firstMeshCenter);


    for (int i = 0; i<2 ; ++i)
    {
        PGMeshEntity* meshEntity = (PGMeshEntity*)meshList[i];
        Mesh* mesh = meshEntity->get_mesh();
        Mesh::ConstVertexIter cvIt = mesh->vertices_begin();
        Mesh::ConstVertexIter cvIt_end = mesh->vertices_end();
        meshEntity->get_bb_center(currEntityCenter);

        double offset[3] = {0,0,0};
        offset[0] =currEntityCenter[0] - RCenter[0];
        offset[1]= currEntityCenter[1] - RCenter[1];
        offset[2]= currEntityCenter[2] - RCenter[2];

        RCenter+=3;
        //** update the leftmost point for the next entity *//
        //** adjust the position of all points of current entity *//
        for ( ; cvIt != cvIt_end; ++cvIt )
        {
            OpenMesh::Vec3d tmpPoint = mesh->point(cvIt);
            tmpPoint[0] -= offset[0];
            tmpPoint[1] -= offset[1];
            tmpPoint[2] -= offset[2];
            mesh->set_point( cvIt.handle(), tmpPoint ); //** modify core mesh D.S. embedded in PGMeshEntity D.S., updating the corresponding render in PGMeshEntity D.S. is needed *//
        }
        //** update the center point of PGMeshEntity instance bounding box *//
        meshEntity->cal_bounding_box();
        meshEntity->update_rendering();
        mesh->update_face_normals();
    }

误差计算

上文中已经说过,误差可以简单计算为两个模型对应点之间的欧氏距离。可视化误差实际上就是给模型B(或A)着色,用颜色来表示误差。具体做法是,声明一个向量ErrorB,用来存放模型B的每个点距离模型A的对应点的距离,然后设置一个colorMap,根据距离,选取colorMap中的颜色,作为B中点的颜色,最后绘制出来。误差计算代码如下:

void SequenceWaterMark::error_Map()
{
    BaseEntity * entity_meshA;
    BaseEntity * entity_meshB;
    entity_meshA = meshList[0];
    entity_meshB = meshList[1];

    PolygonMesh::Mesh * _meshA = ((PolygonMesh::PGMeshEntity *) entity_meshA)->get_mesh();
    PolygonMesh::Mesh * _meshB = ((PolygonMesh::PGMeshEntity *) entity_meshB)->get_mesh();

    //可视化的量
    vector<double> ErrorB;

    //用来存放每个点的三维坐标
    VectorXd ACoor(3);
    VectorXd BCoor(3);

    int ia = 0;
    for ( auto va_it = _meshA->vertices_begin();va_it != _meshA->vertices_end();++va_it, ia++ )
    {
        auto t_p = _meshA->point(va_it.handle());

        ACoor[0] = t_p[0];
        ACoor[1] = t_p[1];
        ACoor[2] = t_p[2];

        int ib = 0;
        double dis = 0.0;
        for ( auto vb_it = _meshB->vertices_begin();vb_it != _meshB->vertices_end();++vb_it, ib++  )
        {
            auto t_pb = _meshB->point(vb_it.handle());

            if ( ia == ib )
            {
                BCoor[0] = t_pb[0];
                BCoor[1] = t_pb[1];
                BCoor[2] = t_pb[2];

                dis = (ACoor - BCoor).norm();
                ErrorB.push_back( dis );
                break;
            }
            
        }
    }

    vector<double>::iterator max_it;
    max_it = max_element( ErrorB.begin(), ErrorB.end() );
    double maxD = *max_it;

    vector<double>::iterator min_it;
    min_it = min_element( ErrorB.begin(), ErrorB.end() );
    double minD = *min_it;

    Mesh::Color CL;
    int v = 0;
    for (auto vit = _meshB->vertices_begin();vit != _meshB->vertices_end();++vit, v++)
    {
        ErrorB[v] = 100.0f * ( ErrorB[v] - minD )/( maxD - minD );
        double clampV = ErrorB[v]< 99.0f ? ErrorB[v] : 99.0f;
        clampV = clampV > 0.0f ? clampV : 0.0f;
        int colorPercent = (int)clampV;
        unsigned char* colorPtr = ErrorColorMap + colorPercent * 3;
        CL.values_[0] = colorPtr[0];
        CL.values_[1] = colorPtr[1];
        CL.values_[2] = colorPtr[2];
        _meshB->set_color(vit.handle(), CL);//动态显示
    }
    _meshB->update_face_normals();
    entity_meshB->update_rendering();

最后为了便于查看,将第二个模型的位置稍微偏移一下

    //为了显示方便,将第二帧偏移一下
    PGMeshEntity* meshEntity = (PGMeshEntity*)meshList[1];
    Mesh* mesh = meshEntity->get_mesh();
    Mesh::ConstVertexIter cvIt = mesh->vertices_begin();
    Mesh::ConstVertexIter cvIt_end = mesh->vertices_end();
    meshEntity->get_bb_center(currEntityCenter);

    double radius = meshEntity->get_bb_radius();

    double offset[3] = {0,0,0};
    offset[0] =currEntityCenter[0] + radius;
    offset[1]= currEntityCenter[1];
    offset[2]= currEntityCenter[2];

    //** update the leftmost point for the next entity *//
    //** adjust the position of all points of current entity *//
    for ( ; cvIt != cvIt_end; ++cvIt )
    {
        OpenMesh::Vec3d tmpPoint = mesh->point(cvIt);
        tmpPoint[0] += offset[0];
        tmpPoint[1] += offset[1];
        tmpPoint[2] += offset[2];
        mesh->set_point( cvIt.handle(), tmpPoint ); //** modify core mesh D.S. embedded in PGMeshEntity D.S., updating the corresponding render in PGMeshEntity D.S. is needed *//
    }
    //** update the center point of PGMeshEntity instance bounding box *//
    meshEntity->cal_bounding_box();
    meshEntity->update_rendering();
    mesh->update_face_normals();
}

我们用一个简单的模型来验证上述代码
下图为输入的两个模型,左边为模型A,右边为模型B
enter description here

下图为执行结果
enter description here enter description here

用matlab绘制颜色条

现在已经得到了误差图,但是我们仍然不知道颜色与误差之间的关系,换句话说,只有上面的执行结果,我们并不了解深蓝色对应的误差到底是大还是小,因此需要将我们用来表示误差的颜色映射到一个颜色条上。
1.首先在matlab中输入一个矩阵MAP,表示要绘制的颜色条包含的RGB值
2.将MAP的每个值除以255,即AMAP = MAP/255
3.将AMAP传入COLORMAP函数中,即执行COLORMAP(AMAP)
4.绘制结果,即执行figure;colorbar;
结果如下:
enter description here

原文地址:https://www.cnblogs.com/scut-linmaojiang/p/4897816.html