Important: Please read the Qt Code of Conduct  https://forum.qt.io/topic/113070/qtcodeofconduct
convert Eigen MatrixXd to QImage

I want to convert matrixXd of Eigen to QImage(format, grayscale)。Here is my code, but the result is wrong. I am newer in QT and Eigen.
ObjWindow::ObjWindow(QWidget *parent) : QWidget(parent), ui(new Ui::ObjWindow) { ui>setupUi(this); int height = 100; int width = 100; Eigen::MatrixXd doubleM(height, width); for (int i = 0;i<height; i++) { for (int k = 0; k<width; k++) { if (i>=50) { doubleM(i, k) = 200; }; }; }; QImage xx = Eigen2QImage(doubleM); ui>label>setPixmap(QPixmap::fromImage(xx)); } QImage ObjWindow::Eigen2QImage(const MatrixXd &src) { double scale = 255.0; double max_value = src.maxCoeff(); double min_value = src.minCoeff(); QImage dest(src.cols(), src.rows(), QImage::Format_Grayscale8); for (int y = 0; y < src.rows(); ++y) { const double *src_row = src.row(y).data(); uchar * destrow = dest.scanLine(y); for (int x = 0; x < src.cols() ; ++x) { uchar gray = (uchar)(src_row[x] / max_value * 255); destrow[x] = gray; } } return dest; }

@hei6775 said in convert Eigen MatrixXd to QImage:
but the result is wrong.
This is no valid error description.
Apart from this  row is x (horizontal) in Qt (and maybe also in eigen I would guess)

The Image become:

@hei6775 said in convert Eigen MatrixXd to QImage:
Shouldn't you do modulo here:
uchar gray = (uchar)(src_row[x] / max_value % 255);
?

@jsulm error: invalid operands to binary expression ('double' and 'double'). modulo is invalid for double type.

@hei6775 Then fix it... c basics
What's the format of the eigen image? How must the gray value be interpreted / what's the range of it?

@ChristianEhrlicher double. Eigen::MatrixXd mean a matrix of dynamic size and double type.
The problem(@jsulm mentioned) is wrong direction.
I print the value ofsrc_row[x]
, this is incorrect value.// the first pixel in the loop qDebug() << src_row[x]; // output: // 1.05908e319

Eigen uses expression templates and lazyevaluation. You're taking a pointer to data contained in an rvalue here
src.row(y).data()
. Anything can be there after the object goes out of scope.

@hei6775 said in convert Eigen MatrixXd to QImage:
const double *src_row = src.row(y).data();
I think you should change this to:
const auto srcRow = src.row(y); const double *src_row = srcRow.data();
To not loose temporary container

@KroMignon said in convert Eigen MatrixXd to QImage:
I think you should change this to:
Yes, in principle, but you must not use
auto
withEigen
.

@KroMignon said in convert Eigen MatrixXd to QImage:
const auto srcRow = src.row(y);
const double *src_row = srcRow.data();This doesn't seem to work

@hei6775 said in convert Eigen MatrixXd to QImage:
This doesn't seem to work
Yes, in principle, but you must not use auto with Eigen.

@kshegunov said in convert Eigen MatrixXd to QImage:
Yes, in principle, but you must not use auto with Eigen.
What is the problem with
auto
andEigen
?
Can you explain more, I don't knowEigen
and always pleased to complete my knowledge about C++ :)

@KroMignon said in convert Eigen MatrixXd to QImage:
What is the problem with auto and Eigen?
I'm going to spare you my personal opinion on
auto
, but this is it:@kshegunov said in convert Eigen MatrixXd to QImage:
Eigen uses expression templates and lazyevaluation.
And here's a reference if you want to read even more: https://eigen.tuxfamily.org/dox/TopicPitfalls.html
In a nutshell Eigen builds up a sort of a parse tree from its methods and delays evaluation to the last possible moment. It has the advantage that it's really efficient to pack up complex expressions in a single pass, but doesn't play well withauto
, becauseauto
captures a type which isn't a real type, but rather an "evaluation step" type.

@kshegunov said in convert Eigen MatrixXd to QImage:
In a nutshell Eigen builds up a sort of a parse tree from its methods and delays evaluation to the last possible moment. It has the advantage that it's really efficient to pack up complex expressions in a single pass, but doesn't play well with auto, because auto captures a type which isn't a real type, or rather a "evaluation step" type.
Thanks for the link, so if I understand it right, there should be a call to
eval()
to ensure getting right type:
So this should then work?const auto srcRow = src.row(y).eval(); const double *src_row = srcRow.data();

@KroMignon said in convert Eigen MatrixXd to QImage:
Thanks for the link, so if I understand it right, there should be a call to eval() to ensure getting right type:
Not really. Instead of bending backwards to enforce compiletime type deduction, you just declare the type explicitly:
Eigen::VectorXd row = src.row(y);

@kshegunov Thanks, for now I never used Eigen, but when I will have to use it I will try to remember this pitfall :)

@KroMignon when i use
eval()
. It work. Thanks

@hei6775 said in convert Eigen MatrixXd to QImage:
when i use eval(). It work. Thanks
Yes it works, but as @kshegunov has written and as you can read it in documentation (https://eigen.tuxfamily.org/dox/TopicPitfalls.html), this not be the best way to do with
Eigen
.
It would be better to not useauto
but to specify right variable type like:const Eigen::VectorXd row = src.row(y); const double *src_row = srcRow.data();

@KroMignon yes, you are right! Thanks.