昨天在修改了可以调试出来的错误之后,提取出的水印和嵌入的仍然相去甚远。这个时候我觉得有必要整理一下嵌入和提取的整个过程。

嵌入过程:

Step1,嵌入的时候对网格的拉普拉斯矩阵L进行特征值分解,得到特征值和特征向量;

Step2,将特征向量单位化;

Step3,解方程:R . E = V(1),E,V已知求出R

其中R是频谱系数矩阵,E是单位化的特征向量矩阵,V是顶点坐标矩阵

Step4,修改R的R',其中R'= R + △ (2),R,△已知,求R'

Step5,根据矩阵方程(1)求出V', R'. E = V'(3),R', E已知,求V'

再来重温一下提取过程:

Step1,将原始水印M和网格水印M'对齐(放入同一坐标系下)

Step2,计算M的频谱系数R和M'的频谱系数R'

Step3,根据下式计算Qj即 △

Step4, 再根据下式计算出嵌入水印的符号,这里相当于得到的是嵌入的水印b',只是记为了aj

Step5,最后根据下式得出原始水印序列b

注意,在计算M'的频谱系数R'的时候,

用的是R'. E'= V'(4),E',V'已知,求R'

对比(3)和(4)式,

R'. E = V'(3)

R'. E' = V'(4)

可以看到两个等式中有两个量是相同的,即R'和V'而E和E'很可能是不相等的,所以用(4)式计算出的R'和(2)R'= R + △ (2)式中的R'是不同的,自然提取出来的 △ 也不正确。所以我觉得,是这篇论文本身有问题。。。

我觉得正确的提取方法应该是用式(3),输入水印网格,然后获取V'矩阵,用原始矩阵的E,两者结合求出R',与原始水印的R相减才能得到△

为了验证我的想法,我首先将原始网格中的E矩阵写入文件

//将单位化的特征向量写入文件中

ofstream NormEfile;

NormEfile.open("D:\\Ne.txt",ios_base::out );

if ( NormEfile)

{

for ( int i = 0; i < m_vertexNum; i++)

{

for (int j = 0; j < m_vertexNum; j++)

{

NormEfile<<E_matrix(i,j)<<" ";

}

}

}

NormEfile.close();

但是在读取的过程中遇到了问题。

Matlab计算出的R

获取出的R矩阵

也就是说 wRs应该是获取出的R矩阵的第一行

wRs = R_matrix.col(0);

输出wRs和R矩阵的第一行,结果却便了。。。

结果是循环的索引值写错了,修改后,结果如下:

但是Qi的值仍然错误

调试的时候发现,Ru读取的时候也出错了。。。

改正后问题仍然没有得到解决,观察上面的输出,估计问题是出在Ru上,输出Ru进行观察

原来是每次打开的文件都是Rs,忘记改成相应的文件了。。。。

修改之后,仍然错误。检查读出的pRu

文件中的Ru如下,显然读取错误了。

再检查pRs

读取的结果是正确的。明明是一样的读取方式,为啥会出错?

结果是下面一个判断写错了。。。

今天犯的很多错误都是这方面的,总结出来的教训是一定要仔细。

修改了上述错误后,终于提取出来了!

记录下将二维数组读出文件的方法(写入在前面有记录)

//从文件中将原始网格的E矩阵读取出来

double *pE = new double[m_vertexNum * m_vertexNum];

ifstream NERfile;

NERfile.open("D:\\Ne.txt",ios_base::in );

if (NERfile)

{

// read into memory

NERfile.seekg (0, NERfile.end);

int length = NERfile.tellg();

NERfile.seekg (0, NERfile.beg);

char *buffer = new char[length];

NERfile.read(buffer, length);

NERfile.close();

// parse into array

std::istringstream iss(buffer);

int i = 0;

while (iss >> pE[i++]);

delete [] buffer;

// print or use it.

}

NERfile.close();

int ecount = 0;

for ( int i = 0; i < m_vertexNum; i++ )

{

for ( int j = 0; j < m_vertexNum; j++ )

{

E_matrix(i,j) = pE[ecount++];

}

}

总算提取成功了。

值得注意的是,当模型的顶点个数为奇数时,产生的Wb和P的位数可能比顶点个数多一些,这是因为码片速率和原始的水印序列a的乘积很难刚好等于顶点个数。所以在读取Wb和P的时候应该改写一下while语句,如下:

while ( i<m_vertexNum )

{

iss >> RB[i++];

}

最后,new出来的数组最好用delete语句释放掉。

