误差可视化小结
2015-10-21 14:57
344 查看
误差可视化小结
问题描述
在做水印工作的时候,需要衡量原模型与水印模型之间的误差。为了更加直观的看出误差的大小,可以将误差进行可视化。下图是可视化误差的一个例子,其中左边的模型为原始模型A,右边第二行的模型是某个算法计算出的原模型的近似模型B,右边第三行的模型是一个有色的模型,通过颜色表示出模型A、B之间的误差,颜色条显示不同颜色与误差大小的关系。![](http://images2015.cnblogs.com/blog/718109/201510/718109-20151021145702020-1667450408.png)
在水印工作中,也许要对原始模型和水印模型的误差进行衡量,误差可简单计算为两个模型上对应点之间的欧氏距离。在计算误差之前,首先要确保两个模型已经对齐(最简单的处理可以将两个模型的中点放置在一起),代码如下:
//将两个模型的中心移到一起 //将原始中心读取出来 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
![](http://images2015.cnblogs.com/blog/718109/201510/718109-20151021145703724-944646988.png)
下图为执行结果
![](http://images2015.cnblogs.com/blog/718109/201510/718109-20151021145704520-286738186.png)
![](http://images2015.cnblogs.com/blog/718109/201510/718109-20151021145705114-1664065257.png)
用matlab绘制颜色条
现在已经得到了误差图,但是我们仍然不知道颜色与误差之间的关系,换句话说,只有上面的执行结果,我们并不了解深蓝色对应的误差到底是大还是小,因此需要将我们用来表示误差的颜色映射到一个颜色条上。1.首先在matlab中输入一个矩阵MAP,表示要绘制的颜色条包含的RGB值
2.将MAP的每个值除以255,即AMAP = MAP/255
3.将AMAP传入COLORMAP函数中,即执行COLORMAP(AMAP)
4.绘制结果,即执行figure;colorbar;
结果如下:
![](http://images2015.cnblogs.com/blog/718109/201510/718109-20151021145706020-849951659.png)
相关文章推荐
- C#指针操作Marshal实例
- 坚持了两年,该离开了
- hibernate.properties
- java.util.ConcurrentModificationException的解决办法
- Android编程之图片颜色处理方法
- Node入门训练【5】【利用http请求抓取网页数据】
- struts2标签详解
- 为何我工作十年,内心仍无比恐慌(腾讯产品总监曹菲)
- CI理念
- SYSTEMTIME、 time_t、tm 的相互转换
- VC程序异常中断的原因
- 欢迎使用CSDN-markdown编辑器
- 考勤管理系统概念设计
- 域名、建站笔记
- 利用触发器自动生成日志(在触发器内部判断是添加、修改、还是删除)
- 第三章家庭作业
- checkBox的使用
- hibernate.properties
- redis连接远程服务器
- MATLAB常用数学函数