• C++实现网格水印之调试笔记(六)—— 提取完成


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

    嵌入过程:

    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语句释放掉。

  • 相关阅读:
    《设计模式》(精华集)
    TClientDataSet使用(二)
    害我查了半天的错误!av错误,小心Component对象使用Application当Owner
    释放自己
    最近在转C#
    TClientDataSet的使用技巧
    小心使用可修改的常量。
    指数函数和正弦函数相乘
    adb 常用命令
    win7下ie9设置无法保存的问题
  • 原文地址:https://www.cnblogs.com/scut-linmaojiang/p/4480354.html
Copyright © 2020-2023  润新知