2015-11-25 11 views
6

की मैं इस तरह से OpenCV की imread() का उपयोग कर एक QRC से एक छवि में पढ़ना चाहते हैं का उपयोग कर एक QRC से एक छवि पढ़ें:imread() OpenCV

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

लेकिन अंतिम img आकार [0x0] । मैंने यह भी कोशिश की है:

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

लेकिन मुझे जो आकार मिलता है वह वही है। मैं QImage में छवि को cv::Mat में बदलने के लिए लोड नहीं करना चाहता हूं। क्या इसे आसान तरीके से करने का कोई तरीका है? यदि यह है, तो मैं यह कैसे कर सकता हूं?

धन्यवाद

+0

नमस्ते, अपने सुझाव के लिए धन्यवाद, लेकिन मैं पहले से ही की कोशिश की है कि है, लेकिन है कि मैं 'QFileInfo (" QRC से प्राप्त ... ") .filePath()' हमेशा एक ही पथ है: ": /TempIcons/logo.png" –

उत्तर

7

@TheDarkKnight के रूप में बताया, imread क्यूटी संसाधनों के बारे में पता नहीं है। लेकिन आप अपनी खुद की लोडर, QFile का उपयोग करता है संसाधन से बाइनरी डेटा पुनः प्राप्त करने के लिख सकते हैं, और (के रूप में imread द्वारा आंतरिक रूप से किया जाता है) का उपयोग करता है imdecode छवि को पढ़ने के लिए:

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 लोड हो रहा है और दोनों के साथ और क्लोनिंग के बिना this कोड का उपयोग कर 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; 
} 
+0

हैलो @ मिकी। आपके द्वारा प्रदान किया गया कोड बहुत उपयोगी है। मैंने समय और परिणामों का परीक्षण किया जो 'QImage' से 'Mat' में कनवर्ट करते हैं, लगभग उसी समय आपके कोड का उपयोग करते हैं। –

+0

@AngieQuijano gald इससे मदद मिली! QImage में मैट टेस्ट में भी विचार करें, जिस समय QImage छवि लोड करने के लिए लेता है। मैं अभी यह जांच रहा हूं, इसलिए मैं अधिक जानकारी के साथ उत्तर अपडेट कर सकता हूं। – Miki

+2

@AngieQuijano, मैं कुछ परीक्षण चलाता हूं।'QImage' लोड हो रहा है और' Mat 'में कनवर्ट करना इस फ़ंक्शन का उपयोग करने से 10 गुना धीमा है। परिणाम और परीक्षण कोड के साथ जवाब अद्यतन किया गया। – Miki

2

समस्या यहाँ है कि imread() भार एक फ़ाइल से एक छवि।

इसके विपरीत, क्यूटी के संसाधन प्रणाली छवियों directly into the program's executable से डेटा संकलित करता है। क्यूटी के QFile संचालन जानते हैं कि जब उन्हें ": /" से शुरू होने वाला पथ प्रदान किया जाता है, तो यह डिस्क के बजाए एम्बेडेड संसाधनों को संदर्भित करता है।

इसलिए, मुझे नहीं लगता कि आप imread() उपयोग करने के लिए सीधे कि क्यूटी के संसाधनों में रखा गया है एक फ़ाइल का उपयोग कर सकेंगे है।