Reputation: 1
I’ve found similar topics but not this particular one. Any ideas what’s wrong with the following code? It returns ‘loaded=false’, which obviously means that image data cannot be loaded.
cv::Mat mymat;
QImage qimg;
mymat = cv::imread("C:\\testimages\\img1.png");
int len = mymat.total()*mymat.elemSize();
bool loaded = qimg.loadFromData((uchar*)mymat.data, len, "PNG");
Thank you!
Upvotes: 0
Views: 1214
Reputation: 98425
The cv::Mat
type holds a decoded image. Thus you cannot ask QImage
to decode it again using the loadFromData()
method.
You need to set up an image with format matching the element type, retrieved using Mat::type()
, then either copy the raw data from the matrix to the image, or set up a QImage
header for the data. In OpenCV terminology, a "header" means an object that doesn't hold its own data.
The code below sets up a header QImage
.
QMap<int, QImage::Format> fmtMap;
fmtMap.insert(CV8_UC4, QImage::Format_ARGB32);
fmtMap.insert(CV_8UC3, QImage::Format_RGB888)
// We should convert to a color image since 8-bit indexed images can't be painted on
cv::Mat mat = cv::imread("C:\\testimages\\img1.png", CV_LOAD_IMAGE_COLOR);
Q_ASSERT(fmtMap.contains(cvImage.type());
Q_ASSERT(mat.isContinuous());
QImage img(cvImage.data, cvImage.cols, cvImage.rows, fmtMap[cvImage.type()]);
// The matrix *must* outlive the image, otherwise the image will access a dangling pointer to data
It may be easier to load the image using QImage
, and then create a header matrix for it.
QMap<QImage::Format, int> fmtMap;
fmtMap.insert(QImage::Format_ARGB32, CV8_UC4);
fmtMap.insert(QImage::Format_RGB32, CV8_UC4);
fmtMap.insert(QImage::Format_RGB888, CV_8UC3);
QImage img;
img.load("C:\\testimages\\img1.png");
Q_ASSERT(fmtMap.contains(img.format()));
cv::Mat mat(img.height(), img.width(), fmtMap[img.format()], img.bits());
// The image *must* outlive the matrix, otherwise the matrix will access a dangling pointer to data
Upvotes: 1