• 误差可视化小结


    误差可视化小结

    问题描述

    在做水印工作的时候,需要衡量原模型与水印模型之间的误差。为了更加直观的看出误差的大小,可以将误差进行可视化。下图是可视化误差的一个例子,其中左边的模型为原始模型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

  • 相关阅读:
    emergency mode(紧急模式)问题处理方法
    NFS简介与安装
    NACOS动态配置
    Mysql应用日志时间与系统时间相差八小时
    SQL*LOADER错误总结
    设置SQL*Plus运行环境
    对象切片
    编译原理:代码优化
    编译原理:运行时机制
    编译原理:剖析python编译阶段
  • 原文地址:https://www.cnblogs.com/scut-linmaojiang/p/4897816.html
Copyright © 2020-2023  润新知