Read image from qrc using imread () OpenCV

I want to read an image from qrc using imread() OpenCV as follows:

 Mat img = imread(":/TempIcons/logo.png"); 

but the final img size is [0x0]. I also tried:

 Mat img = imread("qrc://TempIcons/logo.png"); 

but the size that I get is the same. I do not want to load the image in QImage and then convert it to cv::Mat . Is there any way to make this easy ?. If so, how can I do this?

thanks

+6
source share
2 answers

As @TheDarkKnight noted, imread does not know Qt resources. However, you can write your own bootloader that uses QFile to extract binary data from the resource and uses imdecode (as done internally with imread ) to read the image:

 Mat loadFromQrc(QString qrc, int flag = IMREAD_COLOR) { //double tic = double(getTickCount()); QFile file(qrc); Mat m; if(file.open(QIODevice::ReadOnly)) { qint64 sz = file.size(); std::vector<uchar> buf(sz); file.read((char*)buf.data(), sz); m = imdecode(buf, flag); } //double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency(); //qDebug() << "OpenCV loading time: " << toc; return m; } 

You can call it like this:

 Mat m = loadFromQrc("qrc_path"); 

or by specifying a flag:

 Mat m = loadFromQrc("qrc_path", IMREAD_GRAYSCALE); 

Performance

I tried loading the image using loadFromQrc and loaded QImage and converted to Mat using this code, both with and without cloning. loadFromQrc result will be 10 times faster than loading QImage and convert it to Mat .

Results in ms:

 Load Mat : 4.85965 QImage to Mat (no clone): 49.3999 QImage to Mat (clone) : 49.8497 

Test code:

 #include <vector> #include <iostream> #include <QDebug> #include <QtWidgets> #include <opencv2/opencv.hpp> using namespace cv; Mat loadFromQrc(QString qrc, int flag = IMREAD_COLOR) { QFile file(qrc); Mat m; if(file.open(QIODevice::ReadOnly)) { qint64 sz = file.size(); std::vector<uchar> buf(sz); file.read((char*)buf.data(), sz); m = imdecode(buf, flag); } return m; } cv::Mat QImageToCvMat( const QImage &inImage, bool inCloneImageData = true ) { switch ( inImage.format() ) { // 8-bit, 4 channel case QImage::Format_RGB32: { cv::Mat mat( inImage.height(), inImage.width(), CV_8UC4, const_cast<uchar*>(inImage.bits()), inImage.bytesPerLine() ); return (inCloneImageData ? mat.clone() : mat); } // 8-bit, 3 channel case QImage::Format_RGB888: { if ( !inCloneImageData ) qWarning() << "ASM::QImageToCvMat() - Conversion requires cloning since we use a temporary QImage"; QImage swapped = inImage.rgbSwapped(); return cv::Mat( swapped.height(), swapped.width(), CV_8UC3, const_cast<uchar*>(swapped.bits()), swapped.bytesPerLine() ).clone(); } // 8-bit, 1 channel case QImage::Format_Indexed8: { cv::Mat mat( inImage.height(), inImage.width(), CV_8UC1, const_cast<uchar*>(inImage.bits()), inImage.bytesPerLine() ); return (inCloneImageData ? mat.clone() : mat); } default: qWarning() << "ASM::QImageToCvMat() - QImage format not handled in switch:" << inImage.format(); break; } return cv::Mat(); } int main(int argc, char *argv[]) { QString url = "..."; { double tic = double(getTickCount()); Mat m1 = loadFromQrc(url); double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency(); qDebug() << "Load Mat: " << toc; if(m1.data != NULL) { imshow("m1", m1); waitKey(1); } } // { // double tic = double(getTickCount()); // QImage img; // img.load(url); // Mat m2 = QImageToCvMat(img, false); // double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency(); // qDebug() << "QImage to Mat (no clone): " << toc; // if(m2.data != NULL) // { // imshow("m2", m2); // waitKey(1); // } // } // { // double tic = double(getTickCount()); // QImage img; // img.load(url); // Mat m3 = QImageToCvMat(img, true); // double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency(); // qDebug() << "QImage to Mat (clone): " << toc; // if(m3.data != NULL) // { // imshow("m3", m3); // waitKey(1); // } // } waitKey(); return 0; } 
+7
source

The problem is that imread() loads the image from the file.

In contrast, the Qt resource system compiles data from images directly into an executable program file . Qt QFile know that when they are given a path starting with ": /", it refers to built-in resources, not to disk.

Therefore, I do not think that you can use imread() to directly access the file that was placed in Qt resources.

+2
source

All Articles