【问题标题】:How to compute the orthonormal basis of a non square (rectangular) matrix如何计算非方形(矩形)矩阵的标准正交基
【发布时间】:2013-06-17 16:41:46
【问题描述】:

我需要找到一种方法来计算矩阵范围的正交基。在 matlab this function 中做到了。

我需要在 c/c++ 中执行此操作,我实际上正在使用 OpenCV

但是,我没有在 OpenCV 中找到任何提供此功能的东西。

我尝试过使用 cvSVD,但结果不正确。

有什么线索吗?

【问题讨论】:

  • 一旦问题不够明确,我就对其进行了编辑。我在 c 中这样做
  • SVD 不会这样做,但 Gram-Schmidt 算法会这样做,尽管我认为 OpenCV 没有该算法。
  • 下面我发布的答案是一个完整的 C++ 工作算法。将它移植到 C 将是微不足道的。
  • @Dogbert 我今晚会尝试实现它,我没有将您的答案设置为正确,因为我没有时间测试它!

标签: c++ c opencv matrix orthogonal


【解决方案1】:

如果您需要现有的工具包/库来处理这个问题,上面的@PureW 提供了一个有效的答案。如果您需要自己实现此功能,您正在寻找 Gram-Schmidt 算法的实现。

这是一个帮助您验证代码的示例问题:

http://www.mia.uni-saarland.de/Teaching/NAVC-SS11/sol_c8.pdf

这是代码(请参阅参考资料以获取完整学分)。请注意:此示例假设您有一组适当缩放的数据。如果矩阵的缩放比例不佳,则可能需要考虑 LU 分解或适当的枢轴策略。参考资料中也有关于此主题的有用链接。

#include <cstdlib>
#include <iostream>
#include <math.h>
using namespace std;

// example: http://www.mia.uni-saarland.de/Teaching/NAVC-SS11/sol_c8.pdf
// page 5

double a[3][3] = {
    {1.0, 2.0, 1.0},
    {0.0, 1.0, 2.0},
    {1.0, 2.0, 0.0}
};
// any column of a is a vector

double r[3][3], q[3][3];

int main(int argc, char *argv[]) {
    int k, i, j;
    for (k=0; k<3; k++){
      r[k][k]=0; // equivalent to sum = 0
      for (i=0; i<3; i++)
        r[k][k] = r[k][k] + a[i][k] * a[i][k]; // rkk = sqr(a0k) + sqr(a1k) + sqr(a2k) 
      r[k][k] = sqrt(r[k][k]);  // ||a||
      cout << endl << "R"<<k<<k<<": " << r[k][k];

      for (i=0; i<3; i++) {
          q[i][k] = a[i][k]/r[k][k];
          cout << " q"<<i<<k<<": "<<q[i][k] << " ";
      }

      for(j=k+1; j<3; j++) {
        r[k][j]=0;
        for(i=0; i<3; i++) r[k][j] += q[i][k] * a[i][j];
        cout << endl << "r"<<k<<j<<": " <<r[k][j] <<endl;

        for (i=0; i<3; i++) a[i][j] = a[i][j] - r[k][j]*q[i][k];

        for (i=0; i<3; i++) cout << "a"<<j<<": " << a[i][j]<< " ";
      }
}

    system("PAUSE");
    return EXIT_SUCCESS;
}

参考资料:


  1. http://www.cplusplus.com/forum/general/88888/
  2. http://www.mia.uni-saarland.de/Teaching/NAVC-SS11/sol_c8.pdf
  3. http://en.wikipedia.org/wiki/Pivot_element
  4. http://math.fullerton.edu/mathews/n2003/PivotingMod.html
  5. http://www.mathworks.com/support/solutions/en/data/1-FA9A48/index.html?solution=1-FA9A48

【讨论】:

  • 我认为如果输入矩阵不是正方形或者'3'被用作'rows'和'cols',这个例子会更容易理解
  • 没错,但我已经承认这是参考部分中其他人的代码。此外,更改代码以适应不同的矩阵大小非常容易。最后,介绍了通用算法本身,这是大部分工作。
  • 当然,我明白这一点。尽管如此,我需要一个适用于任何类型矩阵的版本;仍在尝试实施。
【解决方案2】:

这是在openCV中,它适用于只要m>n的矩形矩阵,根据this paper

- (CvMat *) buildOrthonormal:(CvMat *) matrix {

    NSInteger rows = matrix->rows;
    NSInteger cols = matrix->cols;

    CvMat *Q = cvCreateMat(rows, cols, kMatrixType);
    CvMat *R = cvCreateMat(cols, cols, kMatrixType);  

    for (NSInteger k = 0; k < cols; k++) {
        cvSetReal2D(R, k, k, 0.0f);

        for (NSInteger i = 0; i < rows; i++) {
            double value = cvGetReal2D(R, k, k) + cvGetReal2D(matrix, i, k) * cvGetReal2D(matrix, i, k);
            cvSetReal2D(R, k, k, value);
        }
        cvSetReal2D(R, k, k, sqrt(cvGetReal2D(R, k, k)));    

        for (NSInteger i = 0; i < rows; i++) {
            double value = cvGetReal2D(matrix, i, k) / cvGetReal2D(R, k, k);
            cvSetReal2D(Q, i, k, value);
        }

        for (NSInteger j = k + 1; j < cols; j++) {
            cvSetReal2D(R, k, j, 0.0f);
            for (NSInteger i = 0; i < rows; i++) {
                double value = cvGetReal2D(R, k, j) + cvGetReal2D(Q, i, k) * cvGetReal2D(matrix, i, j);
                cvSetReal2D(R, k, j, value);
            }

            for (NSInteger i = 0; i < rows; i++) {
                double value = cvGetReal2D(matrix, i, j) - cvGetReal2D(R, k, j) * cvGetReal2D(Q, i, k);
                cvSetReal2D(matrix, i, j, value);
            }
        }
    }
    cvReleaseMat(&R);

    return Q;
}

【讨论】:

    【解决方案3】:

    您想查看Gnu Scientific Library,这是一个构建在 BLAS 库之上的经过良好测试的优秀库。它实现了许多不同的矩阵运算,通常是我开始学习线性代数的地方。也许these 之一适合您?

    【讨论】:

      【解决方案4】:

      Matlab 可以生成代码。你为什么不试试呢??? 先生成,再检查,最后使用,就这样

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-31
        • 2023-02-24
        • 1970-01-01
        • 2013-10-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多