2015-11-25 13 views
6

I mit imread() von OpenCV auf diese Weise ein Bild von einem qrc lesen möchten:ein Bild von einem qrc Lesen mit imread() von OpenCV

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

aber die endgültige img Größe ist [0x0] . Ich habe auch versucht:

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

aber die Größe, die ich bekomme, ist das gleiche. Ich möchte das Bild in QImage nicht laden, um es dann in cv::Mat zu transformieren. Gibt es eine Möglichkeit, dies auf einfache Weise zu tun? Wenn es ist, wie kann ich es tun ?.

Danke

+0

Hallo, vielen Dank für Ihren Vorschlag, aber ich habe auch schon versucht, aber dass ich von 'QFileInfo (" qrc erhalten ... . ") .filePath()' ist immer der gleiche Pfad: ": /TempIcons/logo.png" –

Antwort

7

Wie @TheDarkKnight wies darauf hin, imread ist nicht bewusst, Qt-Ressourcen. Sie können Ihre eigenen loader, die QFile verwendet jedoch schreiben die Binärdaten aus der Ressource abzurufen, und verwendet imdecode (wie intern von imread getan), um das Bild zu lesen:

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

Sie nennen es mögen:

Mat m = loadFromQrc("qrc_path"); 

oder Angabe ein flag:

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

Leistung

I mit loadFromQrc das Bild versuchte, das Laden und die QImage Laden und Umwandeln in Matthis Code verwendet, sowohl mit als auch ohne Klonen. loadFromQrc Ergebnisse 10 mal schneller als Laden einer QImage und konvertieren Sie es in Mat.

Ergebnisse in ms:

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

Prüfregeln:

#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; 
} 
+0

Hallo @Miki. Der von Ihnen bereitgestellte Code ist sehr nützlich. Ich habe Zeiten und Ergebnisse getestet, die von "QImage" zu "Mat" konvertiert werden, fast die gleiche Zeit wie die Verwendung Ihres Codes. –

+0

@AngieQuijano gald es half! Berücksichtigen Sie im QImage to Mat-Test auch die Zeit, die QImage benötigt, um das Bild zu laden. Ich überprüfe das jetzt, damit ich die Antwort mit weiteren Details aktualisieren kann. – Miki

+2

@AngieQuijano, ich mache einen Test.Das Laden eines 'QImage' und das Konvertieren in' Mat' ist 10 Mal langsamer als die Verwendung dieser Funktion. Die Antwort wurde mit Ergebnissen und Testcode aktualisiert. – Miki

2

Das hier Problem, dass imread() Lasten aus einer Datei ein Bild ist.

Im Gegensatz dazu kompiliert Qt Resource System die Daten von Bildern directly into the program's executable. Qt's QFile Operationen wissen, dass, wenn sie einen Pfad beginnend mit ": /" zur Verfügung gestellt werden, bezieht sie sich auf die eingebetteten Ressourcen, anstatt auf der Festplatte.

Daher glaube ich nicht, dass Sie imread() verwenden können, um direkt auf eine Datei zuzugreifen, die in Qt-Ressourcen platziert wurde.