Чтение изображения из qrc с помощью imread () из OpenCV

Я хочу прочитать изображение с QRC с помощью imread() OpenCV таким образом:

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

но последний img размер [0x0]. Я также попробовал:

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

но размер, который я получаю, такой же. Я не хочу загружать изображение в QImage затем преобразовать его в cv::Mat, Есть ли способ сделать это простым способом? Если это так, как я могу это сделать?

Спасибо

6

Решение

Как отметил @TheDarkKnight, imread не знает о ресурсах Qt. Однако вы можете написать свой собственный погрузчик, который использует QFile извлекать двоичные данные из ресурса и использует imdecode (как сделано внутри imread) читать изображение:

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;
}

Вы можете назвать это как:

Mat m = loadFromQrc("qrc_path");

или указав флаг:

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

Спектакль

Я попытался загрузить изображение с loadFromQrcи загрузка QImage и преобразование в Mat с помощью этот код, как с клонированием, так и без него. loadFromQrc результаты будут в 10 раз быстрее, чем загрузка QImage и преобразовать его в Mat,

Результаты в мс:

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

Тестовый код:

#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;
}
8

Другие решения

Проблема здесь в том, что imread() загружает изображение из файла.

Напротив, система ресурсов Qt компилирует данные из изображений непосредственно в исполняемый файл программы. механизм Qt QFile Операции знают, что когда им предоставляется путь, начинающийся с «: /», он ссылается на встроенные ресурсы, а не на диск.

Поэтому я не думаю, что вы сможете использовать imread() для прямого доступа к файлу, который был помещен в ресурсы Qt.

2

По вопросам рекламы [email protected]