Yalantis/uCrop · error · CImgInstanceException

eigen(): Instance is not a square matrix.

Error message

eigen(): Instance is not a square matrix.

What it means

CImg::eigen() computes eigenvalues and eigenvectors of the image viewed as a matrix, which requires a non-empty, single-channel 2D square matrix (_width==_height, _depth<=1, _spectrum<=1). It throws CImgInstanceException when a non-square or multi-channel/volumetric instance is passed.

Source

Thrown at ucrop/src/main/jni/CImg.h:33147

    }

    //! Solve a tridiagonal system of linear equations \newinstance.
    template<typename t>
    CImg<_cimg_Ttfloat> get_solve_tridiagonal(const CImg<t>& A) const {
      return CImg<_cimg_Ttfloat>(*this,false).solve_tridiagonal(A);
    }

    //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix.
    /**
       \param[out] val Vector of the estimated eigenvalues, in decreasing order.
       \param[out] vec Matrix of the estimated eigenvectors, sorted by columns.
    **/
    template<typename t>
    const CImg<T>& eigen(CImg<t>& val, CImg<t> &vec) const {
      if (is_empty()) { val.assign(); vec.assign(); }
      else {
        if (_width!=_height || _depth>1 || _spectrum>1)
          throw CImgInstanceException(_cimg_instance
                                      "eigen(): Instance is not a square matrix.",
                                      cimg_instance);

        if (val.size()<(ulongT)_width) val.assign(1,_width);
        if (vec.size()<(ulongT)_width*_width) vec.assign(_width,_width);
        switch (_width) {
        case 1 : { val[0] = (t)(*this)[0]; vec[0] = (t)1; } break;
        case 2 : {
          const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a + d;
          double f = e*e - 4*(a*d - b*c);
          if (f<0) cimg::warn(_cimg_instance
                              "eigen(): Complex eigenvalues found.",
                              cimg_instance);
          f = std::sqrt(f);
          const double
            l1 = 0.5*(e - f),
            l2 = 0.5*(e + f),
            b2 = b*b,

View on GitHub (pinned to f788b534b4)

Solutions

  1. Ensure the instance is square: img.assign(n,n,1,1).
  2. Extract a channel/plane first: img.get_channel(0).eigen(val,vec).
  3. For non-square matrices, use SVD instead: img.get_SVD(U,S,V) or symmetric_eigen() for square symmetric matrices.

Example fix

// before
CImg<float> m(4,5); // non-square -> throws
m.eigen(val,vec);
// after
CImg<float> m(5,5);
if (m.width()==m.height() && m.depth()<=1 && m.spectrum()<=1)
  m.eigen(val,vec);
Defensive patterns

Strategy: validation

Validate before calling

if (!img.is_empty() && img.width()==img.height() && img.depth()<=1 && img.spectrum()<=1) img.eigen(val, vec);

Type guard

bool isSquareMatrix(const CImg<T>& m){ return !m.is_empty() && m.width()==m.height() && m.depth()<=1 && m.spectrum()<=1; }

Try / catch

try { img.eigen(val, vec); } catch (CImgInstanceException& e) { std::cerr << e.what() << '\n'; }

Prevention

When it happens

Trigger: Calling img.eigen(val,vec) on a rectangular matrix, on a color image (spectrum>1), or on volumetric data (depth>1).

Common situations: Computing eigen-decompositions of covariance images that came out rectangular; passing an RGB image instead of a channel; using eigen() on symmetric-input assumptions but giving non-square data.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/7de1d30203f33ff5. Report an issue: GitHub.