Как вычислить ортонормированный базис неквадратной (прямоугольной) матрицы

Мне нужно найти способ вычисления ортонормированного основания для диапазона матрицы. В матлаб эта функция Является ли.

Мне нужно сделать это в C / C ++, и я на самом деле работаю с OpenCV

Тем не менее, я не нашел ничего, что обеспечивает такую ​​возможность в OpenCV.

Я пытался работать с cvSVD, но мои результаты не верны.

Есть какие-нибудь подсказки?

1

Решение

Это в openCV, и оно работает с прямоугольной матрицей до тех пор, пока m> n, в соответствии с Эта бумага

- (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;
}
2

Другие решения

Если вам нужен существующий инструментарий / библиотека для этого, @PureW выше предоставил правильный ответ. Если вам нужно реализовать эту функцию самостоятельно, вы ищете реализацию алгоритма Грамма-Шмидта.

Вот пример проблемы, чтобы помочь вам проверить свой код:

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
5

Вы хотите посмотреть в Научная библиотека Гну Это хорошая и хорошо протестированная библиотека, созданная поверх BLAS-библиотек. Он реализует множество различных матричных операций и, как правило, я бы начал с линейной алгебры. Может быть один из эти подойдет тебе?

1

Matlab может генерировать коды. Почему бы вам не попробовать ???
Сначала создайте, затем изучите и, наконец, используйте его, вот и все

0
По вопросам рекламы [email protected]