zoukankan      html  css  js  c++  java
  • OpenCV-Core学习日志:数学基础函数实验

    6.

             。

    5.Rodrigues

             李代数中有三种求导方式:基于指数映射求导、基于BCH公式求导、基于扰动方式求导。

             三种求导方式的具体理论及其如何应用并不能一两句话讲清楚,具体可参见相关文献。

             这里主要是验证基于指数映射求导和基于BCH公式求导的一致性,OpenCV中Rodrigues是基于指数映射求导(具体可参见源码),这里实现基于BCH公式求导,具体公式如下图。

              以下是详细代码,依赖于C++14、OpenCV4.x和Spdlog。

     1 #include <opencv2/opencv.hpp>
     2 #include <spdlog/spdlog.h>
     3 using namespace std;
     4 using namespace cv;
     5 
     6 #ifndef  RAD2DEG
     7 #define RAD2DEG (180 * 0.3183098861837906715)
     8 #define DEG2RAD (3.14159265358979323846 * 0.0055555555555555556)
     9 #endif
    10 
    11 Matx33d eulerRot(Matx31d radian)
    12 {
    13     Matx33d R;
    14     double sinR = sin(radian.val[0]);
    15     double sinP = sin(radian.val[1]);
    16     double sinY = sin(radian.val[2]);
    17     double cosR = cos(radian.val[0]);
    18     double cosP = cos(radian.val[1]);
    19     double cosY = cos(radian.val[2]);
    20 
    21     //RPY indicates: first Yaw aroundZ, second Pitch aroundY, third Roll aroundX
    22     R.val[0] = cosY * cosP; R.val[1] = cosY * sinP * sinR - sinY * cosR; R.val[2] = cosY * sinP * cosR + sinY * sinR;
    23     R.val[3] = sinY * cosP; R.val[4] = sinY * sinP * sinR + cosY * cosR; R.val[5] = sinY * sinP * cosR - cosY * sinR;
    24     R.val[6] = -sinP;       R.val[7] = cosP * sinR;                      R.val[8] = cosP * cosR;
    25     return R;
    26 }
    27 
    28 static void checkRodrigues(int argc = 0, char** argv = 0)
    29 {
    30     int N = 999;
    31     for (int k = 0; k < N; ++k)
    32     {
    33         //1.GenerateSimDataAndGT
    34         Matx31d degree = Matx31d::randu(-180, 180);
    35         Matx33d R = eulerRot(degree * DEG2RAD);
    36         Matx31d r; cv::Rodrigues(R, r);
    37         Matx31d PW(r.randu(-999, 999)(0), r.randu(-999, 999)(0), r.randu(0, 999)(0));
    38         Matx31d PC = R * PW;
    39 
    40         //2.CalcByExpMap
    41         Matx<double, 3, 9> dPCdR; dPCdR <<
    42             PW(0), PW(1), PW(2), 0, 0, 0, 0, 0, 0,
    43             0, 0, 0, PW(0), PW(1), PW(2), 0, 0, 0,
    44             0, 0, 0, 0, 0, 0, PW(0), PW(1), PW(2);
    45         Mat_<double> dRdr;
    46         cv::Rodrigues(r, Matx33d(), dRdr);
    47         transpose(dRdr, dRdr);
    48         Matx33d dPCdr1 = dPCdR * Matx<double, 9, 3>(dRdr.ptr<double>());
    49 
    50         //3.CalcByBCH
    51         double theta = sqrt(r.val[0] * r.val[0] + r.val[1] * r.val[1] + r.val[2] * r.val[2]);
    52         double itheta = 1 / theta;
    53         double sn = sin(theta);
    54         double cs1 = 1 - cos(theta);
    55         Matx31d n(r.val[0] * itheta, r.val[1] * itheta, r.val[2] * itheta);
    56         Matx33d nskew(0, -n.val[2], n.val[1], n.val[2], 0, -n.val[0], -n.val[1], n.val[0], 0);
    57         Matx33d Jl = itheta * sn * Matx33d::eye() + itheta * cs1 * nskew + (1 - itheta * sn) * n * n.t();
    58         Matx33d skewPC(0, -PC.val[2], PC.val[1], PC.val[2], 0, -PC.val[0], -PC.val[1], PC.val[0], 0);
    59         Matx33d dPCdr2 = -skewPC * Jl;
    60 
    61         //4.AnalyzeError
    62         double infdPCdr1dPCdr2 = norm(dPCdr1, dPCdr2, NORM_INF);
    63 
    64         //5.PrintError
    65         cout << endl << "LoopCount: " << k << endl;
    66         if (infdPCdr1dPCdr2 > 1e-9)
    67         {
    68             cout << endl << "5.1PrintError" << endl;
    69             cout << endl << "infdPCdr1dPCdr2: " << infdPCdr1dPCdr2 << endl;
    70             if (0)
    71             {
    72                 cout << endl << "5.2PrintDiff" << endl;
    73                 cout << endl << "dPCdr1: " << endl << dPCdr1 << endl;
    74                 cout << endl << "dPCdr2: " << endl << dPCdr2 << endl;
    75                 cout << endl << "5.3PrintOthers" << endl;
    76                 cout << endl << "PW: " << endl << PW << endl;
    77                 cout << endl << "PC: " << endl << PC << endl;
    78                 cout << endl << "r-degree: " << endl << r.t() << endl << degree.t() << endl;
    79             }
    80             cout << endl << "Press any key to continue" << endl;
    81             std::getchar();
    82         }
    83     }
    84 }
    85 
    86 int main(int argc, char** argv) { checkRodrigues(argc, argv); return 0; }
    View Code

    4.PCAProject

             关于PCA的基础知识如下图像所示。

             提供的checkPCAProject具有以下目的:验证以上提到的三种计算方法的计算结果与PCAProject的结果的一致性,实现理论验证和接口测试的双重目的。

             由于不同的计算方法得到的特征向量可能存在正负号的差别(这对实际应用无影响),这就导致主分量变换的结果并不一样,所以代码中没有直接判断正向变换的一致性,而是判断重建结果的一致性。

             以下是详细代码,依赖于C++14、OpenCV4.x和Spdlog。

     1 #include <opencv2/opencv.hpp>
     2 #include <spdlog/spdlog.h>
     3 using namespace std;
     4 using namespace cv;
     5 
     6 #ifndef RandomMM
     7 #define RandomMM(min, max) (rand() % ((max) - (min) + 1) + (min))
     8 #endif
     9 
    10 static void checkPCAProject(int argc = 0, char** argv = 0)
    11 {
    12     int N = 99;
    13     for (int k = 0; k < N; ++k)
    14     {
    15         //1.GenerateSimDataAndGT
    16         Mat_<double> X(RandomMM(100, 999), RandomMM(1, 99)); randu(X, -999, 999);
    17         Mat_<double> C, O; cv::calcCovarMatrix(X, C, O, COVAR_NORMAL | COVAR_ROWS | COVAR_SCALE);
    18 
    19         //2.CalcByEigenDecompsition
    20         Mat_<double> w1, vt1;
    21         cv::eigen(C, w1, vt1);
    22 
    23         //3.CalcBySVDCovarMatrix
    24         Mat_<double> w2, vt2, u2;
    25         cv::SVDecomp(C, w2, u2, vt2, SVD::FULL_UV);
    26 
    27         //4.CalcBySVDCenteredSampleMatrix
    28         Mat_<double> w3, vt3, u3;
    29         Mat_<double> Xo(X.size()); for (int i = 0; i < X.cols; ++i) Xo.col(i) = X.col(i) - O(i);
    30         cv::SVDecomp(Xo, w3, u3, vt3, SVD::FULL_UV);
    31         pow(w3, 2, w3); w3 *= (1. / X.rows);
    32 
    33         //5.CalcByPCA
    34         Mat_<double> w4, vt4;
    35         cv::PCACompute(X, O, vt4, w4, 0);
    36 
    37         //6.PCAProject
    38         Mat_<double> Y1 = Xo * vt1.t();
    39         Mat_<double> Y2 = Xo * vt2.t();
    40         Mat_<double> Y3 = Xo * vt3.t();
    41         Mat_<double> Y4 = Xo * vt4.t();
    42         Mat_<double> Y5; cv::PCAProject(X, O, vt4, Y5);
    43 
    44         //7.PACBackProject
    45         Mat_<double> Z1 = Y1 * vt1; for (int i = 0; i < X.cols; ++i) Z1.col(i) += O(i);
    46         Mat_<double> Z2 = Y2 * vt2; for (int i = 0; i < X.cols; ++i) Z2.col(i) += O(i);
    47         Mat_<double> Z3 = Y3 * vt3; for (int i = 0; i < X.cols; ++i) Z3.col(i) += O(i);
    48         Mat_<double> Z4 = Y4 * vt4; for (int i = 0; i < X.cols; ++i) Z4.col(i) += O(i);
    49         Mat_<double> Z5; cv::PCABackProject(Y5, O, vt4, Z5);
    50 
    51         //8.AnalyzeError
    52         double infY1Y5 = norm(Y1, Y5, NORM_INF);
    53         double infY2Y5 = norm(Y2, Y5, NORM_INF);
    54         double infY3Y5 = norm(Y3, Y5, NORM_INF);
    55         double infY4Y5 = norm(Y4, Y5, NORM_INF);
    56         double infZ1Z5 = norm(Z1, Z5, NORM_INF);
    57         double infZ2Z5 = norm(Z2, Z5, NORM_INF);
    58         double infZ3Z5 = norm(Z3, Z5, NORM_INF);
    59         double infZ4Z5 = norm(Z4, Z5, NORM_INF);
    60 
    61         //9.PrintError
    62         cout << endl << "LoopCount: " << k << endl;
    63         if (/*infY1Y5 > 1e-6 || infY2Y5 > 1e-6 || infY3Y5 > 1e-6 || infY4Y5 > 1e-6 || */infZ1Z5 > 1e-6 || infZ2Z5 > 1e-6 || infZ3Z5 > 1e-6 || infZ4Z5 > 1e-6)
    64         {
    65             cout << endl << "5.1PrintError" << endl;
    66             cout << endl << "infY1Y5: " << infY1Y5 << endl;
    67             cout << endl << "infY2Y5: " << infY2Y5 << endl;
    68             cout << endl << "infY3Y5: " << infY3Y5 << endl;
    69             cout << endl << "infY4Y5: " << infY4Y5 << endl;
    70             cout << endl << "infZ1Z5: " << infZ1Z5 << endl;
    71             cout << endl << "infZ2Z5: " << infZ2Z5 << endl;
    72             cout << endl << "infZ3Z5: " << infZ3Z5 << endl;
    73             cout << endl << "infZ4Z5: " << infZ4Z5 << endl;
    74             if (0)
    75             {
    76                 cout << endl << "5.2PrintDiff" << endl;
    77                 cout << endl << "Y1: " << endl << Y1 << endl;
    78                 cout << endl << "Y2: " << endl << Y2 << endl;
    79                 cout << endl << "Y3: " << endl << Y3 << endl;
    80                 cout << endl << "Y4: " << endl << Y4 << endl;
    81                 cout << endl << "Y5: " << endl << Y5 << endl;
    82                 cout << endl;
    83                 cout << endl << "Z1: " << endl << Z1 << endl;
    84                 cout << endl << "Z2: " << endl << Z2 << endl;
    85                 cout << endl << "Z3: " << endl << Z3 << endl;
    86                 cout << endl << "Z4: " << endl << Z4 << endl;
    87                 cout << endl << "Z5: " << endl << Z5 << endl;
    88                 cout << endl << "5.3PrintOthers" << endl;
    89                 cout << endl << "C: " << endl << C << endl;
    90                 cout << endl << "X: " << endl << X << endl;
    91             }
    92             cout << endl << "Press any key to continue" << endl;
    93             std::getchar();
    94         }
    95     }
    96 }
    97 
    98 int main(int argc, char** argv) { checkPCAProject(argc, argv); return 0; }
    View Code

    3.eigen

             仅方阵且可相似对角化才能进行特征值分解,关于相似对角化有以下:

             (1)充要条件:有n个线性无关的特征向量

             (2)充分条件:k重特征值有k个线性无关特征向量(这样就肯定有n个线性无关的特征向量)

             (3)充分条件:有n个不同特征值(因为有定理表述不同特征值对应的特征向量线性无关)

             (4)充分条件:为正规矩阵(因为正规矩阵要么有n个不同的特征值要么k重特征值对应k个线性无关的特征向量)

             提供的checkEigen具有以下目的:验证特征值分解eigen、奇异值分解SVD、主成分分析PCA三者结果的一致性,或者说基于后两者验证前者的正确性。

             以下是详细代码,依赖于C++14、OpenCV4.x和Spdlog。

     1 #include <opencv2/opencv.hpp>
     2 #include <spdlog/spdlog.h>
     3 using namespace std;
     4 using namespace cv;
     5 
     6 #ifndef RandomMM
     7 #define RandomMM(min, max) (rand() % ((max) - (min) + 1) + (min))
     8 #endif
     9 
    10 static void checkEigen(int argc = 0, char** argv = 0)
    11 {
    12     int N = 99;
    13     for (int k = 0; k < N; ++k)
    14     {
    15         //1.GenerateSimDataAndGT
    16         Mat_<double> X(RandomMM(111, 999), RandomMM(11, 99)); cv::randu(X, -999, 999);
    17         Mat_<double> C, O; cv::calcCovarMatrix(X, C, O, COVAR_NORMAL | COVAR_ROWS | COVAR_SCALE);
    18 
    19         //2.CalcByEigenDecompsition
    20         Mat_<double> w1, vt1;
    21         cv::eigen(C, w1, vt1);
    22 
    23         //3.CalcBySVDCovarMatrix
    24         Mat_<double> w2, vt2, u2;
    25         cv::SVDecomp(C, w2, u2, vt2, SVD::FULL_UV);
    26 
    27         //4.CalcBySVDCenteredSampleMatrix
    28         Mat_<double> w3, vt3, u3;
    29         Mat_<double> Xo(X.size()); for (int i = 0; i < X.cols; ++i) Xo.col(i) = X.col(i) - O(i);
    30         cv::SVDecomp(Xo, w3, u3, vt3, SVD::FULL_UV);
    31         pow(w3, 2, w3); w3 *= (1. / X.rows);
    32 
    33         //5.CalcByPCA
    34         Mat_<double> w4, vt4;
    35         cv::PCACompute(X, O, vt4, w4);
    36 
    37         //6.AnalyzeError
    38         double infvt1vt2 = norm(cv::abs(vt1), cv::abs(vt2), NORM_INF);
    39         double infvt1vt3 = norm(cv::abs(vt1), cv::abs(vt3), NORM_INF);
    40         double infvt1vt4 = norm(cv::abs(vt1), cv::abs(vt4), NORM_INF);
    41         double infw1w2 = norm(w1, w2, NORM_INF);
    42         double infw1w3 = norm(w1, w3, NORM_INF);
    43         double infw1w4 = norm(w1, w4, NORM_INF);
    44 
    45         //7.PrintError
    46         cout << endl << "LoopCount: " << k << endl;
    47         if (infvt1vt2 > 1e-6 || infvt1vt3 > 1e-6 || infvt1vt4 > 1e-6 || infw1w2 > 1e-6 || infw1w3 > 1e-6 || infw1w4 > 1e-6)
    48         {
    49             cout << endl << "5.1PrintError" << endl;
    50             cout << endl << "infvt1vt2: " << infvt1vt2 << endl;
    51             cout << endl << "infvt1vt3: " << infvt1vt3 << endl;
    52             cout << endl << "infvt1vt4: " << infvt1vt4 << endl;
    53             cout << endl << "infw1w2: " << infw1w2 << endl;
    54             cout << endl << "infw1w3: " << infw1w2 << endl;
    55             cout << endl << "infw1w4: " << infw1w2 << endl;
    56             if (0)
    57             {
    58                 cout << endl << "5.2PrintDiff" << endl;
    59                 cout << endl << "vt1: " << endl << vt1 << endl;
    60                 cout << endl << "vt2: " << endl << vt2 << endl;
    61                 cout << endl << "vt3: " << endl << vt3 << endl;
    62                 cout << endl << "vt4: " << endl << vt4 << endl;
    63                 cout << endl << "w1: " << endl << w1 << endl;
    64                 cout << endl << "w2: " << endl << w2 << endl;
    65                 cout << endl << "w3: " << endl << w3 << endl;
    66                 cout << endl << "w4: " << endl << w4 << endl;
    67                 cout << endl << "5.3PrintOthers" << endl;
    68                 cout << endl << "C: " << endl << C << endl;
    69                 cout << endl << "X: " << endl << X << endl;
    70             }
    71             cout << endl << "Press any key to continue" << endl;
    72             std::getchar();
    73         }
    74     }
    75 }
    76 
    77 int main(int argc, char** argv) { checkEigen(argc, argv); return 0; }
    View Code

    2.calcCovarMatrix

             关于期望和协方差的基础知识如下图像所示。

     

             提供的checkCalcCovarMatrix具有以下目的:验证公式计算的结果与calcCovarMatrix的结果的一致性,实现理论验证和接口测试的双重目的。

             以下是详细代码,依赖于C++14、OpenCV4.x和Spdlog。

     1 #include <opencv2/opencv.hpp>
     2 #include <spdlog/spdlog.h>
     3 using namespace std;
     4 using namespace cv;
     5 
     6 #ifndef RandomMM
     7 #define RandomMM(min, max) (rand() % ((max) - (min) + 1) + (min))
     8 #endif
     9 
    10 static void checkCalcCovarMatrix(int argc = 0, char** argv = 0)
    11 {
    12     int N = 999;
    13     for (int k = 0; k < N; ++k)
    14     {
    15         //1.GenerateSimDataAndGT
    16         Mat_<double> X(RandomMM(111,999), RandomMM(111,999)); randu(X, -999, 999);
    17 
    18         //2.CalcByOpenCV
    19         Mat_<double> C1, O1;
    20         cv::calcCovarMatrix(X, C1, O1, COVAR_NORMAL | COVAR_ROWS | COVAR_SCALE);
    21 
    22         //3.CalcByTheory
    23         Mat_<double> O2(1, X.cols); for (int j = 0; j < X.cols; ++j) O2(j) = mean(X.col(j))[0];
    24         Mat_<double> C2; mulTransposed(X, C2, true, O2, 1. / X.rows);
    25         //Mat_<double> C3 = 1. / X.rows * X.t() * X - O2.t() * O2; C2 = C3;
    26 
    27         //4.AnalyzeError
    28         double infO1O2 = norm(O1, O2, NORM_INF);
    29         double infC1C2 = norm(C1, C2, NORM_INF);
    30 
    31         //5.PrintError
    32         cout << endl << "LoopCount: " << k << endl;
    33         if (infO1O2 > 0 || infC1C2 > 0)
    34         {
    35             cout << endl << "5.1PrintError" << endl;
    36             cout << endl << "infO1O2: " << infO1O2 << endl;
    37             cout << endl << "infC1C2: " << infC1C2 << endl;
    38             if (0)
    39             {
    40                 cout << endl << "5.2PrintDiff" << endl;
    41                 cout << endl << "O1: " << endl << O1 << endl;
    42                 cout << endl << "O2: " << endl << O2 << endl;
    43                 cout << endl << "C1: " << endl << C1 << endl;
    44                 cout << endl << "C2: " << endl << C2 << endl;
    45                 cout << endl << "5.3PrintOthers" << endl;
    46                 cout << endl << "X: " << endl << X << endl;
    47             }
    48             cout << endl << "Press any key to continue" << endl;
    49             std::getchar();
    50         }
    51     }
    52 }
    53 
    54 int main(int argc, char** argv) { checkCalcCovarMatrix(argc, argv); return 0; }
    View Code

    1.SVDecomp

             任意矩阵A都能进行奇异值分解,且不论A的是否为方阵或是否满秩(包括行满秩、列满秩及全满秩),A的SVD形式都可以归结为两种:完整型和缩减型。

             假设Amn是m行n列的矩阵且秩为r,则:

             (1)完整型:Amn=Umm*Wmn*Trans(Vnn)

             (2)缩减型:Amn=Umr*Wrr*Trans(Vnr)

             根据A是否满秩,可根据以上两种形式衍生出多种形式,但无非都是r或取m或n等变化,典型地,满秩方阵的两种形式一致。

             SVDecomp正是提供了以上两种分解形式,通过设置flags可得到不同的分解形式,flags取值如下:

             (1)NO_UV:仅返回奇异值向量W,返回空U和空V。

             (2)FULL_UV:按完整型进行SVD,对满秩方阵无影响,对欠秩矩阵和非方阵有作用。

             (3)MODIFY_A:暂无作用。

             默认是缩减型SVD。需要注意的是无论flags取什么值,返回的W都是维度相同的向量且维度等于行数和列数的较小者,只是对于欠秩矩阵,W最后几维的数值为0。

             提供的checkSVDecomp具有以下目的:

             (1)如何使用SVDecomp。

             (2)测试SVDecomp的正确性:通过对比分析原始矩阵和重建矩阵来测试。

             以下是详细代码,依赖于C++14、OpenCV4.x和Spdlog。

     1 #include <opencv2/opencv.hpp>
     2 #include <spdlog/spdlog.h>
     3 using namespace std;
     4 using namespace cv;
     5 
     6 static void checkSVDecomp(int argc = 0, char** argv = 0)
     7 {
     8     int N = 999;
     9     for (int k = 0; k < N / 2; ++k)
    10     {
    11         //1.GenerateSimDataAndGT
    12         Mat_<double> A(5, 3); cv::randu(A, -999, 999);
    13 
    14         //2.DecomposeByShortSVD
    15         Mat_<double> U1, W1, VT1;
    16         cv::SVDecomp(A, W1, U1, VT1);
    17 
    18         //3.DecomposeByFullSVD
    19         Mat_<double> U2, W2, VT2;
    20         cv::SVDecomp(A, W2, U2, VT2, SVD::FULL_UV);
    21 
    22         //4.AnalyzeError
    23         double infA0A1 = norm(U1 * Matx33d::diag(W1) * VT1, A, NORM_INF);
    24         Mat_<double> W2_(A.size(), 0.); for (int k = 0; k < 3; ++k) W2_(k, k) = W2(k);
    25         double infA0A2 = norm(U2 * W2_ * VT2, A, NORM_INF);
    26 
    27         //5.PrintError
    28         cout << endl << "LoopCount: " << k << endl;
    29         if (infA0A1 > 1E-6 || infA0A2 > 1E-6)
    30         {
    31             cout << endl << "5.1PrintError" << endl;
    32             cout << endl << "infA0A1: " << infA0A1 << endl;
    33             cout << endl << "infA0A2: " << infA0A2 << endl;
    34             cout << endl << "5.2PrintDiff" << endl;
    35             cout << endl << "U1:" << endl << U1 << endl;
    36             cout << endl << "U2:" << endl << U2 << endl;
    37             cout << endl << "W1:" << endl << W1 << endl;
    38             cout << endl << "W2:" << endl << W2 << endl;
    39             cout << endl << "VT1:" << endl << VT1 << endl;
    40             cout << endl << "VT2:" << endl << VT2 << endl;
    41             cout << endl << "5.3PrintOthers" << endl;
    42             cout << endl << "Press any key to continue" << endl;
    43             std::getchar();
    44         }
    45     }
    46     for (int k = N / 2; k < N; ++k)
    47     {
    48         //1.GenerateSimDataAndGT
    49         Mat_<double> A(3, 5); cv::randu(A, -999, 999);
    50 
    51         //2.DecomposeByShortSVD
    52         Mat_<double> U1, W1, VT1;
    53         cv::SVDecomp(A, W1, U1, VT1);
    54 
    55         //3.DecomposeByFullSVD
    56         Mat_<double> U2, W2, VT2;
    57         cv::SVDecomp(A, W2, U2, VT2, SVD::FULL_UV);
    58 
    59         //4.AnalyzeError
    60         double infA0A1 = norm(U1 * Matx33d::diag(W1) * VT1, A, NORM_INF);
    61         Mat_<double> W2_(A.size(), 0.); for (int k = 0; k < 3; ++k) W2_(k, k) = W2(k);
    62         double infA0A2 = norm(U2 * W2_ * VT2, A, NORM_INF);
    63 
    64         //5.PrintError
    65         cout << endl << "LoopCount: " << k << endl;
    66         if (infA0A1 > 1E-6 || infA0A2 > 1E-6)
    67         {
    68             cout << endl << "5.1PrintError" << endl;
    69             cout << endl << "infA0A1: " << infA0A1 << endl;
    70             cout << endl << "infA0A2: " << infA0A2 << endl;
    71             cout << endl << "5.2PrintDiff" << endl;
    72             cout << endl << "U1:" << endl << U1 << endl;
    73             cout << endl << "U2:" << endl << U2 << endl;
    74             cout << endl << "W1:" << endl << W1 << endl;
    75             cout << endl << "W2:" << endl << W2 << endl;
    76             cout << endl << "VT1:" << endl << VT1 << endl;
    77             cout << endl << "VT2:" << endl << VT2 << endl;
    78             cout << endl << "5.3PrintOthers" << endl;
    79             cout << endl << "Press any key to continue" << endl;
    80             std::getchar();
    81         }
    82     }
    83 }
    84 
    85 int main(int argc, char** argv) { checkSVDecomp(argc, argv); return 0; }
    View Code
  • 相关阅读:
    推送技术 --SignalR
    软件解耦
    xrBarCode 条形码的密度设置
    Javascript 中方法的重写
    数据库锁
    oracle instr,substr 截取字符串
    循环读取写入表
    Oracle For 循环,字符串拼接,查找
    iis,webservice 启用 acrobat.exe 打印
    iis,webservice 打印
  • 原文地址:https://www.cnblogs.com/dzyBK/p/13917147.html
Copyright © 2011-2022 走看看