Преобразование cv::mat в QImage с помощью QImage::loadFromData

Нашел похожие темы, но не эту. Есть идеи, что не так со следующим кодом? Он возвращает «loaded=false», что, очевидно, означает, что данные изображения не могут быть загружены.

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");

Спасибо!


person ichos    schedule 02.10.2013    source источник
comment
Вы можете использовать реализацию с открытым исходным кодом в отношении проблемы преобразования qimage-cv::mat: github.com/dbzhang800/QtOpenCV/blob/master/cvmatandqimage.cpp. Удачи.   -  person baci    schedule 03.10.2013


Ответы (1)


Тип cv::Mat содержит декодированное изображение. Таким образом, вы не можете попросить QImage снова декодировать его, используя метод loadFromData().

Вам нужно настроить изображение с форматом, соответствующим типу элемента, полученному с помощью Mat::type(), затем либо скопировать необработанные данные из матрицы в изображение, либо настроить заголовок QImage для данных. В терминологии OpenCV «заголовок» означает объект, который не содержит собственных данных.

Код ниже устанавливает заголовок 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

Может быть проще загрузить изображение с помощью QImage, а затем создать для него матрицу заголовков.

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
person Kuba hasn't forgotten Monica    schedule 02.10.2013
comment
Спасибо за эту информацию! Мне удалось загрузить изображение с помощью конструктора QImage, аналогичного тому, что вы предложили: но я хотел использовать метод loadFromData(). - person ichos; 04.10.2013
comment
Вы не можете использовать loadFromData(), так как он не делает то, что вы хотите. То, что вы хотите, если вы действительно хотите сделать QImage копию Mat, в значительной степени является memcpy в bits(). - person Kuba hasn't forgotten Monica; 04.10.2013
comment
Небольшая опечатка на карте: CV8_UC4 должен быть CV_8UC4. Простой вопрос: как будет выглядеть перевернутая карта, как увидеть разницу в 0xrrggbb и 0xrrggbb. - person Patrick Z; 09.02.2021