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