Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/calib3d/src/dls.h
16354 views
1
#ifndef DLS_H_
2
#define DLS_H_
3
4
#include "precomp.hpp"
5
6
#include <iostream>
7
8
using namespace std;
9
using namespace cv;
10
11
class dls
12
{
13
public:
14
dls(const cv::Mat& opoints, const cv::Mat& ipoints);
15
~dls();
16
17
bool compute_pose(cv::Mat& R, cv::Mat& t);
18
19
private:
20
21
// initialisation
22
template <typename OpointType, typename IpointType>
23
void init_points(const cv::Mat& opoints, const cv::Mat& ipoints)
24
{
25
for(int i = 0; i < N; i++)
26
{
27
p.at<double>(0,i) = opoints.at<OpointType>(i).x;
28
p.at<double>(1,i) = opoints.at<OpointType>(i).y;
29
p.at<double>(2,i) = opoints.at<OpointType>(i).z;
30
31
// compute mean of object points
32
mn.at<double>(0) += p.at<double>(0,i);
33
mn.at<double>(1) += p.at<double>(1,i);
34
mn.at<double>(2) += p.at<double>(2,i);
35
36
// make z into unit vectors from normalized pixel coords
37
double sr = std::pow(ipoints.at<IpointType>(i).x, 2) +
38
std::pow(ipoints.at<IpointType>(i).y, 2) + (double)1;
39
sr = std::sqrt(sr);
40
41
z.at<double>(0,i) = ipoints.at<IpointType>(i).x / sr;
42
z.at<double>(1,i) = ipoints.at<IpointType>(i).y / sr;
43
z.at<double>(2,i) = (double)1 / sr;
44
}
45
46
mn.at<double>(0) /= (double)N;
47
mn.at<double>(1) /= (double)N;
48
mn.at<double>(2) /= (double)N;
49
}
50
51
// main algorithm
52
cv::Mat LeftMultVec(const cv::Mat& v);
53
void run_kernel(const cv::Mat& pp);
54
void build_coeff_matrix(const cv::Mat& pp, cv::Mat& Mtilde, cv::Mat& D);
55
void compute_eigenvec(const cv::Mat& Mtilde, cv::Mat& eigenval_real, cv::Mat& eigenval_imag,
56
cv::Mat& eigenvec_real, cv::Mat& eigenvec_imag);
57
void fill_coeff(const cv::Mat * D);
58
59
// useful functions
60
cv::Mat cayley_LS_M(const std::vector<double>& a, const std::vector<double>& b,
61
const std::vector<double>& c, const std::vector<double>& u);
62
cv::Mat Hessian(const double s[]);
63
cv::Mat cayley2rotbar(const cv::Mat& s);
64
cv::Mat skewsymm(const cv::Mat * X1);
65
66
// extra functions
67
cv::Mat rotx(const double t);
68
cv::Mat roty(const double t);
69
cv::Mat rotz(const double t);
70
cv::Mat mean(const cv::Mat& M);
71
bool is_empty(const cv::Mat * v);
72
bool positive_eigenvalues(const cv::Mat * eigenvalues);
73
74
cv::Mat p, z, mn; // object-image points
75
int N; // number of input points
76
std::vector<double> f1coeff, f2coeff, f3coeff, cost_; // coefficient for coefficients matrix
77
std::vector<cv::Mat> C_est_, t_est_; // optimal candidates
78
cv::Mat C_est__, t_est__; // optimal found solution
79
double cost__; // optimal found solution
80
};
81
82
class EigenvalueDecomposition {
83
private:
84
85
// Holds the data dimension.
86
int n;
87
88
// Stores real/imag part of a complex division.
89
double cdivr, cdivi;
90
91
// Pointer to internal memory.
92
double *d, *e, *ort;
93
double **V, **H;
94
95
// Holds the computed eigenvalues.
96
Mat _eigenvalues;
97
98
// Holds the computed eigenvectors.
99
Mat _eigenvectors;
100
101
// Allocates memory.
102
template<typename _Tp>
103
_Tp *alloc_1d(int m) {
104
return new _Tp[m];
105
}
106
107
// Allocates memory.
108
template<typename _Tp>
109
_Tp *alloc_1d(int m, _Tp val) {
110
_Tp *arr = alloc_1d<_Tp> (m);
111
for (int i = 0; i < m; i++)
112
arr[i] = val;
113
return arr;
114
}
115
116
// Allocates memory.
117
template<typename _Tp>
118
_Tp **alloc_2d(int m, int _n) {
119
_Tp **arr = new _Tp*[m];
120
for (int i = 0; i < m; i++)
121
arr[i] = new _Tp[_n];
122
return arr;
123
}
124
125
// Allocates memory.
126
template<typename _Tp>
127
_Tp **alloc_2d(int m, int _n, _Tp val) {
128
_Tp **arr = alloc_2d<_Tp> (m, _n);
129
for (int i = 0; i < m; i++) {
130
for (int j = 0; j < _n; j++) {
131
arr[i][j] = val;
132
}
133
}
134
return arr;
135
}
136
137
void cdiv(double xr, double xi, double yr, double yi) {
138
double r, dv;
139
if (std::abs(yr) > std::abs(yi)) {
140
r = yi / yr;
141
dv = yr + r * yi;
142
cdivr = (xr + r * xi) / dv;
143
cdivi = (xi - r * xr) / dv;
144
} else {
145
r = yr / yi;
146
dv = yi + r * yr;
147
cdivr = (r * xr + xi) / dv;
148
cdivi = (r * xi - xr) / dv;
149
}
150
}
151
152
// Nonsymmetric reduction from Hessenberg to real Schur form.
153
154
void hqr2() {
155
156
// This is derived from the Algol procedure hqr2,
157
// by Martin and Wilkinson, Handbook for Auto. Comp.,
158
// Vol.ii-Linear Algebra, and the corresponding
159
// Fortran subroutine in EISPACK.
160
161
// Initialize
162
int nn = this->n;
163
int n1 = nn - 1;
164
int low = 0;
165
int high = nn - 1;
166
double eps = std::pow(2.0, -52.0);
167
double exshift = 0.0;
168
double p = 0, q = 0, r = 0, s = 0, z = 0, t, w, x, y;
169
170
// Store roots isolated by balanc and compute matrix norm
171
172
double norm = 0.0;
173
for (int i = 0; i < nn; i++) {
174
if (i < low || i > high) {
175
d[i] = H[i][i];
176
e[i] = 0.0;
177
}
178
for (int j = std::max(i - 1, 0); j < nn; j++) {
179
norm = norm + std::abs(H[i][j]);
180
}
181
}
182
183
// Outer loop over eigenvalue index
184
int iter = 0;
185
while (n1 >= low) {
186
187
// Look for single small sub-diagonal element
188
int l = n1;
189
while (l > low) {
190
s = std::abs(H[l - 1][l - 1]) + std::abs(H[l][l]);
191
if (s == 0.0) {
192
s = norm;
193
}
194
if (std::abs(H[l][l - 1]) < eps * s) {
195
break;
196
}
197
l--;
198
}
199
200
// Check for convergence
201
// One root found
202
203
if (l == n1) {
204
H[n1][n1] = H[n1][n1] + exshift;
205
d[n1] = H[n1][n1];
206
e[n1] = 0.0;
207
n1--;
208
iter = 0;
209
210
// Two roots found
211
212
} else if (l == n1 - 1) {
213
w = H[n1][n1 - 1] * H[n1 - 1][n1];
214
p = (H[n1 - 1][n1 - 1] - H[n1][n1]) / 2.0;
215
q = p * p + w;
216
z = std::sqrt(std::abs(q));
217
H[n1][n1] = H[n1][n1] + exshift;
218
H[n1 - 1][n1 - 1] = H[n1 - 1][n1 - 1] + exshift;
219
x = H[n1][n1];
220
221
// Real pair
222
223
if (q >= 0) {
224
if (p >= 0) {
225
z = p + z;
226
} else {
227
z = p - z;
228
}
229
d[n1 - 1] = x + z;
230
d[n1] = d[n1 - 1];
231
if (z != 0.0) {
232
d[n1] = x - w / z;
233
}
234
e[n1 - 1] = 0.0;
235
e[n1] = 0.0;
236
x = H[n1][n1 - 1];
237
s = std::abs(x) + std::abs(z);
238
p = x / s;
239
q = z / s;
240
r = std::sqrt(p * p + q * q);
241
p = p / r;
242
q = q / r;
243
244
// Row modification
245
246
for (int j = n1 - 1; j < nn; j++) {
247
z = H[n1 - 1][j];
248
H[n1 - 1][j] = q * z + p * H[n1][j];
249
H[n1][j] = q * H[n1][j] - p * z;
250
}
251
252
// Column modification
253
254
for (int i = 0; i <= n1; i++) {
255
z = H[i][n1 - 1];
256
H[i][n1 - 1] = q * z + p * H[i][n1];
257
H[i][n1] = q * H[i][n1] - p * z;
258
}
259
260
// Accumulate transformations
261
262
for (int i = low; i <= high; i++) {
263
z = V[i][n1 - 1];
264
V[i][n1 - 1] = q * z + p * V[i][n1];
265
V[i][n1] = q * V[i][n1] - p * z;
266
}
267
268
// Complex pair
269
270
} else {
271
d[n1 - 1] = x + p;
272
d[n1] = x + p;
273
e[n1 - 1] = z;
274
e[n1] = -z;
275
}
276
n1 = n1 - 2;
277
iter = 0;
278
279
// No convergence yet
280
281
} else {
282
283
// Form shift
284
285
x = H[n1][n1];
286
y = 0.0;
287
w = 0.0;
288
if (l < n1) {
289
y = H[n1 - 1][n1 - 1];
290
w = H[n1][n1 - 1] * H[n1 - 1][n1];
291
}
292
293
// Wilkinson's original ad hoc shift
294
295
if (iter == 10) {
296
exshift += x;
297
for (int i = low; i <= n1; i++) {
298
H[i][i] -= x;
299
}
300
s = std::abs(H[n1][n1 - 1]) + std::abs(H[n1 - 1][n1 - 2]);
301
x = y = 0.75 * s;
302
w = -0.4375 * s * s;
303
}
304
305
// MATLAB's new ad hoc shift
306
307
if (iter == 30) {
308
s = (y - x) / 2.0;
309
s = s * s + w;
310
if (s > 0) {
311
s = std::sqrt(s);
312
if (y < x) {
313
s = -s;
314
}
315
s = x - w / ((y - x) / 2.0 + s);
316
for (int i = low; i <= n1; i++) {
317
H[i][i] -= s;
318
}
319
exshift += s;
320
x = y = w = 0.964;
321
}
322
}
323
324
iter = iter + 1; // (Could check iteration count here.)
325
326
// Look for two consecutive small sub-diagonal elements
327
int m = n1 - 2;
328
while (m >= l) {
329
z = H[m][m];
330
r = x - z;
331
s = y - z;
332
p = (r * s - w) / H[m + 1][m] + H[m][m + 1];
333
q = H[m + 1][m + 1] - z - r - s;
334
r = H[m + 2][m + 1];
335
s = std::abs(p) + std::abs(q) + std::abs(r);
336
p = p / s;
337
q = q / s;
338
r = r / s;
339
if (m == l) {
340
break;
341
}
342
if (std::abs(H[m][m - 1]) * (std::abs(q) + std::abs(r)) < eps * (std::abs(p)
343
* (std::abs(H[m - 1][m - 1]) + std::abs(z) + std::abs(
344
H[m + 1][m + 1])))) {
345
break;
346
}
347
m--;
348
}
349
350
for (int i = m + 2; i <= n1; i++) {
351
H[i][i - 2] = 0.0;
352
if (i > m + 2) {
353
H[i][i - 3] = 0.0;
354
}
355
}
356
357
// Double QR step involving rows l:n and columns m:n
358
359
for (int k = m; k <= n1 - 1; k++) {
360
bool notlast = (k != n1 - 1);
361
if (k != m) {
362
p = H[k][k - 1];
363
q = H[k + 1][k - 1];
364
r = (notlast ? H[k + 2][k - 1] : 0.0);
365
x = std::abs(p) + std::abs(q) + std::abs(r);
366
if (x != 0.0) {
367
p = p / x;
368
q = q / x;
369
r = r / x;
370
}
371
}
372
if (x == 0.0) {
373
break;
374
}
375
s = std::sqrt(p * p + q * q + r * r);
376
if (p < 0) {
377
s = -s;
378
}
379
if (s != 0) {
380
if (k != m) {
381
H[k][k - 1] = -s * x;
382
} else if (l != m) {
383
H[k][k - 1] = -H[k][k - 1];
384
}
385
p = p + s;
386
x = p / s;
387
y = q / s;
388
z = r / s;
389
q = q / p;
390
r = r / p;
391
392
// Row modification
393
394
for (int j = k; j < nn; j++) {
395
p = H[k][j] + q * H[k + 1][j];
396
if (notlast) {
397
p = p + r * H[k + 2][j];
398
H[k + 2][j] = H[k + 2][j] - p * z;
399
}
400
H[k][j] = H[k][j] - p * x;
401
H[k + 1][j] = H[k + 1][j] - p * y;
402
}
403
404
// Column modification
405
406
for (int i = 0; i <= std::min(n1, k + 3); i++) {
407
p = x * H[i][k] + y * H[i][k + 1];
408
if (notlast) {
409
p = p + z * H[i][k + 2];
410
H[i][k + 2] = H[i][k + 2] - p * r;
411
}
412
H[i][k] = H[i][k] - p;
413
H[i][k + 1] = H[i][k + 1] - p * q;
414
}
415
416
// Accumulate transformations
417
418
for (int i = low; i <= high; i++) {
419
p = x * V[i][k] + y * V[i][k + 1];
420
if (notlast) {
421
p = p + z * V[i][k + 2];
422
V[i][k + 2] = V[i][k + 2] - p * r;
423
}
424
V[i][k] = V[i][k] - p;
425
V[i][k + 1] = V[i][k + 1] - p * q;
426
}
427
} // (s != 0)
428
} // k loop
429
} // check convergence
430
} // while (n1 >= low)
431
432
// Backsubstitute to find vectors of upper triangular form
433
434
if (norm == 0.0) {
435
return;
436
}
437
438
for (n1 = nn - 1; n1 >= 0; n1--) {
439
p = d[n1];
440
q = e[n1];
441
442
// Real vector
443
444
if (q == 0) {
445
int l = n1;
446
H[n1][n1] = 1.0;
447
for (int i = n1 - 1; i >= 0; i--) {
448
w = H[i][i] - p;
449
r = 0.0;
450
for (int j = l; j <= n1; j++) {
451
r = r + H[i][j] * H[j][n1];
452
}
453
if (e[i] < 0.0) {
454
z = w;
455
s = r;
456
} else {
457
l = i;
458
if (e[i] == 0.0) {
459
if (w != 0.0) {
460
H[i][n1] = -r / w;
461
} else {
462
H[i][n1] = -r / (eps * norm);
463
}
464
465
// Solve real equations
466
467
} else {
468
x = H[i][i + 1];
469
y = H[i + 1][i];
470
q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
471
t = (x * s - z * r) / q;
472
H[i][n1] = t;
473
if (std::abs(x) > std::abs(z)) {
474
H[i + 1][n1] = (-r - w * t) / x;
475
} else {
476
H[i + 1][n1] = (-s - y * t) / z;
477
}
478
}
479
480
// Overflow control
481
482
t = std::abs(H[i][n1]);
483
if ((eps * t) * t > 1) {
484
for (int j = i; j <= n1; j++) {
485
H[j][n1] = H[j][n1] / t;
486
}
487
}
488
}
489
}
490
// Complex vector
491
} else if (q < 0) {
492
int l = n1 - 1;
493
494
// Last vector component imaginary so matrix is triangular
495
496
if (std::abs(H[n1][n1 - 1]) > std::abs(H[n1 - 1][n1])) {
497
H[n1 - 1][n1 - 1] = q / H[n1][n1 - 1];
498
H[n1 - 1][n1] = -(H[n1][n1] - p) / H[n1][n1 - 1];
499
} else {
500
cdiv(0.0, -H[n1 - 1][n1], H[n1 - 1][n1 - 1] - p, q);
501
H[n1 - 1][n1 - 1] = cdivr;
502
H[n1 - 1][n1] = cdivi;
503
}
504
H[n1][n1 - 1] = 0.0;
505
H[n1][n1] = 1.0;
506
for (int i = n1 - 2; i >= 0; i--) {
507
double ra, sa;
508
ra = 0.0;
509
sa = 0.0;
510
for (int j = l; j <= n1; j++) {
511
ra = ra + H[i][j] * H[j][n1 - 1];
512
sa = sa + H[i][j] * H[j][n1];
513
}
514
w = H[i][i] - p;
515
516
if (e[i] < 0.0) {
517
z = w;
518
r = ra;
519
s = sa;
520
} else {
521
l = i;
522
if (e[i] == 0) {
523
cdiv(-ra, -sa, w, q);
524
H[i][n1 - 1] = cdivr;
525
H[i][n1] = cdivi;
526
} else {
527
528
// Solve complex equations
529
530
x = H[i][i + 1];
531
y = H[i + 1][i];
532
double vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
533
double vi = (d[i] - p) * 2.0 * q;
534
if (vr == 0.0 && vi == 0.0) {
535
vr = eps * norm * (std::abs(w) + std::abs(q) + std::abs(x)
536
+ std::abs(y) + std::abs(z));
537
}
538
cdiv(x * r - z * ra + q * sa,
539
x * s - z * sa - q * ra, vr, vi);
540
H[i][n1 - 1] = cdivr;
541
H[i][n1] = cdivi;
542
if (std::abs(x) > (std::abs(z) + std::abs(q))) {
543
H[i + 1][n1 - 1] = (-ra - w * H[i][n1 - 1] + q
544
* H[i][n1]) / x;
545
H[i + 1][n1] = (-sa - w * H[i][n1] - q * H[i][n1
546
- 1]) / x;
547
} else {
548
cdiv(-r - y * H[i][n1 - 1], -s - y * H[i][n1], z,
549
q);
550
H[i + 1][n1 - 1] = cdivr;
551
H[i + 1][n1] = cdivi;
552
}
553
}
554
555
// Overflow control
556
557
t = std::max(std::abs(H[i][n1 - 1]), std::abs(H[i][n1]));
558
if ((eps * t) * t > 1) {
559
for (int j = i; j <= n1; j++) {
560
H[j][n1 - 1] = H[j][n1 - 1] / t;
561
H[j][n1] = H[j][n1] / t;
562
}
563
}
564
}
565
}
566
}
567
}
568
569
// Vectors of isolated roots
570
571
for (int i = 0; i < nn; i++) {
572
if (i < low || i > high) {
573
for (int j = i; j < nn; j++) {
574
V[i][j] = H[i][j];
575
}
576
}
577
}
578
579
// Back transformation to get eigenvectors of original matrix
580
581
for (int j = nn - 1; j >= low; j--) {
582
for (int i = low; i <= high; i++) {
583
z = 0.0;
584
for (int k = low; k <= std::min(j, high); k++) {
585
z = z + V[i][k] * H[k][j];
586
}
587
V[i][j] = z;
588
}
589
}
590
}
591
592
// Nonsymmetric reduction to Hessenberg form.
593
void orthes() {
594
// This is derived from the Algol procedures orthes and ortran,
595
// by Martin and Wilkinson, Handbook for Auto. Comp.,
596
// Vol.ii-Linear Algebra, and the corresponding
597
// Fortran subroutines in EISPACK.
598
int low = 0;
599
int high = n - 1;
600
601
for (int m = low + 1; m <= high - 1; m++) {
602
603
// Scale column.
604
605
double scale = 0.0;
606
for (int i = m; i <= high; i++) {
607
scale = scale + std::abs(H[i][m - 1]);
608
}
609
if (scale != 0.0) {
610
611
// Compute Householder transformation.
612
613
double h = 0.0;
614
for (int i = high; i >= m; i--) {
615
ort[i] = H[i][m - 1] / scale;
616
h += ort[i] * ort[i];
617
}
618
double g = std::sqrt(h);
619
if (ort[m] > 0) {
620
g = -g;
621
}
622
h = h - ort[m] * g;
623
ort[m] = ort[m] - g;
624
625
// Apply Householder similarity transformation
626
// H = (I-u*u'/h)*H*(I-u*u')/h)
627
628
for (int j = m; j < n; j++) {
629
double f = 0.0;
630
for (int i = high; i >= m; i--) {
631
f += ort[i] * H[i][j];
632
}
633
f = f / h;
634
for (int i = m; i <= high; i++) {
635
H[i][j] -= f * ort[i];
636
}
637
}
638
639
for (int i = 0; i <= high; i++) {
640
double f = 0.0;
641
for (int j = high; j >= m; j--) {
642
f += ort[j] * H[i][j];
643
}
644
f = f / h;
645
for (int j = m; j <= high; j++) {
646
H[i][j] -= f * ort[j];
647
}
648
}
649
ort[m] = scale * ort[m];
650
H[m][m - 1] = scale * g;
651
}
652
}
653
654
// Accumulate transformations (Algol's ortran).
655
656
for (int i = 0; i < n; i++) {
657
for (int j = 0; j < n; j++) {
658
V[i][j] = (i == j ? 1.0 : 0.0);
659
}
660
}
661
662
for (int m = high - 1; m >= low + 1; m--) {
663
if (H[m][m - 1] != 0.0) {
664
for (int i = m + 1; i <= high; i++) {
665
ort[i] = H[i][m - 1];
666
}
667
for (int j = m; j <= high; j++) {
668
double g = 0.0;
669
for (int i = m; i <= high; i++) {
670
g += ort[i] * V[i][j];
671
}
672
// Double division avoids possible underflow
673
g = (g / ort[m]) / H[m][m - 1];
674
for (int i = m; i <= high; i++) {
675
V[i][j] += g * ort[i];
676
}
677
}
678
}
679
}
680
}
681
682
// Releases all internal working memory.
683
void release() {
684
// releases the working data
685
delete[] d;
686
delete[] e;
687
delete[] ort;
688
for (int i = 0; i < n; i++) {
689
delete[] H[i];
690
delete[] V[i];
691
}
692
delete[] H;
693
delete[] V;
694
}
695
696
// Computes the Eigenvalue Decomposition for a matrix given in H.
697
void compute() {
698
// Allocate memory for the working data.
699
V = alloc_2d<double> (n, n, 0.0);
700
d = alloc_1d<double> (n);
701
e = alloc_1d<double> (n);
702
ort = alloc_1d<double> (n);
703
// Reduce to Hessenberg form.
704
orthes();
705
// Reduce Hessenberg to real Schur form.
706
hqr2();
707
// Copy eigenvalues to OpenCV Matrix.
708
_eigenvalues.create(1, n, CV_64FC1);
709
for (int i = 0; i < n; i++) {
710
_eigenvalues.at<double> (0, i) = d[i];
711
}
712
// Copy eigenvectors to OpenCV Matrix.
713
_eigenvectors.create(n, n, CV_64FC1);
714
for (int i = 0; i < n; i++)
715
for (int j = 0; j < n; j++)
716
_eigenvectors.at<double> (i, j) = V[i][j];
717
// Deallocate the memory by releasing all internal working data.
718
release();
719
}
720
721
public:
722
EigenvalueDecomposition()
723
: n(0), cdivr(0), cdivi(0), d(0), e(0), ort(0), V(0), H(0) {}
724
725
// Initializes & computes the Eigenvalue Decomposition for a general matrix
726
// given in src. This function is a port of the EigenvalueSolver in JAMA,
727
// which has been released to public domain by The MathWorks and the
728
// National Institute of Standards and Technology (NIST).
729
EigenvalueDecomposition(InputArray src) {
730
compute(src);
731
}
732
733
// This function computes the Eigenvalue Decomposition for a general matrix
734
// given in src. This function is a port of the EigenvalueSolver in JAMA,
735
// which has been released to public domain by The MathWorks and the
736
// National Institute of Standards and Technology (NIST).
737
void compute(InputArray src)
738
{
739
/*if(isSymmetric(src)) {
740
// Fall back to OpenCV for a symmetric matrix!
741
cv::eigen(src, _eigenvalues, _eigenvectors);
742
} else {*/
743
Mat tmp;
744
// Convert the given input matrix to double. Is there any way to
745
// prevent allocating the temporary memory? Only used for copying
746
// into working memory and deallocated after.
747
src.getMat().convertTo(tmp, CV_64FC1);
748
// Get dimension of the matrix.
749
this->n = tmp.cols;
750
// Allocate the matrix data to work on.
751
this->H = alloc_2d<double> (n, n);
752
// Now safely copy the data.
753
for (int i = 0; i < tmp.rows; i++) {
754
for (int j = 0; j < tmp.cols; j++) {
755
this->H[i][j] = tmp.at<double>(i, j);
756
}
757
}
758
// Deallocates the temporary matrix before computing.
759
tmp.release();
760
// Performs the eigenvalue decomposition of H.
761
compute();
762
// }
763
}
764
765
~EigenvalueDecomposition() {}
766
767
// Returns the eigenvalues of the Eigenvalue Decomposition.
768
Mat eigenvalues() { return _eigenvalues; }
769
// Returns the eigenvectors of the Eigenvalue Decomposition.
770
Mat eigenvectors() { return _eigenvectors; }
771
};
772
773
#endif // DLS_H
774
775