C++实现网格水印之调试笔记(六)—— 提取完成的更多相关文章

  1. C++实现网格水印之调试笔记(六)——补充

    调用matlab生成的网格水印特征向量矩阵 从文件中读取的原始网格的特征向量矩阵 好吧,之前得出的结果不正确是因为代码写错了.因为实现论文中的提取方案时代码写错了,自己想了另外一个方法,结果方向两者在 ...

  2. C++实现网格水印之调试笔记(五)—— 提取出错

    在实现提取水印的过程中,遇到了一些问题 首先还是根据论文中的思路来梳理一下整个提取流程 读入两个模型,一个原始模型ori_mesh, 一个水印模型wm_mesh. 将两个模型对齐(即放在同一个坐标系下 ...

  3. C++实现网格水印之调试笔记(二)

    整理了一下要实现的论文Watermarking 3D Polygonal Meshes in the Mesh Spectral Domain,步骤如下: 嵌入水印 à 提取水印 à 优化(网格细分) ...

  4. C++实现网格水印之调试笔记(四)—— 完成嵌入

    接下来的问题是,当模型是对称的时候,结果是符合预期的,但是当模型是不对称的时候,结果是错误的,如下: 输入: 顶点:233 输出: 这又是什么鬼...,我的马呢!!! 看来逻辑上还是有错误 注意这时候 ...

  5. C++实现网格水印之调试笔记(三)—— 初有结果

    错误: error C2338: THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD 这种错误 ...

  6. C++实现网格水印之调试笔记(一)

    首先说一下我的一些简单的调试方法,除了常规的断点调试之外,我还会使用注释的方法来调试.当整个工程代码量相当多且调用层次关系较为复杂时,这种方法能够比较高效的定位到出错误的代码段或某个函数,然后在出现错 ...

  7. JavaScript特效(调试笔记)

    JavaScript特效 一.在网页上显示当前的时间日期,例如:“2016年3月26日 星期六”. js源代码: function getTime() { var today = new Date() ...

  8. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  9. python3.4学习笔记(六) 常用快捷键使用技巧,持续更新

    python3.4学习笔记(六) 常用快捷键使用技巧,持续更新 安装IDLE后鼠标右键点击*.py 文件,可以看到Edit with IDLE 选择这个可以直接打开编辑器.IDLE默认不能显示行号,使 ...

随机推荐

  1. unity UGUI动态字体显示模糊

    设置Unity中ttf文件的Character为Unicode,点击apply

  2. Android:调试之DDMS

    DDMS 的全称是Dalvik Debug Monitor Service,是 Android 开发环境中的Dalvik虚拟机调试监控服务. 在Eclipse,项目启动了虚拟器后,右上角选择Open ...

  3. [iOS]iPhone利用<极光推送>实现远程推送

    准备: 1. 一个Xcode工程 2. 开发者账号 3. 真机 (重要,模拟器无法进行远程推送,因为模拟器没有UDID) 第一步:绑定工程的Bundle Identifer 首先当然要登录https: ...

  4. PCL—低层次视觉—点云分割(邻近信息)

    分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最简单的分割方式就是在边界上找些居民问:"小伙子,你到底能不能上油管啊?”.然后把能上油管的居民坐标 ...

  5. mysql优化 mysql explain

    一篇文章: 使用use index优化sql查询   先看一下arena_match_index的表结构,大家注意表的索引结构CREATE TABLE `arena_match_index` (  ` ...

  6. QTP10&QTP11&UFT11.5的安装和破解

    QTP10的安装和破解方法 下载QTP10.0并安装. 安装成功后,在C:\Program Files\Common Files\Mercury Interactive下创建文件夹:License M ...

  7. ActiveMQ之消息指针

    消息指针(Message cursor)是activeMQ里一个非常重要的核心类,它是提供某种优化消息存储的方法.消息中间件的实现一般都是当消费者准备好消费消息的时候,它会从持久化存储中一批一批的读取 ...

  8. 【转载】Java垃圾回收内存清理相关(虚拟机书第三章),GC日志的理解,CPU时间、墙钟时间的介绍

    主要看<深入理解Java虚拟机> 第三张 P84 开始是垃圾收集相关. 1. 1960年诞生于MIT的Lisp是第一门采用垃圾回收的语言. 2. 程序计数器.虚拟机栈.本地方法栈3个区域随 ...

  9. Catalan数推导(转载)

    Raney引理: 设整数序列A = {Ai, i=1, 2, …, N},且部分和Sk=A1+…+Ak,序列中所有的数字的和SN=1,在A的N个循环表示中,有且仅有一个序列B,满足B的任意部分和Si均 ...

  10. php和java的一些比较

    现在市场上的电子商务软件基本上可归结为两大阵营,即PHP阵营和Java阵营.但对接触电子商务不久的用户来说,看到的往往只是它们的表相,只是明显的价格差异,却很难看出它们之间的实际差异.其实,PHP+ ...