File indexing completed on 2025-03-09 03:55:00
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 17-8-2016 0007 * Description : Some matrix utility functions including singular value 0008 * decomposition, inverse, and pseudo-inverse. 0009 * 0010 * SPDX-FileCopyrightText: 2016 by Omar Amin <Omar dot moh dot amin at gmail dot com> 0011 * SPDX-FileCopyrightText: 2019 by Thanh Trung Dinh <dinhthanhtrung1996 at gmail dot com> 0012 * SPDX-FileCopyrightText: 2016-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #include "matrixoperations.h" 0019 0020 // Qt includes 0021 0022 #include <QtGlobal> 0023 0024 namespace Digikam 0025 { 0026 0027 namespace MatrixOperations 0028 { 0029 0030 std::vector<std::vector<float> > inv2(const std::vector<std::vector<float> >& mat) 0031 { 0032 Q_ASSERT((mat.size() == 2) && (mat[0].size() == 2)); 0033 0034 std::vector<std::vector<float> > m(2,std::vector<float>(2, 0)); 0035 0036 float det = mat[0][0]*mat[1][1] - 0037 mat[0][1]*mat[1][0]; 0038 0039 Q_ASSERT(det != 0); 0040 0041 m[0][0] = mat[1][1] / det; 0042 m[0][1] = -mat[0][1] / det; 0043 m[1][0] = -mat[1][0] / det; 0044 m[1][1] = mat[0][0] / det; 0045 0046 return m; 0047 } 0048 0049 std::vector<std::vector<float> > pinv(const std::vector<std::vector<float> >& mat) 0050 { 0051 std::vector<std::vector<float> > result(mat[0].size(), std::vector<float>(mat.size())); 0052 cv::Mat B((int)mat[0].size(), (int)mat.size(), CV_32FC1); 0053 cv::Mat A((int)mat.size(), (int)mat[0].size(), CV_32FC1); 0054 0055 for (unsigned int i = 0 ; i < mat.size() ; ++i) 0056 { 0057 for (unsigned int j = 0 ; j < mat[0].size() ; ++j) 0058 { 0059 A.at<float>(i, j) = mat[i][j]; 0060 } 0061 } 0062 0063 cv::invert(A, B, cv::DECOMP_SVD); 0064 0065 for (int i = 0 ; i < B.rows ; ++i) 0066 { 0067 for (int j = 0 ; j < B.cols ; ++j) 0068 { 0069 result[i][j] = B.at<float>(i, j); 0070 } 0071 } 0072 0073 return result; 0074 } 0075 0076 void stdmattocvmat(const std::vector<std::vector<float> >& src, cv::Mat& dst) 0077 { 0078 for (unsigned int i = 0 ; i < src.size() ; ++i) 0079 { 0080 for (unsigned int j = 0 ; j < src[0].size() ; ++j) 0081 { 0082 dst.at<float>(i, j) = src[i][j]; 0083 } 0084 } 0085 } 0086 0087 void cvmattostdmat(const cv::Mat& dst, std::vector<std::vector<float> >& src) 0088 { 0089 for (unsigned int i = 0 ; i < src.size() ; ++i) 0090 { 0091 for (unsigned int j = 0 ; j < src[0].size() ; ++j) 0092 { 0093 src[i][j] = dst.at<float>(i, j); 0094 } 0095 } 0096 } 0097 0098 void transpose(std::vector<std::vector<float> >& src, 0099 std::vector<std::vector<float> >& dst) 0100 { 0101 for (unsigned int i = 0 ; i < src.size() ; ++i) 0102 { 0103 for (unsigned int j = 0 ; j < src[0].size() ; ++j) 0104 { 0105 dst[i][j] = src[j][i]; 0106 } 0107 } 0108 0109 } 0110 0111 float trace(const std::vector<std::vector<float> >& src) 0112 { 0113 float result = 0.0F; 0114 0115 for (unsigned int i = 0 ; i < src.size() ; ++i) 0116 { 0117 for (unsigned int j = 0 ; j < src[0].size() ; ++j) 0118 { 0119 if (i == j) 0120 { 0121 result += src[i][i]; 0122 } 0123 } 0124 } 0125 0126 return result; 0127 } 0128 0129 bool svd3(std::vector<std::vector<float> >& a, 0130 std::vector<float >& w, 0131 std::vector<std::vector<float> >& v, 0132 std::vector<float >& rv1) 0133 { 0134 const float one = 1.0F; 0135 const long max_iter = 300; 0136 0137 // a is a square matrix 0138 0139 // columns 0140 0141 const long n = (long)a.size(); 0142 0143 // rows 0144 0145 const long m = (long)a.size(); 0146 0147 const float eps = std::numeric_limits<float>::epsilon(); 0148 long nm = 0; 0149 long l = 0; 0150 float g = 0.0F; 0151 float scale = 0.0F; 0152 float anorm = 0.0F; 0153 bool flag = false; 0154 float c = 0.0F; 0155 float f = 0.0F; 0156 float h = 0.0F; 0157 float s = 0.0F; 0158 float x = 0.0F; 0159 float y = 0.0F; 0160 float z = 0.0F; 0161 0162 for (long i = 0 ; i < n ; ++i) 0163 { 0164 l = i + 1; 0165 rv1[i] = scale * g; 0166 g = 0.0F; 0167 s = 0.0F; 0168 scale = 0.0F; 0169 0170 if (i < m) 0171 { 0172 for (long k = i ; k < m ; ++k) 0173 { 0174 scale += std::abs(a[k][i]); 0175 } 0176 0177 if (scale) 0178 { 0179 for (long k = i ; k < m ; ++k) 0180 { 0181 a[k][i] /= scale; 0182 s += a[k][i] * a[k][i]; 0183 } 0184 0185 f = a[i][i]; 0186 g = -signdlib(std::sqrt(s), f); 0187 h = f * g - s; 0188 a[i][i] = f - g; 0189 0190 for (long j = l ; j < n ; ++j) 0191 { 0192 s = 0.0; 0193 0194 for (long k = i ; k < m ; ++k) 0195 { 0196 s += a[k][i] * a[k][j]; 0197 } 0198 0199 f = s / h; 0200 0201 for (long k = i ; k < m ; ++k) 0202 { 0203 a[k][j] += f * a[k][i]; 0204 } 0205 } 0206 0207 for (long k = i ; k < m ; ++k) 0208 { 0209 a[k][i] *= scale; 0210 } 0211 } 0212 } 0213 0214 w[i] = scale * g; 0215 g = 0.0F; 0216 s = 0.0F; 0217 scale = 0.0F; 0218 0219 if ((i < m) && (i < n-1)) 0220 { 0221 for (long k = l ; k < n ; ++k) 0222 { 0223 scale += std::abs(a[i][k]); 0224 } 0225 0226 if (scale) 0227 { 0228 for (long k = l ; k < n ; ++k) 0229 { 0230 a[i][k] /= scale; 0231 s += a[i][k] * a[i][k]; 0232 } 0233 0234 f = a[i][l]; 0235 g = -signdlib(std::sqrt(s), f); 0236 h = f * g - s; 0237 a[i][l] = f - g; 0238 0239 for (long k = l ; k < n ; ++k) 0240 { 0241 rv1[k] = a[i][k] / h; 0242 } 0243 0244 for (long j = l ; j < m ; ++j) 0245 { 0246 s = 0.0; 0247 0248 for (long k = l; k < n; ++k) 0249 { 0250 s += a[j][k] * a[i][k]; 0251 } 0252 0253 for (long k = l; k < n; ++k) 0254 { 0255 a[j][k] += s * rv1[k]; 0256 } 0257 } 0258 0259 for (long k = l ; k < n ; ++k) 0260 { 0261 a[i][k] *= scale; 0262 } 0263 } 0264 } 0265 0266 anorm = std::max(anorm, (std::abs(w[i]) + std::abs(rv1[i]))); 0267 } 0268 0269 for (long i = n-1 ; i >= 0 ; --i) 0270 { 0271 if (i < (n-1)) 0272 { 0273 if (g != 0.0F) 0274 { 0275 for (long j = l ; j < n ; ++j) 0276 { 0277 v[j][i] = (a[i][j] / a[i][l]) / g; 0278 } 0279 0280 for (long j = l ; j < n ; ++j) 0281 { 0282 s = 0.0F; 0283 0284 for (long k = l ; k < n ; ++k) 0285 { 0286 s += a[i][k] * v[k][j]; 0287 } 0288 0289 for (long k = l ; k < n ; ++k) 0290 { 0291 v[k][j] += s*v[k][i]; 0292 } 0293 } 0294 } 0295 0296 for (long j = l ; j < n ; ++j) 0297 { 0298 v[i][j] = v[j][i] = 0.0; 0299 } 0300 } 0301 0302 v[i][i] = 1.0; 0303 g = rv1[i]; 0304 l = i; 0305 } 0306 0307 for (long i = std::min(m,n) - 1 ; i >= 0 ; --i) 0308 { 0309 l = i + 1; 0310 g = w[i]; 0311 0312 for (long j = l ; j < n ; ++j) 0313 { 0314 a[i][j] = 0.0; 0315 } 0316 0317 if (g != 0) 0318 { 0319 g = 1.0F / g; 0320 0321 for (long j = l ; j < n ; ++j) 0322 { 0323 s = 0.0; 0324 0325 for (long k = l ; k < m ; ++k) 0326 { 0327 s += a[k][i] * a[k][j]; 0328 } 0329 0330 f = (s / a[i][i]) * g; 0331 0332 for (long k = i ; k < m ; ++k) 0333 { 0334 a[k][j] += f * a[k][i]; 0335 } 0336 } 0337 0338 for (long j = i ; j < m ; ++j) 0339 { 0340 a[j][i] *= g; 0341 } 0342 } 0343 else 0344 { 0345 for (long j = i ; j < m ; ++j) 0346 { 0347 a[j][i] = 0.0; 0348 } 0349 } 0350 0351 ++a[i][i]; 0352 } 0353 0354 for (long k = n-1 ; k >= 0 ; --k) 0355 { 0356 for (long its = 1 ; its <= max_iter ; ++its) 0357 { 0358 flag = true; 0359 0360 for (l = k ; l >= 1 ; --l) 0361 { 0362 nm = l - 1; 0363 0364 if (std::abs(rv1[l]) <= (eps * anorm)) 0365 { 0366 flag = false; 0367 break; 0368 } 0369 0370 if (std::abs(w[nm]) <= (eps * anorm)) 0371 { 0372 break; 0373 } 0374 } 0375 0376 if (flag) 0377 { 0378 c = 0.0F; 0379 s = 1.0F; 0380 0381 for (long i = l ; i <= k ; ++i) 0382 { 0383 f = s * rv1[i]; 0384 rv1[i] = c * rv1[i]; 0385 0386 if (std::abs(f) <= (eps * anorm)) 0387 { 0388 break; 0389 } 0390 0391 g = w[i]; 0392 h = pythag(f, g); 0393 w[i] = h; 0394 h = 1.0F / h; 0395 c = g * h; 0396 s = -f * h; 0397 0398 for (long j = 0 ; j < m ; ++j) 0399 { 0400 y = a[j][nm]; 0401 z = a[j][i]; 0402 a[j][nm] = y * c + z * s; 0403 a[j][i] = z * c - y * s; 0404 } 0405 } 0406 } 0407 0408 z = w[k]; 0409 0410 if (l == k) 0411 { 0412 if (z < 0.0) 0413 { 0414 w[k] = -z; 0415 0416 for (long j = 0 ; j < n ; ++j) 0417 { 0418 v[j][k] = -v[j][k]; 0419 } 0420 } 0421 0422 break; 0423 } 0424 0425 if (its == max_iter) 0426 { 0427 return false; 0428 } 0429 0430 x = w[l]; 0431 nm = k - 1; 0432 y = w[nm]; 0433 g = rv1[nm]; 0434 h = rv1[k]; 0435 f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0F * h * y); 0436 g = pythag(f, one); 0437 f = ((x - z) * (x + z) + h * ((y / (f + signdlib(g, f))) - h)) / x; 0438 c = s = 1.0; 0439 0440 for (long j = l ; j <= nm ; ++j) 0441 { 0442 long i = j + 1; 0443 g = rv1[i]; 0444 y = w[i]; 0445 h = s * g; 0446 g = c * g; 0447 z = pythag(f, h); 0448 rv1[j] = z; 0449 c = f/z; 0450 s = h/z; 0451 f = x*c + g*s; 0452 g = g*c - x*s; 0453 h = y*s; 0454 y *= c; 0455 0456 for (long jj = 0 ; jj < n ; ++jj) 0457 { 0458 x = v[jj][j]; 0459 z = v[jj][i]; 0460 v[jj][j] = x*c + z*s; 0461 v[jj][i] = z*c - x*s; 0462 } 0463 0464 z = pythag(f,h); 0465 w[j] = z; 0466 0467 if (z != 0) 0468 { 0469 z = 1.0F / z; 0470 c = f * z; 0471 s = h * z; 0472 } 0473 0474 f = c*g + s*y; 0475 x = c*y - s*g; 0476 0477 for (long jj = 0 ; jj < m ; ++jj) 0478 { 0479 y = a[jj][j]; 0480 z = a[jj][i]; 0481 a[jj][j] = y*c + z*s; 0482 a[jj][i] = z*c - y*s; 0483 } 0484 } 0485 0486 rv1[l] = 0.0; 0487 rv1[k] = f; 0488 w[k] = x; 0489 } 0490 } 0491 0492 return true; 0493 } 0494 0495 void svd(const std::vector<std::vector<float> >& m, 0496 std::vector<std::vector<float> >& u, 0497 std::vector<std::vector<float> >& w, 0498 std::vector<std::vector<float> >& v) 0499 { 0500 0501 // initialization 0502 0503 u.resize(2); 0504 w.resize(2); 0505 v.resize(2); 0506 0507 for (unsigned int i = 0 ; i < 2 ; ++i) 0508 { 0509 0510 u[i].resize(2); 0511 w[i].resize(2); 0512 v[i].resize(2); 0513 0514 for (unsigned int j = 0 ; j < 2 ; ++j) 0515 { 0516 u[i][j] = m[i][j]; 0517 } 0518 } 0519 0520 std::vector<float> W(2); 0521 std::vector<float> rv1(2); 0522 svd3(u, W, v, rv1); 0523 0524 // get w from W 0525 0526 for (unsigned int i = 0 ; i < 2 ; ++i) 0527 { 0528 for (unsigned int j = 0 ; j < 2 ; ++j) 0529 { 0530 if (i == j) 0531 { 0532 w[i][j] = W[i]; 0533 } 0534 else 0535 { 0536 w[i][j] = 0.0; 0537 } 0538 } 0539 } 0540 } 0541 0542 float determinant(const std::vector<std::vector<float> >& u) 0543 { 0544 float result = u[0][0]*u[1][1] - u[1][0]*u[0][1]; 0545 0546 return result; 0547 } 0548 0549 } // namespace MatrixOperations 0550 0551 } // namespace Digikam